Commit 928e28cd authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Use runtime stubs for coercions in wrappers.

This makes sure we use WebAssembly runtime stubs when performing value
coercions in wrapper code that is compiled into {WasmCode}. It hence
removes the last {RelocInfo::CODE_TARGET} references in {WasmCode}.

R=clemensh@chromium.org
BUG=v8:7424

Change-Id: Ic96e541abe98f90796a6506b09ff99557743b6f7
Reviewed-on: https://chromium-review.googlesource.com/1104462
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53846}
parent 78b5b32f
......@@ -1198,8 +1198,10 @@ namespace internal {
\
/* Wasm */ \
ASM(WasmCompileLazy) \
TFC(WasmAllocateHeapNumber, AllocateHeapNumber, 1) \
TFC(WasmArgumentsAdaptor, ArgumentAdaptor, 1) \
TFC(WasmCallJavaScript, CallTrampoline, 1) \
TFC(WasmToNumber, TypeConversion, 1) \
TFS(WasmStackGuard) \
TFS(ThrowWasmTrapUnreachable) \
TFS(ThrowWasmTrapMemOutOfBounds) \
......
......@@ -10,53 +10,63 @@
namespace v8 {
namespace internal {
typedef compiler::Node Node;
class WasmBuiltinsAssembler : public CodeStubAssembler {
public:
explicit WasmBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
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)));
protected:
TNode<Object> UncheckedParameter(int index) {
return UncheckedCast<Object>(Parameter(index));
}
TNode<Code> LoadBuiltinFromFrame(Builtins::Name id) {
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() + id * kPointerSize)));
return target;
}
};
TF_BUILTIN(WasmAllocateHeapNumber, WasmBuiltinsAssembler) {
TNode<Object> context = UncheckedParameter(Descriptor::kContext);
TNode<Code> target = LoadBuiltinFromFrame(Builtins::kAllocateHeapNumber);
TailCallStub(AllocateHeapNumberDescriptor(), target, context);
}
TF_BUILTIN(WasmArgumentsAdaptor, WasmBuiltinsAssembler) {
TNode<Object> context = UncheckedParameter(Descriptor::kContext);
TNode<Object> function = UncheckedParameter(Descriptor::kFunction);
TNode<Object> new_target = UncheckedParameter(Descriptor::kNewTarget);
TNode<Object> argc1 = UncheckedParameter(Descriptor::kActualArgumentsCount);
TNode<Object> argc2 = UncheckedParameter(Descriptor::kExpectedArgumentsCount);
TNode<Code> target =
LoadBuiltinFromFrame(Builtins::kArgumentsAdaptorTrampoline);
TailCallStub(ArgumentAdaptorDescriptor{}, 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)));
TF_BUILTIN(WasmCallJavaScript, WasmBuiltinsAssembler) {
TNode<Object> context = UncheckedParameter(Descriptor::kContext);
TNode<Object> function = UncheckedParameter(Descriptor::kFunction);
TNode<Object> argc = UncheckedParameter(Descriptor::kActualArgumentsCount);
TNode<Code> target = LoadBuiltinFromFrame(Builtins::kCall_ReceiverIsAny);
TailCallStub(CallTrampolineDescriptor{}, target, context, function, argc);
}
TF_BUILTIN(WasmToNumber, WasmBuiltinsAssembler) {
TNode<Object> context = UncheckedParameter(Descriptor::kContext);
TNode<Object> argument = UncheckedParameter(Descriptor::kArgument);
TNode<Code> target = LoadBuiltinFromFrame(Builtins::kToNumber);
TailCallStub(TypeConversionDescriptor(), target, context, argument);
}
TF_BUILTIN(WasmStackGuard, CodeStubAssembler) {
TNode<Object> instance = UncheckedCast<Object>(
LoadFromParentFrame(WasmCompiledFrameConstants::kWasmInstanceOffset));
......
......@@ -4007,21 +4007,27 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
public:
WasmWrapperGraphBuilder(Zone* zone, wasm::ModuleEnv* env, JSGraph* jsgraph,
wasm::FunctionSig* sig,
compiler::SourcePositionTable* spt)
compiler::SourcePositionTable* spt,
StubCallMode stub_mode)
: WasmGraphBuilder(env, zone, jsgraph, sig, spt),
isolate_(jsgraph->isolate()),
jsgraph_(jsgraph) {}
jsgraph_(jsgraph),
stub_mode_(stub_mode) {}
Node* BuildAllocateHeapNumberWithValue(Node* value, Node* control) {
MachineOperatorBuilder* machine = mcgraph()->machine();
CommonOperatorBuilder* common = mcgraph()->common();
Callable callable =
Builtins::CallableFor(isolate_, Builtins::kAllocateHeapNumber);
Node* target = jsgraph()->HeapConstant(callable.code());
Node* target = (stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
? mcgraph()->RelocatableIntPtrConstant(
wasm::WasmCode::kWasmAllocateHeapNumber,
RelocInfo::WASM_STUB_CALL)
: jsgraph()->HeapConstant(
BUILTIN_CODE(isolate_, AllocateHeapNumber));
if (!allocate_heap_number_operator_.is_set()) {
auto call_descriptor = Linkage::GetStubCallDescriptor(
mcgraph()->zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags,
Operator::kNoThrow, MachineType::AnyTagged(), 1, Linkage::kNoContext);
mcgraph()->zone(), AllocateHeapNumberDescriptor(), 0,
CallDescriptor::kNoFlags, Operator::kNoThrow,
MachineType::AnyTagged(), 1, Linkage::kNoContext, stub_mode_);
allocate_heap_number_operator_.set(common->Call(call_descriptor));
}
Node* heap_number = graph()->NewNode(allocate_heap_number_operator_.get(),
......@@ -4180,11 +4186,15 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
}
Node* BuildJavaScriptToNumber(Node* node, Node* js_context) {
Callable callable = Builtins::CallableFor(isolate_, Builtins::kToNumber);
auto call_descriptor = Linkage::GetStubCallDescriptor(
mcgraph()->zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags,
Operator::kNoProperties);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
mcgraph()->zone(), TypeConversionDescriptor(), 0,
CallDescriptor::kNoFlags, Operator::kNoProperties,
MachineType::AnyTagged(), 1, Linkage::kPassContext, stub_mode_);
Node* stub_code =
(stub_mode_ == StubCallMode::kCallWasmRuntimeStub)
? mcgraph()->RelocatableIntPtrConstant(
wasm::WasmCode::kWasmToNumber, RelocInfo::WASM_STUB_CALL)
: jsgraph()->HeapConstant(BUILTIN_CODE(isolate_, ToNumber));
Node* result =
graph()->NewNode(mcgraph()->common()->Call(call_descriptor), stub_code,
......@@ -4707,6 +4717,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
private:
Isolate* const isolate_;
JSGraph* jsgraph_;
StubCallMode stub_mode_;
SetOncePointer<const Operator> allocate_heap_number_operator_;
};
} // namespace
......@@ -4732,7 +4743,8 @@ MaybeHandle<Code> CompileJSToWasmWrapper(
Node* effect = nullptr;
wasm::ModuleEnv env(module, use_trap_handler, wasm::kRuntimeExceptionSupport);
WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, func->sig, nullptr);
WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, func->sig, nullptr,
StubCallMode::kCallOnHeapBuiltin);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.BuildJSToWasmWrapper(index, call_target);
......@@ -4810,7 +4822,8 @@ MaybeHandle<Code> CompileWasmToJSWrapper(
wasm::kRuntimeExceptionSupport);
WasmWrapperGraphBuilder builder(&zone, &env, &jsgraph, sig,
source_position_table);
source_position_table,
StubCallMode::kCallWasmRuntimeStub);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.BuildWasmToJSWrapper(target, index);
......@@ -4876,7 +4889,8 @@ MaybeHandle<Code> CompileWasmInterpreterEntry(Isolate* isolate,
Node* control = nullptr;
Node* effect = nullptr;
WasmWrapperGraphBuilder builder(&zone, nullptr, &jsgraph, sig, nullptr);
WasmWrapperGraphBuilder builder(&zone, nullptr, &jsgraph, sig, nullptr,
StubCallMode::kCallWasmRuntimeStub);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.BuildWasmInterpreterEntry(func_index);
......@@ -4936,7 +4950,8 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
Node* control = nullptr;
Node* effect = nullptr;
WasmWrapperGraphBuilder builder(&zone, nullptr, &jsgraph, sig, nullptr);
WasmWrapperGraphBuilder builder(&zone, nullptr, &jsgraph, sig, nullptr,
StubCallMode::kCallOnHeapBuiltin);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.BuildCWasmEntry();
......
......@@ -38,11 +38,9 @@ enum class TrapId : uint32_t;
namespace wasm {
struct DecodeStruct;
class SignatureMap;
// Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
typedef compiler::Node TFNode;
typedef compiler::MachineGraph TFGraph;
class NativeModule;
class WasmCode;
} // namespace wasm
......@@ -151,7 +149,6 @@ struct WasmInstanceCacheNodes {
// Abstracts details of building TurboFan graph nodes for wasm to separate
// the wasm decoder from the internal details of TurboFan.
typedef ZoneVector<Node*> NodeVector;
class WasmGraphBuilder {
public:
enum EnforceBoundsCheck : bool {
......
......@@ -178,17 +178,6 @@ void WasmCode::Validate() const {
!it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
switch (mode) {
case RelocInfo::CODE_TARGET: {
Address target = it.rinfo()->target_address();
Code* code = native_module_->ReverseTrampolineLookup(target);
// TODO(7424): This is by now limited to only contain references to a
// limited set of builtins. This code will eventually be completely free
// of {RelocInfo::CODE_TARGET} relocation entries altogether.
int builtin_index = code->builtin_index();
CHECK(builtin_index == Builtins::kAllocateHeapNumber ||
builtin_index == Builtins::kToNumber);
break;
}
case RelocInfo::WASM_STUB_CALL: {
Address target = it.rinfo()->wasm_stub_call_address();
WasmCode* code = native_module_->Lookup(target);
......@@ -509,7 +498,6 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code,
// Apply the relocation delta by iterating over the RelocInfo.
intptr_t delta = ret->instruction_start() - code->InstructionStart();
int mode_mask = RelocInfo::kApplyMask |
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL);
RelocIterator orig_it(*code, mode_mask);
for (RelocIterator it(ret->instructions(), ret->reloc_info(),
......@@ -523,12 +511,6 @@ WasmCode* NativeModule::AddAnonymousCode(Handle<Code> code,
runtime_stub(static_cast<WasmCode::RuntimeStubId>(stub_call_tag));
it.rinfo()->set_wasm_stub_call_address(code->instruction_start(),
SKIP_ICACHE_FLUSH);
} else if (RelocInfo::IsCodeTarget(mode)) {
Code* call_target =
Code::GetCodeFromTargetAddress(orig_it.rinfo()->target_address());
it.rinfo()->set_target_address(
GetLocalAddressFor(handle(call_target, call_target->GetIsolate())),
SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
} else {
it.rinfo()->apply(delta);
}
......@@ -562,7 +544,6 @@ WasmCode* NativeModule::AddCode(
source_pos.reset(new byte[source_pos_table->length()]);
source_pos_table->copy_out(0, source_pos.get(), source_pos_table->length());
}
TurboAssembler* origin = reinterpret_cast<TurboAssembler*>(desc.origin);
WasmCode* ret = AddOwnedCode(
{desc.buffer, static_cast<size_t>(desc.instr_size)},
std::move(reloc_info), static_cast<size_t>(desc.reloc_size),
......@@ -576,7 +557,6 @@ WasmCode* NativeModule::AddCode(
AllowDeferredHandleDereference embedding_raw_address;
intptr_t delta = ret->instructions().start() - desc.buffer;
int mode_mask = RelocInfo::kApplyMask |
RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL);
for (RelocIterator it(ret->instructions(), ret->reloc_info(),
ret->constant_pool(), mode_mask);
......@@ -589,14 +569,6 @@ WasmCode* NativeModule::AddCode(
runtime_stub(static_cast<WasmCode::RuntimeStubId>(stub_call_tag));
it.rinfo()->set_wasm_stub_call_address(code->instruction_start(),
SKIP_ICACHE_FLUSH);
} else if (RelocInfo::IsCodeTarget(mode)) {
// rewrite code handles to direct pointers to the first instruction in the
// code object
Handle<Object> p = it.rinfo()->target_object_handle(origin);
Code* code = Code::cast(*p);
it.rinfo()->set_target_address(
GetLocalAddressFor(handle(code, code->GetIsolate())),
SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
} else {
it.rinfo()->apply(delta);
}
......@@ -699,17 +671,6 @@ Address NativeModule::GetLocalAddressFor(Handle<Code> code) {
}
}
Code* NativeModule::ReverseTrampolineLookup(Address target) {
// Uses sub-optimal linear search, but is only used for debugging.
for (auto pair : trampolines_) {
if (pair.second == target) {
return Code::GetCodeFromTargetAddress(pair.first);
}
}
UNREACHABLE();
return nullptr;
}
Address NativeModule::AllocateForCode(size_t size) {
// This happens under a lock assumed by the caller.
size = RoundUp(size, kCodeAlignment);
......
......@@ -33,9 +33,11 @@ struct WasmModule;
// elements of the list coincide with {compiler::TrapId}, order matters.
#define WASM_RUNTIME_STUB_LIST(V, VTRAP) \
FOREACH_WASM_TRAPREASON(VTRAP) \
V(WasmAllocateHeapNumber) \
V(WasmArgumentsAdaptor) \
V(WasmCallJavaScript) \
V(WasmStackGuard) \
V(WasmToNumber) \
V(DoubleToI)
struct AddressRange {
......@@ -362,8 +364,6 @@ class V8_EXPORT_PRIVATE NativeModule final {
WasmCode::FlushICache);
Address GetLocalAddressFor(Handle<Code>);
Address CreateTrampolineTo(Handle<Code>);
// TODO(7424): Only used for debugging in {WasmCode::Validate}. Remove.
Code* ReverseTrampolineLookup(Address target);
WasmCode* CreateEmptyJumpTable(uint32_t num_wasm_functions);
......@@ -389,6 +389,7 @@ class V8_EXPORT_PRIVATE NativeModule final {
// Maps from instruction start of an immovable code object to instruction
// start of the trampoline.
// TODO(mstarzinger): By now trampolines are unused. Remove.
std::unordered_map<Address, Address> trampolines_;
// Jump table used to easily redirect wasm function calls.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment