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/assembler-inl.h" | 9 #include "src/assembler-inl.h" |
10 #include "src/base/platform/elapsed-timer.h" | 10 #include "src/base/platform/elapsed-timer.h" |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 inputs[count++] = control; | 96 inputs[count++] = control; |
97 | 97 |
98 Node* node = | 98 Node* node = |
99 jsgraph->graph()->NewNode(jsgraph->common()->Call(desc), count, inputs); | 99 jsgraph->graph()->NewNode(jsgraph->common()->Call(desc), count, inputs); |
100 *effect_ptr = node; | 100 *effect_ptr = node; |
101 return node; | 101 return node; |
102 } | 102 } |
103 | 103 |
104 } // namespace | 104 } // namespace |
105 | 105 |
106 // TODO(eholk): Support trap handlers on other platforms. | |
107 #if V8_TARGET_ARCH_X64 && V8_OS_LINUX | |
108 const bool kTrapHandlerSupported = true; | |
109 #else | |
110 const bool kTrapHandlerSupported = false; | |
111 #endif | |
112 | |
113 // A helper that handles building graph fragments for trapping. | 106 // A helper that handles building graph fragments for trapping. |
114 // To avoid generating a ton of redundant code that just calls the runtime | 107 // To avoid generating a ton of redundant code that just calls the runtime |
115 // to trap, we generate a per-trap-reason block of code that all trap sites | 108 // to trap, we generate a per-trap-reason block of code that all trap sites |
116 // in this function will branch to. | 109 // in this function will branch to. |
117 class WasmTrapHelper : public ZoneObject { | 110 class WasmTrapHelper : public ZoneObject { |
118 public: | 111 public: |
119 explicit WasmTrapHelper(WasmGraphBuilder* builder) | 112 explicit WasmTrapHelper(WasmGraphBuilder* builder) |
120 : builder_(builder), | 113 : builder_(builder), |
121 jsgraph_(builder->jsgraph()), | 114 jsgraph_(builder->jsgraph()), |
122 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) {} | 115 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) {} |
(...skipping 2679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2802 int pos = 0; | 2795 int pos = 0; |
2803 args[pos++] = HeapConstant(wasm_code); | 2796 args[pos++] = HeapConstant(wasm_code); |
2804 | 2797 |
2805 // Convert JS parameters to WASM numbers. | 2798 // Convert JS parameters to WASM numbers. |
2806 for (int i = 0; i < wasm_count; ++i) { | 2799 for (int i = 0; i < wasm_count; ++i) { |
2807 Node* param = Param(i + 1); | 2800 Node* param = Param(i + 1); |
2808 Node* wasm_param = FromJS(param, context, sig->GetParam(i)); | 2801 Node* wasm_param = FromJS(param, context, sig->GetParam(i)); |
2809 args[pos++] = wasm_param; | 2802 args[pos++] = wasm_param; |
2810 } | 2803 } |
2811 | 2804 |
| 2805 // Set the ThreadInWasm flag before we do the actual call. |
| 2806 if (trap_handler::UseTrapHandler()) { |
| 2807 // TODO(eholk): Set the flag directly without a runtime call. We should be |
| 2808 // able to store directly to a location in the isolate (later TLS) that sets |
| 2809 // the g_thread_in_wasm_code flag. |
| 2810 BuildCallToRuntime(Runtime::kSetThreadInWasm, jsgraph(), |
| 2811 jsgraph()->isolate()->native_context(), nullptr, 0, |
| 2812 effect_, *control_); |
| 2813 } |
| 2814 |
2812 args[pos++] = *effect_; | 2815 args[pos++] = *effect_; |
2813 args[pos++] = *control_; | 2816 args[pos++] = *control_; |
2814 | 2817 |
2815 // Call the WASM code. | 2818 // Call the WASM code. |
2816 CallDescriptor* desc = | 2819 CallDescriptor* desc = |
2817 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); | 2820 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); |
2818 | 2821 |
2819 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); | 2822 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); |
2820 *effect_ = call; | 2823 *effect_ = call; |
| 2824 |
| 2825 // Clear the ThreadInWasmFlag |
| 2826 if (trap_handler::UseTrapHandler()) { |
| 2827 // TODO(eholk): Set the flag directly without a runtime call. We should be |
| 2828 // able to store directly to a location in the isolate (later TLS) that sets |
| 2829 // the g_thread_in_wasm_code flag. |
| 2830 BuildCallToRuntime(Runtime::kClearThreadInWasm, jsgraph(), |
| 2831 jsgraph()->isolate()->native_context(), nullptr, 0, |
| 2832 effect_, *control_); |
| 2833 } |
| 2834 |
2821 Node* retval = call; | 2835 Node* retval = call; |
2822 Node* jsval = ToJS( | 2836 Node* jsval = ToJS( |
2823 retval, sig->return_count() == 0 ? wasm::kWasmStmt : sig->GetReturn()); | 2837 retval, sig->return_count() == 0 ? wasm::kWasmStmt : sig->GetReturn()); |
2824 Return(jsval); | 2838 Return(jsval); |
2825 } | 2839 } |
2826 | 2840 |
2827 int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count, | 2841 int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count, |
2828 wasm::FunctionSig* sig) { | 2842 wasm::FunctionSig* sig) { |
2829 // Convert WASM numbers to JS values. | 2843 // Convert WASM numbers to JS values. |
2830 int param_index = 0; | 2844 int param_index = 0; |
(...skipping 24 matching lines...) Expand all Loading... |
2855 jsgraph()->isolate()->native_context(), nullptr, | 2869 jsgraph()->isolate()->native_context(), nullptr, |
2856 0, effect_, *control_)); | 2870 0, effect_, *control_)); |
2857 return; | 2871 return; |
2858 } | 2872 } |
2859 | 2873 |
2860 Node** args = Buffer(wasm_count + 7); | 2874 Node** args = Buffer(wasm_count + 7); |
2861 | 2875 |
2862 Node* call; | 2876 Node* call; |
2863 bool direct_call = false; | 2877 bool direct_call = false; |
2864 | 2878 |
| 2879 if (trap_handler::UseTrapHandler()) { |
| 2880 BuildCallToRuntime(Runtime::kClearThreadInWasm, jsgraph(), |
| 2881 jsgraph()->isolate()->native_context(), nullptr, 0, |
| 2882 effect_, *control_); |
| 2883 } |
| 2884 |
2865 if (target->IsJSFunction()) { | 2885 if (target->IsJSFunction()) { |
2866 Handle<JSFunction> function = Handle<JSFunction>::cast(target); | 2886 Handle<JSFunction> function = Handle<JSFunction>::cast(target); |
2867 if (function->shared()->internal_formal_parameter_count() == wasm_count) { | 2887 if (function->shared()->internal_formal_parameter_count() == wasm_count) { |
2868 direct_call = true; | 2888 direct_call = true; |
2869 int pos = 0; | 2889 int pos = 0; |
2870 args[pos++] = jsgraph()->Constant(target); // target callable. | 2890 args[pos++] = jsgraph()->Constant(target); // target callable. |
2871 // Receiver. | 2891 // Receiver. |
2872 if (is_sloppy(function->shared()->language_mode()) && | 2892 if (is_sloppy(function->shared()->language_mode()) && |
2873 !function->shared()->native()) { | 2893 !function->shared()->native()) { |
2874 args[pos++] = | 2894 args[pos++] = |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2919 args[pos++] = HeapConstant(isolate->native_context()); | 2939 args[pos++] = HeapConstant(isolate->native_context()); |
2920 args[pos++] = *effect_; | 2940 args[pos++] = *effect_; |
2921 args[pos++] = *control_; | 2941 args[pos++] = *control_; |
2922 | 2942 |
2923 call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); | 2943 call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args); |
2924 } | 2944 } |
2925 | 2945 |
2926 *effect_ = call; | 2946 *effect_ = call; |
2927 SetSourcePosition(call, 0); | 2947 SetSourcePosition(call, 0); |
2928 | 2948 |
| 2949 if (trap_handler::UseTrapHandler()) { |
| 2950 BuildCallToRuntime(Runtime::kSetThreadInWasm, jsgraph(), |
| 2951 jsgraph()->isolate()->native_context(), nullptr, 0, |
| 2952 effect_, *control_); |
| 2953 } |
| 2954 |
2929 // Convert the return value back. | 2955 // Convert the return value back. |
2930 Node* i32_zero = jsgraph()->Int32Constant(0); | 2956 Node* i32_zero = jsgraph()->Int32Constant(0); |
2931 Node* val = sig->return_count() == 0 | 2957 Node* val = sig->return_count() == 0 |
2932 ? i32_zero | 2958 ? i32_zero |
2933 : FromJS(call, HeapConstant(isolate->native_context()), | 2959 : FromJS(call, HeapConstant(isolate->native_context()), |
2934 sig->GetReturn()); | 2960 sig->GetReturn()); |
2935 Return(val); | 2961 Return(val); |
2936 } | 2962 } |
2937 | 2963 |
2938 void WasmGraphBuilder::BuildWasmInterpreterEntry( | 2964 void WasmGraphBuilder::BuildWasmInterpreterEntry( |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3189 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); | 3215 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond, position); |
3190 } | 3216 } |
3191 | 3217 |
3192 Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype, | 3218 Node* WasmGraphBuilder::LoadMem(wasm::ValueType type, MachineType memtype, |
3193 Node* index, uint32_t offset, | 3219 Node* index, uint32_t offset, |
3194 uint32_t alignment, | 3220 uint32_t alignment, |
3195 wasm::WasmCodePosition position) { | 3221 wasm::WasmCodePosition position) { |
3196 Node* load; | 3222 Node* load; |
3197 | 3223 |
3198 // WASM semantics throw on OOB. Introduce explicit bounds check. | 3224 // WASM semantics throw on OOB. Introduce explicit bounds check. |
3199 if (!FLAG_wasm_trap_handler || !kTrapHandlerSupported) { | 3225 if (!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED) { |
3200 BoundsCheckMem(memtype, index, offset, position); | 3226 BoundsCheckMem(memtype, index, offset, position); |
3201 } | 3227 } |
3202 bool aligned = static_cast<int>(alignment) >= | 3228 bool aligned = static_cast<int>(alignment) >= |
3203 ElementSizeLog2Of(memtype.representation()); | 3229 ElementSizeLog2Of(memtype.representation()); |
3204 | 3230 |
3205 if (aligned || | 3231 if (aligned || |
3206 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { | 3232 jsgraph()->machine()->UnalignedLoadSupported(memtype, alignment)) { |
3207 if (FLAG_wasm_trap_handler && kTrapHandlerSupported) { | 3233 if (FLAG_wasm_trap_handler && V8_TRAP_HANDLER_SUPPORTED) { |
3208 DCHECK(FLAG_wasm_guard_pages); | 3234 DCHECK(FLAG_wasm_guard_pages); |
3209 Node* position_node = jsgraph()->Int32Constant(position); | 3235 Node* position_node = jsgraph()->Int32Constant(position); |
3210 load = graph()->NewNode(jsgraph()->machine()->ProtectedLoad(memtype), | 3236 load = graph()->NewNode(jsgraph()->machine()->ProtectedLoad(memtype), |
3211 MemBuffer(offset), index, position_node, *effect_, | 3237 MemBuffer(offset), index, position_node, *effect_, |
3212 *control_); | 3238 *control_); |
3213 } else { | 3239 } else { |
3214 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), | 3240 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
3215 MemBuffer(offset), index, *effect_, *control_); | 3241 MemBuffer(offset), index, *effect_, *control_); |
3216 } | 3242 } |
3217 } else { | 3243 } else { |
3218 // TODO(eholk): Support unaligned loads with trap handlers. | 3244 // TODO(eholk): Support unaligned loads with trap handlers. |
3219 DCHECK(!FLAG_wasm_trap_handler || !kTrapHandlerSupported); | 3245 DCHECK(!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED); |
3220 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype), | 3246 load = graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype), |
3221 MemBuffer(offset), index, *effect_, *control_); | 3247 MemBuffer(offset), index, *effect_, *control_); |
3222 } | 3248 } |
3223 | 3249 |
3224 *effect_ = load; | 3250 *effect_ = load; |
3225 | 3251 |
3226 #if defined(V8_TARGET_BIG_ENDIAN) | 3252 #if defined(V8_TARGET_BIG_ENDIAN) |
3227 load = BuildChangeEndianness(load, memtype, type); | 3253 load = BuildChangeEndianness(load, memtype, type); |
3228 #endif | 3254 #endif |
3229 | 3255 |
(...skipping 13 matching lines...) Expand all Loading... |
3243 return load; | 3269 return load; |
3244 } | 3270 } |
3245 | 3271 |
3246 | 3272 |
3247 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, | 3273 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
3248 uint32_t offset, uint32_t alignment, Node* val, | 3274 uint32_t offset, uint32_t alignment, Node* val, |
3249 wasm::WasmCodePosition position) { | 3275 wasm::WasmCodePosition position) { |
3250 Node* store; | 3276 Node* store; |
3251 | 3277 |
3252 // WASM semantics throw on OOB. Introduce explicit bounds check. | 3278 // WASM semantics throw on OOB. Introduce explicit bounds check. |
3253 if (!FLAG_wasm_trap_handler || !kTrapHandlerSupported) { | 3279 if (!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED) { |
3254 BoundsCheckMem(memtype, index, offset, position); | 3280 BoundsCheckMem(memtype, index, offset, position); |
3255 } | 3281 } |
3256 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3282 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
3257 | 3283 |
3258 bool aligned = static_cast<int>(alignment) >= | 3284 bool aligned = static_cast<int>(alignment) >= |
3259 ElementSizeLog2Of(memtype.representation()); | 3285 ElementSizeLog2Of(memtype.representation()); |
3260 | 3286 |
3261 #if defined(V8_TARGET_BIG_ENDIAN) | 3287 #if defined(V8_TARGET_BIG_ENDIAN) |
3262 val = BuildChangeEndianness(val, memtype); | 3288 val = BuildChangeEndianness(val, memtype); |
3263 #endif | 3289 #endif |
3264 | 3290 |
3265 if (aligned || | 3291 if (aligned || |
3266 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { | 3292 jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
3267 if (FLAG_wasm_trap_handler && kTrapHandlerSupported) { | 3293 if (FLAG_wasm_trap_handler && V8_TRAP_HANDLER_SUPPORTED) { |
3268 Node* position_node = jsgraph()->Int32Constant(position); | 3294 Node* position_node = jsgraph()->Int32Constant(position); |
3269 store = graph()->NewNode( | 3295 store = graph()->NewNode( |
3270 jsgraph()->machine()->ProtectedStore(memtype.representation()), | 3296 jsgraph()->machine()->ProtectedStore(memtype.representation()), |
3271 MemBuffer(offset), index, val, position_node, *effect_, *control_); | 3297 MemBuffer(offset), index, val, position_node, *effect_, *control_); |
3272 } else { | 3298 } else { |
3273 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); | 3299 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
3274 store = | 3300 store = |
3275 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), | 3301 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
3276 index, val, *effect_, *control_); | 3302 index, val, *effect_, *control_); |
3277 } | 3303 } |
3278 } else { | 3304 } else { |
3279 // TODO(eholk): Support unaligned stores with trap handlers. | 3305 // TODO(eholk): Support unaligned stores with trap handlers. |
3280 DCHECK(!FLAG_wasm_trap_handler || !kTrapHandlerSupported); | 3306 DCHECK(!FLAG_wasm_trap_handler || !V8_TRAP_HANDLER_SUPPORTED); |
3281 UnalignedStoreRepresentation rep(memtype.representation()); | 3307 UnalignedStoreRepresentation rep(memtype.representation()); |
3282 store = | 3308 store = |
3283 graph()->NewNode(jsgraph()->machine()->UnalignedStore(rep), | 3309 graph()->NewNode(jsgraph()->machine()->UnalignedStore(rep), |
3284 MemBuffer(offset), index, val, *effect_, *control_); | 3310 MemBuffer(offset), index, val, *effect_, *control_); |
3285 } | 3311 } |
3286 | 3312 |
3287 *effect_ = store; | 3313 *effect_ = store; |
3288 | 3314 |
3289 return store; | 3315 return store; |
3290 } | 3316 } |
(...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4143 function_->code_start_offset), | 4169 function_->code_start_offset), |
4144 compile_ms); | 4170 compile_ms); |
4145 } | 4171 } |
4146 | 4172 |
4147 return code; | 4173 return code; |
4148 } | 4174 } |
4149 | 4175 |
4150 } // namespace compiler | 4176 } // namespace compiler |
4151 } // namespace internal | 4177 } // namespace internal |
4152 } // namespace v8 | 4178 } // namespace v8 |
OLD | NEW |