Bug 1234845 part 10 - Remove ExecuteType and InitialFrameFlags enums. r=luke
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 21 Jan 2016 20:01:18 +0100
changeset 281091 b4328eb7bc5f815db24b8c475f13c3c175001638
parent 281090 9e34df8e0e84d59eea4950af27136dcf4cee51f9
child 281092 c1fbfe097769ebd5b1eb5e6935a40ad32f16f105
push id29930
push usercbook@mozilla.com
push dateFri, 22 Jan 2016 11:05:50 +0000
treeherdermozilla-central@7104d650a97d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1234845
milestone46.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
Bug 1234845 part 10 - Remove ExecuteType and InitialFrameFlags enums. r=luke
js/src/builtin/Eval.cpp
js/src/jit/BaselineJIT.cpp
js/src/vm/Debugger.cpp
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
js/src/vm/Stack-inl.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -209,18 +209,17 @@ TryEvalJSON(JSContext* cx, JSLinearStrin
     if (!linearChars.init(cx, str))
         return EvalJSON_Failure;
 
     return linearChars.isLatin1()
            ? ParseEvalStringAsJSON(cx, linearChars.latin1Range(), rval)
            : ParseEvalStringAsJSON(cx, linearChars.twoByteRange(), rval);
 }
 
-// Define subset of ExecuteType so that casting performs the injection.
-enum EvalType { DIRECT_EVAL = EXECUTE_DIRECT_EVAL, INDIRECT_EVAL = EXECUTE_INDIRECT_EVAL };
+enum EvalType { DIRECT_EVAL, INDIRECT_EVAL };
 
 // Common code implementing direct and indirect eval.
 //
 // Evaluate call.argv[2], if it is a string, in the context of the given calling
 // frame, with the provided scope chain, with the semantics of either a direct
 // or indirect eval (see ES5 10.4.2).  If this is an indirect eval, scopeobj
 // must be a global object.
 //
@@ -325,17 +324,17 @@ EvalKernel(JSContext* cx, const CallArgs
         if (compiled->strict())
             staticScope->setStrict();
 
         esg.setNewScript(compiled);
     }
 
     // Look up the newTarget from the frame iterator.
     Value newTargetVal = NullValue();
-    return ExecuteKernel(cx, esg.script(), *scopeobj, newTargetVal, ExecuteType(evalType),
+    return ExecuteKernel(cx, esg.script(), *scopeobj, newTargetVal,
                          NullFramePtr() /* evalInFrame */, args.rval().address());
 }
 
 bool
 js::DirectEvalStringFromIon(JSContext* cx,
                             HandleObject scopeobj, HandleScript callerScript,
                             HandleValue newTargetValue, HandleString str,
                             jsbytecode* pc, MutableHandleValue vp)
