[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:
Michael Starzinger 2018-04-16 08:36:06 -07:00 committed by Commit Bot
parent 3baf75f734
commit 120dfa48cf
34 changed files with 133 additions and 114 deletions

View File

@ -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

View File

@ -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) \

View File

@ -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);

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -2928,6 +2928,9 @@ void CodeGenerator::AssembleConstructFrame() {
}
} else {
__ StubPrologue(info()->GetOutputStackFrameType());
if (call_descriptor->IsWasmFunctionCall()) {
__ Push(kWasmInstanceRegister);
}
}
unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());

View File

@ -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;

View File

@ -3586,6 +3586,9 @@ void CodeGenerator::AssembleConstructFrame() {
}
} else {
__ StubPrologue(info()->GetOutputStackFrameType());
if (call_descriptor->IsWasmFunctionCall()) {
__ push(kWasmInstanceRegister);
}
}
}

View File

@ -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();
}

View File

@ -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.

View File

@ -3199,6 +3199,9 @@ void CodeGenerator::AssembleConstructFrame() {
}
} else {
__ StubPrologue(info()->GetOutputStackFrameType());
if (call_descriptor->IsWasmFunctionCall()) {
__ Push(kWasmInstanceRegister);
}
}
}

View File

@ -3453,6 +3453,9 @@ void CodeGenerator::AssembleConstructFrame() {
}
} else {
__ StubPrologue(info()->GetOutputStackFrameType());
if (call_descriptor->IsWasmFunctionCall()) {
__ Push(kWasmInstanceRegister);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -3120,6 +3120,9 @@ void CodeGenerator::AssembleConstructFrame() {
}
} else {
__ StubPrologue(info()->GetOutputStackFrameType());
if (call_descriptor->IsWasmFunctionCall()) {
__ pushq(kWasmInstanceRegister);
}
}
unwinding_info_writer_.MarkFrameConstructed(pc_base);

View File

@ -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.

View File

@ -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(); }

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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 =

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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