diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index b35a280aa58f..7108177f385b 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -2071,22 +2071,6 @@ EmitNameOp(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callC return true; } -static inline bool -EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op) -{ - if (Emit1(cx, bce, op) < 0) - return false; - CheckTypeSet(cx, bce, op); - - if (op == JSOP_CALLELEM) { - if (Emit1(cx, bce, JSOP_SWAP) < 0) - return false; - if (Emit1(cx, bce, JSOP_NOTEARG) < 0) - return false; - } - return true; -} - static bool EmitPropLHS(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce) { @@ -2234,6 +2218,11 @@ EmitNameIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce) return true; } +/* + * Emit bytecode to put operands for a JSOP_GETELEM/CALLELEM/SETELEM/DELELEM + * opcode onto the stack in the right order. In the case of SETELEM, the + * value to be assigned must already be pushed. + */ static bool EmitElemOperands(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce) { @@ -2244,6 +2233,24 @@ EmitElemOperands(ExclusiveContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter * return false; if (!EmitTree(cx, bce, pn->pn_right)) return false; + if (op == JSOP_SETELEM && Emit2(cx, bce, JSOP_PICK, (jsbytecode)2) < 0) + return false; + return true; +} + +static inline bool +EmitElemOpBase(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op) +{ + if (Emit1(cx, bce, op) < 0) + return false; + CheckTypeSet(cx, bce, op); + + if (op == JSOP_CALLELEM) { + if (Emit1(cx, bce, JSOP_SWAP) < 0) + return false; + if (Emit1(cx, bce, JSOP_NOTEARG) < 0) + return false; + } return true; } @@ -2913,20 +2920,16 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, { JS_ASSERT(emitOption != DefineVars); - /* - * Now emit the lvalue opcode sequence. If the lvalue is a nested - * destructuring initialiser-form, call ourselves to handle it, then - * pop the matched value. Otherwise emit an lvalue bytecode sequence - * ending with a JSOP_ENUMELEM or equivalent op. - */ + // Now emit the lvalue opcode sequence. If the lvalue is a nested + // destructuring initialiser-form, call ourselves to handle it, then pop + // the matched value. Otherwise emit an lvalue bytecode sequence followed + // by an assignment op. if (pn->isKind(PNK_ARRAY) || pn->isKind(PNK_OBJECT)) { if (!EmitDestructuringOpsHelper(cx, bce, pn, emitOption)) return false; if (emitOption == InitializeVars) { - /* - * Per its post-condition, EmitDestructuringOpsHelper has left the - * to-be-destructured value on top of the stack. - */ + // Per its post-condition, EmitDestructuringOpsHelper has left the + // to-be-destructured value on top of the stack. if (Emit1(cx, bce, JSOP_POP) < 0) return false; } @@ -2936,8 +2939,6 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, JS_ASSERT(pn->getOp() == JSOP_GETLOCAL); JS_ASSERT(pn->pn_dflags & PND_BOUND); } else { - // All paths below must pop after assigning to the lhs. - switch (pn->getKind()) { case PNK_NAME: if (!BindNameToSlot(cx, bce, pn)) @@ -2975,8 +2976,6 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, if (!EmitIndexOp(cx, pn->getOp(), atomIndex, bce)) return false; - if (Emit1(cx, bce, JSOP_POP) < 0) - return false; break; } @@ -2984,8 +2983,6 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, case JSOP_SETARG: if (!EmitVarOp(cx, pn, pn->getOp(), bce)) return false; - if (Emit1(cx, bce, JSOP_POP) < 0) - return false; break; default: @@ -3008,16 +3005,13 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, return false; if (!EmitAtomOp(cx, pn, JSOP_SETPROP, bce)) return false; - if (Emit1(cx, bce, JSOP_POP) < 0) - return false; break; case PNK_ELEM: // See the comment at `case PNK_DOT:` above. This case, - // `[a[x]] = [b]`, is handled much the same way, but no JSOP_SWAP - // is necessary because there is a specialized opcode for that, - // JSOP_ENUMELEM. - if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, bce)) + // `[a[x]] = [b]`, is handled much the same way. The JSOP_SWAP + // is emitted by EmitElemOperands. + if (!EmitElemOp(cx, pn, JSOP_SETELEM, bce)) return false; break; @@ -3026,13 +3020,11 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, if (!EmitTree(cx, bce, pn)) return false; - // Pop the call return value and the RHS, presumably for the - // benefit of bytecode analysis. (The interpreter will never reach - // these instructions since we just emitted JSOP_SETCALL, which - // always throws. It's possible no analyses actually depend on this - // either.) - if (Emit1(cx, bce, JSOP_POP) < 0) - return false; + // Pop the call return value. Below, we pop the RHS too, balancing + // the stack --- presumably for the benefit of bytecode + // analysis. (The interpreter will never reach these instructions + // since we just emitted JSOP_SETCALL, which always throws. It's + // possible no analyses actually depend on this either.) if (Emit1(cx, bce, JSOP_POP) < 0) return false; break; @@ -3040,6 +3032,10 @@ EmitDestructuringLHS(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, default: MOZ_ASSUME_UNREACHABLE("EmitDestructuringLHS: bad lhs kind"); } + + // Pop the assigned value. + if (Emit1(cx, bce, JSOP_POP) < 0) + return false; } return true; diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index ee2e0ca761ec..38e2bc69b9b6 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -1727,25 +1727,6 @@ BaselineCompiler::emit_JSOP_SETELEM() return true; } -bool -BaselineCompiler::emit_JSOP_ENUMELEM() -{ - // ENUMELEM is a SETELEM with a different stack arrangement. - // Instead of: OBJ ID RHS - // The stack is: RHS OBJ ID - - // Keep object and index in R0 and R1, and keep RHS on the stack. - frame.popRegsAndSync(2); - - // Call IC. - ICSetElem_Fallback::Compiler stubCompiler(cx); - if (!emitOpIC(stubCompiler.getStub(&stubSpace_))) - return false; - - frame.pop(); - return true; -} - typedef bool (*DeleteElementFn)(JSContext *, HandleValue, HandleValue, bool *); static const VMFunction DeleteElementStrictInfo = FunctionInfo(DeleteElement); static const VMFunction DeleteElementNonStrictInfo = FunctionInfo(DeleteElement); diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h index 8cc0432ddf11..7672be2afe57 100644 --- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -98,7 +98,6 @@ namespace jit { _(JSOP_GETELEM) \ _(JSOP_SETELEM) \ _(JSOP_CALLELEM) \ - _(JSOP_ENUMELEM) \ _(JSOP_DELELEM) \ _(JSOP_IN) \ _(JSOP_GETGNAME) \ diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 00bb9956633f..0f7e235058c8 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -4932,7 +4932,6 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub, FallbackICSpew(cx, stub, "SetElem(%s)", js_CodeName[JSOp(*pc)]); JS_ASSERT(op == JSOP_SETELEM || - op == JSOP_ENUMELEM || op == JSOP_INITELEM || op == JSOP_INITELEM_ARRAY); diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 890effb1cb37..df811fa1dab8 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -273,11 +273,7 @@ OPDEF(JSOP_DEFAULT, 122,"default", NULL, 5, 1, 0, JOF_JUMP) */ OPDEF(JSOP_EVAL, 123,"eval", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) -/* - * ECMA-compliant helper for 'for (x[i] in o)' loops. - */ -OPDEF(JSOP_ENUMELEM, 124,"enumelem", NULL, 1, 3, 0, JOF_BYTE |JOF_SET|JOF_TMPSLOT) - +OPDEF(JSOP_UNUSED124, 124, "unused124", NULL, 1, 0, 0, JOF_BYTE) OPDEF(JSOP_UNUSED125, 125, "unused125", NULL, 1, 0, 0, JOF_BYTE) OPDEF(JSOP_UNUSED126, 126, "unused126", NULL, 1, 0, 0, JOF_BYTE) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index dbecc2b4719e..f36d344e93c6 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1603,6 +1603,7 @@ CASE(JSOP_UNUSED103) CASE(JSOP_UNUSED104) CASE(JSOP_UNUSED105) CASE(JSOP_UNUSED107) +CASE(JSOP_UNUSED124) CASE(JSOP_UNUSED125) CASE(JSOP_UNUSED126) CASE(JSOP_UNUSED132) @@ -2477,22 +2478,6 @@ CASE(JSOP_SETELEM) } END_CASE(JSOP_SETELEM) -CASE(JSOP_ENUMELEM) -{ - RootedObject &obj = rootObject0; - RootedValue &rval = rootValue0; - - /* Funky: the value to set is under the [obj, id] pair. */ - FETCH_OBJECT(cx, -2, obj); - RootedId &id = rootId0; - FETCH_ELEMENT_ID(-1, id); - rval = REGS.sp[-3]; - if (!JSObject::setGeneric(cx, obj, obj, id, &rval, script->strict())) - goto error; - REGS.sp -= 3; -} -END_CASE(JSOP_ENUMELEM) - CASE(JSOP_EVAL) { CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);