@@ -406,17 +405,17 @@ js::DirectEvalStringFromIon(JSContext* c
 
         if (compiled->strict())
             staticScope->setStrict();
 
         esg.setNewScript(compiled);
     }
 
     return ExecuteKernel(cx, esg.script(), *scopeobj, newTargetValue,
-                         ExecuteType(DIRECT_EVAL), NullFramePtr() /* evalInFrame */, vp.address());
+                         NullFramePtr() /* evalInFrame */, vp.address());
 }
 
 bool
 js::IndirectEval(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     Rooted<GlobalObject*> global(cx, &args.callee().global());
     RootedObject globalLexical(cx, &global->lexicalScope());
@@ -478,17 +477,17 @@ js::ExecuteInGlobalAndReturnScope(JSCont
     // Unlike the non-syntactic scope chain API used by the subscript loader,
     // this API creates a fresh block scope each time.
     RootedObject enclosingStaticScope(cx, script->enclosingStaticScope());
     scope = ClonedBlockObject::createNonSyntactic(cx, enclosingStaticScope, scope);
     if (!scope)
         return false;
 
     RootedValue rval(cx);
-    if (!ExecuteKernel(cx, script, *scope, UndefinedValue(), EXECUTE_GLOBAL_OR_MODULE,
+    if (!ExecuteKernel(cx, script, *scope, UndefinedValue(),
                        NullFramePtr() /* evalInFrame */, rval.address()))
     {
         return false;
     }
 
     scopeArg.set(scope);
     return true;
 }
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -374,19 +374,17 @@ jit::CanEnterBaselineMethod(JSContext* c
         if (!state.maybeCreateThisForConstructor(cx)) {
             if (cx->isThrowingOutOfMemory()) {
                 cx->recoverFromOutOfMemory();
                 return Method_Skipped;
             }
             return Method_Error;
         }
     } else {
-        MOZ_ASSERT(state.isExecute());
-        ExecuteType type = state.asExecute()->type();
-        if (type == EXECUTE_DEBUG) {
+        if (state.asExecute()->isDebuggerEval()) {
             JitSpew(JitSpew_BaselineAbort, "debugger frame");
             return Method_CantCompile;
         }
     }
 
     RootedScript script(cx, state.script());
     return CanEnterBaselineJIT(cx, script, /* osrFrame = */ nullptr);
 };
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -6727,18 +6727,17 @@ EvaluateInEnv(JSContext* cx, Handle<Env*
 
     // Again, executeInGlobal is not considered eval.
     if (frame) {
         if (script->strict())
             staticScope->as<StaticEvalObject>().setStrict();
         script->setActiveEval();
     }
 
-    ExecuteType type = !frame ? EXECUTE_GLOBAL_OR_MODULE : EXECUTE_DEBUG;
-    return ExecuteKernel(cx, script, *env, NullValue(), type, frame, rval.address());
+    return ExecuteKernel(cx, script, *env, NullValue(), frame, rval.address());
 }
 
 enum EvalBindings { EvalHasExtraBindings = true, EvalWithDefaultBindings = false };
 
 static bool
 DebuggerGenericEval(JSContext* cx, const char* fullMethodName, const Value& code,
                     EvalBindings evalWithBindings, HandleValue bindings, HandleValue options,
                     MutableHandleValue vp, Debugger* dbg, HandleObject scope,
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -364,24 +364,24 @@ RunState::maybeCreateThisForConstructor(
 }
 
 static MOZ_NEVER_INLINE bool
 Interpret(JSContext* cx, RunState& state);
 
 InterpreterFrame*
 InvokeState::pushInterpreterFrame(JSContext* cx)
 {
-    return cx->runtime()->interpreterStack().pushInvokeFrame(cx, args_, initial_);
+    return cx->runtime()->interpreterStack().pushInvokeFrame(cx, args_, construct_);
 }
 
 InterpreterFrame*
 ExecuteState::pushInterpreterFrame(JSContext* cx)
 {
     return cx->runtime()->interpreterStack().pushExecuteFrame(cx, script_, newTargetValue_,
-                                                              scopeChain_, type_, evalInFrame_);
+                                                              scopeChain_, evalInFrame_);
 }
 // MSVC with PGO inlines a lot of functions in RunScript, resulting in large
 // stack frames and stack overflow issues, see bug 1167883. Turn off PGO to
 // avoid this.
 #ifdef _MSC_VER
 # pragma optimize("g", off)
 #endif
 bool
@@ -445,19 +445,16 @@ bool
 js::Invoke(JSContext* cx, const CallArgs& args, MaybeConstruct construct)
 {
     MOZ_ASSERT(args.length() <= ARGS_LENGTH_MAX);
     MOZ_ASSERT(!cx->zone()->types.activeAnalysis);
 
     /* Perform GC if necessary on exit from the function. */
     AutoGCIfRequested gcIfRequested(cx->runtime());
 
-    /* MaybeConstruct is a subset of InitialFrameFlags */
-    InitialFrameFlags initial = (InitialFrameFlags) construct;
-
     unsigned skipForCallee = args.length() + 1 + (construct == CONSTRUCT);
     if (args.calleev().isPrimitive())
         return ReportIsNotFunction(cx, args.calleev(), skipForCallee, construct);
 
     /* Invoke non-functions. */
     if (MOZ_UNLIKELY(!args.callee().is<JSFunction>())) {
         MOZ_ASSERT_IF(construct, !args.callee().constructHook());
         JSNative call = args.callee().callHook();
@@ -477,17 +474,17 @@ js::Invoke(JSContext* cx, const CallArgs
         MOZ_ASSERT_IF(construct, !fun->isConstructor());
         return CallJSNative(cx, fun->native(), args);
     }
 
     if (!fun->getOrCreateScript(cx))
         return false;
 
     /* Run function until JSOP_RETRVAL, JSOP_RETURN or error. */
-    InvokeState state(cx, args, initial);
+    InvokeState state(cx, args, construct);
 
     // Check to see if createSingleton flag should be set for this frame.
     if (construct) {
         jsbytecode* pc;
         if (JSScript* script = cx->currentScript(&pc)) {
             if (ObjectGroup::useSingletonForNewObject(cx, script, pc))
                 state.setCreateSingleton();
         }
@@ -645,21 +642,20 @@ js::InvokeSetter(JSContext* cx, const Va
     JS_CHECK_RECURSION(cx, return false);
 
     RootedValue ignored(cx);
     return Invoke(cx, thisv, fval, 1, v.address(), &ignored);
 }
 
 bool
 js::ExecuteKernel(JSContext* cx, HandleScript script, JSObject& scopeChainArg,
-                  const Value& newTargetValue, ExecuteType type, AbstractFramePtr evalInFrame,
+                  const Value& newTargetValue, AbstractFramePtr evalInFrame,
                   Value* result)
 {
-    MOZ_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
-    MOZ_ASSERT_IF(type == EXECUTE_GLOBAL_OR_MODULE && !script->module(),
+    MOZ_ASSERT_IF(script->isGlobalCode(),
                   IsGlobalLexicalScope(&scopeChainArg) || !IsSyntacticScope(&scopeChainArg));
 #ifdef DEBUG
     RootedObject terminatingScope(cx, &scopeChainArg);
     while (IsSyntacticScope(terminatingScope))
         terminatingScope = terminatingScope->enclosingScope();
     MOZ_ASSERT(terminatingScope->is<GlobalObject>() ||
                script->hasNonSyntacticScope());
 #endif
@@ -675,17 +671,17 @@ js::ExecuteKernel(JSContext* cx, HandleS
 
     if (script->isEmpty()) {
         if (result)
             result->setUndefined();
         return true;
     }
 
     probes::StartExecution(script);
-    ExecuteState state(cx, script, newTargetValue, scopeChainArg, type, evalInFrame, result);
+    ExecuteState state(cx, script, newTargetValue, scopeChainArg, evalInFrame, result);
     bool ok = RunScript(cx, state);
     probes::StopExecution(script);
 
     return ok;
 }
 
 bool
 js::Execute(JSContext* cx, HandleScript script, JSObject& scopeChainArg, Value* rval)
@@ -708,17 +704,17 @@ js::Execute(JSContext* cx, HandleScript 
 #ifdef DEBUG
     JSObject* s = scopeChain;
     do {
         assertSameCompartment(cx, s);
         MOZ_ASSERT_IF(!s->enclosingScope(), s->is<GlobalObject>());
     } while ((s = s->enclosingScope()));
 #endif
 
-    return ExecuteKernel(cx, script, *scopeChain, NullValue(), EXECUTE_GLOBAL_OR_MODULE,
+    return ExecuteKernel(cx, script, *scopeChain, NullValue(),
                          NullFramePtr() /* evalInFrame */, rval);
 }
 
 bool
 js::HasInstance(JSContext* cx, HandleObject obj, HandleValue v, bool* bp)
 {
     const Class* clasp = obj->getClass();
     RootedValue local(cx, v);
@@ -2772,17 +2768,17 @@ CASE(JSOP_NEW)
 CASE(JSOP_CALL)
 CASE(JSOP_CALLITER)
 CASE(JSOP_SUPERCALL)
 CASE(JSOP_FUNCALL)
 {
     if (REGS.fp()->hasPushedSPSFrame())
         cx->runtime()->spsProfiler.updatePC(script, REGS.pc);
 
-    bool construct = (*REGS.pc == JSOP_NEW || *REGS.pc == JSOP_SUPERCALL);
+    MaybeConstruct construct = MaybeConstruct(*REGS.pc == JSOP_NEW || *REGS.pc == JSOP_SUPERCALL);
     unsigned argStackSlots = GET_ARGC(REGS.pc) + construct;
 
     MOZ_ASSERT(REGS.stackDepth() >= 2u + GET_ARGC(REGS.pc));
     CallArgs args = CallArgsFromSp(argStackSlots, REGS.sp, construct);
 
     JSFunction* maybeFun;
     bool isFunction = IsFunctionObject(args.calleev(), &maybeFun);
 
@@ -2810,23 +2806,22 @@ CASE(JSOP_FUNCALL)
 
     {
         MOZ_ASSERT(maybeFun);
         ReservedRooted<JSFunction*> fun(&rootFunction0, maybeFun);
         ReservedRooted<JSScript*> funScript(&rootScript0, fun->getOrCreateScript(cx));
         if (!funScript)
             goto error;
 
-        InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
         bool createSingleton = ObjectGroup::useSingletonForNewObject(cx, script, REGS.pc);
 
         TypeMonitorCall(cx, args, construct);
 
         mozilla::Maybe<InvokeState> state;
-        state.emplace(cx, args, initial);
+        state.emplace(cx, args, construct);
 
         if (createSingleton)
             state->setCreateSingleton();
 
         if (!createSingleton && jit::IsIonEnabled(cx)) {
             jit::MethodStatus status = jit::CanEnter(cx, state.ref());
             if (status == jit::Method_Error)
                 goto error;
@@ -2850,17 +2845,17 @@ CASE(JSOP_FUNCALL)
                 interpReturnOK = !IsErrorStatus(exec);
                 goto jit_return;
             }
         }
 
         state.reset();
         funScript = fun->nonLazyScript();
 
-        if (!activation.pushInlineFrame(args, funScript, initial))
+        if (!activation.pushInlineFrame(args, funScript, construct))
             goto error;
 
         if (createSingleton)
             REGS.fp()->setCreateSingleton();
     }
 
     SET_SCRIPT(REGS.fp()->script());
 
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -35,21 +35,16 @@ extern bool
 BoxNonStrictThis(JSContext* cx, HandleValue thisv, MutableHandleValue vp);
 
 extern bool
 GetFunctionThis(JSContext* cx, AbstractFramePtr frame, MutableHandleValue res);
 
 extern bool
 GetNonSyntacticGlobalThis(JSContext* cx, HandleObject scopeChain, MutableHandleValue res);
 
-enum MaybeConstruct {
-    NO_CONSTRUCT = INITIAL_NONE,
-    CONSTRUCT = INITIAL_CONSTRUCT
-};
-
 /*
  * numToSkip is the number of stack values the expression decompiler should skip
  * before it reaches |v|. If it's -1, the decompiler will search the stack.
  */
 extern bool
 ReportIsNotFunction(JSContext* cx, HandleValue v, int numToSkip,
                     MaybeConstruct construct = NO_CONSTRUCT);
 
@@ -108,18 +103,17 @@ InternalConstructWithProvidedThis(JSCont
 /*
  * Executes a script with the given scopeChain/this. The 'type' indicates
  * whether this is eval code or global code. To support debugging, the
  * evalFrame parameter can point to an arbitrary frame in the context's call
  * stack to simulate executing an eval in that frame.
  */
 extern bool
 ExecuteKernel(JSContext* cx, HandleScript script, JSObject& scopeChain,
-              const Value& newTargetVal, ExecuteType type, AbstractFramePtr evalInFrame,
-              Value* result);
+              const Value& newTargetVal, AbstractFramePtr evalInFrame, Value* result);
 
 /* Execute a script with the given scopeChain as global code. */
 extern bool
 Execute(JSContext* cx, HandleScript script, JSObject& scopeChain, Value* rval);
 
 class ExecuteState;
 class InvokeState;
 
@@ -164,67 +158,63 @@ class RunState
     RunState(const ExecuteState& other) = delete;
     RunState(const InvokeState& other) = delete;
     void operator=(const RunState& other) = delete;
 };
 
 // Eval or global script.
 class ExecuteState : public RunState
 {
-    ExecuteType type_;
-
     RootedValue newTargetValue_;
     RootedObject scopeChain_;
 
     AbstractFramePtr evalInFrame_;
     Value* result_;
 
   public:
     ExecuteState(JSContext* cx, JSScript* script, const Value& newTargetValue,
-                 JSObject& scopeChain, ExecuteType type, AbstractFramePtr evalInFrame,
-                 Value* result)
+                 JSObject& scopeChain, AbstractFramePtr evalInFrame, Value* result)
       : RunState(cx, Execute, script),
-        type_(type),
         newTargetValue_(cx, newTargetValue),
         scopeChain_(cx, &scopeChain),
         evalInFrame_(evalInFrame),
         result_(result)
     { }
 
     Value newTarget() { return newTargetValue_; }
     JSObject* scopeChain() const { return scopeChain_; }
-    ExecuteType type() const { return type_; }
+    bool isDebuggerEval() const { return !!evalInFrame_; }
 
     virtual InterpreterFrame* pushInterpreterFrame(JSContext* cx);
 
     virtual void setReturnValue(Value v) {
         if (result_)
             *result_ = v;
     }
 };
 
 // Data to invoke a function.
 class InvokeState : public RunState
 {
     const CallArgs& args_;
-    InitialFrameFlags initial_;
+    MaybeConstruct construct_;
     bool createSingleton_;
 
   public:
-    InvokeState(JSContext* cx, const CallArgs& args, InitialFrameFlags initial)
+    InvokeState(JSContext* cx, const CallArgs& args, MaybeConstruct construct)
       : RunState(cx, Invoke, args.callee().as<JSFunction>().nonLazyScript()),
         args_(args),
-        initial_(initial),
+        construct_(construct),
         createSingleton_(false)
     { }
 
     bool createSingleton() const { return createSingleton_; }
     void setCreateSingleton() { createSingleton_ = true; }
 
-    bool constructing() const { return InitialFrameFlagsAreConstructing(initial_); }
+    bool constructing() const { return construct_; }
     const CallArgs& args() const { return args_; }
 
     virtual InterpreterFrame* pushInterpreterFrame(JSContext* cx);
 
     virtual void setReturnValue(Value v) {
         args_.rval().set(v);
     }
 };
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -71,23 +71,24 @@ inline ClonedBlockObject&
 InterpreterFrame::extensibleLexicalScope() const
 {
     return NearestEnclosingExtensibleLexicalScope(scopeChain());
 }
 
 inline void
 InterpreterFrame::initCallFrame(JSContext* cx, InterpreterFrame* prev, jsbytecode* prevpc,
                                 Value* prevsp, JSFunction& callee, JSScript* script, Value* argv,
-                                uint32_t nactual, InterpreterFrame::Flags flagsArg)
+                                uint32_t nactual, MaybeConstruct constructing)
 {
-    MOZ_ASSERT((flagsArg & ~CONSTRUCTING) == 0);
     MOZ_ASSERT(callee.nonLazyScript() == script);
 
     /* Initialize stack frame members. */
-    flags_ = HAS_SCOPECHAIN | flagsArg;
+    flags_ = HAS_SCOPECHAIN;
+    if (constructing)
+        flags_ |= CONSTRUCTING;
     argv_ = argv;
     script_ = script;
     nactual_ = nactual;
     scopeChain_ = callee.environment();
     prev_ = prev;
     prevpc_ = prevpc;
     prevsp_ = prevsp;
 
@@ -269,81 +270,80 @@ InterpreterStack::allocateFrame(JSContex
     }
 
     frameCount_++;
     return buffer;
 }
 
 MOZ_ALWAYS_INLINE InterpreterFrame*
 InterpreterStack::getCallFrame(JSContext* cx, const CallArgs& args, HandleScript script,
-                               InterpreterFrame::Flags* flags, Value** pargv)
+                               MaybeConstruct constructing, Value** pargv)
 {
     JSFunction* fun = &args.callee().as<JSFunction>();
 
     MOZ_ASSERT(fun->nonLazyScript() == script);
     unsigned nformal = fun->nargs();
     unsigned nvals = script->nslots();
 
     if (args.length() >= nformal) {
         *pargv = args.array();
         uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
         return reinterpret_cast<InterpreterFrame*>(buffer);
     }
 
     // Pad any missing arguments with |undefined|.
     MOZ_ASSERT(args.length() < nformal);
 
-    bool isConstructing = *flags & InterpreterFrame::CONSTRUCTING;
-    unsigned nfunctionState = 2 + isConstructing; // callee, |this|, |new.target|
+    unsigned nfunctionState = 2 + constructing; // callee, |this|, |new.target|
 
     nvals += nformal + nfunctionState;
     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
     if (!buffer)
         return nullptr;
 
     Value* argv = reinterpret_cast<Value*>(buffer);
     unsigned nmissing = nformal - args.length();
 
     mozilla::PodCopy(argv, args.base(), 2 + args.length());
     SetValueRangeToUndefined(argv + 2 + args.length(), nmissing);
 
-    if (isConstructing)
+    if (constructing)
         argv[2 + nformal] = args.newTarget();
 
     *pargv = argv + 2;
     return reinterpret_cast<InterpreterFrame*>(argv + nfunctionState + nformal);
 }
 
 MOZ_ALWAYS_INLINE bool
 InterpreterStack::pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
-                                  HandleScript script, InitialFrameFlags initial)
+                                  HandleScript script, MaybeConstruct constructing)
 {
     RootedFunction callee(cx, &args.callee().as<JSFunction>());
     MOZ_ASSERT(regs.sp == args.end());
     MOZ_ASSERT(callee->nonLazyScript() == script);
 
     script->ensureNonLazyCanonicalFunction(cx);
 
     InterpreterFrame* prev = regs.fp();
     jsbytecode* prevpc = regs.pc;
     Value* prevsp = regs.sp;
     MOZ_ASSERT(prev);
 
     LifoAlloc::Mark mark = allocator_.mark();
 
-    InterpreterFrame::Flags flags = ToFrameFlags(initial);
     Value* argv;
-    InterpreterFrame* fp = getCallFrame(cx, args, script, &flags, &argv);
+    InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
     if (!fp)
         return false;
 
     fp->mark_ = mark;
 
     /* Initialize frame, locals, regs. */
-    fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, args.length(), flags);
+    fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, args.length(),
+                      constructing);
 
     regs.prepareToRun(*fp, script);
     return true;
 }
 
 MOZ_ALWAYS_INLINE bool
 InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
                                            HandleFunction callee, HandleValue newTarget,
@@ -355,17 +355,17 @@ InterpreterStack::resumeGeneratorCallFra
     jsbytecode* prevpc = regs.pc;
     Value* prevsp = regs.sp;
     MOZ_ASSERT(prev);
 
     script->ensureNonLazyCanonicalFunction(cx);
 
     LifoAlloc::Mark mark = allocator_.mark();
 
-    bool constructing = newTarget.isObject();
+    MaybeConstruct constructing = MaybeConstruct(newTarget.isObject());
 
     // Include callee, |this|, and maybe |new.target|
     unsigned nformal = callee->nargs();
     unsigned nvals = 2 + constructing + nformal + script->nslots();
 
     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value));
     if (!buffer)
         return false;
