[wasm-c-api] New call descriptor and stackframe kind
So far, calls to Wasm C/C++ API functions reused the call descriptors of WasmImportWrappers, and the stack frame type of regular Wasm functions. This CL cleans that up by introducing separate implementations for both. No change in functionality or performance is expected. Change-Id: I79301fa81da52283cc776ddf19d4712372f3a58b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1632235 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#61914}
This commit is contained in:
parent
f6e3993825
commit
65f3861e3b
@ -2402,7 +2402,8 @@ void TurboAssembler::EnterFrame(StackFrame::Type type) {
|
||||
// sp[1] : type
|
||||
// sp[0] : for alignment
|
||||
} else if (type == StackFrame::WASM_COMPILED ||
|
||||
type == StackFrame::WASM_COMPILE_LAZY) {
|
||||
type == StackFrame::WASM_COMPILE_LAZY ||
|
||||
type == StackFrame::WASM_EXIT) {
|
||||
Register type_reg = temps.AcquireX();
|
||||
Mov(type_reg, StackFrame::TypeToMarker(type));
|
||||
Push(lr, fp);
|
||||
|
@ -168,8 +168,9 @@ StackFrame::Type OptimizedCompilationInfo::GetOutputStackFrameType() const {
|
||||
case Code::BUILTIN:
|
||||
return StackFrame::STUB;
|
||||
case Code::WASM_FUNCTION:
|
||||
case Code::WASM_TO_CAPI_FUNCTION:
|
||||
return StackFrame::WASM_COMPILED;
|
||||
case Code::WASM_TO_CAPI_FUNCTION:
|
||||
return StackFrame::WASM_EXIT;
|
||||
case Code::JS_TO_WASM_FUNCTION:
|
||||
return StackFrame::JS_TO_WASM;
|
||||
case Code::WASM_TO_JS_FUNCTION:
|
||||
|
@ -833,12 +833,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
break;
|
||||
case kArchCallCFunction: {
|
||||
int const num_parameters = MiscField::decode(instr->opcode());
|
||||
if (linkage()->GetIncomingDescriptor()->IsWasmCapiFunction()) {
|
||||
// Put the return address in a stack slot.
|
||||
if (linkage()->GetIncomingDescriptor()->kind() ==
|
||||
CallDescriptor::kCallWasmImportWrapper) {
|
||||
// WasmCapiFunctionWrappers, which are reusing the WasmImportWrapper
|
||||
// call descriptor, also need access to the PC.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
__ str(pc, MemOperand(fp, WasmExitFrameConstants::kCallingPCOffset));
|
||||
}
|
||||
if (instr->InputAt(0)->IsImmediate()) {
|
||||
@ -3008,7 +3004,8 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ Push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper()) {
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// WASM import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
@ -3018,11 +3015,12 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ ldr(kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Push(kWasmInstanceRegister);
|
||||
// Reserve PC slot space for WasmCapiFunction wrappers.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());
|
||||
}
|
||||
|
@ -744,14 +744,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
break;
|
||||
case kArchCallCFunction: {
|
||||
int const num_parameters = MiscField::decode(instr->opcode());
|
||||
Label return_location;
|
||||
if (linkage()->GetIncomingDescriptor()->IsWasmCapiFunction()) {
|
||||
// Put the return address in a stack slot.
|
||||
Register scratch = x8;
|
||||
Label return_location;
|
||||
if (linkage()->GetIncomingDescriptor()->kind() ==
|
||||
CallDescriptor::kCallWasmImportWrapper) {
|
||||
// WasmCapiFunctionWrappers, which are reusing the WasmImportWrapper
|
||||
// call descriptor, need access to the calling PC.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
__ Adr(scratch, &return_location);
|
||||
__ Str(scratch,
|
||||
MemOperand(fp, WasmExitFrameConstants::kCallingPCOffset));
|
||||
@ -2559,7 +2555,8 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ Str(kWasmInstanceRegister,
|
||||
MemOperand(fp, WasmCompiledFrameConstants::kWasmInstanceOffset));
|
||||
} break;
|
||||
case CallDescriptor::kCallWasmImportWrapper: {
|
||||
case CallDescriptor::kCallWasmImportWrapper:
|
||||
case CallDescriptor::kCallWasmCapiFunction: {
|
||||
UseScratchRegisterScope temps(tasm());
|
||||
__ LoadTaggedPointerField(
|
||||
kJSFunctionRegister,
|
||||
@ -2567,8 +2564,11 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ LoadTaggedPointerField(
|
||||
kWasmInstanceRegister,
|
||||
FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ Claim(required_slots +
|
||||
3); // Claim extra slots for marker + instance + pc.
|
||||
int extra_slots =
|
||||
call_descriptor->kind() == CallDescriptor::kCallWasmImportWrapper
|
||||
? 2 // Import wrapper: marker + instance.
|
||||
: 3; // C-API function: marker + instance + PC.
|
||||
__ Claim(required_slots + extra_slots);
|
||||
Register scratch = temps.AcquireX();
|
||||
__ Mov(scratch,
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
|
@ -814,11 +814,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchCallCFunction: {
|
||||
int const num_parameters = MiscField::decode(instr->opcode());
|
||||
Label return_location;
|
||||
if (linkage()->GetIncomingDescriptor()->kind() ==
|
||||
CallDescriptor::kCallWasmImportWrapper) {
|
||||
// WasmCapiFunctionWrappers, which are reusing the WasmImportWrapper
|
||||
// call descriptor, also need access to the PC.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
if (linkage()->GetIncomingDescriptor()->IsWasmCapiFunction()) {
|
||||
// Put the return address in a stack slot.
|
||||
Register scratch = eax;
|
||||
__ push(scratch);
|
||||
__ PushPC();
|
||||
@ -4236,7 +4233,8 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ push(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper()) {
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// WASM import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
@ -4248,12 +4246,13 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
Operand(kWasmInstanceRegister,
|
||||
Tuple2::kValue1Offset - kHeapObjectTag));
|
||||
__ push(kWasmInstanceRegister);
|
||||
// Reserve PC slot space for WasmCapiFunction wrappers.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int required_slots = frame()->GetTotalFrameSlotCount() -
|
||||
call_descriptor->CalculateFixedFrameSize();
|
||||
|
@ -907,6 +907,7 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
|
||||
? g.UseFixed(callee, kJavaScriptCallCodeStartRegister)
|
||||
: g.UseRegister(callee));
|
||||
break;
|
||||
case CallDescriptor::kCallWasmCapiFunction:
|
||||
case CallDescriptor::kCallWasmFunction:
|
||||
case CallDescriptor::kCallWasmImportWrapper:
|
||||
buffer->instruction_args.push_back(
|
||||
@ -2631,6 +2632,7 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
|
||||
case CallDescriptor::kCallJSFunction:
|
||||
opcode = kArchCallJSFunction | MiscField::encode(flags);
|
||||
break;
|
||||
case CallDescriptor::kCallWasmCapiFunction:
|
||||
case CallDescriptor::kCallWasmFunction:
|
||||
case CallDescriptor::kCallWasmImportWrapper:
|
||||
opcode = kArchCallWasmFunction | MiscField::encode(flags);
|
||||
|
@ -902,11 +902,8 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArchCallCFunction: {
|
||||
int const num_parameters = MiscField::decode(instr->opcode());
|
||||
Label return_location;
|
||||
if (linkage()->GetIncomingDescriptor()->kind() ==
|
||||
CallDescriptor::kCallWasmImportWrapper) {
|
||||
// WasmCapiFunctionWrappers, which are reusing the WasmImportWrapper
|
||||
// call descriptor, also need access to the PC.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
if (linkage()->GetIncomingDescriptor()->IsWasmCapiFunction()) {
|
||||
// Put the return address in a stack slot.
|
||||
__ leaq(kScratchRegister, Operand(&return_location, 0));
|
||||
__ movq(MemOperand(rbp, WasmExitFrameConstants::kCallingPCOffset),
|
||||
kScratchRegister);
|
||||
@ -3746,7 +3743,8 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
__ StubPrologue(info()->GetOutputStackFrameType());
|
||||
if (call_descriptor->IsWasmFunctionCall()) {
|
||||
__ pushq(kWasmInstanceRegister);
|
||||
} else if (call_descriptor->IsWasmImportWrapper()) {
|
||||
} else if (call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
// WASM import wrappers are passed a tuple in the place of the instance.
|
||||
// Unpack the tuple into the instance and the target callable.
|
||||
// This must be done here in the codegen because it cannot be expressed
|
||||
@ -3758,11 +3756,12 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
kWasmInstanceRegister,
|
||||
FieldOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
|
||||
__ pushq(kWasmInstanceRegister);
|
||||
// Reserve PC slot space for WasmCapiFunction wrappers.
|
||||
// TODO(jkummerow): Separate the call descriptors for clarity.
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
// Reserve space for saving the PC later.
|
||||
__ AllocateStackSpace(kSystemPointerSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unwinding_info_writer_.MarkFrameConstructed(pc_base);
|
||||
}
|
||||
|
@ -37,6 +37,9 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k) {
|
||||
case CallDescriptor::kCallAddress:
|
||||
os << "Addr";
|
||||
break;
|
||||
case CallDescriptor::kCallWasmCapiFunction:
|
||||
os << "WasmExit";
|
||||
break;
|
||||
case CallDescriptor::kCallWasmFunction:
|
||||
os << "WasmFunction";
|
||||
break;
|
||||
@ -147,11 +150,9 @@ int CallDescriptor::CalculateFixedFrameSize() const {
|
||||
case kCallBuiltinPointer:
|
||||
return TypedFrameConstants::kFixedSlotCount;
|
||||
case kCallWasmFunction:
|
||||
return WasmCompiledFrameConstants::kFixedSlotCount;
|
||||
case kCallWasmImportWrapper:
|
||||
// TODO(jkummerow): Introduce a separate "wasm-to-capi" frame type,
|
||||
// and let other CallWasmImportWrapper frames go back to having the
|
||||
// same size as CallWasmFunction frames.
|
||||
return WasmCompiledFrameConstants::kFixedSlotCount;
|
||||
case kCallWasmCapiFunction:
|
||||
return WasmExitFrameConstants::kFixedSlotCount;
|
||||
}
|
||||
UNREACHABLE();
|
||||
|
@ -175,6 +175,7 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
kCallCodeObject, // target is a Code object
|
||||
kCallJSFunction, // target is a JSFunction object
|
||||
kCallAddress, // target is a machine pointer
|
||||
kCallWasmCapiFunction, // target is a Wasm C API function
|
||||
kCallWasmFunction, // target is a wasm function
|
||||
kCallWasmImportWrapper, // target is a wasm import wrapper
|
||||
kCallBuiltinPointer, // target is a builtin pointer
|
||||
@ -236,6 +237,9 @@ class V8_EXPORT_PRIVATE CallDescriptor final
|
||||
// Returns {true} if this descriptor is a call to a WebAssembly function.
|
||||
bool IsWasmImportWrapper() const { return kind_ == kCallWasmImportWrapper; }
|
||||
|
||||
// Returns {true} if this descriptor is a call to a Wasm C API function.
|
||||
bool IsWasmCapiFunction() const { return kind_ == kCallWasmCapiFunction; }
|
||||
|
||||
bool RequiresFrameAsIncoming() const {
|
||||
return IsCFunctionCall() || IsJSFunctionCall() || IsWasmFunctionCall();
|
||||
}
|
||||
|
@ -6224,7 +6224,7 @@ wasm::WasmCode* CompileWasmImportCallWrapper(wasm::WasmEngine* wasm_engine,
|
||||
// Schedule and compile to machine code.
|
||||
CallDescriptor* incoming =
|
||||
GetWasmCallDescriptor(&zone, sig, WasmGraphBuilder::kNoRetpoline,
|
||||
WasmGraphBuilder::kExtraCallableParam);
|
||||
WasmCallKind::kWasmImportWrapper);
|
||||
if (machine.Is32()) {
|
||||
incoming = GetI32WasmCallDescriptor(&zone, incoming);
|
||||
}
|
||||
@ -6279,7 +6279,7 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine,
|
||||
// Run the compiler pipeline to generate machine code.
|
||||
CallDescriptor* call_descriptor =
|
||||
GetWasmCallDescriptor(&zone, sig, WasmGraphBuilder::kNoRetpoline,
|
||||
WasmGraphBuilder::kExtraCallableParam);
|
||||
WasmCallKind::kWasmCapiFunction);
|
||||
if (mcgraph->machine()->Is32()) {
|
||||
call_descriptor = GetI32WasmCallDescriptor(&zone, call_descriptor);
|
||||
}
|
||||
@ -6559,10 +6559,11 @@ class LinkageLocationAllocator {
|
||||
// General code uses the above configuration data.
|
||||
CallDescriptor* GetWasmCallDescriptor(
|
||||
Zone* zone, wasm::FunctionSig* fsig,
|
||||
WasmGraphBuilder::UseRetpoline use_retpoline,
|
||||
WasmGraphBuilder::ExtraCallableParam extra_callable_param) {
|
||||
WasmGraphBuilder::UseRetpoline use_retpoline, WasmCallKind call_kind) {
|
||||
// The extra here is to accomodate the instance object as first parameter
|
||||
// and, when specified, the additional callable.
|
||||
bool extra_callable_param =
|
||||
call_kind == kWasmImportWrapper || call_kind == kWasmCapiFunction;
|
||||
int extra_params = extra_callable_param ? 2 : 1;
|
||||
LocationSignature::Builder locations(zone, fsig->return_count(),
|
||||
fsig->parameter_count() + extra_params);
|
||||
@ -6627,14 +6628,20 @@ CallDescriptor* GetWasmCallDescriptor(
|
||||
MachineType target_type = MachineType::Pointer();
|
||||
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
|
||||
|
||||
CallDescriptor::Kind kind = extra_callable_param
|
||||
? CallDescriptor::kCallWasmImportWrapper
|
||||
: CallDescriptor::kCallWasmFunction;
|
||||
CallDescriptor::Kind descriptor_kind;
|
||||
if (call_kind == kWasmFunction) {
|
||||
descriptor_kind = CallDescriptor::kCallWasmFunction;
|
||||
} else if (call_kind == kWasmImportWrapper) {
|
||||
descriptor_kind = CallDescriptor::kCallWasmImportWrapper;
|
||||
} else {
|
||||
DCHECK_EQ(call_kind, kWasmCapiFunction);
|
||||
descriptor_kind = CallDescriptor::kCallWasmCapiFunction;
|
||||
}
|
||||
|
||||
CallDescriptor::Flags flags =
|
||||
use_retpoline ? CallDescriptor::kRetpoline : CallDescriptor::kNoFlags;
|
||||
return new (zone) CallDescriptor( // --
|
||||
kind, // kind
|
||||
descriptor_kind, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
locations.Build(), // location_sig
|
||||
|
@ -164,10 +164,6 @@ class WasmGraphBuilder {
|
||||
kRetpoline = true,
|
||||
kNoRetpoline = false
|
||||
};
|
||||
enum ExtraCallableParam : bool { // --
|
||||
kExtraCallableParam = true,
|
||||
kNoExtraCallableParam = false
|
||||
};
|
||||
|
||||
V8_EXPORT_PRIVATE WasmGraphBuilder(
|
||||
wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
|
||||
@ -610,12 +606,13 @@ class WasmGraphBuilder {
|
||||
TrapId GetTrapIdForTrap(wasm::TrapReason reason);
|
||||
};
|
||||
|
||||
enum WasmCallKind { kWasmFunction, kWasmImportWrapper, kWasmCapiFunction };
|
||||
|
||||
V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor(
|
||||
Zone* zone, wasm::FunctionSig* signature,
|
||||
WasmGraphBuilder::UseRetpoline use_retpoline =
|
||||
WasmGraphBuilder::kNoRetpoline,
|
||||
WasmGraphBuilder::ExtraCallableParam callable_param =
|
||||
WasmGraphBuilder::kNoExtraCallableParam);
|
||||
WasmCallKind kind = kWasmFunction);
|
||||
|
||||
V8_EXPORT_PRIVATE CallDescriptor* GetI32WasmCallDescriptor(
|
||||
Zone* zone, CallDescriptor* call_descriptor);
|
||||
|
@ -210,13 +210,13 @@ class TypedFrameConstants : public CommonFrameConstants {
|
||||
(TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kSystemPointerSize)
|
||||
#define TYPED_FRAME_SIZE(count) \
|
||||
(TypedFrameConstants::kFixedFrameSize + (count)*kSystemPointerSize)
|
||||
#define TYPED_FRAME_SIZE_FROM_SP(count) \
|
||||
#define TYPED_FRAME_SIZE_FROM_FP(count) \
|
||||
(TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kSystemPointerSize)
|
||||
#define DEFINE_TYPED_FRAME_SIZES(count) \
|
||||
static constexpr int kFixedFrameSize = TYPED_FRAME_SIZE(count); \
|
||||
static constexpr int kFixedSlotCount = kFixedFrameSize / kSystemPointerSize; \
|
||||
static constexpr int kFixedFrameSizeFromFp = \
|
||||
TYPED_FRAME_SIZE_FROM_SP(count); \
|
||||
TYPED_FRAME_SIZE_FROM_FP(count); \
|
||||
static constexpr int kFixedSlotCountFromFp = \
|
||||
kFixedFrameSizeFromFp / kSystemPointerSize
|
||||
|
||||
|
@ -223,6 +223,9 @@ inline BuiltinFrame::BuiltinFrame(StackFrameIteratorBase* iterator)
|
||||
inline WasmCompiledFrame::WasmCompiledFrame(StackFrameIteratorBase* iterator)
|
||||
: StandardFrame(iterator) {}
|
||||
|
||||
inline WasmExitFrame::WasmExitFrame(StackFrameIteratorBase* iterator)
|
||||
: WasmCompiledFrame(iterator) {}
|
||||
|
||||
inline WasmInterpreterEntryFrame::WasmInterpreterEntryFrame(
|
||||
StackFrameIteratorBase* iterator)
|
||||
: StandardFrame(iterator) {}
|
||||
|
@ -163,16 +163,7 @@ bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
|
||||
if (!js_frame->function().IsJSFunction()) return false;
|
||||
return js_frame->function().shared().IsSubjectToDebugging();
|
||||
}
|
||||
// Apart from JavaScript frames, only Wasm frames are valid, with the
|
||||
// exception of Wasm-to-Capi frames.
|
||||
// TODO(jkummerow): Give Wasm-to-Capi frames their own marker.
|
||||
if (frame->is_wasm_compiled()) {
|
||||
wasm::WasmCodeRefScope scope;
|
||||
if (static_cast<WasmCompiledFrame*>(frame)->wasm_code()->kind() ==
|
||||
wasm::WasmCode::kWasmToCapiWrapper) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Apart from JavaScript frames, only Wasm frames are valid.
|
||||
return frame->is_wasm();
|
||||
}
|
||||
|
||||
@ -520,8 +511,9 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
|
||||
if (wasm_code != nullptr) {
|
||||
switch (wasm_code->kind()) {
|
||||
case wasm::WasmCode::kFunction:
|
||||
case wasm::WasmCode::kWasmToCapiWrapper:
|
||||
return WASM_COMPILED;
|
||||
case wasm::WasmCode::kWasmToCapiWrapper:
|
||||
return WASM_EXIT;
|
||||
case wasm::WasmCode::kWasmToJsWrapper:
|
||||
return WASM_TO_JS;
|
||||
case wasm::WasmCode::kRuntimeStub:
|
||||
@ -593,6 +585,7 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
|
||||
case WASM_TO_JS:
|
||||
case WASM_COMPILED:
|
||||
case WASM_COMPILE_LAZY:
|
||||
case WASM_EXIT:
|
||||
return candidate;
|
||||
case JS_TO_WASM:
|
||||
case OPTIMIZED:
|
||||
@ -675,15 +668,9 @@ Address ExitFrame::GetCallerStackPointer() const {
|
||||
|
||||
StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
|
||||
if (fp == 0) return NONE;
|
||||
Address sp = ComputeStackPointer(fp);
|
||||
StackFrame::Type type = ComputeFrameType(fp);
|
||||
if (type == StackFrame::WASM_COMPILED) {
|
||||
// {sp} is only needed for finding the PC slot, the rest is handled
|
||||
// via safepoint.
|
||||
sp = fp + WasmExitFrameConstants::kWasmInstanceOffset;
|
||||
DCHECK_EQ(sp - 1 * kPCOnStackSize,
|
||||
fp + WasmExitFrameConstants::kCallingPCOffset);
|
||||
}
|
||||
Address sp = (type == WASM_EXIT) ? WasmExitFrame::ComputeStackPointer(fp)
|
||||
: ExitFrame::ComputeStackPointer(fp);
|
||||
FillState(fp, sp, state);
|
||||
DCHECK_NE(*state->pc_address, kNullAddress);
|
||||
return type;
|
||||
@ -703,7 +690,7 @@ StackFrame::Type ExitFrame::ComputeFrameType(Address fp) {
|
||||
|
||||
StackFrame::Type frame_type = static_cast<StackFrame::Type>(marker_int >> 1);
|
||||
if (frame_type == EXIT || frame_type == BUILTIN_EXIT ||
|
||||
frame_type == WASM_COMPILED) {
|
||||
frame_type == WASM_EXIT) {
|
||||
return frame_type;
|
||||
}
|
||||
|
||||
@ -716,6 +703,15 @@ Address ExitFrame::ComputeStackPointer(Address fp) {
|
||||
return Memory<Address>(fp + ExitFrameConstants::kSPOffset);
|
||||
}
|
||||
|
||||
Address WasmExitFrame::ComputeStackPointer(Address fp) {
|
||||
// For WASM_EXIT frames, {sp} is only needed for finding the PC slot,
|
||||
// everything else is handled via safepoint information.
|
||||
Address sp = fp + WasmExitFrameConstants::kWasmInstanceOffset;
|
||||
DCHECK_EQ(sp - 1 * kPCOnStackSize,
|
||||
fp + WasmExitFrameConstants::kCallingPCOffset);
|
||||
return sp;
|
||||
}
|
||||
|
||||
void ExitFrame::FillState(Address fp, Address sp, State* state) {
|
||||
state->sp = sp;
|
||||
state->fp = fp;
|
||||
@ -938,6 +934,14 @@ void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
|
||||
case WASM_COMPILE_LAZY:
|
||||
frame_header_size = WasmCompiledFrameConstants::kFixedFrameSizeFromFp;
|
||||
break;
|
||||
case WASM_EXIT:
|
||||
// The last value in the frame header is the calling PC, which should
|
||||
// not be visited.
|
||||
static_assert(WasmExitFrameConstants::kFixedSlotCountFromFp ==
|
||||
WasmCompiledFrameConstants::kFixedSlotCountFromFp + 1,
|
||||
"WasmExitFrame has one slot more than WasmCompiledFrame");
|
||||
frame_header_size = WasmCompiledFrameConstants::kFixedFrameSizeFromFp;
|
||||
break;
|
||||
case OPTIMIZED:
|
||||
case INTERPRETED:
|
||||
case BUILTIN:
|
||||
|
@ -70,6 +70,7 @@ class StackHandler {
|
||||
V(JS_TO_WASM, JsToWasmFrame) \
|
||||
V(WASM_INTERPRETER_ENTRY, WasmInterpreterEntryFrame) \
|
||||
V(C_WASM_ENTRY, CWasmEntryFrame) \
|
||||
V(WASM_EXIT, WasmExitFrame) \
|
||||
V(WASM_COMPILE_LAZY, WasmCompileLazyFrame) \
|
||||
V(INTERPRETED, InterpretedFrame) \
|
||||
V(STUB, StubFrame) \
|
||||
@ -171,6 +172,7 @@ class StackFrame {
|
||||
bool is_optimized() const { return type() == OPTIMIZED; }
|
||||
bool is_interpreted() const { return type() == INTERPRETED; }
|
||||
bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
|
||||
bool is_wasm_exit() const { return type() == WASM_EXIT; }
|
||||
bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
|
||||
bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
|
||||
bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
|
||||
@ -925,7 +927,7 @@ class BuiltinFrame final : public JavaScriptFrame {
|
||||
friend class StackFrameIteratorBase;
|
||||
};
|
||||
|
||||
class WasmCompiledFrame final : public StandardFrame {
|
||||
class WasmCompiledFrame : public StandardFrame {
|
||||
public:
|
||||
Type type() const override { return WASM_COMPILED; }
|
||||
|
||||
@ -968,6 +970,18 @@ class WasmCompiledFrame final : public StandardFrame {
|
||||
WasmModuleObject module_object() const;
|
||||
};
|
||||
|
||||
class WasmExitFrame : public WasmCompiledFrame {
|
||||
public:
|
||||
Type type() const override { return WASM_EXIT; }
|
||||
static Address ComputeStackPointer(Address fp);
|
||||
|
||||
protected:
|
||||
inline explicit WasmExitFrame(StackFrameIteratorBase* iterator);
|
||||
|
||||
private:
|
||||
friend class StackFrameIteratorBase;
|
||||
};
|
||||
|
||||
class WasmInterpreterEntryFrame final : public StandardFrame {
|
||||
public:
|
||||
Type type() const override { return WASM_INTERPRETER_ENTRY; }
|
||||
|
@ -425,6 +425,7 @@ FRAME_MARKERS = (
|
||||
"JS_TO_WASM",
|
||||
"WASM_INTERPRETER_ENTRY",
|
||||
"C_WASM_ENTRY",
|
||||
"WASM_EXIT",
|
||||
"WASM_COMPILE_LAZY",
|
||||
"INTERPRETED",
|
||||
"STUB",
|
||||
|
Loading…
Reference in New Issue
Block a user