author | Eric Faust <efaustbmo@gmail.com> |
Wed, 26 Nov 2014 14:42:53 -0800 | |
changeset 242115 | e39cad980949bbdfbdaacdb6252de18df20033a7 |
parent 242114 | 9d174d48ff39933020b81512fb82cd7bf8f93f90 |
child 242116 | d6ec04c0c78f14a04366f821172d9b815c89b0aa |
push id | 4311 |
push user | raliiev@mozilla.com |
push date | Mon, 12 Jan 2015 19:37:41 +0000 |
treeherder | mozilla-beta@150c9fed433b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Waldo |
bugs | 1101905 |
milestone | 36.0a1 |
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/builtin/Eval.cpp +++ b/js/src/builtin/Eval.cpp @@ -186,25 +186,18 @@ ParseEvalStringAsJSON(JSContext *cx, con JSONParser<CharT> parser(cx, jsonChars, JSONParserBase::NoError); if (!parser.parse(rval)) return EvalJSON_Failure; return rval.isUndefined() ? EvalJSON_NotJSON : EvalJSON_Success; } static EvalJSONResult -TryEvalJSON(JSContext *cx, JSScript *callerScript, JSFlatString *str, MutableHandleValue rval) +TryEvalJSON(JSContext *cx, JSFlatString *str, MutableHandleValue rval) { - // Don't use the JSON parser if the caller is strict mode code, because in - // strict mode object literals must not have repeated properties, and the - // JSON parser cheerfully (and correctly) accepts them. If you're parsing - // JSON with eval and using strict mode, you deserve to be slow. - if (callerScript && callerScript->strict()) - return EvalJSON_NotJSON; - if (str->hasLatin1Chars()) { AutoCheckCannotGC nogc; if (!EvalStringMightBeJSON(str->latin1Range(nogc))) return EvalJSON_NotJSON; } else { AutoCheckCannotGC nogc; if (!EvalStringMightBeJSON(str->twoByteRange(nogc))) return EvalJSON_NotJSON; @@ -284,17 +277,17 @@ EvalKernel(JSContext *cx, const CallArgs thisv = ObjectValue(*thisobj); } Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx)); if (!flatStr) return false; RootedScript callerScript(cx, caller ? caller.script() : nullptr); - EvalJSONResult ejr = TryEvalJSON(cx, callerScript, flatStr, args.rval()); + EvalJSONResult ejr = TryEvalJSON(cx, flatStr, args.rval()); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); if (evalType == DIRECT_EVAL && caller.isNonEvalFunctionFrame()) esg.lookupInEvalCache(flatStr, callerScript, pc); @@ -316,17 +309,17 @@ EvalKernel(JSContext *cx, const CallArgs CompileOptions options(cx); options.setFileAndLine(filename, 1) .setCompileAndGo(true) .setForEval(true) .setNoScriptRval(false) .setMutedErrors(mutedErrors) .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset) - .maybeMakeStrictMode(evalType == DIRECT_EVAL && callerScript && callerScript->strict()); + .maybeMakeStrictMode(evalType == DIRECT_EVAL && IsStrictEvalPC(pc)); AutoStableStringChars flatChars(cx); if (!flatChars.initTwoByte(cx, flatStr)) return false; const char16_t *chars = flatChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership @@ -362,17 +355,17 @@ js::DirectEvalStringFromIon(JSContext *c // ES5 15.1.2.1 steps 2-8. unsigned staticLevel = callerScript->staticLevel() + 1; Rooted<JSFlatString*> flatStr(cx, str->ensureFlat(cx)); if (!flatStr) return false; - EvalJSONResult ejr = TryEvalJSON(cx, callerScript, flatStr, vp); + EvalJSONResult ejr = TryEvalJSON(cx, flatStr, vp); if (ejr != EvalJSON_NotJSON) return ejr == EvalJSON_Success; EvalScriptGuard esg(cx); esg.lookupInEvalCache(flatStr, callerScript, pc); if (!esg.foundScript()) { @@ -390,17 +383,17 @@ js::DirectEvalStringFromIon(JSContext *c CompileOptions options(cx); options.setFileAndLine(filename, 1) .setCompileAndGo(true) .setForEval(true) .setNoScriptRval(false) .setMutedErrors(mutedErrors) .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset) - .maybeMakeStrictMode(callerScript->strict()); + .maybeMakeStrictMode(IsStrictEvalPC(pc)); AutoStableStringChars flatChars(cx); if (!flatChars.initTwoByte(cx, flatStr)) return false; const char16_t *chars = flatChars.twoByteRange().start().get(); SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller() ? SourceBufferHolder::GiveOwnership @@ -451,17 +444,19 @@ bool js::DirectEval(JSContext *cx, const CallArgs &args) { // Direct eval can assume it was called from an interpreted or baseline frame. ScriptFrameIter iter(cx); AbstractFramePtr caller = iter.abstractFramePtr(); MOZ_ASSERT(caller.scopeChain()->global().valueIsEval(args.calleev())); MOZ_ASSERT(JSOp(*iter.pc()) == JSOP_EVAL || - JSOp(*iter.pc()) == JSOP_SPREADEVAL); + JSOp(*iter.pc()) == JSOP_STRICTEVAL || + JSOp(*iter.pc()) == JSOP_SPREADEVAL || + JSOp(*iter.pc()) == JSOP_STRICTSPREADEVAL); MOZ_ASSERT_IF(caller.isFunctionFrame(), caller.compartment() == caller.callee()->compartment()); RootedObject scopeChain(cx, caller.scopeChain()); return EvalKernel(cx, args, DIRECT_EVAL, caller, scopeChain, iter.pc()); } bool
--- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -6205,17 +6205,21 @@ EmitCallOrNew(ExclusiveContext *cx, Byte if (!spread) { if (EmitCall(cx, bce, pn->getOp(), argc, pn) < 0) return false; } else { if (Emit1(cx, bce, pn->getOp()) < 0) return false; } CheckTypeSet(cx, bce, pn->getOp()); - if (pn->isOp(JSOP_EVAL) || pn->isOp(JSOP_SPREADEVAL)) { + if (pn->isOp(JSOP_EVAL) || + pn->isOp(JSOP_STRICTEVAL) || + pn->isOp(JSOP_SPREADEVAL) || + pn->isOp(JSOP_STRICTSPREADEVAL)) + { uint32_t lineNum = bce->parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin); EMIT_UINT16_IMM_OP(JSOP_LINENO, lineNum); } if (pn->pn_xflags & PNX_SETCALL) { if (Emit1(cx, bce, JSOP_SETCALL) < 0) return false; } return true;
--- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -3246,17 +3246,18 @@ Parser<ParseHandler>::bindVarOrGlobalCon template <> bool Parser<FullParseHandler>::makeSetCall(ParseNode *pn, unsigned msg) { MOZ_ASSERT(pn->isKind(PNK_CALL)); MOZ_ASSERT(pn->isArity(PN_LIST)); MOZ_ASSERT(pn->isOp(JSOP_CALL) || pn->isOp(JSOP_SPREADCALL) || - pn->isOp(JSOP_EVAL) || pn->isOp(JSOP_SPREADEVAL) || + pn->isOp(JSOP_EVAL) || pn->isOp(JSOP_STRICTEVAL) || + pn->isOp(JSOP_SPREADEVAL) || pn->isOp(JSOP_STRICTSPREADEVAL) || pn->isOp(JSOP_FUNCALL) || pn->isOp(JSOP_FUNAPPLY)); if (!report(ParseStrictError, pc->sc->strict, pn, msg)) return false; handler.markAsSetCall(pn); return true; } @@ -6246,17 +6247,18 @@ bool Parser<FullParseHandler>::checkAndMarkAsIncOperand(ParseNode *kid, TokenKind tt, bool preorder) { // Check. if (!kid->isKind(PNK_NAME) && !kid->isKind(PNK_DOT) && !kid->isKind(PNK_ELEM) && !(kid->isKind(PNK_CALL) && (kid->isOp(JSOP_CALL) || kid->isOp(JSOP_SPREADCALL) || - kid->isOp(JSOP_EVAL) || kid->isOp(JSOP_SPREADEVAL) || + kid->isOp(JSOP_EVAL) || kid->isOp(JSOP_STRICTEVAL) || + kid->isOp(JSOP_SPREADEVAL) || kid->isOp(JSOP_STRICTSPREADEVAL) || kid->isOp(JSOP_FUNCALL) || kid->isOp(JSOP_FUNAPPLY)))) { report(ParseError, false, null(), JSMSG_BAD_OPERAND, incop_name_str[tt == TOK_DEC]); return false; } if (!checkStrictAssignment(kid)) @@ -7529,17 +7531,17 @@ Parser<ParseHandler>::memberExpr(TokenKi nextMember = handler.newList(PNK_TAGGED_TEMPLATE, null(), JSOP_CALL); if (!nextMember) return null(); if (JSAtom *atom = handler.isName(lhs)) { if (tt == TOK_LP && atom == context->names().eval) { /* Select JSOP_EVAL and flag pc as heavyweight. */ - op = JSOP_EVAL; + op = pc->sc->strict ? JSOP_STRICTEVAL : JSOP_EVAL; pc->sc->setBindingsAccessedDynamically(); /* * In non-strict mode code, direct calls to eval can add * variables to the call object. */ if (pc->sc->isFunctionBox() && !pc->sc->strict) pc->sc->asFunctionBox()->setHasExtensibleScope(); @@ -7557,18 +7559,24 @@ Parser<ParseHandler>::memberExpr(TokenKi handler.setBeginPosition(nextMember, lhs); handler.addList(nextMember, lhs); if (tt == TOK_LP) { bool isSpread = false; if (!argumentList(nextMember, &isSpread)) return null(); - if (isSpread) - op = (op == JSOP_EVAL ? JSOP_SPREADEVAL : JSOP_SPREADCALL); + if (isSpread) { + if (op == JSOP_EVAL) + op = JSOP_SPREADEVAL; + else if (op == JSOP_STRICTEVAL) + op = JSOP_STRICTSPREADEVAL; + else + op = JSOP_SPREADCALL; + } } else { if (!taggedTemplate(nextMember, tt)) return null(); } handler.setOp(nextMember, op); } else { tokenStream.ungetToken(); return lhs;
--- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -2753,16 +2753,22 @@ BaselineCompiler::emit_JSOP_FUNAPPLY() bool BaselineCompiler::emit_JSOP_EVAL() { return emitCall(); } bool +BaselineCompiler::emit_JSOP_STRICTEVAL() +{ + return emitCall(); +} + +bool BaselineCompiler::emit_JSOP_SPREADCALL() { return emitSpreadCall(); } bool BaselineCompiler::emit_JSOP_SPREADNEW() { @@ -2770,16 +2776,22 @@ BaselineCompiler::emit_JSOP_SPREADNEW() } bool BaselineCompiler::emit_JSOP_SPREADEVAL() { return emitSpreadCall(); } +bool +BaselineCompiler::emit_JSOP_STRICTSPREADEVAL() +{ + return emitSpreadCall(); +} + typedef bool (*ImplicitThisFn)(JSContext *, HandleObject, HandlePropertyName, MutableHandleValue); static const VMFunction ImplicitThisInfo = FunctionInfo<ImplicitThisFn>(ImplicitThisOperation); bool BaselineCompiler::emit_JSOP_IMPLICITTHIS() { frame.syncStack(0);
--- a/js/src/jit/BaselineCompiler.h +++ b/js/src/jit/BaselineCompiler.h @@ -146,19 +146,21 @@ namespace jit { _(JSOP_CHECKALIASEDLEXICAL) \ _(JSOP_INITALIASEDLEXICAL) \ _(JSOP_UNINITIALIZED) \ _(JSOP_CALL) \ _(JSOP_FUNCALL) \ _(JSOP_FUNAPPLY) \ _(JSOP_NEW) \ _(JSOP_EVAL) \ + _(JSOP_STRICTEVAL) \ _(JSOP_SPREADCALL) \ _(JSOP_SPREADNEW) \ _(JSOP_SPREADEVAL) \ + _(JSOP_STRICTSPREADEVAL) \ _(JSOP_IMPLICITTHIS) \ _(JSOP_INSTANCEOF) \ _(JSOP_TYPEOF) \ _(JSOP_TYPEOFEXPR) \ _(JSOP_SETCALL) \ _(JSOP_THROW) \ _(JSOP_THROWING) \ _(JSOP_TRY) \
--- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -8652,17 +8652,17 @@ IsOptimizableCallStringSplit(Value calle return true; } static bool TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsbytecode *pc, JSOp op, uint32_t argc, Value *vp, bool constructing, bool isSpread, bool useNewType) { - if (useNewType || op == JSOP_EVAL) + if (useNewType || op == JSOP_EVAL || op == JSOP_STRICTEVAL) return true; if (stub->numOptimizedStubs() >= ICCall_Fallback::MAX_OPTIMIZED_STUBS) { // TODO: Discard all stubs in this IC and replace with inert megamorphic stub. // But for now we just bail. return true; } @@ -8982,22 +8982,28 @@ DoCallFallback(JSContext *cx, BaselineFr cx->runtime()->spsProfiler.updatePC(script, pc); if (!MaybeCloneFunctionAtCallsite(cx, &callee, script, pc)) return false; if (op == JSOP_NEW) { if (!InvokeConstructor(cx, callee, argc, args, res)) return false; - } else if (op == JSOP_EVAL && frame->scopeChain()->global().valueIsEval(callee)) { + } else if ((op == JSOP_EVAL || op == JSOP_STRICTEVAL) && + frame->scopeChain()->global().valueIsEval(callee)) + { if (!DirectEval(cx, CallArgsFromVp(argc, vp))) return false; res.set(vp[0]); } else { - MOZ_ASSERT(op == JSOP_CALL || op == JSOP_FUNCALL || op == JSOP_FUNAPPLY || op == JSOP_EVAL); + MOZ_ASSERT(op == JSOP_CALL || + op == JSOP_FUNCALL || + op == JSOP_FUNAPPLY || + op == JSOP_EVAL || + op == JSOP_STRICTEVAL); if (!Invoke(cx, thisv, callee, argc, args, res)) return false; } types::TypeScript::Monitor(cx, script, pc, res); // Check if debug mode toggling made the stub invalid. if (stub.invalid()) @@ -9036,17 +9042,17 @@ DoSpreadCallFallback(JSContext *cx, Base RootedValue callee(cx, vp[0]); RootedValue thisv(cx, vp[1]); RootedValue arr(cx, vp[2]); bool constructing = (op == JSOP_SPREADNEW); // Try attaching a call stub. - if (op != JSOP_SPREADEVAL && + if (op != JSOP_SPREADEVAL && op != JSOP_STRICTSPREADEVAL && !TryAttachCallStub(cx, stub, script, pc, op, 1, vp, constructing, true, false)) { return false; } // Maybe update PC in profiler entry before leaving this script by call. if (cx->runtime()->spsProfiler.enabled() && frame->hasPushedSPSFrame()) cx->runtime()->spsProfiler.updatePC(script, pc);
--- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -1657,16 +1657,17 @@ IonBuilder::inspectOpcode(JSOp op) case JSOP_FUNAPPLY: return jsop_funapply(GET_ARGC(pc)); case JSOP_CALL: case JSOP_NEW: return jsop_call(GET_ARGC(pc), (JSOp)*pc == JSOP_NEW); case JSOP_EVAL: + case JSOP_STRICTEVAL: return jsop_eval(GET_ARGC(pc)); case JSOP_INT8: return pushConstant(Int32Value(GET_INT8(pc))); case JSOP_UINT16: return pushConstant(Int32Value(GET_UINT16(pc)));
--- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -117,17 +117,17 @@ js::StackUses(JSScript *script, jsbyteco MOZ_ASSERT(js_CodeSpec[op].nuses == -1); switch (op) { case JSOP_POPN: return GET_UINT16(pc); default: /* stack: fun, this, [argc arguments] */ MOZ_ASSERT(op == JSOP_NEW || op == JSOP_CALL || op == JSOP_EVAL || - op == JSOP_FUNCALL || op == JSOP_FUNAPPLY); + op == JSOP_STRICTEVAL || op == JSOP_FUNCALL || op == JSOP_FUNAPPLY); return 2 + GET_ARGC(pc); } } unsigned js::StackDefs(JSScript *script, jsbytecode *pc) { JSOp op = (JSOp) *pc;
--- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -689,16 +689,23 @@ IsSetElemPC(jsbytecode *pc) } inline bool IsCallPC(jsbytecode *pc) { return js_CodeSpec[*pc].format & JOF_INVOKE; } +inline bool +IsStrictEvalPC(jsbytecode *pc) +{ + JSOp op = JSOp(*pc); + return op == JSOP_STRICTEVAL || op == JSOP_STRICTSPREADEVAL; +} + static inline int32_t GetBytecodeInteger(jsbytecode *pc) { switch (JSOp(*pc)) { case JSOP_ZERO: return 0; case JSOP_ONE: return 1; case JSOP_UINT16: return GET_UINT16(pc); case JSOP_UINT24: return GET_UINT24(pc);
--- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -2906,19 +2906,25 @@ void js::DescribeScriptedCallerForCompilation(JSContext *cx, MutableHandleScript maybeScript, const char **file, unsigned *linenop, uint32_t *pcOffset, bool *mutedErrors, LineOption opt) { if (opt == CALLED_FROM_JSOP_EVAL) { jsbytecode *pc = nullptr; maybeScript.set(cx->currentScript(&pc)); - MOZ_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_SPREADEVAL); - MOZ_ASSERT(*(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH - : JSOP_SPREADEVAL_LENGTH)) == JSOP_LINENO); + static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH, + "next op after a spread must be at consistent offset"); + static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH, + "next op after a direct eval must be at consistent offset"); + MOZ_ASSERT(JSOp(*pc) == JSOP_EVAL || JSOp(*pc) == JSOP_STRICTEVAL || + JSOp(*pc) == JSOP_SPREADEVAL || JSOp(*pc) == JSOP_STRICTSPREADEVAL); + mozilla::DebugOnly<bool> isSpread = JSOp(*pc) == JSOP_SPREADEVAL || + JSOp(*pc) == JSOP_STRICTSPREADEVAL; + MOZ_ASSERT(*(pc + (isSpread ? JSOP_SPREADEVAL_LENGTH : JSOP_EVAL_LENGTH)) == JSOP_LINENO); *file = maybeScript->filename(); *linenop = GET_UINT16(pc + (JSOp(*pc) == JSOP_EVAL ? JSOP_EVAL_LENGTH : JSOP_SPREADEVAL_LENGTH)); *pcOffset = pc - maybeScript->code(); *mutedErrors = maybeScript->mutedErrors(); return; }
--- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1585,26 +1585,24 @@ CASE(EnableInterruptsPseudoOpcode) /* Commence executing the actual opcode. */ SANITY_CHECKS(); DISPATCH_TO(op); } /* Various 1-byte no-ops. */ CASE(JSOP_NOP) CASE(JSOP_UNUSED2) -CASE(JSOP_UNUSED50) CASE(JSOP_UNUSED51) CASE(JSOP_UNUSED52) CASE(JSOP_UNUSED83) CASE(JSOP_UNUSED92) CASE(JSOP_UNUSED103) CASE(JSOP_UNUSED104) CASE(JSOP_UNUSED105) CASE(JSOP_UNUSED107) -CASE(JSOP_UNUSED124) CASE(JSOP_UNUSED125) CASE(JSOP_UNUSED126) CASE(JSOP_UNUSED146) CASE(JSOP_UNUSED147) CASE(JSOP_UNUSED148) CASE(JSOP_BACKPATCH) CASE(JSOP_UNUSED150) CASE(JSOP_UNUSED157) @@ -2449,17 +2447,20 @@ CASE(JSOP_STRICTSETELEM) if (!SetObjectElementOperation(cx, obj, id, value, *REGS.pc == JSOP_STRICTSETELEM)) goto error; REGS.sp[-3] = value; REGS.sp -= 2; } END_CASE(JSOP_SETELEM) CASE(JSOP_EVAL) +CASE(JSOP_STRICTEVAL) { + static_assert(JSOP_EVAL_LENGTH == JSOP_STRICTEVAL_LENGTH, + "eval and stricteval must be the same size"); CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp); if (REGS.fp()->scopeChain()->global().valueIsEval(args.calleev())) { if (!DirectEval(cx, args)) goto error; } else { if (!Invoke(cx, args)) goto error; } @@ -2470,17 +2471,20 @@ END_CASE(JSOP_EVAL) CASE(JSOP_SPREADNEW) CASE(JSOP_SPREADCALL) if (REGS.fp()->hasPushedSPSFrame()) cx->runtime()->spsProfiler.updatePC(script, REGS.pc); /* FALL THROUGH */ CASE(JSOP_SPREADEVAL) +CASE(JSOP_STRICTSPREADEVAL) { + static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH, + "spreadeval and strictspreadeval must be the same size"); MOZ_ASSERT(REGS.stackDepth() >= 3); HandleValue callee = REGS.stackHandleAt(-3); HandleValue thisv = REGS.stackHandleAt(-2); HandleValue arr = REGS.stackHandleAt(-1); MutableHandleValue ret = REGS.stackHandleAt(-3); if (!SpreadCallOperation(cx, script, REGS.pc, thisv, callee, arr, ret)) goto error; @@ -4029,16 +4033,17 @@ js::SpreadCallOperation(JSContext *cx, H if (!InvokeConstructor(cx, args)) return false; break; case JSOP_SPREADCALL: if (!Invoke(cx, args)) return false; break; case JSOP_SPREADEVAL: + case JSOP_STRICTSPREADEVAL: if (cx->global()->valueIsEval(args.calleev())) { if (!DirectEval(cx, args)) return false; } else { if (!Invoke(cx, args)) return false; } break;
--- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -400,17 +400,17 @@ 1234567890123456789012345678901234567890 * * If 'eval' in global scope is not original one, invokes the function * with 'this' and 'args', and pushes return value onto the stack. * Category: Statements * Type: Function * Operands: * Stack: callee, this, args => rval */ \ - macro(JSOP_SPREADEVAL,43, "spreadeval", NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET) \ + macro(JSOP_SPREADEVAL,43, "spreadeval", NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSLOPPY) \ \ /* * Duplicates the Nth value from the top onto the stack. * Category: Operator * Type: Stack Operations * Operands: uint24_t n * Stack: v[n], v[n-1], ..., v[1], v[0] => * v[n], v[n-1], ..., v[1], v[0], v[n] @@ -462,17 +462,29 @@ 1234567890123456789012345678901234567890 * and pushes the value back on the stack. If the set failed, then throw * a TypeError, per usual strict mode semantics. * Category: Variables and Scopes * Type: Variables * Operands: uint32_t nameIndex * Stack: scope, val => val */ \ macro(JSOP_STRICTSETNAME, 49, "strict-setname", NULL, 5, 2, 1, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_CHECKSTRICT) \ - macro(JSOP_UNUSED50, 50, "unused50", NULL, 1, 0, 0, JOF_BYTE) \ + /* + * spreadcall variant of JSOP_EVAL + * + * Invokes 'eval' with 'args' and pushes the return value onto the stack. + * + * If 'eval' in global scope is not original one, invokes the function + * with 'this' and 'args', and pushes return value onto the stack. + * Category: Statements + * Type: Function + * Operands: + * Stack: callee, this, args => rval + */ \ + macro(JSOP_STRICTSPREADEVAL, 50, "strict-spreadeval", NULL, 1, 3, 1, JOF_BYTE|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \ macro(JSOP_UNUSED51, 51, "unused51", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED52, 52, "unused52", NULL, 1, 0, 0, JOF_BYTE) \ \ /* * Pops the top of stack value, pushes property of it onto the stack. * Category: Literals * Type: Object * Operands: uint32_t nameIndex @@ -1164,19 +1176,31 @@ 1234567890123456789012345678901234567890 * If 'eval' in global scope is not original one, invokes the function * with 'this' and 'args', and pushes return value onto the stack. * Category: Statements * Type: Function * Operands: uint16_t argc * Stack: callee, this, args[0], ..., args[argc-1] => rval * nuses: (argc+2) */ \ - macro(JSOP_EVAL, 123,"eval", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \ + macro(JSOP_EVAL, 123,"eval", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSLOPPY) \ \ - macro(JSOP_UNUSED124, 124, "unused124", NULL, 1, 0, 0, JOF_BYTE) \ + /* ECMA-compliant call to eval op. */ \ + /* + * Invokes 'eval' with 'args' and pushes return value onto the stack. + * + * If 'eval' in global scope is not original one, invokes the function + * with 'this' and 'args', and pushes return value onto the stack. + * Category: Statements + * Type: Function + * Operands: uint16_t argc + * Stack: callee, this, args[0], ..., args[argc-1] => rval + * nuses: (argc+2) + */ \ + macro(JSOP_STRICTEVAL, 124, "strict-eval", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET|JOF_CHECKSTRICT) \ macro(JSOP_UNUSED125, 125, "unused125", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED126, 126, "unused126", NULL, 1, 0, 0, JOF_BYTE) \ \ /* * 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.
--- a/js/src/vm/Xdr.h +++ b/js/src/vm/Xdr.h @@ -29,17 +29,17 @@ namespace js { * https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode * * === GREETINGS, FELLOW SUBTRAHEND INCREMENTER! === * For the time being, please increment the subtrahend by 2 each time it * changes, because we have two flavors of bytecode: with JSOP_SYMBOL (in * Nightly) and without (all others). FIXME: Bug 1066322 - Enable ES6 symbols * in all builds. */ -static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 216; +static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 218; static_assert(XDR_BYTECODE_VERSION_SUBTRAHEND % 2 == 0, "see the comment above"); static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - (XDR_BYTECODE_VERSION_SUBTRAHEND #ifdef JS_HAS_SYMBOLS + 1 #endif ));