author | Tooru Fujisawa <arai_a@mac.com> |
Wed, 23 Sep 2015 16:41:45 +0900 | |
changeset 263936 | 92c771c3f3e212729c8c08e6cab04205bf780e6e |
parent 263935 | 345255320643d943c45f4358beaa0e5b46dfd204 |
child 263937 | f97d1d74be6a4b141757d57d192c2210a0762282 |
push id | 65481 |
push user | arai_a@mac.com |
push date | Wed, 23 Sep 2015 07:43:28 +0000 |
treeherder | mozilla-inbound@c57ca7dcefef [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1199345, 1201869 |
milestone | 44.0a1 |
backs out | 15f4976a4937ca83384b3f90317028c349b4ea13 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -3884,18 +3884,23 @@ BytecodeEmitter::emitDestructuringOpsArr ParseNode* elem = member; if (elem->isKind(PNK_ASSIGN)) { pndefault = elem->pn_right; elem = elem->pn_left; } if (elem->isKind(PNK_SPREAD)) { /* Create a new array with the rest of the iterator */ - if (!emitUint32Operand(JSOP_NEWARRAY, 0)) // ... OBJ? ITER ARRAY - return false; + ptrdiff_t off; + if (!emitN(JSOP_NEWARRAY, 3, &off)) // ... 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 return false; if (!emit1(JSOP_POP)) // ... OBJ? ARRAY return false; needToPopIterator = false; } else { @@ -7204,45 +7209,39 @@ BytecodeEmitter::emitArray(ParseNode* pn * array and in source order evaluating each element value and adding * it to the array, without invoking latent setters. We use the * JSOP_NEWINIT and JSOP_INITELEM_ARRAY bytecodes to ignore setters and * to avoid dup'ing and popping the array as each element is added, as * JSOP_SETELEM/JSOP_SETPROP would do. */ MOZ_ASSERT(op == JSOP_NEWARRAY || op == JSOP_SPREADCALLARRAY); - uint32_t nspread = 0; + int32_t nspread = 0; for (ParseNode* elt = pn; elt; elt = elt->pn_next) { if (elt->isKind(PNK_SPREAD)) nspread++; } - // 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"); + ptrdiff_t off; + if (!emitN(op, 3, &off)) // ARRAY + return false; + checkTypeSet(op); + jsbytecode* pc = code(off); // For arrays with spread, this is a very pessimistic allocation, the // minimum possible final size. - if (!emitUint32Operand(op, count - nspread)) // ARRAY - return false; + SET_UINT24(pc, count - nspread); ParseNode* pn2 = pn; - uint32_t index; + jsatomid atomIndex; bool afterSpread = false; - for (index = 0; pn2; index++, pn2 = pn2->pn_next) { + for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) { if (!afterSpread && pn2->isKind(PNK_SPREAD)) { afterSpread = true; - if (!emitNumberOp(index)) // ARRAY INDEX + if (!emitNumberOp(atomIndex)) // ARRAY INDEX return false; } if (!updateSourceCoordNotes(pn2->pn_pos.begin)) return false; if (pn2->isKind(PNK_ELISION)) { if (!emit1(JSOP_HOLE)) return false; } else { @@ -7258,21 +7257,22 @@ BytecodeEmitter::emitArray(ParseNode* pn if (!emit2(JSOP_PICK, 2)) // ITER ARRAY INDEX return false; if (!emitSpread()) // ARRAY INDEX return false; } else if (afterSpread) { if (!emit1(JSOP_INITELEM_INC)) return false; } else { - if (!emitUint32Operand(JSOP_INITELEM_ARRAY, index)) - return false; - } - } - MOZ_ASSERT(index == count); + if (!emitN(JSOP_INITELEM_ARRAY, 3, &off)) + return false; + SET_UINT24(code(off), atomIndex); + } + } + MOZ_ASSERT(atomIndex == count); if (afterSpread) { if (!emit1(JSOP_POP)) // ARRAY return false; } return true; } bool
--- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -1,17 +1,16 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jit/BaselineCompiler.h" -#include "mozilla/Casting.h" #include "mozilla/UniquePtr.h" #include "jit/BaselineIC.h" #include "jit/BaselineJIT.h" #include "jit/FixedList.h" #include "jit/IonAnalysis.h" #include "jit/JitcodeMap.h" #include "jit/JitSpewer.h" @@ -28,18 +27,16 @@ #include "jit/MacroAssembler-inl.h" #include "vm/Interpreter-inl.h" #include "vm/NativeObject-inl.h" using namespace js; using namespace js::jit; -using mozilla::AssertedCast; - BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript* script) : BaselineCompilerSpecific(cx, alloc, script), yieldOffsets_(cx), modifiesArguments_(false) { } bool @@ -1785,23 +1782,20 @@ BaselineCompiler::emit_JSOP_LINENO() return true; } bool BaselineCompiler::emit_JSOP_NEWARRAY() { frame.syncStack(0); - 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"); + uint32_t length = GET_UINT24(pc); // Pass length in R0. - masm.move32(Imm32(AssertedCast<int32_t>(length)), R0.scratchReg()); + masm.move32(Imm32(length), R0.scratchReg()); ObjectGroup* group = ObjectGroup::allocationSiteGroup(cx, script, pc, JSProto_Array); if (!group) return false; ICNewArray_Fallback::Compiler stubCompiler(cx, group); if (!emitOpIC(stubCompiler.getStub(&stubSpace_))) return false; @@ -1845,22 +1839,17 @@ BaselineCompiler::emit_JSOP_NEWARRAY_COP bool BaselineCompiler::emit_JSOP_INITELEM_ARRAY() { // Keep the object and rhs on the stack. frame.syncStack(0); // Load object in R0, index in R1. masm.loadValue(frame.addressOfStackValue(frame.peek(-2)), R0); - 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); + masm.moveValue(Int32Value(GET_UINT24(pc)), R1); // Call IC. ICSetElem_Fallback::Compiler stubCompiler(cx); if (!emitOpIC(stubCompiler.getStub(&stubSpace_))) return false; // Pop the rhs, so that the object is on the top of the stack. frame.pop();
--- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3684,21 +3684,17 @@ DoSetElemFallback(JSContext* cx, Baselin oldCapacity = GetAnyBoxedOrUnboxedCapacity(obj); oldInitLength = GetAnyBoxedOrUnboxedInitializedLength(obj); } if (op == JSOP_INITELEM) { if (!InitElemOperation(cx, obj, index, rhs)) return false; } else if (op == JSOP_INITELEM_ARRAY) { - 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)); + MOZ_ASSERT(uint32_t(index.toInt32()) == GET_UINT24(pc)); if (!InitArrayElemOperation(cx, pc, obj, index.toInt32(), rhs)) return false; } else if (op == JSOP_INITELEM_INC) { if (!InitArrayElemOperation(cx, pc, obj, index.toInt32(), rhs)) return false; } else { if (!SetObjectElement(cx, obj, index, rhs, JSOp(*pc) == JSOP_STRICTSETELEM, script, pc)) return false;
--- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -1786,17 +1786,17 @@ IonBuilder::inspectOpcode(JSOp op) return true; case JSOP_NEWINIT: if (GET_UINT8(pc) == JSProto_Array) return jsop_newarray(0); return jsop_newobject(); case JSOP_NEWARRAY: - return jsop_newarray(GET_UINT32(pc)); + return jsop_newarray(GET_UINT24(pc)); case JSOP_NEWARRAY_COPYONWRITE: return jsop_newarray_copyonwrite(); case JSOP_NEWOBJECT: return jsop_newobject(); case JSOP_INITELEM: @@ -7044,24 +7044,23 @@ IonBuilder::jsop_initelem_array() HeapTypeSetKey elemTypes = initializer->property(JSID_VOID); if (!TypeSetIncludes(elemTypes.maybeTypes(), value->type(), value->resultTypeSet())) { elemTypes.freeze(constraints()); needStub = true; } } } - uint32_t index = GET_UINT32(pc); if (needStub) { - MCallInitElementArray* store = MCallInitElementArray::New(alloc(), obj, index, value); + MCallInitElementArray* store = MCallInitElementArray::New(alloc(), obj, GET_UINT24(pc), value); current->add(store); return resumeAfter(store); } - return initializeArrayElement(obj, index, value, unboxedType, /* addResumePoint = */ true); + return initializeArrayElement(obj, GET_UINT24(pc), value, unboxedType, /* addResumePoint = */ true); } bool IonBuilder::initializeArrayElement(MDefinition* obj, size_t index, MDefinition* value, JSValueType unboxedType, bool addResumePointAndIncrementInitializedLength) { MConstant* id = MConstant::New(alloc(), Int32Value(index));
--- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -3603,18 +3603,17 @@ CASE(JSOP_NEWINIT) goto error; PUSH_OBJECT(*obj); } END_CASE(JSOP_NEWINIT) CASE(JSOP_NEWARRAY) CASE(JSOP_SPREADCALLARRAY) { - uint32_t length = GET_UINT32(REGS.pc); - JSObject* obj = NewArrayOperation(cx, script, REGS.pc, length); + JSObject* obj = NewArrayOperation(cx, script, REGS.pc, GET_UINT24(REGS.pc)); if (!obj) goto error; PUSH_OBJECT(*obj); } END_CASE(JSOP_NEWARRAY) CASE(JSOP_NEWARRAY_COPYONWRITE) { @@ -3700,17 +3699,17 @@ END_CASE(JSOP_INITELEM) CASE(JSOP_INITELEM_ARRAY) { MOZ_ASSERT(REGS.stackDepth() >= 2); HandleValue val = REGS.stackHandleAt(-1); ReservedRooted<JSObject*> obj(&rootObject0, ®S.sp[-2].toObject()); - uint32_t index = GET_UINT32(REGS.pc); + uint32_t index = GET_UINT24(REGS.pc); if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val)) goto error; REGS.sp--; } END_CASE(JSOP_INITELEM_ARRAY) CASE(JSOP_INITELEM_INC)
--- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -842,20 +842,20 @@ 1234567890123456789012345678901234567890 */ \ macro(JSOP_NEWINIT, 89, "newinit", NULL, 5, 0, 1, JOF_UINT8) \ /* * Pushes newly created array onto the stack. * * This opcode takes the final length, which is preallocated. * Category: Literals * Type: Array - * Operands: uint32_t length + * Operands: uint24_t length * Stack: => obj */ \ - macro(JSOP_NEWARRAY, 90, "newarray", NULL, 5, 0, 1, JOF_UINT32) \ + macro(JSOP_NEWARRAY, 90, "newarray", NULL, 4, 0, 1, JOF_UINT24) \ /* * Pushes newly created object onto the stack. * * This opcode takes an object with the final shape, which can be set at * the start and slots then filled in directly. * Category: Literals * Type: Object * Operands: uint32_t baseobjIndex @@ -915,20 +915,20 @@ 1234567890123456789012345678901234567890 \ /* * Initialize an array element. * * Pops the top two values on the stack as 'val' and 'obj', sets 'index' * property of 'obj' as 'val', pushes 'obj' onto the stack. * Category: Literals * Type: Array - * Operands: uint32_t index + * Operands: uint24_t index * Stack: obj, val => obj */ \ - macro(JSOP_INITELEM_ARRAY,96, "initelem_array", NULL, 5, 2, 1, JOF_UINT32|JOF_ELEM|JOF_SET|JOF_DETECTING) \ + macro(JSOP_INITELEM_ARRAY,96, "initelem_array", NULL, 4, 2, 1, JOF_UINT24|JOF_ELEM|JOF_SET|JOF_DETECTING) \ \ /* * Initialize a getter in an object literal. * * Pops the top two values on the stack as 'val' and 'obj', defines getter * of 'obj' as 'val', pushes 'obj' onto the stack. * Category: Literals * Type: Object @@ -1272,22 +1272,23 @@ 1234567890123456789012345678901234567890 * Stack: receiver, obj, propval => obj[propval] */ \ macro(JSOP_GETELEM_SUPER, 125, "getelem-super", NULL, 1, 3, 1, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC) \ /* * Pushes newly created array for a spread call onto the stack. This has * 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: uint32_t length + * Operands: uint24_t length * Stack: => obj */ \ - macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 5, 0, 1, JOF_UINT32) \ + macro(JSOP_SPREADCALLARRAY, 126, "spreadcallarray", NULL, 4, 0, 1, JOF_UINT24) \ \ /* * Defines the given function on the current scope. * * This is used for global scripts and also in some cases for function * scripts where use of dynamic scoping inhibits optimization. * Category: Variables and Scopes * Type: Variables
--- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -24,17 +24,17 @@ namespace js { * versions. If deserialization fails, the data should be invalidated if * possible. * * When you change this, run make_opcode_doc.py and copy the new output into * this wiki page: * * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 308; +static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 307; static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND); static_assert(JSErr_Limit == 408, "GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or " "removed MSG_DEFs from js.msg, you should increment " "XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's " "expected JSErr_Limit value.");