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 |