mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1519880 part 2 - Split Baseline's FrameInfo class in CompilerFrameInfo and InterpreterFrameInfo. r=djvj
InterpreterFrameInfo is just a very simple interface on top of masm. CompilerFrameInfo maintains the virtual stack based on the script it's compiling. Differential Revision: https://phabricator.services.mozilla.com/D16480 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
4d6a88776b
commit
ed23e847c7
@ -45,27 +45,30 @@ using mozilla::Maybe;
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
BaselineCompilerHandler::BaselineCompilerHandler(TempAllocator& alloc,
|
||||
BaselineCompilerHandler::BaselineCompilerHandler(MacroAssembler& masm,
|
||||
TempAllocator& alloc,
|
||||
JSScript* script)
|
||||
: alloc_(alloc),
|
||||
: frame_(script, masm),
|
||||
alloc_(alloc),
|
||||
script_(script),
|
||||
pc_(script->code()),
|
||||
compileDebugInstrumentation_(script->isDebuggee()) {}
|
||||
|
||||
BaselineInterpreterHandler::BaselineInterpreterHandler() {}
|
||||
BaselineInterpreterHandler::BaselineInterpreterHandler(MacroAssembler& masm)
|
||||
: frame_(masm) {}
|
||||
|
||||
template <typename Handler>
|
||||
template <typename... HandlerArgs>
|
||||
BaselineCodeGen<Handler>::BaselineCodeGen(JSContext* cx, TempAllocator& alloc,
|
||||
JSScript* script,
|
||||
HandlerArgs&&... args)
|
||||
: handler(std::forward<HandlerArgs>(args)...),
|
||||
: handler(masm, std::forward<HandlerArgs>(args)...),
|
||||
cx(cx),
|
||||
script(script),
|
||||
ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script)),
|
||||
alloc_(alloc),
|
||||
analysis_(alloc, script),
|
||||
frame(script, masm),
|
||||
frame(handler.frame()),
|
||||
traceLoggerToggleOffsets_(cx),
|
||||
icEntryIndex_(0),
|
||||
pushedBeforeCall_(0),
|
||||
@ -89,6 +92,11 @@ BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc,
|
||||
#endif
|
||||
}
|
||||
|
||||
BaselineInterpreterGenerator::BaselineInterpreterGenerator(JSContext* cx,
|
||||
TempAllocator& alloc)
|
||||
// Note: the nullptr script here is temporary. See bug 1519378.
|
||||
: BaselineCodeGen(cx, alloc, /* script = */ nullptr) {}
|
||||
|
||||
bool BaselineCompilerHandler::init() {
|
||||
uint32_t len = script_->length();
|
||||
|
||||
@ -502,6 +510,39 @@ void BaselineCodeGen<Handler>::prepareVMCall() {
|
||||
masm.Push(BaselineFrameReg);
|
||||
}
|
||||
|
||||
template <>
|
||||
void BaselineCompilerCodeGen::storeFrameSizeAndPushDescriptor(
|
||||
uint32_t frameBaseSize, uint32_t argSize, const Address& frameSizeAddr) {
|
||||
uint32_t frameVals = frame.nlocals() + frame.stackDepth();
|
||||
|
||||
uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value));
|
||||
masm.store32(Imm32(frameFullSize), frameSizeAddr);
|
||||
|
||||
uint32_t descriptor = MakeFrameDescriptor(
|
||||
frameFullSize + argSize, FrameType::BaselineJS, ExitFrameLayout::Size());
|
||||
masm.push(Imm32(descriptor));
|
||||
}
|
||||
|
||||
template <>
|
||||
void BaselineInterpreterCodeGen::storeFrameSizeAndPushDescriptor(
|
||||
uint32_t frameBaseSize, uint32_t argSize, const Address& frameSizeAddr) {
|
||||
MOZ_CRASH("NYI: interpreter storeFrameSizeAndPushDescriptor");
|
||||
}
|
||||
|
||||
template <>
|
||||
void BaselineCompilerCodeGen::computeFullFrameSize(uint32_t frameBaseSize,
|
||||
Register dest) {
|
||||
uint32_t frameVals = frame.nlocals() + frame.stackDepth();
|
||||
uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value));
|
||||
masm.move32(Imm32(frameFullSize), dest);
|
||||
}
|
||||
|
||||
template <>
|
||||
void BaselineInterpreterCodeGen::computeFullFrameSize(uint32_t frameBaseSize,
|
||||
Register dest) {
|
||||
MOZ_CRASH("NYI: interpreter computeFullFrameSize");
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::callVM(const VMFunction& fun,
|
||||
CallVMPhase phase) {
|
||||
@ -533,16 +574,10 @@ bool BaselineCodeGen<Handler>::callVM(const VMFunction& fun,
|
||||
|
||||
Address frameSizeAddress(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfFrameSize());
|
||||
uint32_t frameVals = frame.nlocals() + frame.stackDepth();
|
||||
uint32_t frameBaseSize =
|
||||
BaselineFrame::FramePointerOffset + BaselineFrame::Size();
|
||||
uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value));
|
||||
if (phase == POST_INITIALIZE) {
|
||||
masm.store32(Imm32(frameFullSize), frameSizeAddress);
|
||||
uint32_t descriptor =
|
||||
MakeFrameDescriptor(frameFullSize + argSize, FrameType::BaselineJS,
|
||||
ExitFrameLayout::Size());
|
||||
masm.push(Imm32(descriptor));
|
||||
storeFrameSizeAndPushDescriptor(frameBaseSize, argSize, frameSizeAddress);
|
||||
} else {
|
||||
MOZ_ASSERT(phase == CHECK_OVER_RECURSED);
|
||||
Label afterWrite;
|
||||
@ -557,7 +592,7 @@ bool BaselineCodeGen<Handler>::callVM(const VMFunction& fun,
|
||||
masm.jump(&afterWrite);
|
||||
|
||||
masm.bind(&writePostInitialize);
|
||||
masm.move32(Imm32(frameFullSize), ICTailCallReg);
|
||||
computeFullFrameSize(frameBaseSize, ICTailCallReg);
|
||||
|
||||
masm.bind(&afterWrite);
|
||||
masm.store32(ICTailCallReg, frameSizeAddress);
|
||||
@ -3738,7 +3773,7 @@ template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_FINALLY() {
|
||||
// JSOP_FINALLY has a def count of 2, but these values are already on the
|
||||
// stack (they're pushed by JSOP_GOSUB). Update the compiler's stack state.
|
||||
frame.setStackDepth(frame.stackDepth() + 2);
|
||||
frame.incStackDepth(2);
|
||||
|
||||
// To match the interpreter, emit an interrupt check at the start of the
|
||||
// finally block.
|
||||
@ -4116,7 +4151,7 @@ bool BaselineCodeGen<Handler>::emitReturn() {
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_RETURN() {
|
||||
MOZ_ASSERT(frame.stackDepth() == 1);
|
||||
frame.assertStackDepth(1);
|
||||
|
||||
frame.popValue(JSReturnOperand);
|
||||
return emitReturn();
|
||||
@ -4138,7 +4173,7 @@ void BaselineCodeGen<Handler>::emitLoadReturnValue(ValueOperand val) {
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_RETRVAL() {
|
||||
MOZ_ASSERT(frame.stackDepth() == 0);
|
||||
frame.assertStackDepth(0);
|
||||
|
||||
masm.moveValue(UndefinedValue(), JSReturnOperand);
|
||||
|
||||
@ -4715,7 +4750,7 @@ static const VMFunction CreateGeneratorInfo =
|
||||
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_GENERATOR() {
|
||||
MOZ_ASSERT(frame.stackDepth() == 0);
|
||||
frame.assertStackDepth(0);
|
||||
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
|
||||
@ -4733,7 +4768,7 @@ bool BaselineCodeGen<Handler>::emit_JSOP_GENERATOR() {
|
||||
template <typename Handler>
|
||||
bool BaselineCodeGen<Handler>::emit_JSOP_INITIALYIELD() {
|
||||
frame.syncStack(0);
|
||||
MOZ_ASSERT(frame.stackDepth() == 1);
|
||||
frame.assertStackDepth(1);
|
||||
|
||||
Register genObj = R2.scratchReg();
|
||||
masm.unboxObject(frame.addressOfStackValue(-1), genObj);
|
||||
@ -4763,7 +4798,7 @@ bool BaselineCodeGen<Handler>::emit_JSOP_INITIALYIELD() {
|
||||
}
|
||||
|
||||
typedef bool (*NormalSuspendFn)(JSContext*, HandleObject, BaselineFrame*,
|
||||
jsbytecode*, uint32_t);
|
||||
jsbytecode*);
|
||||
static const VMFunction NormalSuspendInfo =
|
||||
FunctionInfo<NormalSuspendFn>(jit::NormalSuspend, "NormalSuspend");
|
||||
|
||||
@ -4775,9 +4810,7 @@ bool BaselineCodeGen<Handler>::emit_JSOP_YIELD() {
|
||||
Register genObj = R2.scratchReg();
|
||||
masm.unboxObject(R0, genObj);
|
||||
|
||||
MOZ_ASSERT(frame.stackDepth() >= 1);
|
||||
|
||||
if (frame.stackDepth() == 1) {
|
||||
if (frame.hasKnownStackDepth(1)) {
|
||||
// If the expression stack is empty, we can inline the YIELD.
|
||||
|
||||
Register temp = R1.scratchReg();
|
||||
@ -4803,7 +4836,6 @@ bool BaselineCodeGen<Handler>::emit_JSOP_YIELD() {
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R1.scratchReg());
|
||||
|
||||
prepareVMCall();
|
||||
pushArg(Imm32(frame.stackDepth()));
|
||||
pushBytecodePCArg();
|
||||
pushArg(R1.scratchReg());
|
||||
pushArg(genObj);
|
||||
|
@ -266,7 +266,7 @@ class BaselineCodeGen {
|
||||
|
||||
TempAllocator& alloc_;
|
||||
BytecodeAnalysis analysis_;
|
||||
FrameInfo frame;
|
||||
typename Handler::FrameInfoT& frame;
|
||||
|
||||
js::Vector<CodeOffset> traceLoggerToggleOffsets_;
|
||||
|
||||
@ -322,6 +322,10 @@ class BaselineCodeGen {
|
||||
|
||||
void prepareVMCall();
|
||||
|
||||
void storeFrameSizeAndPushDescriptor(uint32_t frameBaseSize, uint32_t argSize,
|
||||
const Address& frameSizeAddr);
|
||||
void computeFullFrameSize(uint32_t frameBaseSize, Register dest);
|
||||
|
||||
enum CallVMPhase { POST_INITIALIZE, CHECK_OVER_RECURSED };
|
||||
bool callVM(const VMFunction& fun, CallVMPhase phase = POST_INITIALIZE);
|
||||
|
||||
@ -423,6 +427,7 @@ using RetAddrEntryVector = js::Vector<RetAddrEntry, 16, SystemAllocPolicy>;
|
||||
|
||||
// Interface used by BaselineCodeGen for BaselineCompiler.
|
||||
class BaselineCompilerHandler {
|
||||
CompilerFrameInfo frame_;
|
||||
TempAllocator& alloc_;
|
||||
FixedList<Label> labels_;
|
||||
RetAddrEntryVector retAddrEntries_;
|
||||
@ -431,10 +436,15 @@ class BaselineCompilerHandler {
|
||||
bool compileDebugInstrumentation_;
|
||||
|
||||
public:
|
||||
BaselineCompilerHandler(TempAllocator& alloc, JSScript* script);
|
||||
using FrameInfoT = CompilerFrameInfo;
|
||||
|
||||
BaselineCompilerHandler(MacroAssembler& masm, TempAllocator& alloc,
|
||||
JSScript* script);
|
||||
|
||||
MOZ_MUST_USE bool init();
|
||||
|
||||
CompilerFrameInfo& frame() { return frame_; }
|
||||
|
||||
jsbytecode* pc() const { return pc_; }
|
||||
jsbytecode* maybePC() const { return pc_; }
|
||||
|
||||
@ -563,8 +573,14 @@ class BaselineCompiler final : private BaselineCompilerCodeGen {
|
||||
|
||||
// Interface used by BaselineCodeGen for BaselineInterpreterGenerator.
|
||||
class BaselineInterpreterHandler {
|
||||
InterpreterFrameInfo frame_;
|
||||
|
||||
public:
|
||||
explicit BaselineInterpreterHandler();
|
||||
using FrameInfoT = InterpreterFrameInfo;
|
||||
|
||||
explicit BaselineInterpreterHandler(MacroAssembler& masm);
|
||||
|
||||
InterpreterFrameInfo& frame() { return frame_; }
|
||||
|
||||
// Interpreter doesn't know the pc statically.
|
||||
jsbytecode* maybePC() const { return nullptr; }
|
||||
@ -583,6 +599,7 @@ using BaselineInterpreterCodeGen = BaselineCodeGen<BaselineInterpreterHandler>;
|
||||
|
||||
class BaselineInterpreterGenerator final : private BaselineInterpreterCodeGen {
|
||||
public:
|
||||
BaselineInterpreterGenerator(JSContext* cx, TempAllocator& alloc);
|
||||
};
|
||||
|
||||
extern const VMFunction NewArrayCopyOnWriteInfo;
|
||||
|
@ -10,7 +10,7 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
void FrameInfo::pop(StackAdjustment adjust) {
|
||||
void CompilerFrameInfo::pop(StackAdjustment adjust) {
|
||||
spIndex--;
|
||||
StackValue* popped = &stack[spIndex];
|
||||
|
||||
@ -21,7 +21,7 @@ void FrameInfo::pop(StackAdjustment adjust) {
|
||||
popped->reset();
|
||||
}
|
||||
|
||||
void FrameInfo::popn(uint32_t n, StackAdjustment adjust) {
|
||||
void CompilerFrameInfo::popn(uint32_t n, StackAdjustment adjust) {
|
||||
uint32_t poppedStack = 0;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
if (peek(-1)->kind() == StackValue::Stack) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
bool FrameInfo::init(TempAllocator& alloc) {
|
||||
bool CompilerFrameInfo::init(TempAllocator& alloc) {
|
||||
// An extra slot is needed for global scopes because INITGLEXICAL (stack
|
||||
// depth 1) is compiled as a SETPROP (stack depth 2) on the global lexical
|
||||
// scope.
|
||||
@ -30,7 +30,7 @@ bool FrameInfo::init(TempAllocator& alloc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void FrameInfo::sync(StackValue* val) {
|
||||
void CompilerFrameInfo::sync(StackValue* val) {
|
||||
switch (val->kind()) {
|
||||
case StackValue::Stack:
|
||||
break;
|
||||
@ -60,7 +60,7 @@ void FrameInfo::sync(StackValue* val) {
|
||||
val->setStack();
|
||||
}
|
||||
|
||||
void FrameInfo::syncStack(uint32_t uses) {
|
||||
void CompilerFrameInfo::syncStack(uint32_t uses) {
|
||||
MOZ_ASSERT(uses <= stackDepth());
|
||||
|
||||
uint32_t depth = stackDepth() - uses;
|
||||
@ -71,7 +71,7 @@ void FrameInfo::syncStack(uint32_t uses) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t FrameInfo::numUnsyncedSlots() {
|
||||
uint32_t CompilerFrameInfo::numUnsyncedSlots() {
|
||||
// Start at the bottom, find the first value that's not synced.
|
||||
uint32_t i = 0;
|
||||
for (; i < stackDepth(); i++) {
|
||||
@ -82,7 +82,7 @@ uint32_t FrameInfo::numUnsyncedSlots() {
|
||||
return i;
|
||||
}
|
||||
|
||||
void FrameInfo::popValue(ValueOperand dest) {
|
||||
void CompilerFrameInfo::popValue(ValueOperand dest) {
|
||||
StackValue* val = peek(-1);
|
||||
|
||||
switch (val->kind()) {
|
||||
@ -115,7 +115,7 @@ void FrameInfo::popValue(ValueOperand dest) {
|
||||
pop(DontAdjustStack);
|
||||
}
|
||||
|
||||
void FrameInfo::popRegsAndSync(uint32_t uses) {
|
||||
void CompilerFrameInfo::popRegsAndSync(uint32_t uses) {
|
||||
// x86 has only 3 Value registers. Only support 2 regs here for now,
|
||||
// so that there's always a scratch Value register for reg -> reg
|
||||
// moves.
|
||||
@ -146,8 +146,23 @@ void FrameInfo::popRegsAndSync(uint32_t uses) {
|
||||
}
|
||||
}
|
||||
|
||||
void FrameInfo::storeStackValue(int32_t depth, const Address& dest,
|
||||
const ValueOperand& scratch) {
|
||||
void InterpreterFrameInfo::popRegsAndSync(uint32_t uses) {
|
||||
switch (uses) {
|
||||
case 1:
|
||||
popValue(R0);
|
||||
break;
|
||||
case 2: {
|
||||
popValue(R1);
|
||||
popValue(R0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("Invalid uses");
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerFrameInfo::storeStackValue(int32_t depth, const Address& dest,
|
||||
const ValueOperand& scratch) {
|
||||
const StackValue* source = peek(depth);
|
||||
switch (source->kind()) {
|
||||
case StackValue::Constant:
|
||||
@ -183,7 +198,7 @@ void FrameInfo::storeStackValue(int32_t depth, const Address& dest,
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void FrameInfo::assertValidState(const BytecodeInfo& info) {
|
||||
void CompilerFrameInfo::assertValidState(const BytecodeInfo& info) {
|
||||
// Check stack depth.
|
||||
MOZ_ASSERT(stackDepth() == info.stackDepth);
|
||||
|
||||
@ -222,7 +237,7 @@ void FrameInfo::assertValidState(const BytecodeInfo& info) {
|
||||
}
|
||||
#endif
|
||||
|
||||
PCMappingSlotInfo::SlotLocation FrameInfo::stackValueSlotLocation(
|
||||
PCMappingSlotInfo::SlotLocation CompilerFrameInfo::stackValueSlotLocation(
|
||||
int32_t depth) {
|
||||
const StackValue* stackVal = peek(depth);
|
||||
|
||||
|
@ -22,13 +22,24 @@ namespace jit {
|
||||
|
||||
struct BytecodeInfo;
|
||||
|
||||
// FrameInfo overview.
|
||||
// [SMDOC] Baseline FrameInfo overview.
|
||||
//
|
||||
// FrameInfo is used by the compiler to track values stored in the frame. This
|
||||
// includes locals, arguments and stack values. Locals and arguments are always
|
||||
// fully synced. Stack values can either be synced, stored as constant, stored
|
||||
// in a Value register or refer to a local slot. Syncing a StackValue ensures
|
||||
// it's stored on the stack, e.g. kind == Stack.
|
||||
// FrameInfo is used by BaselineCodeGen to track values stored in the frame.
|
||||
// There are two implementations:
|
||||
//
|
||||
// InterpreterFrameInfo
|
||||
// --------------------
|
||||
// The InterpreterFrameInfo class is used by the interpreter generator and is
|
||||
// a very simple interface on top of the MacroAssembler, because the stack is
|
||||
// always synced.
|
||||
//
|
||||
// CompilerFrameInfo
|
||||
// -----------------
|
||||
// The CompilerFrameInfo class is more complicated because it maintains a
|
||||
// virtual stack to optimize some common stack operations. Locals and arguments
|
||||
// are always fully synced. Stack values can either be synced, stored as
|
||||
// constant, stored in a Value register or refer to a local slot. Syncing a
|
||||
// StackValue ensures it's stored on the stack, e.g. kind == Stack.
|
||||
//
|
||||
// To see how this works, consider the following statement:
|
||||
//
|
||||
@ -159,16 +170,56 @@ class StackValue {
|
||||
enum StackAdjustment { AdjustStack, DontAdjustStack };
|
||||
|
||||
class FrameInfo {
|
||||
JSScript* script;
|
||||
protected:
|
||||
MacroAssembler& masm;
|
||||
|
||||
public:
|
||||
explicit FrameInfo(MacroAssembler& masm) : masm(masm) {}
|
||||
|
||||
Address addressOfLocal(size_t local) const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfLocal(local));
|
||||
}
|
||||
Address addressOfArg(size_t arg) const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfArg(arg));
|
||||
}
|
||||
Address addressOfThis() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfThis());
|
||||
}
|
||||
Address addressOfEvalNewTarget() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfEvalNewTarget());
|
||||
}
|
||||
Address addressOfCalleeToken() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfCalleeToken());
|
||||
}
|
||||
Address addressOfEnvironmentChain() const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfEnvironmentChain());
|
||||
}
|
||||
Address addressOfFlags() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags());
|
||||
}
|
||||
Address addressOfReturnValue() const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfReturnValue());
|
||||
}
|
||||
Address addressOfArgsObj() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj());
|
||||
}
|
||||
Address addressOfScratchValue() const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfScratchValue());
|
||||
}
|
||||
};
|
||||
|
||||
class CompilerFrameInfo : public FrameInfo {
|
||||
JSScript* script;
|
||||
FixedList<StackValue> stack;
|
||||
size_t spIndex;
|
||||
|
||||
public:
|
||||
FrameInfo(JSScript* script, MacroAssembler& masm)
|
||||
: script(script), masm(masm), stack(), spIndex(0) {}
|
||||
|
||||
CompilerFrameInfo(JSScript* script, MacroAssembler& masm)
|
||||
: FrameInfo(masm), script(script), stack(), spIndex(0) {}
|
||||
MOZ_MUST_USE bool init(TempAllocator& alloc);
|
||||
|
||||
size_t nlocals() const { return script->nfixed(); }
|
||||
@ -202,6 +253,10 @@ class FrameInfo {
|
||||
}
|
||||
}
|
||||
|
||||
void assertStackDepth(uint32_t depth) { MOZ_ASSERT(stackDepth() == depth); }
|
||||
void incStackDepth(int32_t diff) { setStackDepth(stackDepth() + diff); }
|
||||
bool hasKnownStackDepth(uint32_t depth) { return stackDepth() == depth; }
|
||||
|
||||
inline void pop(StackAdjustment adjust = AdjustStack);
|
||||
inline void popn(uint32_t n, StackAdjustment adjust = AdjustStack);
|
||||
inline void push(const Value& val) {
|
||||
@ -237,38 +292,16 @@ class FrameInfo {
|
||||
StackValue* sv = rawPush();
|
||||
sv->setStack();
|
||||
}
|
||||
inline Address addressOfLocal(size_t local) const {
|
||||
|
||||
Address addressOfLocal(size_t local) const {
|
||||
MOZ_ASSERT(local < nlocals());
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfLocal(local));
|
||||
return FrameInfo::addressOfLocal(local);
|
||||
}
|
||||
Address addressOfArg(size_t arg) const {
|
||||
MOZ_ASSERT(arg < nargs());
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfArg(arg));
|
||||
}
|
||||
Address addressOfThis() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfThis());
|
||||
}
|
||||
Address addressOfEvalNewTarget() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfEvalNewTarget());
|
||||
}
|
||||
Address addressOfCalleeToken() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::offsetOfCalleeToken());
|
||||
}
|
||||
Address addressOfEnvironmentChain() const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfEnvironmentChain());
|
||||
}
|
||||
Address addressOfFlags() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags());
|
||||
}
|
||||
Address addressOfReturnValue() const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfReturnValue());
|
||||
}
|
||||
Address addressOfArgsObj() const {
|
||||
return Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj());
|
||||
return FrameInfo::addressOfArg(arg);
|
||||
}
|
||||
|
||||
Address addressOfStackValue(int32_t depth) const {
|
||||
const StackValue* value = peek(depth);
|
||||
MOZ_ASSERT(value->kind() == StackValue::Stack);
|
||||
@ -277,10 +310,6 @@ class FrameInfo {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfLocal(nlocals() + slot));
|
||||
}
|
||||
Address addressOfScratchValue() const {
|
||||
return Address(BaselineFrameReg,
|
||||
BaselineFrame::reverseOffsetOfScratchValue());
|
||||
}
|
||||
|
||||
void popValue(ValueOperand dest);
|
||||
|
||||
@ -289,7 +318,7 @@ class FrameInfo {
|
||||
uint32_t numUnsyncedSlots();
|
||||
void popRegsAndSync(uint32_t uses);
|
||||
|
||||
inline void assertSyncedStack() const {
|
||||
void assertSyncedStack() const {
|
||||
MOZ_ASSERT_IF(stackDepth() > 0, peek(-1)->kind() == StackValue::Stack);
|
||||
}
|
||||
|
||||
@ -310,6 +339,54 @@ class FrameInfo {
|
||||
#endif
|
||||
};
|
||||
|
||||
class InterpreterFrameInfo : public FrameInfo {
|
||||
public:
|
||||
explicit InterpreterFrameInfo(MacroAssembler& masm) : FrameInfo(masm) {}
|
||||
|
||||
// These methods are no-ops in the interpreter, because we don't have a
|
||||
// virtual stack there.
|
||||
void syncStack(uint32_t uses) {}
|
||||
void assertSyncedStack() const {}
|
||||
void assertStackDepth(uint32_t depth) {}
|
||||
void incStackDepth(int32_t diff) {}
|
||||
bool hasKnownStackDepth(uint32_t depth) { return false; }
|
||||
uint32_t numUnsyncedSlots() { return 0; }
|
||||
|
||||
bool stackValueHasKnownType(int32_t depth, JSValueType type) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Address addressOfStackValue(int depth) const {
|
||||
MOZ_ASSERT(depth < 0);
|
||||
return Address(masm.getStackPointer(),
|
||||
masm.framePushed() + size_t(-(depth + 1)) * sizeof(Value));
|
||||
}
|
||||
|
||||
void popRegsAndSync(uint32_t uses);
|
||||
|
||||
void pop() { popn(1); }
|
||||
|
||||
void popn(uint32_t n) { masm.addToStackPtr(Imm32(n * sizeof(Value))); }
|
||||
|
||||
void popValue(ValueOperand dest) { masm.popValue(dest); }
|
||||
|
||||
void push(const ValueOperand& val,
|
||||
JSValueType knownType = JSVAL_TYPE_UNKNOWN) {
|
||||
masm.pushValue(val);
|
||||
}
|
||||
void push(const Value& val) { masm.pushValue(val); }
|
||||
|
||||
void pushThis() { masm.pushValue(addressOfThis()); }
|
||||
void pushEvalNewTarget() { masm.pushValue(addressOfEvalNewTarget()); }
|
||||
void pushScratchValue() { masm.pushValue(addressOfScratchValue()); }
|
||||
|
||||
void storeStackValue(int32_t depth, const Address& dest,
|
||||
const ValueOperand& scratch) {
|
||||
masm.loadValue(addressOfStackValue(depth), scratch);
|
||||
masm.storeValue(scratch, dest);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
@ -811,9 +811,12 @@ JSObject* CreateGenerator(JSContext* cx, BaselineFrame* frame) {
|
||||
}
|
||||
|
||||
bool NormalSuspend(JSContext* cx, HandleObject obj, BaselineFrame* frame,
|
||||
jsbytecode* pc, uint32_t stackDepth) {
|
||||
jsbytecode* pc) {
|
||||
MOZ_ASSERT(*pc == JSOP_YIELD || *pc == JSOP_AWAIT);
|
||||
|
||||
MOZ_ASSERT(frame->numValueSlots() > frame->script()->nfixed());
|
||||
uint32_t stackDepth = frame->numValueSlots() - frame->script()->nfixed();
|
||||
|
||||
// Return value is still on the stack.
|
||||
MOZ_ASSERT(stackDepth >= 1);
|
||||
|
||||
|
@ -1017,8 +1017,7 @@ void FrameIsDebuggeeCheck(BaselineFrame* frame);
|
||||
JSObject* CreateGenerator(JSContext* cx, BaselineFrame* frame);
|
||||
|
||||
MOZ_MUST_USE bool NormalSuspend(JSContext* cx, HandleObject obj,
|
||||
BaselineFrame* frame, jsbytecode* pc,
|
||||
uint32_t stackDepth);
|
||||
BaselineFrame* frame, jsbytecode* pc);
|
||||
MOZ_MUST_USE bool FinalSuspend(JSContext* cx, HandleObject obj, jsbytecode* pc);
|
||||
MOZ_MUST_USE bool InterpretResume(JSContext* cx, HandleObject obj,
|
||||
HandleValue val, HandlePropertyName kind,
|
||||
|
Loading…
Reference in New Issue
Block a user