Bug 1234845 part 4 - Eval frame refactoring, remove isFunctionFrame. r=luke

This commit is contained in:
Jan de Mooij 2016-01-14 17:02:43 +01:00
parent 02a60eb403
commit f05a168466
20 changed files with 72 additions and 124 deletions

View File

@ -435,8 +435,7 @@ js::DirectEval(JSContext* cx, const CallArgs& args)
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());
MOZ_ASSERT(caller.compartment() == caller.script()->compartment());
RootedObject scopeChain(cx, caller.scopeChain());
return EvalKernel(cx, args, DIRECT_EVAL, caller, scopeChain, iter.pc());

View File

@ -1579,7 +1579,7 @@ ShellObjectMetadataCallback(JSContext* cx, JSObject*)
RootedId id(cx);
RootedValue callee(cx);
for (NonBuiltinScriptFrameIter iter(cx); !iter.done(); ++iter) {
if (iter.isFunctionFrame() && iter.compartment() == cx->compartment()) {
if (iter.isNonEvalFunctionFrame() && iter.compartment() == cx->compartment()) {
id = INT_TO_JSID(stackIndex);
RootedObject callee(cx, iter.callee(cx));
if (!JS_DefinePropertyById(cx, stack, id, callee, 0,

View File

@ -260,7 +260,10 @@ jit::ExceptionHandlerBailout(JSContext* cx, const InlineFrameIterator& frame,
bool
jit::EnsureHasScopeObjects(JSContext* cx, AbstractFramePtr fp)
{
if (fp.isFunctionFrame() &&
// Ion does not compile eval scripts.
MOZ_ASSERT(!fp.isEvalFrame());
if (fp.isNonEvalFunctionFrame() &&
fp.callee()->needsCallObject() &&
!fp.hasCallObj())
{

View File

@ -50,7 +50,7 @@ BaselineFrame::trace(JSTracer* trc, JitFrameIterator& frameIterator)
if (isEvalFrame()) {
TraceRoot(trc, &evalScript_, "baseline-evalscript");
if (isFunctionFrame())
if (script()->isDirectEvalInFunction())
TraceRoot(trc, evalNewTargetAddress(), "baseline-evalNewTarget");
}

View File

@ -220,7 +220,7 @@ class BaselineFrame
private:
Value* evalNewTargetAddress() const {
MOZ_ASSERT(isEvalFrame());
MOZ_ASSERT(isFunctionFrame());
MOZ_ASSERT(script()->isDirectEvalInFunction());
return (Value*)(reinterpret_cast<const uint8_t*>(this) +
BaselineFrame::Size() +
offsetOfEvalNewTarget());
@ -228,15 +228,16 @@ class BaselineFrame
public:
Value newTarget() const {
MOZ_ASSERT(isFunctionFrame());
if (isEvalFrame())
return *evalNewTargetAddress();
MOZ_ASSERT(isNonEvalFunctionFrame());
if (callee()->isArrow())
return callee()->getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
if (isConstructing())
if (isConstructing()) {
return *(Value*)(reinterpret_cast<const uint8_t*>(this) +
BaselineFrame::Size() +
offsetOfArg(Max(numFormalArgs(), numActualArgs())));
}
return UndefinedValue();
}
@ -388,11 +389,9 @@ class BaselineFrame
void trace(JSTracer* trc, JitFrameIterator& frame);
bool isFunctionFrame() const {
return CalleeTokenIsFunction(calleeToken());
}
bool isGlobalOrModuleFrame() const {
return !isFunctionFrame();
MOZ_ASSERT(!isEvalFrame());
return !CalleeTokenIsFunction(calleeToken());
}
bool isEvalFrame() const {
return flags_ & EVAL;
@ -408,7 +407,7 @@ class BaselineFrame
return isNonStrictEvalFrame() && isNonGlobalEvalFrame();
}
bool isNonEvalFunctionFrame() const {
return isFunctionFrame() && !isEvalFrame();
return CalleeTokenIsFunction(calleeToken()) && !isEvalFrame();
}
bool isDebuggerEvalFrame() const {
return false;

View File

@ -64,7 +64,7 @@ EnsureCanEnterIon(JSContext* cx, ICWarmUpCounter_Fallback* stub, BaselineFrame*
MOZ_ASSERT(LoopEntryCanIonOsr(pc));
JitSpew(JitSpew_BaselineOSR, " Compile at loop entry!");
stat = CanEnterAtBranch(cx, script, frame, pc);
} else if (frame->isFunctionFrame()) {
} else if (frame->isNonEvalFunctionFrame()) {
JitSpew(JitSpew_BaselineOSR, " Compile function from top for later entry!");
stat = CompileFunctionForBaseline(cx, script, frame);
} else {

View File

@ -216,11 +216,7 @@ jit::EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc)
data.maxArgv = thisv.address();
data.scopeChain = fp->scopeChain();
// For eval function frames, set the callee token to the enclosing function.
if (fp->isFunctionFrame())
data.calleeToken = CalleeToToken(&fp->callee(), /* constructing = */ false);
else
data.calleeToken = CalleeToToken(fp->script());
data.calleeToken = CalleeToToken(fp->script());
if (fp->isEvalFrame()) {
if (!vals.reserve(2))
@ -228,7 +224,7 @@ jit::EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc)
vals.infallibleAppend(thisv);
if (fp->isFunctionFrame())
if (fp->script()->isDirectEvalInFunction())
vals.infallibleAppend(fp->newTarget());
else
vals.infallibleAppend(NullValue());

View File

@ -2305,9 +2305,10 @@ CheckFrame(JSContext* cx, BaselineFrame* frame)
{
MOZ_ASSERT(!frame->script()->isGenerator());
MOZ_ASSERT(!frame->isDebuggerEvalFrame());
MOZ_ASSERT(!frame->isEvalFrame());
// This check is to not overrun the stack.
if (frame->isFunctionFrame()) {
if (frame->isNonEvalFunctionFrame()) {
if (TooManyActualArguments(frame->numActualArgs())) {
TrackAndSpewIonAbort(cx, frame->script(), "too many actual arguments");
return false;
@ -2633,7 +2634,7 @@ jit::CompileFunctionForBaseline(JSContext* cx, HandleScript script, BaselineFram
MOZ_ASSERT(frame->callee()->nonLazyScript()->canIonCompile());
MOZ_ASSERT(!frame->callee()->nonLazyScript()->isIonCompilingOffThread());
MOZ_ASSERT(!frame->callee()->nonLazyScript()->hasIonScript());
MOZ_ASSERT(frame->isFunctionFrame());
MOZ_ASSERT(frame->isNonEvalFunctionFrame());
// Mark as forbidden if frame can't be handled.
if (!CheckFrame(cx, frame)) {
@ -2782,27 +2783,18 @@ jit::SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state, AutoVal
data.calleeToken = CalleeToToken(state.script());
if (state.script()->isForEval() &&
!(state.asExecute()->type() & InterpreterFrame::GLOBAL_OR_MODULE))
{
ScriptFrameIter iter(cx);
if (iter.isFunctionFrame())
data.calleeToken = CalleeToToken(iter.callee(cx), /* constructing = */ false);
if (state.script()->isForEval() && state.script()->isDirectEvalInFunction()) {
// Push newTarget onto the stack.
if (!vals.reserve(1))
return false;
ScriptFrameIter iter(cx);
data.maxArgc = 1;
data.maxArgv = vals.begin();
if (iter.isFunctionFrame()) {
if (state.asExecute()->newTarget().isNull())
vals.infallibleAppend(iter.newTarget());
else
vals.infallibleAppend(state.asExecute()->newTarget());
} else {
vals.infallibleAppend(NullValue());
}
if (state.asExecute()->newTarget().isNull())
vals.infallibleAppend(iter.newTarget());
else
vals.infallibleAppend(state.asExecute()->newTarget());
}
}

View File

@ -4732,7 +4732,7 @@ DoTypeMonitorFallback(JSContext* cx, BaselineFrame* frame, ICTypeMonitor_Fallbac
// In derived class constructors (including nested arrows/eval), the
// |this| argument or GETALIASEDVAR can return the magic TDZ value.
MOZ_ASSERT(value.isMagic(JS_UNINITIALIZED_LEXICAL));
MOZ_ASSERT(frame->isFunctionFrame());
MOZ_ASSERT(frame->isNonEvalFunctionFrame() || frame->isEvalFrame());
MOZ_ASSERT(stub->monitorsThis() ||
*GetNextPc(pc) == JSOP_CHECKTHIS ||
*GetNextPc(pc) == JSOP_CHECKRETURN);

View File

@ -394,10 +394,15 @@ JS_FRIEND_API(JSFunction*)
js::GetOutermostEnclosingFunctionOfScriptedCaller(JSContext* cx)
{
ScriptFrameIter iter(cx);
// Skip eval frames.
while (!iter.done() && iter.isEvalFrame())
++iter;
if (iter.done())
return nullptr;
if (!iter.isFunctionFrame())
if (!iter.isNonEvalFunctionFrame())
return nullptr;
RootedFunction curr(cx, iter.callee(cx));

View File

@ -96,7 +96,7 @@ AdvanceToActiveCallLinear(JSContext* cx, NonBuiltinScriptFrameIter& iter, Handle
MOZ_ASSERT(!fun->isBuiltin());
for (; !iter.done(); ++iter) {
if (!iter.isFunctionFrame() || iter.isEvalFrame())
if (!iter.isNonEvalFunctionFrame())
continue;
if (iter.matchCallee(cx, fun))
return true;
@ -252,7 +252,10 @@ CallerGetterImpl(JSContext* cx, const CallArgs& args)
}
++iter;
if (iter.done() || !iter.isFunctionFrame()) {
while (!iter.done() && iter.isEvalFrame())
++iter;
if (iter.done() || !iter.isNonEvalFunctionFrame()) {
args.rval().setNull();
return true;
}
@ -318,7 +321,10 @@ CallerSetterImpl(JSContext* cx, const CallArgs& args)
return true;
++iter;
if (iter.done() || !iter.isFunctionFrame())
while (!iter.done() && iter.isEvalFrame())
++iter;
if (iter.done() || !iter.isNonEvalFunctionFrame())
return true;
RootedObject caller(cx, iter.callee(cx));

View File

@ -3601,14 +3601,14 @@ js::DumpInterpreterFrame(JSContext* cx, InterpreterFrame* start)
else
fprintf(stderr, "InterpreterFrame at %p\n", (void*) i.interpFrame());
if (i.isFunctionFrame()) {
if (i.isNonEvalFunctionFrame()) {
fprintf(stderr, "callee fun: ");
RootedValue v(cx);
JSObject* fun = i.callee(cx);
v.setObject(*fun);
dumpValue(v);
} else {
fprintf(stderr, "global frame, no callee");
fprintf(stderr, "global or eval frame, no callee");
}
fputc('\n', stderr);

View File

@ -4189,7 +4189,7 @@ JSScript::argumentsOptimizationFailed(JSContext* cx, HandleScript script)
if (i.isIon())
continue;
AbstractFramePtr frame = i.abstractFramePtr();
if (frame.isFunctionFrame() && frame.script() == script) {
if (frame.isNonEvalFunctionFrame() && frame.script() == script) {
/* We crash on OOM since cleaning up here would be complicated. */
AutoEnterOOMUnsafeRegion oomUnsafe;
ArgumentsObject* argsobj = ArgumentsObject::createExpected(cx, frame);

View File

@ -1670,6 +1670,9 @@ class JSScript : public js::gc::TenuredCell
/* Return whether this script was compiled for 'eval' */
bool isForEval() const { return isCachedEval() || isActiveEval(); }
/* Return whether this is a 'direct eval' script in a function scope. */
bool isDirectEvalInFunction() const { return isForEval() && savedCallerFun(); }
/*
* Return whether this script is a top-level script.
*

View File

@ -6292,7 +6292,7 @@ DebuggerFrame_getType(JSContext* cx, unsigned argc, Value* vp)
type = cx->names().eval;
else if (frame.isGlobalFrame())
type = cx->names().global;
else if (frame.isFunctionFrame())
else if (frame.isNonEvalFunctionFrame())
type = cx->names().call;
else if (frame.isModuleFrame())
type = cx->names().module;
@ -6363,7 +6363,7 @@ static bool
DebuggerFrame_getConstructing(JSContext* cx, unsigned argc, Value* vp)
{
THIS_FRAME_ITER(cx, argc, vp, "get constructing", args, thisobj, _, iter);
args.rval().setBoolean(iter.isFunctionFrame() && iter.isConstructing());
args.rval().setBoolean(iter.isNonEvalFunctionFrame() && iter.isConstructing());
return true;
}
@ -6533,7 +6533,7 @@ DebuggerFrame_getScript(JSContext* cx, unsigned argc, Value* vp)
Debugger* debug = Debugger::fromChildJSObject(thisobj);
RootedObject scriptObject(cx);
if (frame.isFunctionFrame() && !frame.isEvalFrame()) {
if (frame.isNonEvalFunctionFrame()) {
RootedFunction callee(cx, frame.callee());
if (callee->isInterpreted()) {
RootedScript script(cx, callee->nonLazyScript());

View File

@ -2722,7 +2722,7 @@ DebugScopes::updateLiveScopes(JSContext* cx)
if (frame.scopeChain()->compartment() != cx->compartment())
continue;
if (frame.isFunctionFrame() && frame.callee()->isGenerator())
if (frame.isNonEvalFunctionFrame() && frame.callee()->isGenerator())
continue;
if (!frame.isDebuggee())
@ -2907,7 +2907,7 @@ GetDebugScopeForMissing(JSContext* cx, const ScopeIter& si)
// For example, |let ({} = "") { yield evalInFrame("foo"); }|.
MOZ_ASSERT_IF(si.staticBlock().numVariables() > 0 &&
si.withinInitialFrame() &&
si.initialFrame().isFunctionFrame(),
si.initialFrame().isNonEvalFunctionFrame(),
!si.initialFrame().callee()->isGenerator());
Rooted<StaticBlockObject*> staticBlock(cx, &si.staticBlock());

View File

@ -635,7 +635,7 @@ intrinsic_ActiveFunction(JSContext* cx, unsigned argc, Value* vp)
MOZ_ASSERT(args.length() == 0);
ScriptFrameIter iter(cx);
MOZ_ASSERT(iter.isFunctionFrame());
MOZ_ASSERT(iter.isNonEvalFunctionFrame());
args.rval().setObject(*iter.callee(cx));
return true;
}

View File

@ -44,7 +44,7 @@ IsCacheableNonGlobalScope(JSObject* obj)
inline HandleObject
InterpreterFrame::scopeChain() const
{
MOZ_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isFunctionFrame());
MOZ_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isNonEvalFunctionFrame());
if (!(flags_ & HAS_SCOPECHAIN)) {
scopeChain_ = callee().environment();
flags_ |= HAS_SCOPECHAIN;
@ -563,16 +563,6 @@ AbstractFramePtr::createSingleton() const
return false;
}
inline bool
AbstractFramePtr::isFunctionFrame() const
{
if (isInterpreterFrame())
return asInterpreterFrame()->isFunctionFrame();
if (isBaselineFrame())
return asBaselineFrame()->isFunctionFrame();
return asRematerializedFrame()->isFunctionFrame();
}
inline bool
AbstractFramePtr::isGlobalOrModuleFrame() const
{

View File

@ -44,46 +44,24 @@ InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script, AbstractF
flags_ = type | HAS_SCOPECHAIN;
script_ = script;
JSObject* callee = nullptr;
// 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 (evalInFramePrev) {
if (evalInFramePrev.isFunctionFrame()) {
callee = evalInFramePrev.callee();
if (newTarget.isNull())
newTarget = evalInFramePrev.newTarget();
flags_ |= FUNCTION;
} else {
MOZ_ASSERT(evalInFramePrev.isGlobalOrModuleFrame());
flags_ |= GLOBAL_OR_MODULE;
}
if (newTarget.isNull() && evalInFramePrev.script()->functionOrCallerFunction())
newTarget = evalInFramePrev.newTarget();
} else {
FrameIter iter(cx);
MOZ_ASSERT(!iter.isWasm());
if (iter.isFunctionFrame()) {
if (newTarget.isNull())
newTarget = iter.newTarget();
callee = iter.callee(cx);
flags_ |= FUNCTION;
} else {
MOZ_ASSERT(iter.isGlobalOrModuleFrame());
flags_ |= GLOBAL_OR_MODULE;
}
if (newTarget.isNull() && iter.script()->functionOrCallerFunction())
newTarget = iter.newTarget();
}
}
Value* dstvp = (Value*)this - 2;
if (isFunctionFrame()) {
dstvp[1] = ObjectValue(*callee);
} else {
MOZ_ASSERT(isGlobalOrModuleFrame());
dstvp[1] = NullValue();
}
dstvp[0] = newTarget;
dstvp[1] = NullValue(); //XXX remove, unused callee.
scopeChain_ = scopeChain.get();
prev_ = nullptr;
@ -321,7 +299,7 @@ bool
InterpreterFrame::checkReturn(JSContext* cx, HandleValue thisv)
{
MOZ_ASSERT(script()->isDerivedClassConstructor());
MOZ_ASSERT(isFunctionFrame());
MOZ_ASSERT(isNonEvalFunctionFrame());
MOZ_ASSERT(callee().isClassConstructor());
HandleValue retVal = returnValue();
@ -862,25 +840,6 @@ FrameIter::compartment() const
MOZ_CRASH("Unexpected state");
}
bool
FrameIter::isFunctionFrame() const
{
switch (data_.state_) {
case DONE:
break;
case INTERP:
return interpFrame()->isFunctionFrame();
case JIT:
MOZ_ASSERT(data_.jitFrames_.isScripted());
if (data_.jitFrames_.isBaselineJS())
return data_.jitFrames_.isFunctionFrame();
return ionInlineFrames_.isFunctionFrame();
case WASM:
return true;
}
MOZ_CRASH("Unexpected state");
}
bool
FrameIter::isGlobalOrModuleFrame() const
{
@ -929,7 +888,9 @@ FrameIter::isNonEvalFunctionFrame() const
case INTERP:
return interpFrame()->isNonEvalFunctionFrame();
case JIT:
return !isEvalFrame() && isFunctionFrame();
if (data_.jitFrames_.isBaselineJS())
return data_.jitFrames_.baselineFrame()->isNonEvalFunctionFrame();
return script()->functionNonDelazifying();
case WASM:
return true;
}
@ -1145,7 +1106,7 @@ FrameIter::calleeTemplate() const
case WASM:
break;
case INTERP:
MOZ_ASSERT(isFunctionFrame());
MOZ_ASSERT(isNonEvalFunctionFrame());
return &interpFrame()->callee();
case JIT:
if (data_.jitFrames_.isBaselineJS())
@ -1215,7 +1176,7 @@ FrameIter::numActualArgs() const
case WASM:
break;
case INTERP:
MOZ_ASSERT(isFunctionFrame());
MOZ_ASSERT(isNonEvalFunctionFrame());
return interpFrame()->numActualArgs();
case JIT:
if (data_.jitFrames_.isIonScripted())

View File

@ -202,7 +202,6 @@ class AbstractFramePtr
inline JSCompartment* compartment() const;
inline bool hasCallObj() const;
inline bool isFunctionFrame() const;
inline bool isGlobalOrModuleFrame() const;
inline bool isGlobalFrame() const;
inline bool isModuleFrame() const;
@ -463,11 +462,8 @@ class InterpreterFrame
* module frame: execution of a module
*/
bool isFunctionFrame() const {
return !!(flags_ & FUNCTION);
}
bool isGlobalOrModuleFrame() const {
MOZ_ASSERT(!isEvalFrame());
return !!(flags_ & GLOBAL_OR_MODULE);
}
@ -677,14 +673,12 @@ class InterpreterFrame
*/
JSFunction& callee() const {
MOZ_ASSERT(isFunctionFrame());
MOZ_ASSERT(isNonEvalFunctionFrame());
return calleev().toObject().as<JSFunction>();
}
const Value& calleev() const {
MOZ_ASSERT(isFunctionFrame());
if (isEvalFrame())
return ((const Value*)this)[-1];
MOZ_ASSERT(isNonEvalFunctionFrame());
return argv()[-2];
}
@ -696,10 +690,11 @@ class InterpreterFrame
* frame.
*/
Value newTarget() const {
MOZ_ASSERT(isFunctionFrame());
if (isEvalFrame())
return ((Value*)this)[-2];
MOZ_ASSERT(isNonEvalFunctionFrame());
if (callee().isArrow())
return callee().getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
@ -1846,7 +1841,6 @@ class FrameIter
inline bool isBaseline() const;
inline bool isPhysicalIonFrame() const;
bool isFunctionFrame() const;
bool isGlobalOrModuleFrame() const;
bool isEvalFrame() const;
bool isNonEvalFunctionFrame() const;
@ -1884,7 +1878,7 @@ class FrameIter
JSFunction* callee(JSContext* cx) const;
JSFunction* maybeCallee(JSContext* cx) const {
return isFunctionFrame() ? callee(cx) : nullptr;
return isNonEvalFunctionFrame() ? callee(cx) : nullptr;
}
bool matchCallee(JSContext* cx, HandleFunction fun) const;