[wasm] Allow calling runtime stubs with stub linkage.
This allows WebAssembly runtime stubs implemented as {WasmCode} to be called with regular stub linkage. So far we have only been able to call such stubs with WebAssembly linkage. Also switch two more on-heap builtins over to WebAssembly runtime stubs. R=clemensh@chromium.org BUG=v8:7424 Change-Id: Ifa553b5908ee27a1be780c325a114449d7fe7001 Reviewed-on: https://chromium-review.googlesource.com/1100882 Reviewed-by: Clemens Hammacher <clemensh@chromium.org> Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#53734}
This commit is contained in:
parent
8e2e125791
commit
87fe40134a
@ -1192,6 +1192,8 @@ namespace internal {
|
||||
\
|
||||
/* Wasm */ \
|
||||
ASM(WasmCompileLazy) \
|
||||
TFC(WasmArgumentsAdaptor, ArgumentAdaptor, 1) \
|
||||
TFC(WasmCallJavaScript, CallTrampoline, 1) \
|
||||
TFS(WasmStackGuard) \
|
||||
TFS(ThrowWasmTrapUnreachable) \
|
||||
TFS(ThrowWasmTrapMemOutOfBounds) \
|
||||
|
@ -12,6 +12,52 @@ namespace internal {
|
||||
|
||||
typedef compiler::Node Node;
|
||||
|
||||
TF_BUILTIN(WasmArgumentsAdaptor, CodeStubAssembler) {
|
||||
TNode<Object> context =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kContext));
|
||||
TNode<Object> function =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kFunction));
|
||||
TNode<Object> new_target =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kNewTarget));
|
||||
TNode<Object> argc1 =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kActualArgumentsCount));
|
||||
TNode<Object> argc2 =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kExpectedArgumentsCount));
|
||||
TNode<Object> instance = UncheckedCast<Object>(
|
||||
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
|
||||
TNode<IntPtrT> roots = UncheckedCast<IntPtrT>(
|
||||
Load(MachineType::Pointer(), instance,
|
||||
IntPtrConstant(WasmInstanceObject::kRootsArrayAddressOffset -
|
||||
kHeapObjectTag)));
|
||||
TNode<Code> target = UncheckedCast<Code>(Load(
|
||||
MachineType::TaggedPointer(), roots,
|
||||
IntPtrConstant(Heap::roots_to_builtins_offset() +
|
||||
Builtins::kArgumentsAdaptorTrampoline * kPointerSize)));
|
||||
TailCallStub(ArgumentAdaptorDescriptor(isolate()), target, context, function,
|
||||
new_target, argc1, argc2);
|
||||
}
|
||||
|
||||
TF_BUILTIN(WasmCallJavaScript, CodeStubAssembler) {
|
||||
TNode<Object> context =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kContext));
|
||||
TNode<Object> function =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kFunction));
|
||||
TNode<Object> argc =
|
||||
UncheckedCast<Object>(Parameter(Descriptor::kActualArgumentsCount));
|
||||
TNode<Object> instance = UncheckedCast<Object>(
|
||||
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
|
||||
TNode<IntPtrT> roots = UncheckedCast<IntPtrT>(
|
||||
Load(MachineType::Pointer(), instance,
|
||||
IntPtrConstant(WasmInstanceObject::kRootsArrayAddressOffset -
|
||||
kHeapObjectTag)));
|
||||
TNode<Code> target = UncheckedCast<Code>(
|
||||
Load(MachineType::TaggedPointer(), roots,
|
||||
IntPtrConstant(Heap::roots_to_builtins_offset() +
|
||||
Builtins::kCall_ReceiverIsAny * kPointerSize)));
|
||||
TailCallStub(CallTrampolineDescriptor(isolate()), target, context, function,
|
||||
argc);
|
||||
}
|
||||
|
||||
TF_BUILTIN(WasmStackGuard, CodeStubAssembler) {
|
||||
TNode<Object> instance = UncheckedCast<Object>(
|
||||
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
|
||||
|
@ -614,7 +614,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
if (HasImmediateInput(instr, 0)) {
|
||||
Constant constant = i.ToConstant(instr->InputAt(0));
|
||||
Address wasm_code = static_cast<Address>(constant.ToInt32());
|
||||
if (info()->IsWasm()) {
|
||||
if (DetermineStubCallMode() == StubCallMode::kCallWasmRuntimeStub) {
|
||||
__ wasm_call(wasm_code, constant.rmode());
|
||||
} else {
|
||||
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
|
||||
|
@ -347,7 +347,8 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
|
||||
Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
|
||||
int stack_parameter_count, CallDescriptor::Flags flags,
|
||||
Operator::Properties properties, MachineType return_type,
|
||||
size_t return_count, Linkage::ContextSpecification context_spec) {
|
||||
size_t return_count, Linkage::ContextSpecification context_spec,
|
||||
StubCallMode stub_mode) {
|
||||
const int register_parameter_count = descriptor.GetRegisterParameterCount();
|
||||
const int js_parameter_count =
|
||||
register_parameter_count + stack_parameter_count;
|
||||
@ -387,21 +388,25 @@ CallDescriptor* Linkage::GetStubCallDescriptor(
|
||||
locations.AddParam(regloc(kContextRegister, MachineType::AnyTagged()));
|
||||
}
|
||||
|
||||
// The target for stub calls is a code object.
|
||||
MachineType target_type = MachineType::AnyTagged();
|
||||
LinkageLocation target_loc =
|
||||
LinkageLocation::ForAnyRegister(MachineType::AnyTagged());
|
||||
return new (zone) CallDescriptor( // --
|
||||
CallDescriptor::kCallCodeObject, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
locations.Build(), // location_sig
|
||||
stack_parameter_count, // stack_parameter_count
|
||||
properties, // properties
|
||||
kNoCalleeSaved, // callee-saved registers
|
||||
kNoCalleeSaved, // callee-saved fp
|
||||
CallDescriptor::kCanUseRoots | // flags
|
||||
flags, // flags
|
||||
// The target for stub calls depends on the requested mode.
|
||||
CallDescriptor::Kind kind = stub_mode == StubCallMode::kCallWasmRuntimeStub
|
||||
? CallDescriptor::kCallWasmFunction
|
||||
: CallDescriptor::kCallCodeObject;
|
||||
MachineType target_type = stub_mode == StubCallMode::kCallWasmRuntimeStub
|
||||
? MachineType::Pointer()
|
||||
: MachineType::AnyTagged();
|
||||
LinkageLocation target_loc = LinkageLocation::ForAnyRegister(target_type);
|
||||
return new (zone) CallDescriptor( // --
|
||||
kind, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
locations.Build(), // location_sig
|
||||
stack_parameter_count, // stack_parameter_count
|
||||
properties, // properties
|
||||
kNoCalleeSaved, // callee-saved registers
|
||||
kNoCalleeSaved, // callee-saved fp
|
||||
CallDescriptor::kCanUseRoots | // flags
|
||||
flags, // flags
|
||||
descriptor.DebugName(isolate), descriptor.allocatable_registers());
|
||||
}
|
||||
|
||||
|
@ -394,8 +394,8 @@ class V8_EXPORT_PRIVATE Linkage : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
int stack_parameter_count, CallDescriptor::Flags flags,
|
||||
Operator::Properties properties = Operator::kNoProperties,
|
||||
MachineType return_type = MachineType::AnyTagged(),
|
||||
size_t return_count = 1,
|
||||
ContextSpecification context_spec = kPassContext);
|
||||
size_t return_count = 1, ContextSpecification context_spec = kPassContext,
|
||||
StubCallMode stub_mode = StubCallMode::kCallOnHeapBuiltin);
|
||||
|
||||
static CallDescriptor* GetAllocateCallDescriptor(Isolate* isolate,
|
||||
Zone* zone);
|
||||
|
@ -4479,9 +4479,9 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
|
||||
pos, args);
|
||||
} else if (function->shared()->internal_formal_parameter_count() >= 0) {
|
||||
Callable callable = CodeFactory::ArgumentAdaptor(isolate_);
|
||||
int pos = 0;
|
||||
args[pos++] = jsgraph()->HeapConstant(callable.code());
|
||||
args[pos++] = mcgraph()->RelocatableIntPtrConstant(
|
||||
wasm::WasmCode::kWasmArgumentsAdaptor, RelocInfo::WASM_STUB_CALL);
|
||||
args[pos++] = callable_node; // target callable
|
||||
args[pos++] = undefined_node; // new target
|
||||
args[pos++] = mcgraph()->Int32Constant(wasm_count); // argument count
|
||||
@ -4497,16 +4497,19 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
args[pos++] = undefined_node;
|
||||
}
|
||||
|
||||
call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
isolate_, mcgraph()->zone(), ArgumentAdaptorDescriptor(isolate_),
|
||||
1 + wasm_count, CallDescriptor::kNoFlags, Operator::kNoProperties,
|
||||
MachineType::AnyTagged(), 1, Linkage::kPassContext,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
|
||||
// Convert wasm numbers to JS values.
|
||||
pos = AddArgumentNodes(args, pos, wasm_count, sig_);
|
||||
args[pos++] = function_context;
|
||||
args[pos++] = *effect_;
|
||||
args[pos++] = *control_;
|
||||
call = graph()->NewNode(
|
||||
mcgraph()->common()->Call(Linkage::GetStubCallDescriptor(
|
||||
isolate_, mcgraph()->zone(), callable.descriptor(),
|
||||
1 + wasm_count, CallDescriptor::kNoFlags)),
|
||||
pos, args);
|
||||
call = graph()->NewNode(mcgraph()->common()->Call(call_descriptor),
|
||||
pos, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4514,16 +4517,17 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
|
||||
// We cannot call the target directly, we have to use the Call builtin.
|
||||
if (!call) {
|
||||
int pos = 0;
|
||||
// We cannot call the target directly, we have to use the Call builtin.
|
||||
Callable callable = CodeFactory::Call(isolate_);
|
||||
args[pos++] = jsgraph()->HeapConstant(callable.code());
|
||||
args[pos++] = mcgraph()->RelocatableIntPtrConstant(
|
||||
wasm::WasmCode::kWasmCallJavaScript, RelocInfo::WASM_STUB_CALL);
|
||||
args[pos++] = callable_node;
|
||||
args[pos++] = mcgraph()->Int32Constant(wasm_count); // argument count
|
||||
args[pos++] = undefined_node; // receiver
|
||||
|
||||
call_descriptor = Linkage::GetStubCallDescriptor(
|
||||
isolate_, graph()->zone(), callable.descriptor(), wasm_count + 1,
|
||||
CallDescriptor::kNoFlags);
|
||||
isolate_, graph()->zone(), CallTrampolineDescriptor(isolate_),
|
||||
wasm_count + 1, CallDescriptor::kNoFlags, Operator::kNoProperties,
|
||||
MachineType::AnyTagged(), 1, Linkage::kPassContext,
|
||||
StubCallMode::kCallWasmRuntimeStub);
|
||||
|
||||
// Convert wasm numbers to JS values.
|
||||
pos = AddArgumentNodes(args, pos, wasm_count, sig_);
|
||||
|
@ -699,7 +699,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
if (HasImmediateInput(instr, 0)) {
|
||||
Constant constant = i.ToConstant(instr->InputAt(0));
|
||||
Address wasm_code = static_cast<Address>(constant.ToInt64());
|
||||
if (info()->IsWasm()) {
|
||||
if (DetermineStubCallMode() == StubCallMode::kCallWasmRuntimeStub) {
|
||||
__ near_call(wasm_code, constant.rmode());
|
||||
} else {
|
||||
if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) {
|
||||
@ -751,7 +751,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
if (HasImmediateInput(instr, 0)) {
|
||||
Constant constant = i.ToConstant(instr->InputAt(0));
|
||||
Address wasm_code = static_cast<Address>(constant.ToInt64());
|
||||
if (info()->IsWasm()) {
|
||||
if (DetermineStubCallMode() == StubCallMode::kCallWasmRuntimeStub) {
|
||||
__ near_jmp(wasm_code, constant.rmode());
|
||||
} else {
|
||||
__ Move(kScratchRegister, wasm_code, constant.rmode());
|
||||
|
@ -202,8 +202,6 @@ void WasmCode::Validate() const {
|
||||
// of {RelocInfo::CODE_TARGET} relocation entries altogether.
|
||||
int builtin_index = code->builtin_index();
|
||||
CHECK(builtin_index == Builtins::kAllocateHeapNumber ||
|
||||
builtin_index == Builtins::kArgumentsAdaptorTrampoline ||
|
||||
builtin_index == Builtins::kCall_ReceiverIsAny ||
|
||||
builtin_index == Builtins::kToNumber);
|
||||
break;
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ struct WasmModule;
|
||||
// elements of the list coincide with {compiler::TrapId}, order matters.
|
||||
#define WASM_RUNTIME_STUB_LIST(V, VTRAP) \
|
||||
FOREACH_WASM_TRAPREASON(VTRAP) \
|
||||
V(WasmArgumentsAdaptor) \
|
||||
V(WasmCallJavaScript) \
|
||||
V(WasmStackGuard) \
|
||||
V(DoubleToI)
|
||||
|
||||
|
@ -124,6 +124,8 @@ PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_size, uint32_t,
|
||||
kMemorySizeOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_mask, uint32_t,
|
||||
kMemoryMaskOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, roots_array_address, Address,
|
||||
kRootsArrayAddressOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, stack_limit_address, Address,
|
||||
kStackLimitAddressOffset)
|
||||
PRIMITIVE_ACCESSORS(WasmInstanceObject, imported_function_targets, Address*,
|
||||
|
@ -1327,6 +1327,8 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
|
||||
instance->set_centry_stub(*centry_stub);
|
||||
|
||||
instance->SetRawMemory(nullptr, 0);
|
||||
instance->set_roots_array_address(
|
||||
reinterpret_cast<Address>(isolate->heap()->roots_array_start()));
|
||||
instance->set_stack_limit_address(
|
||||
isolate->stack_guard()->address_of_jslimit());
|
||||
instance->set_globals_start(nullptr);
|
||||
|
@ -394,7 +394,8 @@ class WasmInstanceObject : public JSObject {
|
||||
DECL_PRIMITIVE_ACCESSORS(memory_start, byte*)
|
||||
DECL_PRIMITIVE_ACCESSORS(memory_size, uint32_t)
|
||||
DECL_PRIMITIVE_ACCESSORS(memory_mask, uint32_t)
|
||||
DECL_PRIMITIVE_ACCESSORS(stack_limit_address, Address);
|
||||
DECL_PRIMITIVE_ACCESSORS(roots_array_address, Address)
|
||||
DECL_PRIMITIVE_ACCESSORS(stack_limit_address, Address)
|
||||
DECL_PRIMITIVE_ACCESSORS(imported_function_targets, Address*)
|
||||
DECL_PRIMITIVE_ACCESSORS(globals_start, byte*)
|
||||
DECL_PRIMITIVE_ACCESSORS(imported_mutable_globals, Address*)
|
||||
@ -429,6 +430,7 @@ class WasmInstanceObject : public JSObject {
|
||||
V(kMemoryStartOffset, kPointerSize) /* untagged */ \
|
||||
V(kMemorySizeOffset, kUInt32Size) /* untagged */ \
|
||||
V(kMemoryMaskOffset, kUInt32Size) /* untagged */ \
|
||||
V(kRootsArrayAddressOffset, kPointerSize) /* untagged */ \
|
||||
V(kStackLimitAddressOffset, kPointerSize) /* untagged */ \
|
||||
V(kImportedFunctionTargetsOffset, kPointerSize) /* untagged */ \
|
||||
V(kGlobalsStartOffset, kPointerSize) /* untagged */ \
|
||||
|
Loading…
Reference in New Issue
Block a user