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

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: Comments. 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
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 2166 matching lines...) Expand 10 before | Expand all | Expand 10 after
2177 2177
2178 // Allocate the box for the {value}. 2178 // Allocate the box for the {value}.
2179 vbox = BuildAllocateHeapNumberWithValue(value, if_box); 2179 vbox = BuildAllocateHeapNumberWithValue(value, if_box);
2180 2180
2181 Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box); 2181 Node* control = graph()->NewNode(common->Merge(2), if_smi, if_box);
2182 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi, 2182 value = graph()->NewNode(common->Phi(MachineRepresentation::kTagged, 2), vsmi,
2183 vbox, control); 2183 vbox, control);
2184 return value; 2184 return value;
2185 } 2185 }
2186 2186
2187 Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) { 2187 Node* WasmGraphBuilder::ToJS(Node* node, wasm::LocalType type) {
2188 switch (type) { 2188 switch (type) {
2189 case wasm::kAstI32: 2189 case wasm::kAstI32:
2190 return BuildChangeInt32ToTagged(node); 2190 return BuildChangeInt32ToTagged(node);
2191 case wasm::kAstI64: 2191 case wasm::kAstI64:
2192 // TODO(titzer): i64->JS has no good solution right now. Using lower 32 2192 // TODO(titzer): i64->JS has no good solution right now. Using lower 32
2193 // bits. 2193 // bits.
2194 if (jsgraph()->machine()->Is64()) { 2194 if (jsgraph()->machine()->Is64()) {
2195 // On 32 bit platforms we do not have to do the truncation because the 2195 // On 32 bit platforms we do not have to do the truncation because the
2196 // node we get in as a parameter only contains the low word anyways. 2196 // node we get in as a parameter only contains the low word anyways.
2197 node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), 2197 node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(),
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
2516 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc); 2516 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc);
2517 } 2517 }
2518 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); 2518 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
2519 Node* retval = call; 2519 Node* retval = call;
2520 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && 2520 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
2521 sig->GetReturn(0) == wasm::kAstI64) { 2521 sig->GetReturn(0) == wasm::kAstI64) {
2522 // The return values comes as two values, we pick the low word. 2522 // The return values comes as two values, we pick the low word.
2523 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, 2523 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval,
2524 graph()->start()); 2524 graph()->start());
2525 } 2525 }
2526 Node* jsval = 2526 Node* jsval = ToJS(
2527 ToJS(retval, context, 2527 retval, sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
2528 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
2529 Node* ret = 2528 Node* ret =
2530 graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start); 2529 graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start);
2531 2530
2532 MergeControlToEnd(jsgraph(), ret); 2531 MergeControlToEnd(jsgraph(), ret);
2533 } 2532 }
2534 2533
2535 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function, 2534 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target,
2536 wasm::FunctionSig* sig) { 2535 wasm::FunctionSig* sig) {
2537 int js_count = function->shared()->internal_formal_parameter_count(); 2536 DCHECK(target->IsCallable());
2537
2538 int wasm_count = static_cast<int>(sig->parameter_count()); 2538 int wasm_count = static_cast<int>(sig->parameter_count());
2539 int param_count; 2539 int param_count;
2540 if (jsgraph()->machine()->Is64()) { 2540 if (jsgraph()->machine()->Is64()) {
2541 param_count = wasm_count; 2541 param_count = wasm_count;
2542 } else { 2542 } else {
2543 param_count = Int64Lowering::GetParameterCountAfterLowering(sig); 2543 param_count = Int64Lowering::GetParameterCountAfterLowering(sig);
2544 } 2544 }
2545 2545
2546 // Build the start and the parameter nodes. 2546 // Build the start and the parameter nodes.
2547 Isolate* isolate = jsgraph()->isolate(); 2547 Isolate* isolate = jsgraph()->isolate();
2548 CallDescriptor* desc; 2548 CallDescriptor* desc;
2549 Node* start = Start(param_count + 3); 2549 Node* start = Start(param_count + 3);
2550 *effect_ = start; 2550 *effect_ = start;
2551 *control_ = start; 2551 *control_ = start;
2552 // JS context is the last parameter.
2553 Node* context = HeapConstant(Handle<Context>(function->context(), isolate));
2554 Node** args = Buffer(wasm_count + 7); 2552 Node** args = Buffer(wasm_count + 7);
2555 2553
2556 bool arg_count_before_args = false; 2554 bool arg_count_before_args = false;
2557 bool add_new_target_undefined = false; 2555 bool add_new_target_undefined = false;
2558 2556 bool call_direct = false;
2559 int pos = 0; 2557 int pos = 0;
2560 if (js_count == wasm_count) { 2558 Handle<JSFunction> function;
Mircea Trofin 2016/08/09 14:54:07 For readability/maintainability, could you perhaps
ahaas 2016/08/09 18:00:09 I refactored the code now and think that it's more
2561 // exact arity match, just call the function directly. 2559 if (target->IsJSFunction()) {
2562 desc = Linkage::GetJSCallDescriptor(graph()->zone(), false, wasm_count + 1, 2560 function = Handle<JSFunction>::cast(target);
2563 CallDescriptor::kNoFlags); 2561 if (function->shared()->internal_formal_parameter_count() == wasm_count) {
2564 arg_count_before_args = false; 2562 desc = Linkage::GetJSCallDescriptor(
2565 add_new_target_undefined = true; 2563 graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags);
2566 } else { 2564 arg_count_before_args = false;
2565 add_new_target_undefined = true;
2566 call_direct = true;
2567 }
2568 }
2569 if (!call_direct) {
2567 // Use the Call builtin. 2570 // Use the Call builtin.
2568 Callable callable = CodeFactory::Call(isolate); 2571 Callable callable = CodeFactory::Call(isolate);
2569 args[pos++] = jsgraph()->HeapConstant(callable.code()); 2572 args[pos++] = jsgraph()->HeapConstant(callable.code());
2570 desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(), 2573 desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(),
2571 callable.descriptor(), wasm_count + 1, 2574 callable.descriptor(), wasm_count + 1,
2572 CallDescriptor::kNoFlags); 2575 CallDescriptor::kNoFlags);
2573 arg_count_before_args = true; 2576 arg_count_before_args = true;
2574 } 2577 }
2575 2578
2576 args[pos++] = jsgraph()->Constant(function); // JS function. 2579 args[pos++] = jsgraph()->Constant(target); // target callable.
2577 if (arg_count_before_args) { 2580 if (arg_count_before_args) {
2578 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count 2581 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count
2579 } 2582 }
2580 // Create the receiver constant (either undefined or the global proxy). 2583 // Create the receiver constant (either undefined or the global proxy).
2581 Handle<Object> receiver(isolate->heap()->undefined_value(), isolate); 2584 Handle<Object> receiver(isolate->heap()->undefined_value(), isolate);
2582 if (is_sloppy(function->shared()->language_mode())) { 2585 if (call_direct && is_sloppy(function->shared()->language_mode())) {
2583 receiver = Handle<Object>(function->context()->global_proxy(), isolate); 2586 receiver = handle(function->context()->global_proxy(), isolate);
2584 } 2587 }
2585 args[pos++] = jsgraph()->Constant(receiver); 2588 args[pos++] = jsgraph()->Constant(receiver);
2586
2587 // Convert WASM numbers to JS values. 2589 // Convert WASM numbers to JS values.
2588 int param_index = 0; 2590 int param_index = 0;
2589 for (int i = 0; i < wasm_count; ++i) { 2591 for (int i = 0; i < wasm_count; ++i) {
2590 Node* param = 2592 Node* param =
2591 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start); 2593 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start);
2592 args[pos++] = ToJS(param, context, sig->GetParam(i)); 2594 args[pos++] = ToJS(param, sig->GetParam(i));
2593 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { 2595 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) {
2594 // On 32 bit platforms we have to skip the high word of int64 parameters. 2596 // On 32 bit platforms we have to skip the high word of int64 parameters.
2595 param_index++; 2597 param_index++;
2596 } 2598 }
2597 } 2599 }
2598 2600
2599 if (add_new_target_undefined) { 2601 if (add_new_target_undefined) {
2600 args[pos++] = jsgraph()->UndefinedConstant(); // new target 2602 args[pos++] = jsgraph()->UndefinedConstant(); // new target
2601 } 2603 }
2602 2604
2603 if (!arg_count_before_args) { 2605 if (!arg_count_before_args) {
2604 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count 2606 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count
2605 } 2607 }
2606 args[pos++] = context; 2608 if (call_direct) {
2609 // We do a direct call to JS, we need the context of the function.
2610 args[pos++] = HeapConstant(handle(function->context()));
2611 } else {
2612 args[pos++] = HeapConstant(isolate->native_context());
2613 }
2614
2607 args[pos++] = *effect_; 2615 args[pos++] = *effect_;
2608 args[pos++] = *control_; 2616 args[pos++] = *control_;
2609 2617
2610 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); 2618 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
2611 2619
2612 // Convert the return value back. 2620 // Convert the return value back.
2613 Node* ret; 2621 Node* ret;
2614 Node* val = 2622 Node* val =
2615 FromJS(call, context, 2623 FromJS(call, HeapConstant(isolate->native_context()),
2616 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); 2624 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
2617 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && 2625 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
2618 sig->GetReturn() == wasm::kAstI64) { 2626 sig->GetReturn() == wasm::kAstI64) {
2619 ret = graph()->NewNode(jsgraph()->common()->Return(), val, 2627 ret = graph()->NewNode(jsgraph()->common()->Return(), val,
2620 graph()->NewNode(jsgraph()->machine()->Word32Sar(), 2628 graph()->NewNode(jsgraph()->machine()->Word32Sar(),
2621 val, jsgraph()->Int32Constant(31)), 2629 val, jsgraph()->Int32Constant(31)),
2622 call, start); 2630 call, start);
2623 } else { 2631 } else {
2624 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start); 2632 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start);
2625 } 2633 }
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
3045 3053
3046 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { 3054 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
3047 RecordFunctionCompilation( 3055 RecordFunctionCompilation(
3048 CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index, 3056 CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index,
3049 wasm::WasmName("export"), 3057 wasm::WasmName("export"),
3050 module->module->GetName(func->name_offset, func->name_length)); 3058 module->module->GetName(func->name_offset, func->name_length));
3051 } 3059 }
3052 return code; 3060 return code;
3053 } 3061 }
3054 3062
3055 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, 3063 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
3056 Handle<JSFunction> function,
3057 wasm::FunctionSig* sig, uint32_t index, 3064 wasm::FunctionSig* sig, uint32_t index,
3058 Handle<String> import_module, 3065 Handle<String> import_module,
3059 MaybeHandle<String> import_function) { 3066 MaybeHandle<String> import_function) {
3060 //---------------------------------------------------------------------------- 3067 //----------------------------------------------------------------------------
3061 // Create the Graph 3068 // Create the Graph
3062 //---------------------------------------------------------------------------- 3069 //----------------------------------------------------------------------------
3063 Zone zone(isolate->allocator()); 3070 Zone zone(isolate->allocator());
3064 Graph graph(&zone); 3071 Graph graph(&zone);
3065 CommonOperatorBuilder common(&zone); 3072 CommonOperatorBuilder common(&zone);
3066 MachineOperatorBuilder machine(&zone); 3073 MachineOperatorBuilder machine(&zone);
3067 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); 3074 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
3068 3075
3069 Node* control = nullptr; 3076 Node* control = nullptr;
3070 Node* effect = nullptr; 3077 Node* effect = nullptr;
3071 3078
3072 WasmGraphBuilder builder(&zone, &jsgraph, sig); 3079 WasmGraphBuilder builder(&zone, &jsgraph, sig);
3073 builder.set_control_ptr(&control); 3080 builder.set_control_ptr(&control);
3074 builder.set_effect_ptr(&effect); 3081 builder.set_effect_ptr(&effect);
3075 builder.BuildWasmToJSWrapper(function, sig); 3082 builder.BuildWasmToJSWrapper(target, sig);
3076 3083
3077 Handle<Code> code = Handle<Code>::null(); 3084 Handle<Code> code = Handle<Code>::null();
3078 { 3085 {
3079 if (FLAG_trace_turbo_graph) { // Simple textual RPO. 3086 if (FLAG_trace_turbo_graph) { // Simple textual RPO.
3080 OFStream os(stdout); 3087 OFStream os(stdout);
3081 os << "-- Graph after change lowering -- " << std::endl; 3088 os << "-- Graph after change lowering -- " << std::endl;
3082 os << AsRPO(graph); 3089 os << AsRPO(graph);
3083 } 3090 }
3084 3091
3085 // Schedule and compile to machine code. 3092 // Schedule and compile to machine code.
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
3324 function_->code_start_offset), 3331 function_->code_start_offset),
3325 compile_ms); 3332 compile_ms);
3326 } 3333 }
3327 3334
3328 return code; 3335 return code;
3329 } 3336 }
3330 3337
3331 } // namespace compiler 3338 } // namespace compiler
3332 } // namespace internal 3339 } // namespace internal
3333 } // namespace v8 3340 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/runtime/runtime.h » ('j') | src/wasm/wasm-module.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698