Bug 1199345 - Extend JSOP_NEWARRAY/JSOP_INITELEM_ARRAY/JSOP_SPREADCALLARRAY operand to uint32. r=Waldo

This commit is contained in:
Tooru Fujisawa 2015-08-29 17:56:38 +09:00
parent 5cd0d0b6d1
commit 656eb59dc5
7 changed files with 52 additions and 36 deletions

View File

@ -3889,13 +3889,8 @@ BytecodeEmitter::emitDestructuringOpsArrayHelper(ParseNode* pattern, VarEmitOpti
if (elem->isKind(PNK_SPREAD)) {
/* Create a new array with the rest of the iterator */
ptrdiff_t off;
if (!emitN(JSOP_NEWARRAY, 3, &off)) // ... OBJ? ITER ARRAY
if (!emitUint32Operand(JSOP_NEWARRAY, 0)) // ... OBJ? ITER ARRAY
return false;
checkTypeSet(JSOP_NEWARRAY);
jsbytecode* pc = code(off);
SET_UINT24(pc, 0);
if (!emitNumberOp(0)) // ... OBJ? ITER ARRAY INDEX
return false;
if (!emitSpread()) // ... OBJ? ARRAY INDEX
@ -7214,29 +7209,35 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
*/
MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY);
int32_t nspread = 0;
uint32_t nspread = 0;
for (ParseNode* elt = pn; elt; elt = elt->pn_next) {
if (elt->isKind(PNK_SPREAD))
nspread++;
}
ptrdiff_t off;
if (!emitN(op, 3, &off)) // ARRAY
return false;
checkTypeSet(op);
jsbytecode* pc = code(off);
// Array literal's length is limited to NELEMENTS_LIMIT in parser.
static_assert(NativeObject::MAX_DENSE_ELEMENTS_COUNT <= INT32_MAX,
"array literals' maximum length must not exceed limits "
"required by BaselineCompiler::emit_JSOP_NEWARRAY, "
"BaselineCompiler::emit_JSOP_INITELEM_ARRAY, "
"and DoSetElemFallback's handling of JSOP_INITELEM_ARRAY");
MOZ_ASSERT(count >= nspread);
MOZ_ASSERT(count <= NativeObject::MAX_DENSE_ELEMENTS_COUNT,
"the parser must throw an error if the array exceeds maximum "
"length");
// For arrays with spread, this is a very pessimistic allocation, the
// minimum possible final size.
SET_UINT24(pc, count - nspread);
if (!emitUint32Operand(op, count - nspread)) // ARRAY
return false;
ParseNode* pn2 = pn;
jsatomid atomIndex;
uint32_t index;
bool afterSpread = false;
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
for (index = 0; pn2; index++, pn2 = pn2->pn_next) {
if (!afterSpread && pn2->isKind(PNK_SPREAD)) {
afterSpread = true;
if (!emitNumberOp(atomIndex)) // ARRAY INDEX
if (!emitNumberOp(index)) // ARRAY INDEX
return false;
}
if (!updateSourceCoordNotes(pn2->pn_pos.begin))
@ -7262,12 +7263,11 @@ BytecodeEmitter::emitArray(ParseNode* pn, uint32_t count, JSOp op)
if (!emit1(JSOP_INITELEM_INC))
return false;
} else {
if (!emitN(JSOP_INITELEM_ARRAY, 3, &off))
if (!emitUint32Operand(JSOP_INITELEM_ARRAY, index))
return false;
SET_UINT24(code(off), atomIndex);
}
}
MOZ_ASSERT(atomIndex == count);
MOZ_ASSERT(index == count);
if (afterSpread) {
if (!emit1(JSOP_POP)) // ARRAY
return false;

View File

@ -6,6 +6,7 @@
#include "jit/BaselineCompiler.h"
#include "mozilla/Casting.h"
#include "mozilla/UniquePtr.h"
#include "jit/BaselineIC.h"
@ -32,6 +33,8 @@
using namespace js;
using namespace js::jit;
using mozilla::AssertedCast;
BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script)
: BaselineCompilerSpecific(cx, alloc, script),
yieldOffsets_(cx),
@ -1792,10 +1795,13 @@ BaselineCompiler::emit_JSOP_NEWARRAY()
{
frame.syncStack(0);
uint32_t length = GET_UINT24(pc);
uint32_t length = GET_UINT32(pc);
MOZ_ASSERT(length <= INT32_MAX,
"the bytecode emitter must fail to compile code that would "
"produce JSOP_NEWARRAY with a length exceeding int32_t range");
// Pass length in R0.
masm.move32(Imm32(length), R0.scratchReg());
masm.move32(Imm32(AssertedCast<int32_t>(length)), R0.scratchReg());
ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array);
if (!group)
@ -1849,7 +1855,12 @@ BaselineCompiler::emit_JSOP_INITELEM_ARRAY()
// Load object in R0, index in R1.
masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0);
masm.moveValue(Int32Value(GET_UINT24(pc)), R1);
uint32_t index = GET_UINT32(pc);
MOZ_ASSERT(index <= INT32_MAX,
"the bytecode emitter must fail to compile code that would "
"produce JSOP_INITELEM_ARRAY with a length exceeding "
"int32_t range");
masm.moveValue(Int32Value(AssertedCast<int32_t>(index)), R1);
// Call IC.
ICSetElem_Fallback::Compiler stubCompiler(cx);

