Bug 2065986 - pt1. Introduce bailout stubs in the baseline interpreter and fallback ics r=jandem,iain
Add bailout stubs to the Baseline Interpreter and the Fallback IC compiler. These are currently a no-op - but will be jumped to by the bailout tail after copying a single frame's contents. This allows the frame's return address, that is presently directly copied into the stack, to be materialized with an actual call - making bailout compatible with CET shadow stack on x86_64. Differential Revision: https://phabricator.services.mozilla.com/D320791
This commit is contained in:
committed by
jdemooij@mozilla.com
parent
9a17117b7b
commit
de748cf25a
@@ -7145,6 +7145,23 @@ bool BaselineCompiler::emitBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void BaselineInterpreterGenerator::emitICBailoutStub() {
|
||||
MOZ_ASSERT(handler.currentOp());
|
||||
mozilla::DebugOnly<JSOp> op = *handler.currentOp();
|
||||
MOZ_ASSERT(BytecodeOpHasIC(op) && IsIonInlinableOp(op));
|
||||
|
||||
auto& entry = handler.icReturnOffsets().back();
|
||||
MOZ_ASSERT(entry.op == op);
|
||||
|
||||
Label icReturn;
|
||||
icReturn.bind(entry.offset);
|
||||
entry.bailoutStubOffset = masm.currentOffset();
|
||||
// The bailoutTail jumps here when performing bailout stack
|
||||
// reconstruction.
|
||||
// TODO: call the bailout stub handler.
|
||||
masm.jump(&icReturn);
|
||||
}
|
||||
|
||||
bool BaselineInterpreterGenerator::emitDebugTrap() {
|
||||
CodeOffset offset = masm.nopPatchableToCall();
|
||||
if (!debugTrapOffsets_.append(offset.offset())) {
|
||||
@@ -7234,19 +7251,22 @@ bool BaselineInterpreterGenerator::emitInterpreterLoop() {
|
||||
|
||||
// Emit code for each bytecode op.
|
||||
Label opLabels[JSOP_LIMIT];
|
||||
#define EMIT_OP(OP, ...) \
|
||||
{ \
|
||||
AutoCreatedBy acb(masm, "op=" #OP); \
|
||||
perfSpewer_.recordOffset(masm, JSOp::OP); \
|
||||
masm.bind(&opLabels[uint8_t(JSOp::OP)]); \
|
||||
handler.setCurrentOp(JSOp::OP); \
|
||||
if (!this->emit_##OP()) { \
|
||||
return false; \
|
||||
} \
|
||||
if (!opEpilogue(JSOp::OP, JSOpLength_##OP)) { \
|
||||
return false; \
|
||||
} \
|
||||
handler.resetCurrentOp(); \
|
||||
#define EMIT_OP(OP, ...) \
|
||||
{ \
|
||||
AutoCreatedBy acb(masm, "op=" #OP); \
|
||||
perfSpewer_.recordOffset(masm, JSOp::OP); \
|
||||
masm.bind(&opLabels[uint8_t(JSOp::OP)]); \
|
||||
handler.setCurrentOp(JSOp::OP); \
|
||||
if (!this->emit_##OP()) { \
|
||||
return false; \
|
||||
} \
|
||||
if (!opEpilogue(JSOp::OP, JSOpLength_##OP)) { \
|
||||
return false; \
|
||||
} \
|
||||
if (BytecodeOpHasIC(JSOp::OP) && IsIonInlinableOp(JSOp::OP)) { \
|
||||
this->emitICBailoutStub(); \
|
||||
} \
|
||||
handler.resetCurrentOp(); \
|
||||
}
|
||||
FOR_EACH_OPCODE(EMIT_OP)
|
||||
#undef EMIT_OP
|
||||
|
||||
@@ -629,6 +629,7 @@ class BaselineInterpreterGenerator final : private BaselineInterpreterCodeGen {
|
||||
private:
|
||||
[[nodiscard]] bool emitInterpreterLoop();
|
||||
[[nodiscard]] bool emitDebugTrap();
|
||||
void emitICBailoutStub();
|
||||
|
||||
void emitOutOfLineCodeCoverageInstrumentation();
|
||||
[[nodiscard]] bool emitOutOfLineGeneratorResumePrologue();
|
||||
|
||||
+16
-12
@@ -69,6 +69,7 @@ class MOZ_RAII FallbackICCodeCompiler final {
|
||||
[[nodiscard]] bool emitCall(bool isSpread, bool isConstructing);
|
||||
[[nodiscard]] bool emitGetElem(bool hasReceiver);
|
||||
[[nodiscard]] bool emitGetProp(bool hasReceiver);
|
||||
void emitBailoutStub(BailoutReturnKind kind);
|
||||
|
||||
public:
|
||||
FallbackICCodeCompiler(JSContext* cx, BaselineICFallbackCode& code,
|
||||
@@ -646,6 +647,14 @@ void FallbackICCodeCompiler::enterStubFrame(MacroAssembler& masm,
|
||||
#endif
|
||||
}
|
||||
|
||||
void FallbackICCodeCompiler::emitBailoutStub(BailoutReturnKind kind) {
|
||||
code.initBailoutStubOffset(kind, masm.currentOffset());
|
||||
// The bailoutTail jumps here when performing bailout stack
|
||||
// reconstruction.
|
||||
// TODO: call the bailout stub handler.
|
||||
code.initBailoutReturnOffset(kind, masm.currentOffset());
|
||||
}
|
||||
|
||||
void FallbackICCodeCompiler::assumeStubFrame() {
|
||||
MOZ_ASSERT(!inStubFrame_);
|
||||
inStubFrame_ = true;
|
||||
@@ -830,11 +839,9 @@ bool FallbackICCodeCompiler::emitGetElem(bool hasReceiver) {
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
if (hasReceiver) {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetElemSuper,
|
||||
masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::GetElemSuper);
|
||||
} else {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetElem,
|
||||
masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::GetElem);
|
||||
}
|
||||
|
||||
leaveStubFrame(masm);
|
||||
@@ -1416,11 +1423,9 @@ bool FallbackICCodeCompiler::emitGetProp(bool hasReceiver) {
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
if (hasReceiver) {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetPropSuper,
|
||||
masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::GetPropSuper);
|
||||
} else {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::GetProp,
|
||||
masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::GetProp);
|
||||
}
|
||||
|
||||
leaveStubFrame(masm);
|
||||
@@ -1619,8 +1624,7 @@ bool FallbackICCodeCompiler::emit_SetProp() {
|
||||
// Ion inlined frames. The return address pushed onto reconstructed stack
|
||||
// will point here.
|
||||
assumeStubFrame();
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::SetProp,
|
||||
masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::SetProp);
|
||||
|
||||
leaveStubFrame(masm);
|
||||
EmitReturnFromIC(masm);
|
||||
@@ -1917,9 +1921,9 @@ bool FallbackICCodeCompiler::emitCall(bool isSpread, bool isConstructing) {
|
||||
MOZ_ASSERT(!isSpread);
|
||||
|
||||
if (isConstructing) {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::New, masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::New);
|
||||
} else {
|
||||
code.initBailoutReturnOffset(BailoutReturnKind::Call, masm.currentOffset());
|
||||
emitBailoutStub(BailoutReturnKind::Call);
|
||||
}
|
||||
|
||||
// Load passed-in ThisV into R1 just in case it's needed. Need to do this
|
||||
|
||||
@@ -1379,6 +1379,15 @@ uint8_t* BaselineInterpreter::retAddrForIC(JSOp op) const {
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
uint8_t* BaselineInterpreter::bailoutStubAddrForIC(JSOp op) const {
|
||||
for (const ICReturnOffset& entry : icReturnOffsets_) {
|
||||
if (entry.op == op) {
|
||||
return codeAtOffset(entry.bailoutStubOffset);
|
||||
}
|
||||
}
|
||||
MOZ_CRASH("Unexpected op");
|
||||
}
|
||||
|
||||
bool jit::GenerateBaselineInterpreter(JSContext* cx,
|
||||
BaselineInterpreter& interpreter) {
|
||||
if (IsBaselineInterpreterEnabled()) {
|
||||
|
||||
@@ -484,6 +484,7 @@ class BaselineInterpreter {
|
||||
};
|
||||
struct ICReturnOffset {
|
||||
uint32_t offset;
|
||||
uint32_t bailoutStubOffset = 0;
|
||||
JSOp op;
|
||||
ICReturnOffset(uint32_t offset, JSOp op) : offset(offset), op(op) {}
|
||||
};
|
||||
@@ -575,6 +576,7 @@ class BaselineInterpreter {
|
||||
}
|
||||
|
||||
uint8_t* retAddrForIC(JSOp op) const;
|
||||
uint8_t* bailoutStubAddrForIC(JSOp op) const;
|
||||
|
||||
TrampolinePtr interpretOpAddr() const {
|
||||
return TrampolinePtr(codeAtOffset(interpretOpOffset_));
|
||||
|
||||
@@ -84,6 +84,7 @@ class BaselineICFallbackCode {
|
||||
mozilla::EnumeratedArray<BailoutReturnKind, uint32_t,
|
||||
size_t(BailoutReturnKind::Count)>;
|
||||
BailoutReturnArray bailoutReturnOffsets_ = {};
|
||||
BailoutReturnArray bailoutStubOffsets_ = {};
|
||||
|
||||
public:
|
||||
BaselineICFallbackCode() = default;
|
||||
@@ -97,12 +98,18 @@ class BaselineICFallbackCode {
|
||||
void initBailoutReturnOffset(BailoutReturnKind kind, uint32_t offset) {
|
||||
bailoutReturnOffsets_[kind] = offset;
|
||||
}
|
||||
void initBailoutStubOffset(BailoutReturnKind kind, uint32_t offset) {
|
||||
bailoutStubOffsets_[kind] = offset;
|
||||
}
|
||||
TrampolinePtr addr(BaselineICFallbackKind kind) const {
|
||||
return TrampolinePtr(code_->raw() + offsets_[kind]);
|
||||
}
|
||||
uint8_t* bailoutReturnAddr(BailoutReturnKind kind) const {
|
||||
return code_->raw() + bailoutReturnOffsets_[kind];
|
||||
}
|
||||
uint8_t* bailoutStubAddr(BailoutReturnKind kind) const {
|
||||
return code_->raw() + bailoutStubOffsets_[kind];
|
||||
}
|
||||
};
|
||||
|
||||
enum class DebugTrapHandlerKind { Interpreter, Compiler, Count };
|
||||
|
||||
Reference in New Issue
Block a user