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