Chromium Code Reviews| 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 2457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2468 vbox, control); | 2468 vbox, control); |
| 2469 return value; | 2469 return value; |
| 2470 } | 2470 } |
| 2471 | 2471 |
| 2472 Node* WasmGraphBuilder::ToJS(Node* node, wasm::ValueType type) { | 2472 Node* WasmGraphBuilder::ToJS(Node* node, wasm::ValueType type) { |
| 2473 switch (type) { | 2473 switch (type) { |
| 2474 case wasm::kWasmI32: | 2474 case wasm::kWasmI32: |
| 2475 return BuildChangeInt32ToTagged(node); | 2475 return BuildChangeInt32ToTagged(node); |
| 2476 case wasm::kWasmS128: | 2476 case wasm::kWasmS128: |
| 2477 case wasm::kWasmI64: | 2477 case wasm::kWasmI64: |
| 2478 // Throw a TypeError. The native context is good enough here because we | 2478 UNREACHABLE(); |
| 2479 // only throw a TypeError. | |
| 2480 return BuildCallToRuntime(Runtime::kWasmThrowTypeError, jsgraph(), | |
| 2481 jsgraph()->isolate()->native_context(), nullptr, | |
| 2482 0, effect_, *control_); | |
| 2483 case wasm::kWasmF32: | 2479 case wasm::kWasmF32: |
| 2484 node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(), | 2480 node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(), |
| 2485 node); | 2481 node); |
| 2486 return BuildChangeFloat64ToTagged(node); | 2482 return BuildChangeFloat64ToTagged(node); |
| 2487 case wasm::kWasmF64: | 2483 case wasm::kWasmF64: |
| 2488 return BuildChangeFloat64ToTagged(node); | 2484 return BuildChangeFloat64ToTagged(node); |
| 2489 case wasm::kWasmStmt: | 2485 case wasm::kWasmStmt: |
| 2490 return jsgraph()->UndefinedConstant(); | 2486 return jsgraph()->UndefinedConstant(); |
| 2491 default: | 2487 default: |
| 2492 UNREACHABLE(); | 2488 UNREACHABLE(); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2634 num = BuildChangeTaggedToFloat64(num); | 2630 num = BuildChangeTaggedToFloat64(num); |
| 2635 | 2631 |
| 2636 switch (type) { | 2632 switch (type) { |
| 2637 case wasm::kWasmI32: { | 2633 case wasm::kWasmI32: { |
| 2638 num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(), | 2634 num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToWord32(), |
| 2639 num); | 2635 num); |
| 2640 break; | 2636 break; |
| 2641 } | 2637 } |
| 2642 case wasm::kWasmS128: | 2638 case wasm::kWasmS128: |
| 2643 case wasm::kWasmI64: | 2639 case wasm::kWasmI64: |
| 2644 // Throw a TypeError. The native context is good enough here because we | 2640 UNREACHABLE(); |
| 2645 // only throw a TypeError. | |
| 2646 return BuildCallToRuntime(Runtime::kWasmThrowTypeError, jsgraph(), | |
| 2647 jsgraph()->isolate()->native_context(), nullptr, | |
| 2648 0, effect_, *control_); | |
| 2649 case wasm::kWasmF32: | 2641 case wasm::kWasmF32: |
| 2650 num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(), | 2642 num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(), |
| 2651 num); | 2643 num); |
| 2652 break; | 2644 break; |
| 2653 case wasm::kWasmF64: | 2645 case wasm::kWasmF64: |
| 2654 break; | 2646 break; |
| 2655 default: | 2647 default: |
| 2656 UNREACHABLE(); | 2648 UNREACHABLE(); |
| 2657 return nullptr; | 2649 return nullptr; |
| 2658 } | 2650 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2733 Node* WasmGraphBuilder::BuildLoadHeapNumberValue(Node* value, Node* control) { | 2725 Node* WasmGraphBuilder::BuildLoadHeapNumberValue(Node* value, Node* control) { |
| 2734 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::Float64()), | 2726 return graph()->NewNode(jsgraph()->machine()->Load(MachineType::Float64()), |
| 2735 value, BuildHeapNumberValueIndexConstant(), | 2727 value, BuildHeapNumberValueIndexConstant(), |
| 2736 graph()->start(), control); | 2728 graph()->start(), control); |
| 2737 } | 2729 } |
| 2738 | 2730 |
| 2739 Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() { | 2731 Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() { |
| 2740 return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag); | 2732 return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag); |
| 2741 } | 2733 } |
| 2742 | 2734 |
| 2735 bool HasJSCompatibleSignature(wasm::FunctionSig* sig) { | |
| 2736 for (size_t i = 0; i < sig->parameter_count(); i++) { | |
| 2737 if (sig->GetParam(i) == wasm::kWasmI64) { | |
| 2738 return false; | |
| 2739 } | |
| 2740 if (sig->GetParam(i) == wasm::kWasmS128) { | |
| 2741 return false; | |
| 2742 } | |
| 2743 } | |
| 2744 for (size_t i = 0; i < sig->return_count(); i++) { | |
| 2745 if (sig->GetReturn(i) == wasm::kWasmI64) { | |
|
titzer
2017/01/11 13:40:37
Do you also want to check for S128 here? If so, ma
ahaas
2017/01/11 14:04:45
Done
| |
| 2746 return false; | |
| 2747 } | |
| 2748 } | |
| 2749 return true; | |
| 2750 } | |
| 2751 | |
| 2743 void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, | 2752 void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code, |
| 2744 wasm::FunctionSig* sig) { | 2753 wasm::FunctionSig* sig) { |
| 2745 int wasm_count = static_cast<int>(sig->parameter_count()); | 2754 int wasm_count = static_cast<int>(sig->parameter_count()); |
| 2746 int param_count; | 2755 int count = wasm_count + 3; |
| 2747 if (jsgraph()->machine()->Is64()) { | |
| 2748 param_count = static_cast<int>(sig->parameter_count()); | |
| 2749 } else { | |
| 2750 param_count = Int64Lowering::GetParameterCountAfterLowering(sig); | |
| 2751 } | |
| 2752 int count = param_count + 3; | |
| 2753 Node** args = Buffer(count); | 2756 Node** args = Buffer(count); |
| 2754 | 2757 |
| 2755 // Build the start and the JS parameter nodes. | 2758 // Build the start and the JS parameter nodes. |
| 2756 Node* start = Start(param_count + 5); | 2759 Node* start = Start(wasm_count + 5); |
| 2757 *control_ = start; | 2760 *control_ = start; |
| 2758 *effect_ = start; | 2761 *effect_ = start; |
| 2762 | |
| 2763 if (!HasJSCompatibleSignature(sig_)) { | |
| 2764 // Throw a TypeError. The native context is good enough here because we | |
| 2765 // only throw a TypeError. | |
| 2766 BuildCallToRuntime(Runtime::kWasmThrowTypeError, jsgraph(), | |
| 2767 jsgraph()->isolate()->native_context(), nullptr, 0, | |
| 2768 effect_, *control_); | |
| 2769 | |
| 2770 // Add a dummy call to the wasm function so that the generated wrapper | |
| 2771 // contains a reference to the wrapped wasm function. Without this reference | |
| 2772 // the wasm function could not be re-imported into another wasm module. | |
| 2773 int pos = 0; | |
| 2774 args[pos++] = HeapConstant(wasm_code); | |
| 2775 args[pos++] = *effect_; | |
| 2776 args[pos++] = *control_; | |
| 2777 | |
| 2778 // We only need a dummy call descriptor. | |
| 2779 wasm::FunctionSig::Builder dummy_sig_builder(jsgraph()->zone(), 0, 0); | |
| 2780 CallDescriptor* desc = wasm::ModuleEnv::GetWasmCallDescriptor( | |
| 2781 jsgraph()->zone(), dummy_sig_builder.Build()); | |
| 2782 *effect_ = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); | |
| 2783 Return(jsgraph()->UndefinedConstant()); | |
| 2784 return; | |
| 2785 } | |
| 2786 | |
| 2759 // Create the context parameter | 2787 // Create the context parameter |
| 2760 Node* context = graph()->NewNode( | 2788 Node* context = graph()->NewNode( |
| 2761 jsgraph()->common()->Parameter( | 2789 jsgraph()->common()->Parameter( |
| 2762 Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), | 2790 Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), |
| 2763 graph()->start()); | 2791 graph()->start()); |
| 2764 | 2792 |
| 2765 int pos = 0; | 2793 int pos = 0; |
| 2766 args[pos++] = HeapConstant(wasm_code); | 2794 args[pos++] = HeapConstant(wasm_code); |
| 2767 | 2795 |
| 2768 // Convert JS parameters to WASM numbers. | 2796 // Convert JS parameters to WASM numbers. |
| 2769 for (int i = 0; i < wasm_count; ++i) { | 2797 for (int i = 0; i < wasm_count; ++i) { |
| 2770 Node* param = Param(i + 1); | 2798 Node* param = Param(i + 1); |
| 2771 Node* wasm_param = FromJS(param, context, sig->GetParam(i)); | 2799 Node* wasm_param = FromJS(param, context, sig->GetParam(i)); |
| 2772 args[pos++] = wasm_param; | 2800 args[pos++] = wasm_param; |
| 2773 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kWasmI64) { | |
| 2774 // We make up the high word with SAR to get the proper sign extension. | |
| 2775 args[pos++] = graph()->NewNode(jsgraph()->machine()->Word32Sar(), | |
| 2776 wasm_param, jsgraph()->Int32Constant(31)); | |
| 2777 } | |
| 2778 } | 2801 } |
| 2779 | 2802 |
| 2780 args[pos++] = *effect_; | 2803 args[pos++] = *effect_; |
| 2781 args[pos++] = *control_; | 2804 args[pos++] = *control_; |
| 2782 | 2805 |
| 2783 // Call the WASM code. | 2806 // Call the WASM code. |
| 2784 CallDescriptor* desc = | 2807 CallDescriptor* desc = |
| 2785 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); | 2808 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); |
| 2786 if (jsgraph()->machine()->Is32()) { | 2809 |
| 2787 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc); | |
| 2788 } | |
| 2789 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); | 2810 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); |
| 2790 *effect_ = call; | 2811 *effect_ = call; |
| 2791 Node* retval = call; | 2812 Node* retval = call; |
| 2792 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && | |
| 2793 sig->GetReturn(0) == wasm::kWasmI64) { | |
| 2794 // The return values comes as two values, we pick the low word. | |
| 2795 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, | |
| 2796 graph()->start()); | |
| 2797 } | |
| 2798 Node* jsval = ToJS( | 2813 Node* jsval = ToJS( |
| 2799 retval, sig->return_count() == 0 ? wasm::kWasmStmt : sig->GetReturn()); | 2814 retval, sig->return_count() == 0 ? wasm::kWasmStmt : sig->GetReturn()); |
| 2800 Return(jsval); | 2815 Return(jsval); |
| 2801 } | 2816 } |
| 2802 | 2817 |
| 2803 int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count, | 2818 int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count, |
| 2804 wasm::FunctionSig* sig) { | 2819 wasm::FunctionSig* sig) { |
| 2805 // Convert WASM numbers to JS values. | 2820 // Convert WASM numbers to JS values. |
| 2806 int param_index = 0; | 2821 int param_index = 0; |
| 2807 for (int i = 0; i < param_count; ++i) { | 2822 for (int i = 0; i < param_count; ++i) { |
| 2808 Node* param = Param(param_index++); | 2823 Node* param = Param(param_index++); |
| 2809 args[pos++] = ToJS(param, sig->GetParam(i)); | 2824 args[pos++] = ToJS(param, sig->GetParam(i)); |
| 2810 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kWasmI64) { | |
| 2811 // On 32 bit platforms we have to skip the high word of int64 | |
| 2812 // parameters. | |
| 2813 param_index++; | |
| 2814 } | |
| 2815 } | 2825 } |
| 2816 return pos; | 2826 return pos; |
| 2817 } | 2827 } |
| 2818 | 2828 |
| 2819 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target, | 2829 void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSReceiver> target, |
| 2820 wasm::FunctionSig* sig) { | 2830 wasm::FunctionSig* sig) { |
| 2821 DCHECK(target->IsCallable()); | 2831 DCHECK(target->IsCallable()); |
| 2822 | 2832 |
| 2823 int wasm_count = static_cast<int>(sig->parameter_count()); | 2833 int wasm_count = static_cast<int>(sig->parameter_count()); |
| 2824 int param_count; | |
| 2825 if (jsgraph()->machine()->Is64()) { | |
| 2826 param_count = wasm_count; | |
| 2827 } else { | |
| 2828 param_count = Int64Lowering::GetParameterCountAfterLowering(sig); | |
| 2829 } | |
| 2830 | 2834 |
| 2831 // Build the start and the parameter nodes. | 2835 // Build the start and the parameter nodes. |
| 2832 Isolate* isolate = jsgraph()->isolate(); | 2836 Isolate* isolate = jsgraph()->isolate(); |
| 2833 CallDescriptor* desc; | 2837 CallDescriptor* desc; |
| 2834 Node* start = Start(param_count + 3); | 2838 Node* start = Start(wasm_count + 3); |
| 2835 *effect_ = start; | 2839 *effect_ = start; |
| 2836 *control_ = start; | 2840 *control_ = start; |
| 2841 | |
| 2842 if (!HasJSCompatibleSignature(sig_)) { | |
| 2843 // Throw a TypeError. The native context is good enough here because we | |
| 2844 // only throw a TypeError. | |
| 2845 Return(BuildCallToRuntime(Runtime::kWasmThrowTypeError, jsgraph(), | |
| 2846 jsgraph()->isolate()->native_context(), nullptr, | |
| 2847 0, effect_, *control_)); | |
| 2848 return; | |
| 2849 } | |
| 2850 | |
| 2837 Node** args = Buffer(wasm_count + 7); | 2851 Node** args = Buffer(wasm_count + 7); |
| 2838 | 2852 |
| 2839 Node* call; | 2853 Node* call; |
| 2840 bool direct_call = false; | 2854 bool direct_call = false; |
| 2841 | 2855 |
| 2842 if (target->IsJSFunction()) { | 2856 if (target->IsJSFunction()) { |
| 2843 Handle<JSFunction> function = Handle<JSFunction>::cast(target); | 2857 Handle<JSFunction> function = Handle<JSFunction>::cast(target); |
| 2844 if (function->shared()->internal_formal_parameter_count() == wasm_count) { | 2858 if (function->shared()->internal_formal_parameter_count() == wasm_count) { |
| 2845 direct_call = true; | 2859 direct_call = true; |
| 2846 int pos = 0; | 2860 int pos = 0; |
| (...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3693 Smi::FromInt(instruction.instr_offset)); | 3707 Smi::FromInt(instruction.instr_offset)); |
| 3694 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, | 3708 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, |
| 3695 Smi::FromInt(instruction.landing_offset)); | 3709 Smi::FromInt(instruction.landing_offset)); |
| 3696 } | 3710 } |
| 3697 return fn_protected; | 3711 return fn_protected; |
| 3698 } | 3712 } |
| 3699 | 3713 |
| 3700 } // namespace compiler | 3714 } // namespace compiler |
| 3701 } // namespace internal | 3715 } // namespace internal |
| 3702 } // namespace v8 | 3716 } // namespace v8 |
| OLD | NEW |