View File

@ -3689,7 +3689,11 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
if (!InitElemOperation(cx, obj, index, rhs))
return false;
} else if (op == JSOP_INITELEM_ARRAY) {
MOZ_ASSERT(uint32_t(index.toInt32()) == GET_UINT24(pc));
MOZ_ASSERT(uint32_t(index.toInt32()) <= INT32_MAX,
"the bytecode emitter must fail to compile code that would "
"produce JSOP_INITELEM_ARRAY with an index exceeding "
"int32_t range");
MOZ_ASSERT(uint32_t(index.toInt32()) == GET_UINT32(pc));
if (!InitArrayElemOperation(cx, pc, obj, index.toInt32(), rhs))
return false;
} else if (op == JSOP_INITELEM_INC) {

View File

@ -1794,7 +1794,7 @@ IonBuilder::inspectOpcode(JSOp op)
return jsop_newobject();
case JSOP_NEWARRAY:
return jsop_newarray(GET_UINT24(pc));
return jsop_newarray(GET_UINT32(pc));
case JSOP_NEWARRAY_COPYONWRITE:
return jsop_newarray_copyonwrite();
@ -7052,13 +7052,14 @@ IonBuilder::jsop_initelem_array()
}
}
uint32_t index = GET_UINT32(pc);
if (needStub) {
MCallInitElementArray* store = MCallInitElementArray::New(alloc(), obj, GET_UINT24(pc), value);
MCallInitElementArray* store = MCallInitElementArray::New(alloc(), obj, index, value);
current->add(store);
return resumeAfter(store);
}
return initializeArrayElement(obj, GET_UINT24(pc), value, unboxedType, /* addResumePoint = */ true);
return initializeArrayElement(obj, index, value, unboxedType, /* addResumePoint = */ true);
}
bool

View File

@ -3609,7 +3609,8 @@ END_CASE(JSOP_NEWINIT)
CASE(JSOP_NEWARRAY)
CASE(JSOP_SPREADCALLARRAY)
{
JSObject* obj = NewArrayOperation(cx, script, REGS.pc, GET_UINT24(REGS.pc));
uint32_t length = GET_UINT32(REGS.pc);
JSObject* obj = NewArrayOperation(cx, script, REGS.pc, length);
if (!obj)
goto error;
PUSH_OBJECT(*obj);
@ -3705,7 +3706,7 @@ CASE(JSOP_INITELEM_ARRAY)
ReservedRooted<JSObject*> obj(&rootObject0, &REGS.sp[-2].toObject());
uint32_t index = GET_UINT24(REGS.pc);
uint32_t index = GET_UINT32(REGS.pc);
if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val))
goto error;

View File

@ -847,10 +847,10 @@
* This opcode takes the final length, which is preallocated.
* Category: Literals
* Type: Array
* Operands: uint24_t length
* Operands: uint32_t length
* Stack: => obj
*/ \
macro(JSOP_NEWARRAY, 90, "newarray", NULL, 4, 0, 1, JOF_UINT24) \
macro(JSOP_NEWARRAY, 90, "newarray", NULL, 5, 0, 1, JOF_UINT32) \
/*
* Pushes newly created object onto the stack.
*
@ -920,10 +920,10 @@
* property of 'obj' as 'val', pushes 'obj' onto the stack.
* Category: Literals
* Type: Array
* Operands: uint24_t index
* Operands: uint32_t index
* Stack: obj, val => obj
*/ \
macro(JSOP_INITELEM_ARRAY,96, "initelem_array", NULL, 4, 2, 1, JOF_UINT24|JOF_ELEM|JOF_SET|JOF_DETECTING) \
macro(JSOP_INITELEM_ARRAY,96, "initelem_array", NULL, 5, 2, 1, JOF_UINT32|JOF_ELEM|JOF_SET|JOF_DETECTING) \
\
/*
* Initialize a getter in an object literal.
@ -1277,13 +1277,12 @@
* the same semantics as JSOP_NEWARRAY, but is distinguished to avoid
* using unboxed arrays in spread calls, which would make compiling spread
* calls in baseline more complex.
*
* Category: Literals
* Type: Array
* Operands: uint24_t length
* Operands: uint32_t length
* Stack: => obj
*/ \
macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 4, 0, 1, JOF_UINT24) \
macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 5, 0, 1, JOF_UINT32) \
\
/*
* Defines the given function on the current scope.

View File

@ -29,7 +29,7 @@ namespace js {
*
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 309;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 310;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);