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