@@ -373,20 +373,18 @@ InterpreterStack::resumeGeneratorCallFra
     Value* argv = reinterpret_cast<Value*>(buffer) + 2;
     argv[-2] = ObjectValue(*callee);
     argv[-1] = UndefinedValue();
     SetValueRangeToUndefined(argv, nformal);
     if (constructing)
         argv[nformal] = newTarget;
 
     InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(argv + nformal + constructing);
-    InterpreterFrame::Flags flags = constructing ? ToFrameFlags(INITIAL_CONSTRUCT)
-                                                 : ToFrameFlags(INITIAL_NONE);
     fp->mark_ = mark;
-    fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, 0, flags);
+    fp->initCallFrame(cx, prev, prevpc, prevsp, *callee, script, argv, 0, constructing);
     fp->resumeGeneratorFrame(scopeChain);
 
     regs.prepareToRun(*fp, script);
     return true;
 }
 
 MOZ_ALWAYS_INLINE void
 InterpreterStack::popInlineFrame(InterpreterRegs& regs)
@@ -940,51 +938,49 @@ InterpreterActivation::InterpreterActiva
 }
 
 InterpreterActivation::~InterpreterActivation()
 {
     // Pop all inline frames.
     while (regs_.fp() != entryFrame_)
         popInlineFrame(regs_.fp());
 
-    JSContext* cx = cx_->asJSContext();
-    MOZ_ASSERT(oldFrameCount_ == cx->runtime()->interpreterStack().frameCount_);
-    MOZ_ASSERT_IF(oldFrameCount_ == 0, cx->runtime()->interpreterStack().allocator_.used() == 0);
+    MOZ_ASSERT(oldFrameCount_ == cx_->runtime()->interpreterStack().frameCount_);
+    MOZ_ASSERT_IF(oldFrameCount_ == 0, cx_->runtime()->interpreterStack().allocator_.used() == 0);
 
     if (entryFrame_)
-        cx->runtime()->interpreterStack().releaseFrame(entryFrame_);
+        cx_->runtime()->interpreterStack().releaseFrame(entryFrame_);
 }
 
 inline bool
 InterpreterActivation::pushInlineFrame(const CallArgs& args, HandleScript script,
-                                       InitialFrameFlags initial)
+                                       MaybeConstruct constructing)
 {
-    JSContext* cx = cx_->asJSContext();
-    if (!cx->runtime()->interpreterStack().pushInlineFrame(cx, regs_, args, script, initial))
+    if (!cx_->runtime()->interpreterStack().pushInlineFrame(cx_, regs_, args, script, constructing))
         return false;
     MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment());
     return true;
 }
 
 inline void
 InterpreterActivation::popInlineFrame(InterpreterFrame* frame)
 {
     (void)frame; // Quell compiler warning.
     MOZ_ASSERT(regs_.fp() == frame);
     MOZ_ASSERT(regs_.fp() != entryFrame_);
 
-    cx_->asJSContext()->runtime()->interpreterStack().popInlineFrame(regs_);
+    cx_->runtime()->interpreterStack().popInlineFrame(regs_);
 }
 
 inline bool
 InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget,
                                             HandleObject scopeChain)
 {
-    InterpreterStack& stack = cx_->asJSContext()->runtime()->interpreterStack();
-    if (!stack.resumeGeneratorCallFrame(cx_->asJSContext(), regs_, callee, newTarget, scopeChain))
+    InterpreterStack& stack = cx_->runtime()->interpreterStack();
+    if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, newTarget, scopeChain))
         return false;
 
     MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_);
     return true;
 }
 
 inline bool
 FrameIter::hasCachedSavedFrame() const
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -28,31 +28,25 @@ using namespace js;
 
 using mozilla::Maybe;
 using mozilla::PodCopy;
 
 /*****************************************************************************/
 
 void
 InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script, AbstractFramePtr evalInFramePrev,
