Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index 324d3bea003c73145a5eae7150bb739c21f1a31c..b457efec4ec3e0e34ddd7305b16f1539a29fc631 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -2182,7 +2182,7 @@ Node* WasmGraphBuilder::BuildChangeFloat64ToTagged(Node* value) { |
return value; |
} |
-Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) { |
+Node* WasmGraphBuilder::ToJS(Node* node, wasm::LocalType type) { |
switch (type) { |
case wasm::kAstI32: |
return BuildChangeInt32ToTagged(node); |
@@ -2515,18 +2515,18 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, |
retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, |
graph()->start()); |
} |
- Node* jsval = |
- ToJS(retval, context, |
- sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); |
+ Node* jsval = ToJS( |
+ retval, sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); |
Node* ret = |
graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start); |
MergeControlToEnd(jsgraph(), ret); |
} |
-void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function, |
+void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target, |
wasm::FunctionSig* sig) { |
- int js_count = function->shared()->internal_formal_parameter_count(); |
+ DCHECK(target->IsCallable()); |
+ |
int wasm_count = static_cast<int>(sig->parameter_count()); |
int param_count; |
if (jsgraph()->machine()->Is64()) { |
@@ -2541,61 +2541,71 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function, |
Node* start = Start(param_count + 3); |
*effect_ = start; |
*control_ = start; |
- // JS context is the last parameter. |
- Node* context = HeapConstant(Handle<Context>(function->context(), isolate)); |
Node** args = Buffer(wasm_count + 7); |
- bool arg_count_before_args = false; |
- bool add_new_target_undefined = false; |
+ // The default context of the target. |
+ Handle<Context> target_context = isolate->native_context(); |
+ // Optimization: check if the target is a JSFunction with the right arity so |
+ // that we can call it directly. |
+ bool call_direct = false; |
int pos = 0; |
- if (js_count == wasm_count) { |
- // exact arity match, just call the function directly. |
- desc = Linkage::GetJSCallDescriptor(graph()->zone(), false, wasm_count + 1, |
- CallDescriptor::kNoFlags); |
- arg_count_before_args = false; |
- add_new_target_undefined = true; |
- } else { |
- // Use the Call builtin. |
+ if (target->IsJSFunction()) { |
+ Handle<JSFunction> function = Handle<JSFunction>::cast(target); |
+ if (function->shared()->internal_formal_parameter_count() == wasm_count) { |
+ call_direct = true; |
+ |
+ args[pos++] = jsgraph()->Constant(target); // target callable. |
+ // Receiver. |
+ if (is_sloppy(function->shared()->language_mode()) && |
+ !function->shared()->native()) { |
+ args[pos++] = |
+ HeapConstant(handle(function->context()->global_proxy(), isolate)); |
+ } else { |
+ args[pos++] = jsgraph()->Constant( |
+ handle(isolate->heap()->undefined_value(), isolate)); |
+ } |
+ |
+ desc = Linkage::GetJSCallDescriptor( |
+ graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags); |
+ |
+ // For a direct call we have to use the context of the JSFunction. |
+ target_context = handle(function->context()); |
+ } |
+ } |
+ |
+ // We cannot call the target directly, we have to use the Call builtin. |
+ if (!call_direct) { |
Callable callable = CodeFactory::Call(isolate); |
args[pos++] = jsgraph()->HeapConstant(callable.code()); |
+ args[pos++] = jsgraph()->Constant(target); // target callable |
+ args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count |
+ args[pos++] = jsgraph()->Constant( |
+ handle(isolate->heap()->undefined_value(), isolate)); // receiver |
+ |
desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(), |
callable.descriptor(), wasm_count + 1, |
CallDescriptor::kNoFlags); |
- arg_count_before_args = true; |
} |
- args[pos++] = jsgraph()->Constant(function); // JS function. |
- if (arg_count_before_args) { |
- args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count |
- } |
- // Create the receiver constant (either undefined or the global proxy). |
- Handle<Object> receiver(isolate->heap()->undefined_value(), isolate); |
- if (is_sloppy(function->shared()->language_mode())) { |
- receiver = Handle<Object>(function->context()->global_proxy(), isolate); |
- } |
- args[pos++] = jsgraph()->Constant(receiver); |
- |
// Convert WASM numbers to JS values. |
int param_index = 0; |
for (int i = 0; i < wasm_count; ++i) { |
Node* param = |
graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start); |
- args[pos++] = ToJS(param, context, sig->GetParam(i)); |
+ args[pos++] = ToJS(param, sig->GetParam(i)); |
if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { |
// On 32 bit platforms we have to skip the high word of int64 parameters. |
param_index++; |
} |
} |
- if (add_new_target_undefined) { |
+ if (call_direct) { |
args[pos++] = jsgraph()->UndefinedConstant(); // new target |
- } |
- |
- if (!arg_count_before_args) { |
args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count |
} |
- args[pos++] = context; |
+ |
+ args[pos++] = HeapConstant(target_context); |
args[pos++] = *effect_; |
args[pos++] = *control_; |
@@ -2604,7 +2614,7 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function, |
// Convert the return value back. |
Node* ret; |
Node* val = |
- FromJS(call, context, |
+ FromJS(call, HeapConstant(isolate->native_context()), |
sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); |
if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && |
sig->GetReturn() == wasm::kAstI64) { |
@@ -2960,8 +2970,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module, |
return code; |
} |
-Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, |
- Handle<JSFunction> function, |
+Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target, |
wasm::FunctionSig* sig, uint32_t index, |
Handle<String> import_module, |
MaybeHandle<String> import_function) { |
@@ -2980,7 +2989,7 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, |
WasmGraphBuilder builder(&zone, &jsgraph, sig); |
builder.set_control_ptr(&control); |
builder.set_effect_ptr(&effect); |
- builder.BuildWasmToJSWrapper(function, sig); |
+ builder.BuildWasmToJSWrapper(target, sig); |
Handle<Code> code = Handle<Code>::null(); |
{ |