[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:
Michael Starzinger 2018-06-14 15:28:18 +02:00 committed by Commit Bot
parent 8e2e125791
commit 87fe40134a
12 changed files with 99 additions and 36 deletions

View File

@ -1192,6 +1192,8 @@ namespace internal {
\
/* Wasm */ \
ASM(WasmCompileLazy) \
TFC(WasmArgumentsAdaptor, ArgumentAdaptor, 1) \
TFC(WasmCallJavaScript, CallTrampoline, 1) \
TFS(WasmStackGuard) \
TFS(ThrowWasmTrapUnreachable) \
TFS(ThrowWasmTrapMemOutOfBounds) \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */ \