Commit 7f7545cf authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[wasm] Introduce WasmImportCallKind enum

The WASM engine compiles per-import wrappers for callables imported
into a WASM instance that have one of a number of different shapes,
depending on the type of the imported function and whether there is
a signature match. This CL introduces an enum with a value for each
case in preparation for introducing a per-kind cache.

R=mstarzinger@chromium.org
CC=clemensh@chromium.org

Change-Id: If9b7355ff7c57a329c096f93f3624bc3d6c74e3f
Reviewed-on: https://chromium-review.googlesource.com/1243045
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56210}
parent 9f7ec7d4
This diff is collapsed.
...@@ -68,11 +68,27 @@ class TurbofanWasmCompilationUnit { ...@@ -68,11 +68,27 @@ class TurbofanWasmCompilationUnit {
DISALLOW_COPY_AND_ASSIGN(TurbofanWasmCompilationUnit); DISALLOW_COPY_AND_ASSIGN(TurbofanWasmCompilationUnit);
}; };
// Wraps a JS function, producing a code object that can be called from wasm. // Calls to WASM imports are handled in several different ways, depending
MaybeHandle<Code> CompileWasmToJSWrapper(Isolate*, Handle<JSReceiver> target, // on the type of the target function/callable and whether the signature
wasm::FunctionSig*, uint32_t index, // matches the argument arity.
wasm::ModuleOrigin, enum class WasmImportCallKind {
wasm::UseTrapHandler); kLinkError, // static WASM->WASM type error
kRuntimeTypeError, // runtime WASM->JS type error
kWasmToWasm, // fast WASM->WASM call
kJSFunctionArityMatch, // fast WASM->JS call
kJSFunctionArityMatchSloppy, // fast WASM->JS call, sloppy receiver
kJSFunctionArityMismatch, // WASM->JS, needs adapter frame
kJSFunctionArityMismatchSloppy, // WASM->JS, needs adapter frame, sloppy
kUseCallBuiltin // everything else
};
WasmImportCallKind GetWasmImportCallKind(Handle<JSReceiver> callable,
wasm::FunctionSig* sig);
// Compiles an import call wrapper, which allows WASM to call imports.
MaybeHandle<Code> CompileWasmImportCallWrapper(
Isolate*, WasmImportCallKind, Handle<JSReceiver>, wasm::FunctionSig*,
uint32_t index, wasm::ModuleOrigin, wasm::UseTrapHandler);
// Creates a code object calling a wasm function with the given signature, // Creates a code object calling a wasm function with the given signature,
// callable from JS. // callable from JS.
...@@ -366,10 +382,10 @@ class WasmGraphBuilder { ...@@ -366,10 +382,10 @@ class WasmGraphBuilder {
Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets, Node* BuildWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
wasm::WasmCodePosition position, Node* instance_node, wasm::WasmCodePosition position, Node* instance_node,
UseRetpoline use_retpoline); UseRetpoline use_retpoline);
Node* BuildImportWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets, Node* BuildImportCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
wasm::WasmCodePosition position, int func_index); wasm::WasmCodePosition position, int func_index);
Node* BuildImportWasmCall(wasm::FunctionSig* sig, Node** args, Node*** rets, Node* BuildImportCall(wasm::FunctionSig* sig, Node** args, Node*** rets,
wasm::WasmCodePosition position, Node* func_index); wasm::WasmCodePosition position, Node* func_index);
Node* BuildF32CopySign(Node* left, Node* right); Node* BuildF32CopySign(Node* left, Node* right);
Node* BuildF64CopySign(Node* left, Node* right); Node* BuildF64CopySign(Node* left, Node* right);
......
...@@ -1494,41 +1494,41 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) { ...@@ -1494,41 +1494,41 @@ int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
} }
uint32_t func_index = import.index; uint32_t func_index = import.index;
DCHECK_EQ(num_imported_functions, func_index); DCHECK_EQ(num_imported_functions, func_index);
auto js_receiver = Handle<JSReceiver>::cast(value);
FunctionSig* expected_sig = module_->functions[func_index].sig; FunctionSig* expected_sig = module_->functions[func_index].sig;
if (WasmExportedFunction::IsWasmExportedFunction(*value)) { auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig);
// The imported function is a WASM function from another instance. switch (kind) {
Handle<WasmExportedFunction> imported_function( case compiler::WasmImportCallKind::kLinkError:
WasmExportedFunction::cast(*value), isolate_);
Handle<WasmInstanceObject> imported_instance(
imported_function->instance(), isolate_);
FunctionSig* imported_sig =
imported_instance->module()
->functions[imported_function->function_index()]
.sig;
if (*imported_sig != *expected_sig) {
ReportLinkError( ReportLinkError(
"imported function does not match the expected type", index, "imported function does not match the expected type", index,
module_name, import_name); module_name, import_name);
return -1; return -1;
case compiler::WasmImportCallKind::kWasmToWasm: {
// The imported function is a WASM function from another instance.
auto imported_function = Handle<WasmExportedFunction>::cast(value);
Handle<WasmInstanceObject> imported_instance(
imported_function->instance(), isolate_);
// The import reference is the instance object itself.
Address imported_target = imported_function->GetWasmCallTarget();
ImportedFunctionEntry entry(instance, func_index);
entry.set_wasm_to_wasm(*imported_instance, imported_target);
break;
}
default: {
// The imported function is a callable.
Handle<Code> wrapper_code =
compiler::CompileWasmImportCallWrapper(
isolate_, kind, js_receiver, expected_sig, func_index,
module_->origin, use_trap_handler())
.ToHandleChecked();
RecordStats(*wrapper_code, isolate_->counters());
WasmCode* wasm_code =
native_module->AddImportWrapper(wrapper_code, func_index);
ImportedFunctionEntry entry(instance, func_index);
entry.set_wasm_to_js(*js_receiver, wasm_code);
break;
} }
// The import reference is the instance object itself.
Address imported_target = imported_function->GetWasmCallTarget();
ImportedFunctionEntry entry(instance, func_index);
entry.set_wasm_to_wasm(*imported_instance, imported_target);
} else {
// The imported function is a callable.
Handle<JSReceiver> js_receiver(JSReceiver::cast(*value), isolate_);
Handle<Code> wrapper_code =
compiler::CompileWasmToJSWrapper(
isolate_, js_receiver, expected_sig, func_index,
module_->origin, use_trap_handler())
.ToHandleChecked();
RecordStats(*wrapper_code, isolate_->counters());
WasmCode* wasm_code =
native_module->AddImportWrapper(wrapper_code, func_index);
ImportedFunctionEntry entry(instance, func_index);
entry.set_wasm_to_js(*js_receiver, wasm_code);
} }
num_imported_functions++; num_imported_functions++;
break; break;
......
...@@ -41,8 +41,10 @@ TestingModuleBuilder::TestingModuleBuilder( ...@@ -41,8 +41,10 @@ TestingModuleBuilder::TestingModuleBuilder(
if (maybe_import) { if (maybe_import) {
// Manually compile a wasm to JS wrapper and insert it into the instance. // Manually compile a wasm to JS wrapper and insert it into the instance.
CodeSpaceMemoryModificationScope modification_scope(isolate_->heap()); CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
MaybeHandle<Code> code = compiler::CompileWasmToJSWrapper( auto kind = compiler::GetWasmImportCallKind(maybe_import->js_function,
isolate_, maybe_import->js_function, maybe_import->sig, maybe_import->sig);
MaybeHandle<Code> code = compiler::CompileWasmImportCallWrapper(
isolate_, kind, maybe_import->js_function, maybe_import->sig,
maybe_import_index, test_module_->origin, maybe_import_index, test_module_->origin,
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler
: kNoTrapHandler); : kNoTrapHandler);
......
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