[wasm] Explicitly spill WasmInstanceObject in prologue.
This adds another fixed spill slot to the {WasmCompiledFrame} layout, holding a reference to the current {WasmInstanceObject}. This slot allows the stack walker to retrieve instances for WebAssembly frames without having each code object be coupled to an instance. Hence it enables sharing code across instances in the future. R=titzer@chromium.org BUG=v8:7424 Change-Id: I7fa095c6255754caf564edce4ee7e84dea666783 Reviewed-on: https://chromium-review.googlesource.com/1005516 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Ben Titzer <titzer@chromium.org> Reviewed-by: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#52626}
This commit is contained in:
parent
3baf75f734
commit
120dfa48cf
@ -31,6 +31,7 @@ constexpr Register kJavaScriptCallNewTargetRegister = r3;
|
||||
constexpr Register kOffHeapTrampolineRegister = r6;
|
||||
constexpr Register kRuntimeCallFunctionRegister = r1;
|
||||
constexpr Register kRuntimeCallArgCountRegister = r0;
|
||||
constexpr Register kWasmInstanceRegister = r3;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Static helper functions
|
||||
|
@ -58,6 +58,7 @@ namespace internal {
|
||||
#define kOffHeapTrampolineRegister ip0
|
||||
#define kRuntimeCallFunctionRegister x1
|
||||
#define kRuntimeCallArgCountRegister x0
|
||||
#define kWasmInstanceRegister x7
|
||||
|
||||
#define LS_MACRO_LIST(V) \
|
||||
V(Ldrb, Register&, rt, LDRB_w) \
|
||||
|
@ -2568,8 +2568,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = r3; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2581,7 +2579,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ vstm(db_w, sp, lowest_fp_reg, highest_fp_reg);
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ push(wasm_instance_reg);
|
||||
__ push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(cp, Smi::kZero);
|
||||
@ -2589,7 +2587,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// The entrypoint address is the first return value.
|
||||
__ mov(r8, kReturnRegister0);
|
||||
// The WASM instance is the second return value.
|
||||
__ mov(wasm_instance_reg, kReturnRegister1);
|
||||
__ mov(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
__ vldm(ia_w, sp, lowest_fp_reg, highest_fp_reg);
|
||||
|
@ -3032,8 +3032,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = x7; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -3045,7 +3043,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ Push(x5, x6); // note: pushed twice because alignment required
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ PushArgument(wasm_instance_reg);
|
||||
__ PushArgument(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(cp, Smi::kZero);
|
||||
@ -3053,7 +3051,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// The entrypoint address is the first return value.
|
||||
__ mov(x8, kReturnRegister0);
|
||||
// The WASM instance is the second return value.
|
||||
__ mov(wasm_instance_reg, kReturnRegister1);
|
||||
__ mov(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
__ Pop(x6, x5); // note: pushed twice because alignment required
|
||||
|
@ -2760,8 +2760,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = esi; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2777,7 +2775,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ Push(wasm_instance_reg);
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(esi, Smi::kZero);
|
||||
@ -2785,7 +2783,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// The entrypoint address is the first return value.
|
||||
__ mov(edi, kReturnRegister0);
|
||||
// The WASM instance is the second return value.
|
||||
__ mov(wasm_instance_reg, kReturnRegister1);
|
||||
__ mov(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
for (int i = arraysize(xmm_regs) - 1; i >= 0; --i) {
|
||||
|
@ -2628,8 +2628,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = a0; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2640,13 +2638,13 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ MultiPushFPU(fp_regs);
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ push(wasm_instance_reg);
|
||||
__ push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(kContextRegister, Smi::kZero);
|
||||
__ CallRuntime(Runtime::kWasmCompileLazy);
|
||||
// The WASM instance is the second return value.
|
||||
__ mov(wasm_instance_reg, kReturnRegister1);
|
||||
__ mov(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
__ MultiPopFPU(fp_regs);
|
||||
|
@ -2647,8 +2647,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = a0; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2659,13 +2657,13 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ MultiPushFPU(fp_regs);
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ push(wasm_instance_reg);
|
||||
__ push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(kContextRegister, Smi::kZero);
|
||||
__ CallRuntime(Runtime::kWasmCompileLazy);
|
||||
// The WASM instance is the second return value.
|
||||
__ mov(wasm_instance_reg, kReturnRegister1);
|
||||
__ mov(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
__ MultiPopFPU(fp_regs);
|
||||
|
@ -2651,8 +2651,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = r10; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2663,7 +2661,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ MultiPushDoubles(fp_regs);
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ Push(wasm_instance_reg);
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ LoadSmiLiteral(cp, Smi::kZero);
|
||||
@ -2671,7 +2669,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// The entrypoint address is the first return value.
|
||||
__ mr(r11, kReturnRegister0);
|
||||
// The WASM instance is the second return value.
|
||||
__ mr(wasm_instance_reg, kReturnRegister1);
|
||||
__ mr(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
__ MultiPopDoubles(fp_regs);
|
||||
|
@ -2656,8 +2656,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = r6; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2671,7 +2669,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ MultiPushDoubles(fp_regs);
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ Push(wasm_instance_reg);
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ LoadSmiLiteral(cp, Smi::kZero);
|
||||
@ -2679,7 +2677,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// The entrypoint address is the first return value.
|
||||
__ LoadRR(ip, r2);
|
||||
// The WASM instance is the second return value.
|
||||
__ LoadRR(wasm_instance_reg, kReturnRegister1);
|
||||
__ LoadRR(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
__ MultiPopDoubles(fp_regs);
|
||||
|
@ -2715,8 +2715,6 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
auto wasm_instance_reg = rsi; // TODO(titzer): put in a common place.
|
||||
|
||||
// Save all parameter registers (see wasm-linkage.cc). They might be
|
||||
// overwritten in the runtime call below. We don't have any callee-saved
|
||||
// registers in wasm, so no need to store anything else.
|
||||
@ -2732,7 +2730,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
// Pass the WASM instance as an explicit argument to WasmCompileLazy.
|
||||
__ Push(wasm_instance_reg);
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Initialize the JavaScript context with 0. CEntryStub will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(rsi, Smi::kZero);
|
||||
@ -2740,7 +2738,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
// The entrypoint address is the first return value.
|
||||
__ movq(r11, kReturnRegister0);
|
||||
// The WASM instance is the second return value.
|
||||
__ movq(wasm_instance_reg, kReturnRegister1);
|
||||
__ movq(kWasmInstanceRegister, kReturnRegister1);
|
||||
|
||||
// Restore registers.
|
||||
for (int i = arraysize(xmm_regs) - 1; i >= 0; --i) {
|
||||
|
@ -2928,6 +2928,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());
|
||||
|
@ -2455,6 +2455,18 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
// There is no need to leave the frame, we will not return from the
|
||||
// runtime call.
|
||||
__ EnterFrame(StackFrame::WASM_COMPILED);
|
||||
} else {
|
||||
// Finish the frame that hasn't been fully built yet.
|
||||
// TODO(mstarzinger): This is a work-around, deferred frame building is
|
||||
// actually no longer supported, remove the associated code.
|
||||
UseScratchRegisterScope temps(tasm());
|
||||
__ Claim(2); // Claim extra slots for marker + instance.
|
||||
Register scratch = temps.AcquireX();
|
||||
__ Mov(scratch,
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
__ Str(scratch, MemOperand(fp, TypedFrameConstants::kFrameTypeOffset));
|
||||
__ Str(kWasmInstanceRegister,
|
||||
MemOperand(fp, WasmCompiledFrameConstants::kWasmInstanceOffset));
|
||||
}
|
||||
__ Mov(cp, Smi::kZero);
|
||||
__ CallRuntimeDelayed(zone(), Runtime::kThrowWasmStackOverflow);
|
||||
@ -2487,8 +2499,7 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ Claim(shrink_slots);
|
||||
}
|
||||
break;
|
||||
case CallDescriptor::kCallCodeObject:
|
||||
case CallDescriptor::kCallWasmFunction: {
|
||||
case CallDescriptor::kCallCodeObject: {
|
||||
UseScratchRegisterScope temps(tasm());
|
||||
__ Claim(shrink_slots + 1); // Claim extra slot for frame type marker.
|
||||
Register scratch = temps.AcquireX();
|
||||
@ -2496,6 +2507,16 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
__ Str(scratch, MemOperand(fp, TypedFrameConstants::kFrameTypeOffset));
|
||||
} break;
|
||||
case CallDescriptor::kCallWasmFunction: {
|
||||
UseScratchRegisterScope temps(tasm());
|
||||
__ Claim(shrink_slots + 2); // Claim extra slots for marker + instance.
|
||||
Register scratch = temps.AcquireX();
|
||||
__ Mov(scratch,
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
__ Str(scratch, MemOperand(fp, TypedFrameConstants::kFrameTypeOffset));
|
||||
__ Str(kWasmInstanceRegister,
|
||||
MemOperand(fp, WasmCompiledFrameConstants::kWasmInstanceOffset));
|
||||
} break;
|
||||
case CallDescriptor::kCallAddress:
|
||||
__ Claim(shrink_slots);
|
||||
break;
|
||||
|
@ -3586,6 +3586,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ push(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,14 +123,13 @@ int CallDescriptor::CalculateFixedFrameSize() const {
|
||||
return PushArgumentCount()
|
||||
? OptimizedBuiltinFrameConstants::kFixedSlotCount
|
||||
: StandardFrameConstants::kFixedSlotCount;
|
||||
break;
|
||||
case kCallAddress:
|
||||
return CommonFrameConstants::kFixedSlotCountAboveFp +
|
||||
CommonFrameConstants::kCPSlotCount;
|
||||
break;
|
||||
case kCallCodeObject:
|
||||
case kCallWasmFunction:
|
||||
return TypedFrameConstants::kFixedSlotCount;
|
||||
case kCallWasmFunction:
|
||||
return WasmCompiledFrameConstants::kFixedSlotCount;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -221,8 +221,11 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
// Returns {true} if this descriptor is a call to a JSFunction.
|
||||
bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; }
|
||||
|
||||
// Returns {true} if this descriptor is a call to a WebAssembly function.
|
||||
bool IsWasmFunctionCall() const { return kind_ == kCallWasmFunction; }
|
||||
|
||||
bool RequiresFrameAsIncoming() const {
|
||||
return IsCFunctionCall() || IsJSFunctionCall();
|
||||
return IsCFunctionCall() || IsJSFunctionCall() || IsWasmFunctionCall();
|
||||
}
|
||||
|
||||
// The number of return values from this call.
|
||||
|
@ -3199,6 +3199,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3453,6 +3453,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2233,6 +2233,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
// TODO(mbrandy): Detect cases where ip is the entrypoint (for
|
||||
// efficient intialization of the constant pool pointer register).
|
||||
__ StubPrologue(type);
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2654,6 +2654,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
// TODO(mbrandy): Detect cases where ip is the entrypoint (for
|
||||
// efficient intialization of the constant pool pointer register).
|
||||
__ StubPrologue(type);
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3120,6 +3120,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
}
|
||||
} else {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ pushq(kWasmInstanceRegister);
|
||||
}
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkFrameConstructed(pc_base);
|
||||
|
@ -253,6 +253,13 @@ class ConstructFrameConstants : public TypedFrameConstants {
|
||||
DEFINE_TYPED_FRAME_SIZES(5);
|
||||
};
|
||||
|
||||
class WasmCompiledFrameConstants : public TypedFrameConstants {
|
||||
public:
|
||||
// FP-relative.
|
||||
static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
|
||||
DEFINE_TYPED_FRAME_SIZES(1);
|
||||
};
|
||||
|
||||
class BuiltinContinuationFrameConstants : public TypedFrameConstants {
|
||||
public:
|
||||
// FP-relative.
|
||||
|
@ -208,16 +208,6 @@ DISABLE_ASAN Address ReadMemoryAt(Address address) {
|
||||
return Memory::Address_at(address);
|
||||
}
|
||||
|
||||
WasmInstanceObject* LookupWasmInstanceObjectFromStandardFrame(
|
||||
const StandardFrame* frame) {
|
||||
// TODO(titzer): WASM instances cannot be found from the code in the future.
|
||||
WasmInstanceObject* ret = WasmInstanceObject::GetOwningInstance(
|
||||
frame->isolate()->wasm_engine()->code_manager()->LookupCode(frame->pc()));
|
||||
// This is a live stack frame, there must be a live wasm instance available.
|
||||
DCHECK_NOT_NULL(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SafeStackFrameIterator::SafeStackFrameIterator(
|
||||
@ -881,11 +871,13 @@ void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
case INTERNAL:
|
||||
case CONSTRUCT:
|
||||
case JS_TO_WASM:
|
||||
case C_WASM_ENTRY:
|
||||
frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
|
||||
break;
|
||||
case WASM_TO_JS:
|
||||
case WASM_COMPILED:
|
||||
case WASM_INTERPRETER_ENTRY:
|
||||
case C_WASM_ENTRY:
|
||||
frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
|
||||
frame_header_size = WasmCompiledFrameConstants::kFixedFrameSizeFromFp;
|
||||
break;
|
||||
case OPTIMIZED:
|
||||
case INTERPRETED:
|
||||
@ -959,18 +951,17 @@ void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
}
|
||||
}
|
||||
|
||||
// For wasm-to-js cases, we can skip this.
|
||||
// For the off-heap code cases, we can skip this.
|
||||
if (code != nullptr) {
|
||||
// Visit the return address in the callee and incoming arguments.
|
||||
IteratePc(v, pc_address(), constant_pool_address(), code);
|
||||
}
|
||||
|
||||
if (!is_wasm() && !is_wasm_to_js()) {
|
||||
// If this frame has JavaScript ABI, visit the context (in stub and JS
|
||||
// frames) and the function (in JS frames).
|
||||
v->VisitRootPointers(Root::kTop, nullptr, frame_header_base,
|
||||
frame_header_limit);
|
||||
}
|
||||
// If this frame has JavaScript ABI, visit the context (in stub and JS
|
||||
// frames) and the function (in JS frames). If it has WebAssembly ABI, visit
|
||||
// the instance object.
|
||||
v->VisitRootPointers(Root::kTop, nullptr, frame_header_base,
|
||||
frame_header_limit);
|
||||
}
|
||||
|
||||
void StubFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
|
||||
@ -1808,17 +1799,17 @@ wasm::WasmCode* WasmCompiledFrame::wasm_code() const {
|
||||
}
|
||||
|
||||
WasmInstanceObject* WasmCompiledFrame::wasm_instance() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this);
|
||||
const int offset = WasmCompiledFrameConstants::kWasmInstanceOffset;
|
||||
Object* instance = Memory::Object_at(fp() + offset);
|
||||
return WasmInstanceObject::cast(instance);
|
||||
}
|
||||
|
||||
WasmSharedModuleData* WasmCompiledFrame::shared() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this)
|
||||
->compiled_module()
|
||||
->shared();
|
||||
return wasm_instance()->compiled_module()->shared();
|
||||
}
|
||||
|
||||
WasmCompiledModule* WasmCompiledFrame::compiled_module() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this)->compiled_module();
|
||||
return wasm_instance()->compiled_module();
|
||||
}
|
||||
|
||||
uint32_t WasmCompiledFrame::function_index() const {
|
||||
@ -1835,8 +1826,7 @@ void WasmCompiledFrame::Summarize(std::vector<FrameSummary>* functions) const {
|
||||
DCHECK(functions->empty());
|
||||
wasm::WasmCode* code = wasm_code();
|
||||
int offset = static_cast<int>(pc() - code->instruction_start());
|
||||
Handle<WasmInstanceObject> instance(
|
||||
LookupWasmInstanceObjectFromStandardFrame(this), isolate());
|
||||
Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
|
||||
FrameSummary::WasmCompiledFrameSummary summary(
|
||||
isolate(), instance, code, offset, at_to_number_conversion());
|
||||
functions->push_back(summary);
|
||||
@ -1887,8 +1877,7 @@ void WasmInterpreterEntryFrame::Print(StringStream* accumulator, PrintMode mode,
|
||||
|
||||
void WasmInterpreterEntryFrame::Summarize(
|
||||
std::vector<FrameSummary>* functions) const {
|
||||
Handle<WasmInstanceObject> instance(
|
||||
LookupWasmInstanceObjectFromStandardFrame(this), isolate());
|
||||
Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
|
||||
std::vector<std::pair<uint32_t, int>> interpreted_stack =
|
||||
instance->debug_info()->GetInterpretedStack(fp());
|
||||
|
||||
@ -1901,23 +1890,22 @@ void WasmInterpreterEntryFrame::Summarize(
|
||||
|
||||
Code* WasmInterpreterEntryFrame::unchecked_code() const { UNREACHABLE(); }
|
||||
|
||||
// TODO(titzer): deprecate this method.
|
||||
WasmInstanceObject* WasmInterpreterEntryFrame::wasm_instance() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this);
|
||||
const int offset = WasmCompiledFrameConstants::kWasmInstanceOffset;
|
||||
Object* instance = Memory::Object_at(fp() + offset);
|
||||
return WasmInstanceObject::cast(instance);
|
||||
}
|
||||
|
||||
WasmDebugInfo* WasmInterpreterEntryFrame::debug_info() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this)->debug_info();
|
||||
return wasm_instance()->debug_info();
|
||||
}
|
||||
|
||||
WasmSharedModuleData* WasmInterpreterEntryFrame::shared() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this)
|
||||
->compiled_module()
|
||||
->shared();
|
||||
return wasm_instance()->compiled_module()->shared();
|
||||
}
|
||||
|
||||
WasmCompiledModule* WasmInterpreterEntryFrame::compiled_module() const {
|
||||
return LookupWasmInstanceObjectFromStandardFrame(this)->compiled_module();
|
||||
return wasm_instance()->compiled_module();
|
||||
}
|
||||
|
||||
Script* WasmInterpreterEntryFrame::script() const { return shared()->script(); }
|
||||
|
@ -979,7 +979,7 @@ class WasmCompiledFrame final : public StandardFrame {
|
||||
Code* unchecked_code() const override;
|
||||
|
||||
// Accessors.
|
||||
WasmInstanceObject* wasm_instance() const; // TODO(titzer): deprecate.
|
||||
WasmInstanceObject* wasm_instance() const;
|
||||
wasm::WasmCode* wasm_code() const;
|
||||
uint32_t function_index() const;
|
||||
Script* script() const override;
|
||||
@ -1022,7 +1022,7 @@ class WasmInterpreterEntryFrame final : public StandardFrame {
|
||||
|
||||
// Accessors.
|
||||
WasmDebugInfo* debug_info() const;
|
||||
WasmInstanceObject* wasm_instance() const; // TODO(titzer): deprecate.
|
||||
WasmInstanceObject* wasm_instance() const;
|
||||
|
||||
Script* script() const override;
|
||||
int position() const override;
|
||||
|
@ -31,6 +31,7 @@ constexpr Register kJavaScriptCallNewTargetRegister = edx;
|
||||
constexpr Register kOffHeapTrampolineRegister = ecx;
|
||||
constexpr Register kRuntimeCallFunctionRegister = ebx;
|
||||
constexpr Register kRuntimeCallArgCountRegister = eax;
|
||||
constexpr Register kWasmInstanceRegister = esi;
|
||||
|
||||
// Convenience for platform-independent signatures. We do not normally
|
||||
// distinguish memory operands from other operands on ia32.
|
||||
|
@ -30,6 +30,7 @@ constexpr Register kJavaScriptCallNewTargetRegister = a3;
|
||||
constexpr Register kOffHeapTrampolineRegister = at;
|
||||
constexpr Register kRuntimeCallFunctionRegister = a1;
|
||||
constexpr Register kRuntimeCallArgCountRegister = a0;
|
||||
constexpr Register kWasmInstanceRegister = a0;
|
||||
|
||||
// Forward declaration.
|
||||
class JumpTarget;
|
||||
|
@ -30,6 +30,7 @@ constexpr Register kJavaScriptCallNewTargetRegister = a3;
|
||||
constexpr Register kOffHeapTrampolineRegister = at;
|
||||
constexpr Register kRuntimeCallFunctionRegister = a1;
|
||||
constexpr Register kRuntimeCallArgCountRegister = a0;
|
||||
constexpr Register kWasmInstanceRegister = a0;
|
||||
|
||||
// Forward declaration.
|
||||
class JumpTarget;
|
||||
|
@ -32,6 +32,7 @@ constexpr Register kJavaScriptCallCodeStartRegister = r5;
|
||||
constexpr Register kOffHeapTrampolineRegister = ip;
|
||||
constexpr Register kRuntimeCallFunctionRegister = r4;
|
||||
constexpr Register kRuntimeCallArgCountRegister = r3;
|
||||
constexpr Register kWasmInstanceRegister = r10;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Static helper functions
|
||||
|
@ -28,18 +28,22 @@ namespace internal {
|
||||
namespace {
|
||||
|
||||
WasmInstanceObject* GetWasmInstanceOnStackTop(Isolate* isolate) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
const Address entry = Isolate::c_entry_fp(isolate->thread_local_top());
|
||||
Address pc =
|
||||
Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset);
|
||||
WasmInstanceObject* owning_instance = WasmInstanceObject::GetOwningInstance(
|
||||
isolate->wasm_engine()->code_manager()->LookupCode(pc));
|
||||
CHECK_NOT_NULL(owning_instance);
|
||||
return owning_instance;
|
||||
StackFrameIterator it(isolate, isolate->thread_local_top());
|
||||
// On top: C entry stub.
|
||||
DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
|
||||
it.Advance();
|
||||
// Next: the wasm (compiled or interpreted) frame.
|
||||
WasmInstanceObject* result = nullptr;
|
||||
if (it.frame()->is_wasm_compiled()) {
|
||||
result = WasmCompiledFrame::cast(it.frame())->wasm_instance();
|
||||
} else {
|
||||
DCHECK(it.frame()->is_wasm_interpreter_entry());
|
||||
result = WasmInterpreterEntryFrame::cast(it.frame())->wasm_instance();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO(titzer): rename to GetNativeContextFromWasmInstanceOnStackTop()
|
||||
Context* GetWasmContextOnStackTop(Isolate* isolate) {
|
||||
Context* GetNativeContextFromWasmInstanceOnStackTop(Isolate* isolate) {
|
||||
return GetWasmInstanceOnStackTop(isolate)
|
||||
->compiled_module()
|
||||
->native_context();
|
||||
@ -89,7 +93,7 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
|
||||
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
|
||||
static_cast<MessageTemplate::Template>(message_id));
|
||||
return isolate->Throw(*error_obj);
|
||||
@ -99,7 +103,7 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK_LE(0, args.length());
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
return isolate->StackOverflow();
|
||||
}
|
||||
|
||||
@ -114,7 +118,7 @@ RUNTIME_FUNCTION(Runtime_WasmThrowCreate) {
|
||||
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
DCHECK_EQ(2, args.length());
|
||||
Handle<Object> exception = isolate->factory()->NewWasmRuntimeError(
|
||||
static_cast<MessageTemplate::Template>(
|
||||
@ -141,7 +145,7 @@ RUNTIME_FUNCTION(Runtime_WasmThrow) {
|
||||
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
DCHECK_EQ(0, args.length());
|
||||
Handle<Object> exception(isolate->get_wasm_caught_exception(), isolate);
|
||||
CHECK(!exception.is_null());
|
||||
@ -153,7 +157,7 @@ RUNTIME_FUNCTION(Runtime_WasmGetExceptionRuntimeId) {
|
||||
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
Handle<Object> except_obj(isolate->get_wasm_caught_exception(), isolate);
|
||||
if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
|
||||
Handle<JSReceiver> exception(JSReceiver::cast(*except_obj));
|
||||
@ -174,7 +178,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionGetElement) {
|
||||
// TODO(kschimpf): Can this be replaced with equivalent TurboFan code/calls.
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
DCHECK_EQ(1, args.length());
|
||||
Handle<Object> except_obj(isolate->get_wasm_caught_exception(), isolate);
|
||||
if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
|
||||
@ -203,7 +207,7 @@ RUNTIME_FUNCTION(Runtime_WasmExceptionSetElement) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
Handle<Object> except_obj(isolate->get_wasm_caught_exception(), isolate);
|
||||
if (!except_obj.is_null() && except_obj->IsJSReceiver()) {
|
||||
Handle<JSReceiver> exception(JSReceiver::cast(*except_obj));
|
||||
@ -279,7 +283,7 @@ RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
|
||||
|
||||
// Set the current isolate's context.
|
||||
DCHECK_NULL(isolate->context());
|
||||
isolate->set_context(GetWasmContextOnStackTop(isolate));
|
||||
isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate));
|
||||
|
||||
// Check if this is a real stack overflow.
|
||||
StackLimitCheck check(isolate);
|
||||
|
@ -31,6 +31,7 @@ constexpr Register kJavaScriptCallCodeStartRegister = r4;
|
||||
constexpr Register kOffHeapTrampolineRegister = ip;
|
||||
constexpr Register kRuntimeCallFunctionRegister = r3;
|
||||
constexpr Register kRuntimeCallArgCountRegister = r2;
|
||||
constexpr Register kWasmInstanceRegister = r6;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Static helper functions
|
||||
|
@ -354,6 +354,7 @@ class LiftoffCompiler {
|
||||
DCHECK(instance_loc.IsRegister());
|
||||
DCHECK(!instance_loc.IsAnyRegister());
|
||||
Register instance_reg = Register::from_code(instance_loc.AsRegister());
|
||||
DCHECK_EQ(kWasmInstanceRegister, instance_reg);
|
||||
|
||||
// Parameter 0 is the instance parameter.
|
||||
uint32_t num_params =
|
||||
|
@ -750,6 +750,7 @@ Address CompileLazy(Isolate* isolate,
|
||||
DCHECK(!it.done());
|
||||
DCHECK(it.frame()->is_js_to_wasm() || it.frame()->is_wasm_compiled());
|
||||
Handle<Code> js_to_wasm_caller_code;
|
||||
Handle<WasmInstanceObject> caller_instance;
|
||||
const WasmCode* wasm_caller_code = nullptr;
|
||||
int32_t caller_ret_offset = -1;
|
||||
if (it.frame()->is_js_to_wasm()) {
|
||||
@ -757,6 +758,8 @@ Address CompileLazy(Isolate* isolate,
|
||||
// This wasn't actually an indirect call, but a JS->wasm call.
|
||||
indirectly_called = false;
|
||||
} else {
|
||||
caller_instance =
|
||||
handle(WasmCompiledFrame::cast(it.frame())->wasm_instance(), isolate);
|
||||
wasm_caller_code =
|
||||
isolate->wasm_engine()->code_manager()->LookupCode(it.frame()->pc());
|
||||
auto offset = it.frame()->pc() - wasm_caller_code->instruction_start();
|
||||
@ -799,9 +802,7 @@ Address CompileLazy(Isolate* isolate,
|
||||
// Update import and indirect function tables in the caller.
|
||||
//==========================================================================
|
||||
if (indirectly_called) {
|
||||
DCHECK_NOT_NULL(wasm_caller_code);
|
||||
Handle<WasmInstanceObject> caller_instance(
|
||||
WasmInstanceObject::GetOwningInstance(wasm_caller_code), isolate);
|
||||
DCHECK(!caller_instance.is_null());
|
||||
if (!caller_instance->has_managed_indirect_patcher()) {
|
||||
auto patcher = Managed<IndirectPatcher>::Allocate(isolate);
|
||||
caller_instance->set_managed_indirect_patcher(*patcher);
|
||||
|
@ -773,19 +773,6 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
|
||||
return instance;
|
||||
}
|
||||
|
||||
WasmInstanceObject* WasmInstanceObject::GetOwningInstance(
|
||||
const wasm::WasmCode* code) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object* weak_link = nullptr;
|
||||
DCHECK(code->kind() == wasm::WasmCode::kFunction ||
|
||||
code->kind() == wasm::WasmCode::kInterpreterStub);
|
||||
weak_link = code->native_module()->compiled_module()->weak_owning_instance();
|
||||
DCHECK(weak_link->IsWeakCell());
|
||||
WeakCell* cell = WeakCell::cast(weak_link);
|
||||
if (cell->cleared()) return nullptr;
|
||||
return WasmInstanceObject::cast(cell->value());
|
||||
}
|
||||
|
||||
void WasmInstanceObject::ValidateInstancesChainForTesting(
|
||||
Isolate* isolate, Handle<WasmModuleObject> module_obj, int instance_count) {
|
||||
CHECK_GE(instance_count, 0);
|
||||
|
@ -324,11 +324,6 @@ class WasmInstanceObject : public JSObject {
|
||||
|
||||
static Handle<WasmInstanceObject> New(Isolate*, Handle<WasmCompiledModule>);
|
||||
|
||||
// Assumed to be called with a code object associated to a wasm module
|
||||
// instance. Intended to be called from runtime functions. Returns nullptr on
|
||||
// failing to get owning instance.
|
||||
static WasmInstanceObject* GetOwningInstance(const wasm::WasmCode* code);
|
||||
|
||||
static void ValidateInstancesChainForTesting(
|
||||
Isolate* isolate, Handle<WasmModuleObject> module_obj,
|
||||
int instance_count);
|
||||
|
@ -30,6 +30,7 @@ constexpr Register kJavaScriptCallCodeStartRegister = rcx;
|
||||
constexpr Register kJavaScriptCallNewTargetRegister = rdx;
|
||||
constexpr Register kRuntimeCallFunctionRegister = rbx;
|
||||
constexpr Register kRuntimeCallArgCountRegister = rax;
|
||||
constexpr Register kWasmInstanceRegister = rsi;
|
||||
|
||||
// Default scratch register used by MacroAssembler (and other code that needs
|
||||
// a spare register). The register isn't callee save, and not used by the
|
||||
|
Loading…
Reference in New Issue
Block a user