-                                   const Value& newTargetValue, HandleObject scopeChain,
-                                   ExecuteType type)
+                                   const Value& newTargetValue, HandleObject scopeChain)
 {
-    /*
-     * See encoding of ExecuteType. When GLOBAL isn't set, we are executing a
-     * script in the context of another frame and the frame type is determined
-     * by the context.
-     */
-    flags_ = type | HAS_SCOPECHAIN;
+    flags_ = HAS_SCOPECHAIN;
     script_ = script;
 
     // newTarget = NullValue is an initial sentinel for "please fill me in from the stack".
     // It should never be passed from Ion code.
     RootedValue newTarget(cx, newTargetValue);
-    if (!(flags_ & GLOBAL_OR_MODULE)) {
+    if (script->isDirectEvalInFunction()) {
         if (evalInFramePrev) {
             if (newTarget.isNull() && evalInFramePrev.script()->functionOrCallerFunction())
                 newTarget = evalInFramePrev.newTarget();
         } else {
             FrameIter iter(cx);
             MOZ_ASSERT(!iter.isWasm());
             if (newTarget.isNull() && iter.script()->functionOrCallerFunction())
                 newTarget = iter.newTarget();
@@ -456,49 +450,48 @@ InterpreterRegs::setToEndOfScript()
 {
     sp = fp()->base();
     pc = fp()->script()->lastPC();
 }
 
 /*****************************************************************************/
 
 InterpreterFrame*
-InterpreterStack::pushInvokeFrame(JSContext* cx, const CallArgs& args, InitialFrameFlags initial)
+InterpreterStack::pushInvokeFrame(JSContext* cx, const CallArgs& args, MaybeConstruct constructing)
 {
     LifoAlloc::Mark mark = allocator_.mark();
 
     RootedFunction fun(cx, &args.callee().as<JSFunction>());
     RootedScript script(cx, fun->nonLazyScript());
 
-    InterpreterFrame::Flags flags = ToFrameFlags(initial);
     Value* argv;
-    InterpreterFrame* fp = getCallFrame(cx, args, script, &flags, &argv);
+    InterpreterFrame* fp = getCallFrame(cx, args, script, constructing, &argv);
     if (!fp)
         return nullptr;
 
     fp->mark_ = mark;
-    fp->initCallFrame(cx, nullptr, nullptr, nullptr, *fun, script, argv, args.length(), flags);
+    fp->initCallFrame(cx, nullptr, nullptr, nullptr, *fun, script, argv, args.length(),
+                      constructing);
     return fp;
 }
 
 InterpreterFrame*
 InterpreterStack::pushExecuteFrame(JSContext* cx, HandleScript script, const Value& newTargetValue,
-                                   HandleObject scopeChain, ExecuteType type,
-                                   AbstractFramePtr evalInFrame)
+                                   HandleObject scopeChain, AbstractFramePtr evalInFrame)
 {
     LifoAlloc::Mark mark = allocator_.mark();
 
     unsigned nvars = 1 /* newTarget */ + script->nslots();
     uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvars * sizeof(Value));
     if (!buffer)
         return nullptr;
 
     InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(buffer + 1 * sizeof(Value));
     fp->mark_ = mark;
-    fp->initExecuteFrame(cx, script, evalInFrame, newTargetValue, scopeChain, type);
+    fp->initExecuteFrame(cx, script, evalInFrame, newTargetValue, scopeChain);
     fp->initLocals();
 
     return fp;
 }
 
 /*****************************************************************************/
 
 void
@@ -545,17 +538,17 @@ FrameIter::settleOnActivation()
         if (data_.contextOption_ == CURRENT_CONTEXT && activation->cx() != data_.cx_) {
             ++data_.activations_;
             continue;
         }
 
         // If the caller supplied principals, only show activations which are subsumed (of the same
         // origin or of an origin accessible) by these principals.
         if (data_.principals_) {
-            JSContext* cx = data_.cx_->asJSContext();
+            JSContext* cx = data_.cx_;
             if (JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes) {
                 if (!subsumes(data_.principals_, activation->compartment()->principals())) {
                     ++data_.activations_;
                     continue;
                 }
             }
         }
 
@@ -1699,20 +1692,19 @@ WasmActivation::~WasmActivation()
     // Hide this activation from the profiler before is is destroyed.
     unregisterProfiling();
 
     MOZ_ASSERT(fp_ == nullptr);
 
     MOZ_ASSERT(module_.activation() == this);
     module_.activation() = prevWasmForModule_;
 
-    JSContext* cx = cx_->asJSContext();
-    MOZ_ASSERT(cx->runtime()->wasmActivationStack_ == this);
+    MOZ_ASSERT(cx_->runtime()->wasmActivationStack_ == this);
 
-    cx->runtime()->wasmActivationStack_ = prevWasm_;
+    cx_->runtime()->wasmActivationStack_ = prevWasm_;
 }
 
 InterpreterFrameIterator&
 InterpreterFrameIterator::operator++()
 {
     MOZ_ASSERT(!done());
     if (fp_ != activation_->entryFrame_) {
         pc_ = fp_->prevpc();
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -263,54 +263,24 @@ class AbstractFramePtr
 class NullFramePtr : public AbstractFramePtr
 {
   public:
     NullFramePtr()
       : AbstractFramePtr()
     { }
 };
 
-/*****************************************************************************/
-
-/* Flags specified for a frame as it is constructed. */
-enum InitialFrameFlags {
-    INITIAL_NONE           =          0,
-    INITIAL_CONSTRUCT      =       0x20, /* == InterpreterFrame::CONSTRUCTING, asserted below */
-};
-
-enum ExecuteType {
-    EXECUTE_GLOBAL_OR_MODULE =      0x1, /* == InterpreterFrame::GLOBAL_OR_MODULE */
-    EXECUTE_DIRECT_EVAL    =        0x8, /* == InterpreterFrame::EVAL */
-    EXECUTE_INDIRECT_EVAL  =        0x9, /* == InterpreterFrame::GLOBAL | EVAL */
-    EXECUTE_DEBUG          =       0x18, /* == InterpreterFrame::EVAL | DEBUGGER_EVAL */
-};
+enum MaybeConstruct { NO_CONSTRUCT = false, CONSTRUCT = true };
 
 /*****************************************************************************/
 
 class InterpreterFrame
 {
-  public:
     enum Flags : uint32_t {
-        /* Primary frame type */
-        GLOBAL_OR_MODULE       =        0x1,  /* frame pushed for a global script */
-        /* (0x2, 0x4, 0x8 are unused) */
-
-        /*
-         * Frame pushed for debugger eval.
-         * - Don't bother to JIT it, because it's probably short-lived.
-         * - It is required to have a scope chain object outside the
-         *   js::ScopeObject hierarchy: either a global object, or a
-         *   DebugScopeObject (not a ScopeObject, despite the name)
-         * - If evalInFramePrev_ is set, then this frame was created for an
-         *   "eval in frame" call, which can push a successor to any live
-         *   frame; so its logical "prev" frame is not necessarily the
-         *   previous frame in memory. Iteration should treat
-         *   evalInFramePrev_ as this frame's previous frame.
-         */
-        DEBUGGER_EVAL          =       0x10,
+        /* (0x1, 0x2, 0x4, 0x8, 0x10 are unused) */
 
         CONSTRUCTING           =       0x20,  /* frame is for a constructor invocation */
 
         RESUMED_GENERATOR      =       0x40,  /* frame is for a resumed generator invocation */
 
         /* (0x80 is unused) */
 
         /* Function prologue state */
@@ -346,17 +316,16 @@ class InterpreterFrame
         /*
          * If set, this frame has been on the stack when
          * |js::SavedStacks::saveCurrentStack| was called, and so there is a
          * |js::SavedFrame| object cached for this frame.
          */
         HAS_CACHED_SAVED_FRAME =    0x80000,
     };
 
-  private:
     mutable uint32_t    flags_;         /* bits described by Flags */
     JSScript*           script_;        /* the script we're executing */
     unsigned            nactual_;       /* number of actual arguments, for function frames */
     mutable JSObject*   scopeChain_;    /* if HAS_SCOPECHAIN, current scope chain */
     Value               rval_;          /* if HAS_RVAL, return value of the frame */
     ArgumentsObject*    argsObj_;       /* if HAS_ARGS_OBJ, the call's arguments object */
 
     /*
@@ -401,21 +370,21 @@ class InterpreterFrame
     /*
      * Frame initialization, called by InterpreterStack operations after acquiring
      * the raw memory for the frame:
      */
 
     /* Used for Invoke and Interpret. */
     void initCallFrame(JSContext* cx, InterpreterFrame* prev, jsbytecode* prevpc, Value* prevsp,
                        JSFunction& callee, JSScript* script, Value* argv, uint32_t nactual,
-                       InterpreterFrame::Flags flags);
+                       MaybeConstruct constructing);
 
     /* Used for global and eval frames. */
     void initExecuteFrame(JSContext* cx, HandleScript script, AbstractFramePtr prev,
-                          const Value& newTargetValue, HandleObject scopeChain, ExecuteType type);
+                          const Value& newTargetValue, HandleObject scopeChain);
 
   public:
     /*
      * Frame prologue/epilogue
      *
      * Every stack frame must have 'prologue' called before executing the
      * first op and 'epilogue' called after executing the last op and before
      * popping the frame (whether the exit is exceptional or not).
@@ -730,28 +699,16 @@ class InterpreterFrame
         flags_ |= HAS_CALL_OBJ | HAS_SCOPECHAIN;
         scopeChain_ = scopeChain;
     }
 
     /*
      * Other flags
      */
 
-    InitialFrameFlags initialFlags() const {
-        JS_STATIC_ASSERT((int)INITIAL_NONE == 0);
-        JS_STATIC_ASSERT((int)INITIAL_CONSTRUCT == (int)CONSTRUCTING);
-        uint32_t mask = CONSTRUCTING;
-        MOZ_ASSERT((flags_ & mask) != mask);
-        return InitialFrameFlags(flags_ & mask);
-    }
-
-    void setConstructing() {
-        flags_ |= CONSTRUCTING;
-    }
-
     bool isConstructing() const {
         return !!(flags_ & CONSTRUCTING);
     }
 
     void setResumedGenerator() {
         flags_ |= RESUMED_GENERATOR;
     }
     bool isResumedGenerator() const {
@@ -781,18 +738,32 @@ class InterpreterFrame
         MOZ_ASSERT(isConstructing());
         flags_ |= CREATE_SINGLETON;
     }
     bool createSingleton() const {
         MOZ_ASSERT(isConstructing());
         return flags_ & CREATE_SINGLETON;
     }
 
+    /*
+     * Debugger eval frames.
+     *
+     * - If evalInFramePrev_ is non-null, frame was created for an "eval in
+     *   frame" call, which can push a successor to any live frame; so its
+     *   logical "prev" frame is not necessarily the previous frame in memory.
+     *   Iteration should treat evalInFramePrev_ as this frame's previous frame.
+     *
+     * - Don't bother to JIT it, because it's probably short-lived.
+     *
+     * - It is required to have a scope chain object outside the
+     *   js::ScopeObject hierarchy: either a global object, or a
+     *   DebugScopeObject (not a ScopeObject, despite the name)
+     */
     bool isDebuggerEvalFrame() const {
-        return !!(flags_ & DEBUGGER_EVAL);
+        return isEvalFrame() && !!evalInFramePrev_;
     }
 
     bool prevUpToDate() const {
         return !!(flags_ & PREV_UP_TO_DATE);
     }
 
     void setPrevUpToDate() {
         flags_ |= PREV_UP_TO_DATE;
@@ -831,36 +802,16 @@ class InterpreterFrame
     void setRunningInJit() {
         flags_ |= RUNNING_IN_JIT;
     }
     void clearRunningInJit() {
         flags_ &= ~RUNNING_IN_JIT;
     }
 };
 
-static const size_t VALUES_PER_STACK_FRAME = sizeof(InterpreterFrame) / sizeof(Value);
-
-static inline InterpreterFrame::Flags
-ToFrameFlags(InitialFrameFlags initial)
-{
-    return InterpreterFrame::Flags(initial);
-}
-
-static inline InitialFrameFlags
-InitialFrameFlagsFromConstructing(bool b)
-{
-    return b ? INITIAL_CONSTRUCT : INITIAL_NONE;
-}
-
-static inline bool
-InitialFrameFlagsAreConstructing(InitialFrameFlags initial)
-{
-    return !!(initial & INITIAL_CONSTRUCT);
-}
-
 /*****************************************************************************/
 
 class InterpreterRegs
 {
   public:
     Value* sp;
     jsbytecode* pc;
   private:
@@ -926,17 +877,17 @@ class InterpreterStack
     static const size_t MAX_FRAMES = 50 * 1000;
     static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
     size_t frameCount_;
 
     inline uint8_t* allocateFrame(JSContext* cx, size_t size);
 
     inline InterpreterFrame*
     getCallFrame(JSContext* cx, const CallArgs& args, HandleScript script,
-                 InterpreterFrame::Flags* pflags, Value** pargv);
+                 MaybeConstruct constructing, Value** pargv);
 
     void releaseFrame(InterpreterFrame* fp) {
         frameCount_--;
         allocator_.release(fp->mark_);
     }
 
   public:
     InterpreterStack()
@@ -946,26 +897,26 @@ class InterpreterStack
 
     ~InterpreterStack() {
         MOZ_ASSERT(frameCount_ == 0);
     }
 
     // For execution of eval or global code.
     InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
                                        const Value& newTargetValue, HandleObject scopeChain,
-                                       ExecuteType type, AbstractFramePtr evalInFrame);
+                                       AbstractFramePtr evalInFrame);
 
     // Called to invoke a function.
     InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,
-                                      InitialFrameFlags initial);
+                                      MaybeConstruct constructing);
 
     // The interpreter can push light-weight, "inline" frames without entering a
     // new InterpreterActivation or recursively calling Interpret.
     bool pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const CallArgs& args,
-                         HandleScript script, InitialFrameFlags initial);
+                         HandleScript script, MaybeConstruct constructing);
 
     void popInlineFrame(InterpreterRegs& regs);
 
     bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs,
                                   HandleFunction callee, HandleValue newTarget,
                                   HandleObject scopeChain);
 
     inline void purge(JSRuntime* rt);
@@ -1359,17 +1310,17 @@ class InterpreterActivation : public Act
     size_t oldFrameCount_;
 #endif
 
   public:
     inline InterpreterActivation(RunState& state, JSContext* cx, InterpreterFrame* entryFrame);
     inline ~InterpreterActivation();
 
     inline bool pushInlineFrame(const CallArgs& args, HandleScript script,
-                                InitialFrameFlags initial);
+                                MaybeConstruct constructing);
     inline void popInlineFrame(InterpreterFrame* frame);
 
     inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget,
                                      HandleObject scopeChain);
 
     InterpreterFrame* current() const {
         return regs_.fp();
     }