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

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

Issue 2626853003: [wasm] (To|From)JSWrappers with I64 params throw a TypeError upon call. (Closed)
Patch Set: Created 3 years, 11 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 | « no previous file | src/wasm/wasm-module.cc » ('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 2457 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/wasm/wasm-module.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698