Bug 1227263 part 3 - Remove this-slot from non-function frames. r=efaust

This commit is contained in:
Jan de Mooij 2015-11-26 12:00:05 +01:00
parent 78e54d2bfb
commit 980c73e927
8 changed files with 42 additions and 52 deletions

View File

@ -436,7 +436,7 @@ class BaselineFrame
return FramePointerOffset + js::jit::JitFrameLayout::offsetOfThis();
}
static size_t offsetOfEvalNewTarget() {
return offsetOfArg(0);
return FramePointerOffset + js::jit::JitFrameLayout::offsetOfEvalNewTarget();
}
static size_t offsetOfArg(size_t index) {
return FramePointerOffset + js::jit::JitFrameLayout::offsetOfActualArg(index);

View File

@ -2743,8 +2743,8 @@ jit::SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state, AutoVal
} else {
data.constructing = false;
data.numActualArgs = 0;
data.maxArgc = 1;
data.maxArgv = state.asExecute()->addressOfThisv();
data.maxArgc = 0;
data.maxArgv = nullptr;
data.scopeChain = state.asExecute()->scopeChain();
data.calleeToken = CalleeToToken(state.script());
@ -2756,13 +2756,12 @@ jit::SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state, AutoVal
if (iter.isFunctionFrame())
data.calleeToken = CalleeToToken(iter.callee(cx), /* constructing = */ false);
// Push newTarget onto the stack, as well as Argv.
if (!vals.reserve(2))
// Push newTarget onto the stack.
if (!vals.reserve(1))
return false;
data.maxArgc = 2;
data.maxArgc = 1;
data.maxArgv = vals.begin();
vals.infallibleAppend(state.asExecute()->thisv());
if (iter.isFunctionFrame()) {
if (state.asExecute()->newTarget().isNull())
vals.infallibleAppend(iter.newTarget());

View File

@ -1055,19 +1055,21 @@ MarkThisAndArguments(JSTracer* trc, const JitFrameIterator& frame)
? frame.exitFrame()->as<LazyLinkExitFrameLayout>()->jsFrame()
: frame.jsFrame();
if (!CalleeTokenIsFunction(layout->calleeToken()))
return;
size_t nargs = layout->numActualArgs();
size_t nformals = 0;
size_t newTargetOffset = 0;
if (CalleeTokenIsFunction(layout->calleeToken())) {
JSFunction* fun = CalleeTokenToFunction(layout->calleeToken());
if (!frame.isExitFrameLayout<LazyLinkExitFrameLayout>() &&
!fun->nonLazyScript()->argumentsHasVarBinding())
{
nformals = fun->nargs();
}
newTargetOffset = Max(nargs, fun->nargs());
JSFunction* fun = CalleeTokenToFunction(layout->calleeToken());
if (!frame.isExitFrameLayout<LazyLinkExitFrameLayout>() &&
!fun->nonLazyScript()->argumentsHasVarBinding())
{
nformals = fun->nargs();
}
size_t newTargetOffset = Max(nargs, fun->nargs());
Value* argv = layout->argv();
// Trace |this|.

View File

@ -387,6 +387,9 @@ class JitFrameLayout : public CommonFrameLayout
static size_t offsetOfThis() {
return sizeof(JitFrameLayout);
}
static size_t offsetOfEvalNewTarget() {
return sizeof(JitFrameLayout);
}
static size_t offsetOfActualArgs() {
return offsetOfThis() + sizeof(Value);
}
@ -395,9 +398,11 @@ class JitFrameLayout : public CommonFrameLayout
}
Value thisv() {
MOZ_ASSERT(CalleeTokenIsFunction(calleeToken()));
return argv()[0];
}
Value* argv() {
MOZ_ASSERT(CalleeTokenIsFunction(calleeToken()));
return (Value*)(this + 1);
}
uintptr_t numActualArgs() const {

View File

@ -341,7 +341,7 @@ InvokeState::pushInterpreterFrame(JSContext* cx)
InterpreterFrame*
ExecuteState::pushInterpreterFrame(JSContext* cx)
{
return cx->runtime()->interpreterStack().pushExecuteFrame(cx, script_, thisv_, newTargetValue_,
return cx->runtime()->interpreterStack().pushExecuteFrame(cx, script_, newTargetValue_,
scopeChain_, type_, evalInFrame_);
}
// MSVC with PGO inlines a lot of functions in RunScript, resulting in large
@ -645,12 +645,8 @@ js::ExecuteKernel(JSContext* cx, HandleScript script, JSObject& scopeChainArg,
return true;
}
// It doesn't matter what we pass as thisv, global/eval scripts get |this|
// from the scope chain. TODO: remove thisv from ExecuteState.
RootedValue thisv(cx);
probes::StartExecution(script);
ExecuteState state(cx, script, thisv, newTargetValue, scopeChainArg, type, evalInFrame, result);
ExecuteState state(cx, script, newTargetValue, scopeChainArg, type, evalInFrame, result);
bool ok = RunScript(cx, state);
probes::StopExecution(script);

View File

@ -171,7 +171,6 @@ class ExecuteState : public RunState
{
ExecuteType type_;
RootedValue thisv_;
RootedValue newTargetValue_;
RootedObject scopeChain_;
@ -179,20 +178,17 @@ class ExecuteState : public RunState
Value* result_;
public:
ExecuteState(JSContext* cx, JSScript* script, const Value& thisv, const Value& newTargetValue,
ExecuteState(JSContext* cx, JSScript* script, const Value& newTargetValue,
JSObject& scopeChain, ExecuteType type, AbstractFramePtr evalInFrame,
Value* result)
: RunState(cx, Execute, script),
type_(type),
thisv_(cx, thisv),
newTargetValue_(cx, newTargetValue),
scopeChain_(cx, &scopeChain),
evalInFrame_(evalInFrame),
result_(result)
{ }
Value* addressOfThisv() { return thisv_.address(); }
Value thisv() { return thisv_; }
Value newTarget() { return newTargetValue_; }
JSObject* scopeChain() const { return scopeChain_; }
ExecuteType type() const { return type_; }

View File

@ -34,11 +34,9 @@ using mozilla::PodCopy;
void
InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script, AbstractFramePtr evalInFramePrev,
const Value& thisv, const Value& newTargetValue, HandleObject scopeChain,
const Value& newTargetValue, HandleObject scopeChain,
ExecuteType type)
{
MOZ_ASSERT_IF(type & MODULE, thisv.isUndefined());
/*
* 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
@ -77,8 +75,7 @@ InterpreterFrame::initExecuteFrame(JSContext* cx, HandleScript script, AbstractF
}
}
Value* dstvp = (Value*)this - 3;
dstvp[2] = thisv;
Value* dstvp = (Value*)this - 2;
if (isFunctionFrame()) {
dstvp[1] = ObjectValue(*callee);
@ -454,8 +451,8 @@ InterpreterFrame::markValues(JSTracer* trc, Value* sp, jsbytecode* pc)
unsigned argc = Max(numActualArgs(), numFormalArgs());
TraceRootRange(trc, argc + 2 + isConstructing(), argv_ - 2, "fp argv");
} else {
// Mark callee, |this|, and newTarget
TraceRootRange(trc, 3, ((Value*)this) - 3, "stack callee, this, newTarget");
// Mark callee and newTarget
TraceRootRange(trc, 2, ((Value*)this) - 2, "stack callee and newTarget");
}
}
@ -512,20 +509,20 @@ InterpreterStack::pushInvokeFrame(JSContext* cx, const CallArgs& args, InitialFr
}
InterpreterFrame*
InterpreterStack::pushExecuteFrame(JSContext* cx, HandleScript script, const Value& thisv,
const Value& newTargetValue, HandleObject scopeChain,
ExecuteType type, AbstractFramePtr evalInFrame)
InterpreterStack::pushExecuteFrame(JSContext* cx, HandleScript script, const Value& newTargetValue,
HandleObject scopeChain, ExecuteType type,
AbstractFramePtr evalInFrame)
{
LifoAlloc::Mark mark = allocator_.mark();
unsigned nvars = 3 /* callee, this, newTarget */ + script->nslots();
unsigned nvars = 2 /* callee, newTarget */ + script->nslots();
uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvars * sizeof(Value));
if (!buffer)
return nullptr;
InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(buffer + 3 * sizeof(Value));
InterpreterFrame* fp = reinterpret_cast<InterpreterFrame*>(buffer + 2 * sizeof(Value));
fp->mark_ = mark;
fp->initExecuteFrame(cx, script, evalInFrame, thisv, newTargetValue, scopeChain, type);
fp->initExecuteFrame(cx, script, evalInFrame, newTargetValue, scopeChain, type);
fp->initLocals();
return fp;

View File

@ -427,8 +427,7 @@ class InterpreterFrame
/* Used for global and eval frames. */
void initExecuteFrame(JSContext* cx, HandleScript script, AbstractFramePtr prev,
const Value& thisv, const Value& newTargetValue,
HandleObject scopeChain, ExecuteType type);
const Value& newTargetValue, HandleObject scopeChain, ExecuteType type);
public:
/*
@ -742,7 +741,7 @@ class InterpreterFrame
const Value& maybeCalleev() const {
Value& calleev = flags_ & (EVAL | GLOBAL)
? ((Value*)this)[-2]
? ((Value*)this)[-1]
: argv()[-2];
MOZ_ASSERT(calleev.isObjectOrNull());
return calleev;
@ -751,14 +750,10 @@ class InterpreterFrame
Value& mutableCalleev() const {
MOZ_ASSERT(isFunctionFrame());
if (isEvalFrame())
return ((Value*)this)[-2];
return ((Value*)this)[-1];
return argv()[-2];
}
CallReceiver callReceiver() const {
return CallReceiverFromArgv(argv());
}
/*
* New Target
*
@ -769,7 +764,7 @@ class InterpreterFrame
Value newTarget() const {
MOZ_ASSERT(isFunctionFrame());
if (isEvalFrame())
return ((Value*)this)[-3];
return ((Value*)this)[-2];
if (callee().isArrow())
return callee().getExtendedSlot(FunctionExtended::ARROW_NEWTARGET_SLOT);
@ -1055,9 +1050,9 @@ class InterpreterStack
}
// For execution of eval or global code.
InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script, const Value& thisv,
const Value& newTargetValue, HandleObject scopeChain,
ExecuteType type, AbstractFramePtr evalInFrame);
InterpreterFrame* pushExecuteFrame(JSContext* cx, HandleScript script,
const Value& newTargetValue, HandleObject scopeChain,
ExecuteType type, AbstractFramePtr evalInFrame);
// Called to invoke a function.
InterpreterFrame* pushInvokeFrame(JSContext* cx, const CallArgs& args,