mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 910782 - SpiderMonkey: Reduce indirection in InterpreterActivation. r=luke
This commit is contained in:
parent
bb1470c01a
commit
085e28da19
@ -1440,7 +1440,7 @@ GeneratorState::~GeneratorState()
|
||||
}
|
||||
|
||||
StackFrame *
|
||||
GeneratorState::pushInterpreterFrame(JSContext *cx, FrameGuard *)
|
||||
GeneratorState::pushInterpreterFrame(JSContext *cx)
|
||||
{
|
||||
/*
|
||||
* Write barrier is needed since the generator stack can be updated,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -203,7 +203,7 @@ class RunState
|
||||
|
||||
JSScript *script() const { return script_; }
|
||||
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg) = 0;
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx) = 0;
|
||||
virtual void setReturnValue(Value v) = 0;
|
||||
|
||||
private:
|
||||
@ -240,7 +240,7 @@ class ExecuteState : public RunState
|
||||
JSObject *scopeChain() const { return scopeChain_; }
|
||||
ExecuteType type() const { return type_; }
|
||||
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg);
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx);
|
||||
|
||||
virtual void setReturnValue(Value v) {
|
||||
if (result_)
|
||||
@ -269,7 +269,7 @@ class InvokeState : public RunState
|
||||
bool constructing() const { return InitialFrameFlagsAreConstructing(initial_); }
|
||||
CallArgs &args() const { return args_; }
|
||||
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg);
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx);
|
||||
|
||||
virtual void setReturnValue(Value v) {
|
||||
args_.rval().set(v);
|
||||
@ -288,7 +288,7 @@ class GeneratorState : public RunState
|
||||
GeneratorState(JSContext *cx, JSGenerator *gen, JSGeneratorState futureState);
|
||||
~GeneratorState();
|
||||
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg);
|
||||
virtual StackFrame *pushInterpreterFrame(JSContext *cx);
|
||||
virtual void setReturnValue(Value) { }
|
||||
|
||||
JSGenerator *gen() const { return gen_; }
|
||||
|
@ -840,25 +840,43 @@ Activation::~Activation()
|
||||
cx_->mainThread().activation_ = prev_;
|
||||
}
|
||||
|
||||
InterpreterActivation::InterpreterActivation(JSContext *cx, StackFrame *entry, FrameRegs ®s,
|
||||
jsbytecode *const switchMask)
|
||||
InterpreterActivation::InterpreterActivation(RunState &state, JSContext *cx, StackFrame *entryFrame)
|
||||
: Activation(cx, Interpreter),
|
||||
entry_(entry),
|
||||
regs_(regs),
|
||||
switchMask_(switchMask)
|
||||
state_(state),
|
||||
entryFrame_(entryFrame),
|
||||
opMask_(0)
|
||||
#ifdef DEBUG
|
||||
, oldFrameCount_(cx_->runtime()->interpreterStack().frameCount_)
|
||||
#endif
|
||||
{}
|
||||
{
|
||||
if (!state.isGenerator()) {
|
||||
regs_.prepareToRun(*entryFrame, state.script());
|
||||
JS_ASSERT(regs_.pc == state.script()->code);
|
||||
} else {
|
||||
regs_ = state.asGenerator()->gen()->regs;
|
||||
}
|
||||
|
||||
JS_ASSERT_IF(entryFrame_->isEvalFrame(), state_.script()->isActiveEval);
|
||||
}
|
||||
|
||||
InterpreterActivation::~InterpreterActivation()
|
||||
{
|
||||
// Pop all inline frames.
|
||||
while (regs_.fp() != entry_)
|
||||
while (regs_.fp() != entryFrame_)
|
||||
popInlineFrame(regs_.fp());
|
||||
|
||||
JS_ASSERT(oldFrameCount_ == cx_->runtime()->interpreterStack().frameCount_);
|
||||
JS_ASSERT_IF(oldFrameCount_ == 0, cx_->runtime()->interpreterStack().allocator_.used() == 0);
|
||||
|
||||
if (state_.isGenerator()) {
|
||||
JSGenerator *gen = state_.asGenerator()->gen();
|
||||
gen->fp->unsetPushedSPSFrame();
|
||||
gen->regs = regs_;
|
||||
return;
|
||||
}
|
||||
|
||||
if (entryFrame_)
|
||||
cx_->runtime()->interpreterStack().releaseFrame(entryFrame_);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -876,7 +894,7 @@ InterpreterActivation::popInlineFrame(StackFrame *frame)
|
||||
{
|
||||
(void)frame; // Quell compiler warning.
|
||||
JS_ASSERT(regs_.fp() == frame);
|
||||
JS_ASSERT(regs_.fp() != entry_);
|
||||
JS_ASSERT(regs_.fp() != entryFrame_);
|
||||
|
||||
cx_->runtime()->interpreterStack().popInlineFrame(regs_);
|
||||
}
|
||||
|
@ -471,8 +471,7 @@ FrameRegs::setToEndOfScript()
|
||||
/*****************************************************************************/
|
||||
|
||||
StackFrame *
|
||||
InterpreterStack::pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial,
|
||||
FrameGuard *fg)
|
||||
InterpreterStack::pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial)
|
||||
{
|
||||
LifoAlloc::Mark mark = allocator_.mark();
|
||||
|
||||
@ -487,14 +486,13 @@ InterpreterStack::pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFr
|
||||
|
||||
fp->mark_ = mark;
|
||||
fp->initCallFrame(cx, nullptr, nullptr, nullptr, *fun, script, argv, args.length(), flags);
|
||||
fg->setPushed(*this, fp);
|
||||
return fp;
|
||||
}
|
||||
|
||||
StackFrame *
|
||||
InterpreterStack::pushExecuteFrame(JSContext *cx, HandleScript script, const Value &thisv,
|
||||
HandleObject scopeChain, ExecuteType type,
|
||||
AbstractFramePtr evalInFrame, FrameGuard *fg)
|
||||
AbstractFramePtr evalInFrame)
|
||||
{
|
||||
LifoAlloc::Mark mark = allocator_.mark();
|
||||
|
||||
@ -508,7 +506,6 @@ InterpreterStack::pushExecuteFrame(JSContext *cx, HandleScript script, const Val
|
||||
fp->initExecuteFrame(cx, script, evalInFrame, thisv, *scopeChain, type);
|
||||
fp->initVarsToUndefined();
|
||||
|
||||
fg->setPushed(*this, fp);
|
||||
return fp;
|
||||
}
|
||||
|
||||
@ -1344,7 +1341,7 @@ InterpreterFrameIterator &
|
||||
InterpreterFrameIterator::operator++()
|
||||
{
|
||||
JS_ASSERT(!done());
|
||||
if (fp_ != activation_->entry_) {
|
||||
if (fp_ != activation_->entryFrame_) {
|
||||
pc_ = fp_->prevpc();
|
||||
sp_ = fp_->prevsp();
|
||||
fp_ = fp_->prev();
|
||||
|
@ -27,7 +27,6 @@ class StackFrame;
|
||||
class FrameRegs;
|
||||
|
||||
class InvokeFrameGuard;
|
||||
class FrameGuard;
|
||||
class ExecuteFrameGuard;
|
||||
class GeneratorFrameGuard;
|
||||
|
||||
@ -1024,7 +1023,6 @@ class FrameRegs
|
||||
|
||||
class InterpreterStack
|
||||
{
|
||||
friend class FrameGuard;
|
||||
friend class InterpreterActivation;
|
||||
|
||||
static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
|
||||
@ -1059,11 +1057,10 @@ class InterpreterStack
|
||||
// For execution of eval or global code.
|
||||
StackFrame *pushExecuteFrame(JSContext *cx, HandleScript script, const Value &thisv,
|
||||
HandleObject scopeChain, ExecuteType type,
|
||||
AbstractFramePtr evalInFrame, FrameGuard *fg);
|
||||
AbstractFramePtr evalInFrame);
|
||||
|
||||
// Called to invoke a function.
|
||||
StackFrame *pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial,
|
||||
FrameGuard *fg);
|
||||
StackFrame *pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial);
|
||||
|
||||
// The interpreter can push light-weight, "inline" frames without entering a
|
||||
// new InterpreterActivation or recursively calling Interpret.
|
||||
@ -1098,31 +1095,6 @@ class InvokeArgs : public JS::CallArgs
|
||||
}
|
||||
};
|
||||
|
||||
class RunState;
|
||||
|
||||
class FrameGuard
|
||||
{
|
||||
friend class InterpreterStack;
|
||||
RunState &state_;
|
||||
FrameRegs ®s_;
|
||||
InterpreterStack *stack_;
|
||||
StackFrame *fp_;
|
||||
|
||||
void setPushed(InterpreterStack &stack, StackFrame *fp) {
|
||||
stack_ = &stack;
|
||||
fp_ = fp;
|
||||
}
|
||||
|
||||
public:
|
||||
FrameGuard(RunState &state, FrameRegs ®s);
|
||||
~FrameGuard();
|
||||
|
||||
StackFrame *fp() const {
|
||||
JS_ASSERT(fp_);
|
||||
return fp_;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DefaultHasher<AbstractFramePtr> {
|
||||
typedef AbstractFramePtr Lookup;
|
||||
@ -1214,28 +1186,34 @@ class Activation
|
||||
void operator=(const Activation &other) MOZ_DELETE;
|
||||
};
|
||||
|
||||
// The value to assign to InterpreterActivation's *switchMask_ to enable
|
||||
// interrupts. This value is greater than the greatest opcode, and is chosen
|
||||
// such that the bitwise or of this value with any opcode is this value.
|
||||
// This variable holds a special opcode value which is greater than all normal
|
||||
// opcodes, and is chosen such that the bitwise or of this value with any
|
||||
// opcode is this value.
|
||||
static const jsbytecode EnableInterruptsPseudoOpcode = -1;
|
||||
|
||||
static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
|
||||
"EnableInterruptsPseudoOpcode must be greater than any opcode");
|
||||
static_assert(EnableInterruptsPseudoOpcode == jsbytecode(-1),
|
||||
"EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
|
||||
|
||||
class InterpreterFrameIterator;
|
||||
class RunState;
|
||||
|
||||
class InterpreterActivation : public Activation
|
||||
{
|
||||
friend class js::InterpreterFrameIterator;
|
||||
|
||||
StackFrame *const entry_; // Entry frame for this activation.
|
||||
FrameRegs ®s_;
|
||||
jsbytecode *const switchMask_; // For debugger interrupts, see js::Interpret.
|
||||
RunState &state_;
|
||||
FrameRegs regs_;
|
||||
StackFrame *entryFrame_;
|
||||
jsbytecode opMask_; // For debugger interrupts, see js::Interpret.
|
||||
|
||||
#ifdef DEBUG
|
||||
size_t oldFrameCount_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
inline InterpreterActivation(JSContext *cx, StackFrame *entry, FrameRegs ®s,
|
||||
jsbytecode *const switchMask);
|
||||
inline InterpreterActivation(RunState &state, JSContext *cx, StackFrame *entryFrame);
|
||||
inline ~InterpreterActivation();
|
||||
|
||||
inline bool pushInlineFrame(const CallArgs &args, HandleScript script,
|
||||
@ -1245,9 +1223,15 @@ class InterpreterActivation : public Activation
|
||||
StackFrame *current() const {
|
||||
return regs_.fp();
|
||||
}
|
||||
FrameRegs ®s() const {
|
||||
FrameRegs ®s() {
|
||||
return regs_;
|
||||
}
|
||||
StackFrame *entryFrame() const {
|
||||
return entryFrame_;
|
||||
}
|
||||
jsbytecode opMask() const {
|
||||
return opMask_;
|
||||
}
|
||||
|
||||
// If this js::Interpret frame is running |script|, enable interrupts.
|
||||
void enableInterruptsIfRunning(JSScript *script) {
|
||||
@ -1255,7 +1239,10 @@ class InterpreterActivation : public Activation
|
||||
enableInterruptsUnconditionally();
|
||||
}
|
||||
void enableInterruptsUnconditionally() {
|
||||
*switchMask_ = EnableInterruptsPseudoOpcode;
|
||||
opMask_ = EnableInterruptsPseudoOpcode;
|
||||
}
|
||||
void clearInterruptsMask() {
|
||||
opMask_ = 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1381,8 +1368,8 @@ class InterpreterFrameIterator
|
||||
{
|
||||
if (activation) {
|
||||
fp_ = activation->current();
|
||||
pc_ = activation->regs_.pc;
|
||||
sp_ = activation->regs_.sp;
|
||||
pc_ = activation->regs().pc;
|
||||
sp_ = activation->regs().sp;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user