Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 2208703002: [wasm] Allow import function to be any kind of callables. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/wasm-compiler.h" 5 #include "src/compiler/wasm-compiler.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 10
(...skipping 2164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2175 2175
2176 // Allocate the box for the {value}. 2176 // Allocate the box for the {value}.
2177 vbox = BuildAllocateHeapNumberWithValue(value, if_box); 2177 vbox = BuildAllocateHeapNumberWithValue(value, if_box);
2178 2178
2179 Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box); 2179 Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box);
2180 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi, 2180 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi,
2181 vbox, control); 2181 vbox, control);
2182 return value; 2182 return value;
2183 } 2183 }
2184 2184
2185 Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) { 2185 Node* WasmGraphBuilder::ToJS(Node* node, wasm::LocalType type) {
2186 switch (type) { 2186 switch (type) {
2187 case wasm::kAstI32: 2187 case wasm::kAstI32:
2188 return BuildChangeInt32ToTagged(node); 2188 return BuildChangeInt32ToTagged(node);
2189 case wasm::kAstI64: 2189 case wasm::kAstI64:
2190 // TODO(titzer): i64->JS has no good solution right now. Using lower 32 2190 // TODO(titzer): i64->JS has no good solution right now. Using lower 32
2191 // bits. 2191 // bits.
2192 if (jsgraph()->machine()->Is64()) { 2192 if (jsgraph()->machine()->Is64()) {
2193 // On 32 bit platforms we do not have to do the truncation because the 2193 // On 32 bit platforms we do not have to do the truncation because the
2194 // node we get in as a parameter only contains the low word anyways. 2194 // node we get in as a parameter only contains the low word anyways.
2195 node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), 2195 node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(),
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
2508 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc); 2508 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc);
2509 } 2509 }
2510 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); 2510 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
2511 Node* retval = call; 2511 Node* retval = call;
2512 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && 2512 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
2513 sig->GetReturn(0) == wasm::kAstI64) { 2513 sig->GetReturn(0) == wasm::kAstI64) {
2514 // The return values comes as two values, we pick the low word. 2514 // The return values comes as two values, we pick the low word.
2515 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, 2515 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval,
2516 graph()->start()); 2516 graph()->start());
2517 } 2517 }
2518 Node* jsval = 2518 Node* jsval = ToJS(
2519 ToJS(retval, context, 2519 retval, sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
2520 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
2521 Node* ret = 2520 Node* ret =
2522 graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start); 2521 graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start);
2523 2522
2524 MergeControlToEnd(jsgraph(), ret); 2523 MergeControlToEnd(jsgraph(), ret);
2525 } 2524 }
2526 2525
2527 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function, 2526 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target,
2528 wasm::FunctionSig* sig) { 2527 wasm::FunctionSig* sig) {
2529 int js_count = function->shared()->internal_formal_parameter_count(); 2528 DCHECK(target->IsCallable());
2529
2530 int wasm_count = static_cast<int>(sig->parameter_count()); 2530 int wasm_count = static_cast<int>(sig->parameter_count());
2531 int param_count; 2531 int param_count;
2532 if (jsgraph()->machine()->Is64()) { 2532 if (jsgraph()->machine()->Is64()) {
2533 param_count = wasm_count; 2533 param_count = wasm_count;
2534 } else { 2534 } else {
2535 param_count = Int64Lowering::GetParameterCountAfterLowering(sig); 2535 param_count = Int64Lowering::GetParameterCountAfterLowering(sig);
2536 } 2536 }
2537 2537
2538 // Build the start and the parameter nodes. 2538 // Build the start and the parameter nodes.
2539 Isolate* isolate = jsgraph()->isolate(); 2539 Isolate* isolate = jsgraph()->isolate();
2540 CallDescriptor* desc; 2540 CallDescriptor* desc;
2541 Node* start = Start(param_count + 3); 2541 Node* start = Start(param_count + 3);
2542 *effect_ = start; 2542 *effect_ = start;
2543 *control_ = start; 2543 *control_ = start;
2544 // JS context is the last parameter.
2545 Node* context = HeapConstant(Handle<Context>(function->context(), isolate));
2546 Node** args = Buffer(wasm_count + 7); 2544 Node** args = Buffer(wasm_count + 7);
2547 2545
2548 bool arg_count_before_args = false; 2546 // The default context of the target.
2549 bool add_new_target_undefined = false; 2547 Handle<Context> target_context = isolate->native_context();
2550 2548
2549 // Optimization: check if the target is a JSFunction with the right arity so
2550 // that we can call it directly.
2551 bool call_direct = false;
2551 int pos = 0; 2552 int pos = 0;
2552 if (js_count == wasm_count) { 2553 if (target->IsJSFunction()) {
2553 // exact arity match, just call the function directly. 2554 Handle<JSFunction> function = Handle<JSFunction>::cast(target);
2554 desc = Linkage::GetJSCallDescriptor(graph()->zone(), false, wasm_count + 1, 2555 if (function->shared()->internal_formal_parameter_count() == wasm_count) {
2555 CallDescriptor::kNoFlags); 2556 call_direct = true;
2556 arg_count_before_args = false; 2557
2557 add_new_target_undefined = true; 2558 args[pos++] = jsgraph()->Constant(target); // target callable.
2558 } else { 2559 // Receiver.
2559 // Use the Call builtin. 2560 if (is_sloppy(function->shared()->language_mode()) &&
2561 !function->shared()->native()) {
2562 args[pos++] =
2563 HeapConstant(handle(function->context()->global_proxy(), isolate));
2564 } else {
2565 args[pos++] = jsgraph()->Constant(
2566 handle(isolate->heap()->undefined_value(), isolate));
2567 }
2568
2569 desc = Linkage::GetJSCallDescriptor(
2570 graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
2571
2572 // For a direct call we have to use the context of the JSFunction.
2573 target_context = handle(function->context());
2574 }
2575 }
2576
2577 // We cannot call the target directly, we have to use the Call builtin.
2578 if (!call_direct) {
2560 Callable callable = CodeFactory::Call(isolate); 2579 Callable callable = CodeFactory::Call(isolate);
2561 args[pos++] = jsgraph()->HeapConstant(callable.code()); 2580 args[pos++] = jsgraph()->HeapConstant(callable.code());
2581 args[pos++] = jsgraph()->Constant(target); // target callable
2582 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count
2583 args[pos++] = jsgraph()->Constant(
2584 handle(isolate->heap()->undefined_value(), isolate)); // receiver
2585
2562 desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(), 2586 desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(),
2563 callable.descriptor(), wasm_count + 1, 2587 callable.descriptor(), wasm_count + 1,
2564 CallDescriptor::kNoFlags); 2588 CallDescriptor::kNoFlags);
2565 arg_count_before_args = true;
2566 } 2589 }
2567 2590
2568 args[pos++] = jsgraph()->Constant(function); // JS function.
2569 if (arg_count_before_args) {
2570 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count
2571 }
2572 // Create the receiver constant (either undefined or the global proxy).
2573 Handle<Object> receiver(isolate->heap()->undefined_value(), isolate);
2574 if (is_sloppy(function->shared()->language_mode())) {
2575 receiver = Handle<Object>(function->context()->global_proxy(), isolate);
2576 }
2577 args[pos++] = jsgraph()->Constant(receiver);
2578
2579 // Convert WASM numbers to JS values. 2591 // Convert WASM numbers to JS values.
2580 int param_index = 0; 2592 int param_index = 0;
2581 for (int i = 0; i < wasm_count; ++i) { 2593 for (int i = 0; i < wasm_count; ++i) {
2582 Node* param = 2594 Node* param =
2583 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start); 2595 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start);
2584 args[pos++] = ToJS(param, context, sig->GetParam(i)); 2596 args[pos++] = ToJS(param, sig->GetParam(i));
2585 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { 2597 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) {
2586 // On 32 bit platforms we have to skip the high word of int64 parameters. 2598 // On 32 bit platforms we have to skip the high word of int64 parameters.
2587 param_index++; 2599 param_index++;
2588 } 2600 }
2589 } 2601 }
2590 2602
2591 if (add_new_target_undefined) { 2603 if (call_direct) {
2592 args[pos++] = jsgraph()->UndefinedConstant(); // new target 2604 args[pos++] = jsgraph()->UndefinedConstant(); // new target
2605 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count
2593 } 2606 }
2594 2607
2595 if (!arg_count_before_args) { 2608 args[pos++] = HeapConstant(target_context);
2596 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count
2597 }
2598 args[pos++] = context;
2599 args[pos++] = *effect_; 2609 args[pos++] = *effect_;
2600 args[pos++] = *control_; 2610 args[pos++] = *control_;
2601 2611
2602 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); 2612 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
2603 2613
2604 // Convert the return value back. 2614 // Convert the return value back.
2605 Node* ret; 2615 Node* ret;
2606 Node* val = 2616 Node* val =
2607 FromJS(call, context, 2617 FromJS(call, HeapConstant(isolate->native_context()),
2608 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); 2618 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
2609 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && 2619 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
2610 sig->GetReturn() == wasm::kAstI64) { 2620 sig->GetReturn() == wasm::kAstI64) {
2611 ret = graph()->NewNode(jsgraph()->common()->Return(), val, 2621 ret = graph()->NewNode(jsgraph()->common()->Return(), val,
2612 graph()->NewNode(jsgraph()->machine()->Word32Sar(), 2622 graph()->NewNode(jsgraph()->machine()->Word32Sar(),
2613 val, jsgraph()->Int32Constant(31)), 2623 val, jsgraph()->Int32Constant(31)),
2614 call, start); 2624 call, start);
2615 } else { 2625 } else {
2616 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start); 2626 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start);
2617 } 2627 }
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
2953 2963
2954 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { 2964 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
2955 RecordFunctionCompilation( 2965 RecordFunctionCompilation(
2956 CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index, 2966 CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index,
2957 wasm::WasmName("export"), 2967 wasm::WasmName("export"),
2958 module->module->GetName(func->name_offset, func->name_length)); 2968 module->module->GetName(func->name_offset, func->name_length));
2959 } 2969 }
2960 return code; 2970 return code;
2961 } 2971 }
2962 2972
2963 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, 2973 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
2964 Handle<JSFunction> function,
2965 wasm::FunctionSig* sig, uint32_t index, 2974 wasm::FunctionSig* sig, uint32_t index,
2966 Handle<String> import_module, 2975 Handle<String> import_module,
2967 MaybeHandle<String> import_function) { 2976 MaybeHandle<String> import_function) {
2968 //---------------------------------------------------------------------------- 2977 //----------------------------------------------------------------------------
2969 // Create the Graph 2978 // Create the Graph
2970 //---------------------------------------------------------------------------- 2979 //----------------------------------------------------------------------------
2971 Zone zone(isolate->allocator()); 2980 Zone zone(isolate->allocator());
2972 Graph graph(&zone); 2981 Graph graph(&zone);
2973 CommonOperatorBuilder common(&zone); 2982 CommonOperatorBuilder common(&zone);
2974 MachineOperatorBuilder machine(&zone); 2983 MachineOperatorBuilder machine(&zone);
2975 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); 2984 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
2976 2985
2977 Node* control = nullptr; 2986 Node* control = nullptr;
2978 Node* effect = nullptr; 2987 Node* effect = nullptr;
2979 2988
2980 WasmGraphBuilder builder(&zone, &jsgraph, sig); 2989 WasmGraphBuilder builder(&zone, &jsgraph, sig);
2981 builder.set_control_ptr(&control); 2990 builder.set_control_ptr(&control);
2982 builder.set_effect_ptr(&effect); 2991 builder.set_effect_ptr(&effect);
2983 builder.BuildWasmToJSWrapper(function, sig); 2992 builder.BuildWasmToJSWrapper(target, sig);
2984 2993
2985 Handle<Code> code = Handle<Code>::null(); 2994 Handle<Code> code = Handle<Code>::null();
2986 { 2995 {
2987 if (FLAG_trace_turbo_graph) { // Simple textual RPO. 2996 if (FLAG_trace_turbo_graph) { // Simple textual RPO.
2988 OFStream os(stdout); 2997 OFStream os(stdout);
2989 os << "-- Graph after change lowering -- " << std::endl; 2998 os << "-- Graph after change lowering -- " << std::endl;
2990 os << AsRPO(graph); 2999 os << AsRPO(graph);
2991 } 3000 }
2992 3001
2993 // Schedule and compile to machine code. 3002 // Schedule and compile to machine code.
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
3218 function_->code_start_offset), 3227 function_->code_start_offset),
3219 compile_ms); 3228 compile_ms);
3220 } 3229 }
3221 3230
3222 return code; 3231 return code;
3223 } 3232 }
3224 3233
3225 } // namespace compiler 3234 } // namespace compiler
3226 } // namespace internal 3235 } // namespace internal
3227 } // namespace v8 3236 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698