OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 // The default context of the target. |
2557 bool add_new_target_undefined = false; | 2555 Handle<Context> target_context = isolate->native_context(); |
2558 | 2556 |
2557 // Optimization: check if the target is a JSFunction with the right arity so | |
2558 // that we can call it directly. | |
2559 bool call_direct = false; | |
2559 int pos = 0; | 2560 int pos = 0; |
2560 if (js_count == wasm_count) { | 2561 if (target->IsJSFunction()) { |
2561 // exact arity match, just call the function directly. | 2562 Handle<JSFunction> function = Handle<JSFunction>::cast(target); |
2562 desc = Linkage::GetJSCallDescriptor(graph()->zone(), false, wasm_count + 1, | 2563 if (function->shared()->internal_formal_parameter_count() == wasm_count) { |
2563 CallDescriptor::kNoFlags); | 2564 call_direct = true; |
2564 arg_count_before_args = false; | 2565 |
2565 add_new_target_undefined = true; | 2566 args[pos++] = jsgraph()->Constant(target); // target callable. |
2566 } else { | 2567 // Receiver. |
2567 // Use the Call builtin. | 2568 if (is_sloppy(function->shared()->language_mode())) { |
Benedikt Meurer
2016/08/10 03:29:02
This is wrong. You also need to check for natives
ahaas
2016/08/10 07:12:48
Done.
| |
2569 args[pos++] = | |
2570 HeapConstant(handle(function->context()->global_proxy(), isolate)); | |
2571 } else { | |
2572 args[pos++] = jsgraph()->Constant( | |
2573 handle(isolate->heap()->undefined_value(), isolate)); | |
2574 } | |
2575 | |
2576 desc = Linkage::GetJSCallDescriptor( | |
2577 graph()->zone(), false, wasm_count + 1, CallDescriptor::kNoFlags); | |
2578 | |
2579 // For a direct call we have to use the context of the JSFunction. | |
2580 target_context = handle(function->context()); | |
2581 } | |
2582 } | |
2583 | |
2584 // We cannot call the target directly, we have to use the Call builtin. | |
2585 if (!call_direct) { | |
2568 Callable callable = CodeFactory::Call(isolate); | 2586 Callable callable = CodeFactory::Call(isolate); |
2569 args[pos++] = jsgraph()->HeapConstant(callable.code()); | 2587 args[pos++] = jsgraph()->HeapConstant(callable.code()); |
2588 args[pos++] = jsgraph()->Constant(target); // target callable | |
2589 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count | |
2590 args[pos++] = jsgraph()->Constant( | |
2591 handle(isolate->heap()->undefined_value(), isolate)); // receiver | |
2592 | |
2570 desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(), | 2593 desc = Linkage::GetStubCallDescriptor(isolate, graph()->zone(), |
2571 callable.descriptor(), wasm_count + 1, | 2594 callable.descriptor(), wasm_count + 1, |
2572 CallDescriptor::kNoFlags); | 2595 CallDescriptor::kNoFlags); |
2573 arg_count_before_args = true; | |
2574 } | 2596 } |
2575 | 2597 |
2576 args[pos++] = jsgraph()->Constant(function); // JS function. | |
2577 if (arg_count_before_args) { | |
2578 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count | |
2579 } | |
2580 // Create the receiver constant (either undefined or the global proxy). | |
2581 Handle<Object> receiver(isolate->heap()->undefined_value(), isolate); | |
2582 if (is_sloppy(function->shared()->language_mode())) { | |
2583 receiver = Handle<Object>(function->context()->global_proxy(), isolate); | |
2584 } | |
2585 args[pos++] = jsgraph()->Constant(receiver); | |
2586 | |
2587 // Convert WASM numbers to JS values. | 2598 // Convert WASM numbers to JS values. |
2588 int param_index = 0; | 2599 int param_index = 0; |
2589 for (int i = 0; i < wasm_count; ++i) { | 2600 for (int i = 0; i < wasm_count; ++i) { |
2590 Node* param = | 2601 Node* param = |
2591 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start); | 2602 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start); |
2592 args[pos++] = ToJS(param, context, sig->GetParam(i)); | 2603 args[pos++] = ToJS(param, sig->GetParam(i)); |
2593 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { | 2604 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { |
2594 // On 32 bit platforms we have to skip the high word of int64 parameters. | 2605 // On 32 bit platforms we have to skip the high word of int64 parameters. |
2595 param_index++; | 2606 param_index++; |
2596 } | 2607 } |
2597 } | 2608 } |
2598 | 2609 |
2599 if (add_new_target_undefined) { | 2610 if (call_direct) { |
2600 args[pos++] = jsgraph()->UndefinedConstant(); // new target | 2611 args[pos++] = jsgraph()->UndefinedConstant(); // new target |
2612 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count | |
2601 } | 2613 } |
2602 | 2614 |
2603 if (!arg_count_before_args) { | 2615 args[pos++] = HeapConstant(target_context); |
2604 args[pos++] = jsgraph()->Int32Constant(wasm_count); // argument count | |
2605 } | |
2606 args[pos++] = context; | |
2607 args[pos++] = *effect_; | 2616 args[pos++] = *effect_; |
2608 args[pos++] = *control_; | 2617 args[pos++] = *control_; |
2609 | 2618 |
2610 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); | 2619 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); |
2611 | 2620 |
2612 // Convert the return value back. | 2621 // Convert the return value back. |
2613 Node* ret; | 2622 Node* ret; |
2614 Node* val = | 2623 Node* val = |
2615 FromJS(call, context, | 2624 FromJS(call, HeapConstant(isolate->native_context()), |
2616 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); | 2625 sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); |
2617 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && | 2626 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && |
2618 sig->GetReturn() == wasm::kAstI64) { | 2627 sig->GetReturn() == wasm::kAstI64) { |
2619 ret = graph()->NewNode(jsgraph()->common()->Return(), val, | 2628 ret = graph()->NewNode(jsgraph()->common()->Return(), val, |
2620 graph()->NewNode(jsgraph()->machine()->Word32Sar(), | 2629 graph()->NewNode(jsgraph()->machine()->Word32Sar(), |
2621 val, jsgraph()->Int32Constant(31)), | 2630 val, jsgraph()->Int32Constant(31)), |
2622 call, start); | 2631 call, start); |
2623 } else { | 2632 } else { |
2624 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start); | 2633 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start); |
2625 } | 2634 } |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3045 | 3054 |
3046 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { | 3055 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) { |
3047 RecordFunctionCompilation( | 3056 RecordFunctionCompilation( |
3048 CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index, | 3057 CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index, |
3049 wasm::WasmName("export"), | 3058 wasm::WasmName("export"), |
3050 module->module->GetName(func->name_offset, func->name_length)); | 3059 module->module->GetName(func->name_offset, func->name_length)); |
3051 } | 3060 } |
3052 return code; | 3061 return code; |
3053 } | 3062 } |
3054 | 3063 |
3055 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, | 3064 Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target, |
3056 Handle<JSFunction> function, | |
3057 wasm::FunctionSig* sig, uint32_t index, | 3065 wasm::FunctionSig* sig, uint32_t index, |
3058 Handle<String> import_module, | 3066 Handle<String> import_module, |
3059 MaybeHandle<String> import_function) { | 3067 MaybeHandle<String> import_function) { |
3060 //---------------------------------------------------------------------------- | 3068 //---------------------------------------------------------------------------- |
3061 // Create the Graph | 3069 // Create the Graph |
3062 //---------------------------------------------------------------------------- | 3070 //---------------------------------------------------------------------------- |
3063 Zone zone(isolate->allocator()); | 3071 Zone zone(isolate->allocator()); |
3064 Graph graph(&zone); | 3072 Graph graph(&zone); |
3065 CommonOperatorBuilder common(&zone); | 3073 CommonOperatorBuilder common(&zone); |
3066 MachineOperatorBuilder machine(&zone); | 3074 MachineOperatorBuilder machine(&zone); |
3067 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); | 3075 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); |
3068 | 3076 |
3069 Node* control = nullptr; | 3077 Node* control = nullptr; |
3070 Node* effect = nullptr; | 3078 Node* effect = nullptr; |
3071 | 3079 |
3072 WasmGraphBuilder builder(&zone, &jsgraph, sig); | 3080 WasmGraphBuilder builder(&zone, &jsgraph, sig); |
3073 builder.set_control_ptr(&control); | 3081 builder.set_control_ptr(&control); |
3074 builder.set_effect_ptr(&effect); | 3082 builder.set_effect_ptr(&effect); |
3075 builder.BuildWasmToJSWrapper(function, sig); | 3083 builder.BuildWasmToJSWrapper(target, sig); |
3076 | 3084 |
3077 Handle<Code> code = Handle<Code>::null(); | 3085 Handle<Code> code = Handle<Code>::null(); |
3078 { | 3086 { |
3079 if (FLAG_trace_turbo_graph) { // Simple textual RPO. | 3087 if (FLAG_trace_turbo_graph) { // Simple textual RPO. |
3080 OFStream os(stdout); | 3088 OFStream os(stdout); |
3081 os << "-- Graph after change lowering -- " << std::endl; | 3089 os << "-- Graph after change lowering -- " << std::endl; |
3082 os << AsRPO(graph); | 3090 os << AsRPO(graph); |
3083 } | 3091 } |
3084 | 3092 |
3085 // Schedule and compile to machine code. | 3093 // Schedule and compile to machine code. |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3324 function_->code_start_offset), | 3332 function_->code_start_offset), |
3325 compile_ms); | 3333 compile_ms); |
3326 } | 3334 } |
3327 | 3335 |
3328 return code; | 3336 return code; |
3329 } | 3337 } |
3330 | 3338 |
3331 } // namespace compiler | 3339 } // namespace compiler |
3332 } // namespace internal | 3340 } // namespace internal |
3333 } // namespace v8 | 3341 } // namespace v8 |
OLD | NEW |