| 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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 } | 173 } |
| 174 | 174 |
| 175 // Add a check that traps if {node} is zero. | 175 // Add a check that traps if {node} is zero. |
| 176 Node* ZeroCheck64(wasm::TrapReason reason, Node* node, | 176 Node* ZeroCheck64(wasm::TrapReason reason, Node* node, |
| 177 wasm::WasmCodePosition position) { | 177 wasm::WasmCodePosition position) { |
| 178 return TrapIfEq64(reason, node, 0, position); | 178 return TrapIfEq64(reason, node, 0, position); |
| 179 } | 179 } |
| 180 | 180 |
| 181 Builtins::Name GetBuiltinIdForTrap(wasm::TrapReason reason) { | 181 Builtins::Name GetBuiltinIdForTrap(wasm::TrapReason reason) { |
| 182 bool in_cctest = | 182 bool in_cctest = |
| 183 !builder_->module_ || builder_->module_->instance->context.is_null(); | 183 !builder_->module_ || (builder_->module_->instance && |
| 184 builder_->module_->instance->context.is_null()); |
| 184 if (in_cctest) { | 185 if (in_cctest) { |
| 185 // We use Builtins::builtin_count as a marker to tell the code generator | 186 // We use Builtins::builtin_count as a marker to tell the code generator |
| 186 // to generate a call to a testing c-function instead of a runtime | 187 // to generate a call to a testing c-function instead of a runtime |
| 187 // function. This code should only be called from a cctest. | 188 // function. This code should only be called from a cctest. |
| 188 return Builtins::builtin_count; | 189 return Builtins::builtin_count; |
| 189 } | 190 } |
| 190 | 191 |
| 191 switch (reason) { | 192 switch (reason) { |
| 192 #define TRAPREASON_TO_MESSAGE(name) \ | 193 #define TRAPREASON_TO_MESSAGE(name) \ |
| 193 case wasm::k##name: \ | 194 case wasm::k##name: \ |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 } | 481 } |
| 481 | 482 |
| 482 Node* WasmGraphBuilder::Int64Constant(int64_t value) { | 483 Node* WasmGraphBuilder::Int64Constant(int64_t value) { |
| 483 return jsgraph()->Int64Constant(value); | 484 return jsgraph()->Int64Constant(value); |
| 484 } | 485 } |
| 485 | 486 |
| 486 void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position, | 487 void WasmGraphBuilder::StackCheck(wasm::WasmCodePosition position, |
| 487 Node** effect, Node** control) { | 488 Node** effect, Node** control) { |
| 488 if (FLAG_wasm_no_stack_checks) return; | 489 if (FLAG_wasm_no_stack_checks) return; |
| 489 // We do not generate stack checks for cctests. | 490 // We do not generate stack checks for cctests. |
| 490 if (!module_ || module_->instance->context.is_null()) return; | 491 if (!module_ || (module_->instance && module_->instance->context.is_null())) |
| 492 return; |
| 491 if (effect == nullptr) effect = effect_; | 493 if (effect == nullptr) effect = effect_; |
| 492 if (control == nullptr) control = control_; | 494 if (control == nullptr) control = control_; |
| 493 | 495 |
| 494 Node* limit = graph()->NewNode( | 496 Node* limit = graph()->NewNode( |
| 495 jsgraph()->machine()->Load(MachineType::Pointer()), | 497 jsgraph()->machine()->Load(MachineType::Pointer()), |
| 496 jsgraph()->ExternalConstant( | 498 jsgraph()->ExternalConstant( |
| 497 ExternalReference::address_of_stack_limit(jsgraph()->isolate())), | 499 ExternalReference::address_of_stack_limit(jsgraph()->isolate())), |
| 498 jsgraph()->IntPtrConstant(0), *effect, *control); | 500 jsgraph()->IntPtrConstant(0), *effect, *control); |
| 499 Node* pointer = graph()->NewNode(jsgraph()->machine()->LoadStackPointer()); | 501 Node* pointer = graph()->NewNode(jsgraph()->machine()->LoadStackPointer()); |
| 500 | 502 |
| (...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1789 BuildCCall(sig_builder.Build(), args), position); | 1791 BuildCCall(sig_builder.Build(), args), position); |
| 1790 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1792 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
| 1791 Node* load = | 1793 Node* load = |
| 1792 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1794 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
| 1793 *effect_, *control_); | 1795 *effect_, *control_); |
| 1794 *effect_ = load; | 1796 *effect_ = load; |
| 1795 return load; | 1797 return load; |
| 1796 } | 1798 } |
| 1797 | 1799 |
| 1798 Node* WasmGraphBuilder::GrowMemory(Node* input) { | 1800 Node* WasmGraphBuilder::GrowMemory(Node* input) { |
| 1801 // GrowMemory will not be called from asm.js, hence we cannot be in |
| 1802 // lazy-compilation mode, hence the instance will be set. |
| 1803 DCHECK_NOT_NULL(module_); |
| 1804 DCHECK_NOT_NULL(module_->instance); |
| 1805 |
| 1799 Diamond check_input_range( | 1806 Diamond check_input_range( |
| 1800 graph(), jsgraph()->common(), | 1807 graph(), jsgraph()->common(), |
| 1801 graph()->NewNode(jsgraph()->machine()->Uint32LessThanOrEqual(), input, | 1808 graph()->NewNode(jsgraph()->machine()->Uint32LessThanOrEqual(), input, |
| 1802 jsgraph()->Uint32Constant(FLAG_wasm_max_mem_pages)), | 1809 jsgraph()->Uint32Constant(FLAG_wasm_max_mem_pages)), |
| 1803 BranchHint::kTrue); | 1810 BranchHint::kTrue); |
| 1804 | 1811 |
| 1805 check_input_range.Chain(*control_); | 1812 check_input_range.Chain(*control_); |
| 1806 | 1813 |
| 1807 Node* parameters[] = {BuildChangeUint32ToSmi(input)}; | 1814 Node* parameters[] = {BuildChangeUint32ToSmi(input)}; |
| 1808 Node* old_effect = *effect_; | 1815 Node* old_effect = *effect_; |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2279 } | 2286 } |
| 2280 } | 2287 } |
| 2281 return call; | 2288 return call; |
| 2282 } | 2289 } |
| 2283 | 2290 |
| 2284 Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets, | 2291 Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, Node*** rets, |
| 2285 wasm::WasmCodePosition position) { | 2292 wasm::WasmCodePosition position) { |
| 2286 DCHECK_NULL(args[0]); | 2293 DCHECK_NULL(args[0]); |
| 2287 | 2294 |
| 2288 // Add code object as constant. | 2295 // Add code object as constant. |
| 2289 Handle<Code> code = module_->GetFunctionCode(index); | 2296 Handle<Code> code = module_->instance |
| 2297 ? module_->GetFunctionCode(index) |
| 2298 : jsgraph()->isolate()->builtins()->Illegal(); |
| 2290 DCHECK(!code.is_null()); | 2299 DCHECK(!code.is_null()); |
| 2291 args[0] = HeapConstant(code); | 2300 args[0] = HeapConstant(code); |
| 2292 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); | 2301 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); |
| 2293 | 2302 |
| 2294 return BuildWasmCall(sig, args, rets, position); | 2303 return BuildWasmCall(sig, args, rets, position); |
| 2295 } | 2304 } |
| 2296 | 2305 |
| 2297 Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args, | 2306 Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args, |
| 2298 Node*** rets, | 2307 Node*** rets, |
| 2299 wasm::WasmCodePosition position) { | 2308 wasm::WasmCodePosition position) { |
| 2300 DCHECK_NOT_NULL(args[0]); | 2309 DCHECK_NOT_NULL(args[0]); |
| 2301 DCHECK(module_ && module_->instance); | 2310 DCHECK_NOT_NULL(module_); |
| 2302 | 2311 |
| 2303 // Assume only one table for now. | 2312 // Assume only one table for now. |
| 2304 uint32_t table_index = 0; | 2313 uint32_t table_index = 0; |
| 2305 wasm::FunctionSig* sig = module_->GetSignature(sig_index); | 2314 wasm::FunctionSig* sig = module_->GetSignature(sig_index); |
| 2306 | 2315 |
| 2307 DCHECK(module_->IsValidTable(table_index)); | 2316 DCHECK(module_->IsValidTable(table_index)); |
| 2308 | 2317 |
| 2309 EnsureFunctionTableNodes(); | 2318 EnsureFunctionTableNodes(); |
| 2310 MachineOperatorBuilder* machine = jsgraph()->machine(); | 2319 MachineOperatorBuilder* machine = jsgraph()->machine(); |
| 2311 Node* key = args[0]; | 2320 Node* key = args[0]; |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3036 MachineType load_rep = | 3045 MachineType load_rep = |
| 3037 wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn()); | 3046 wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn()); |
| 3038 val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, | 3047 val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, |
| 3039 Int32Constant(0), *effect_, *control_); | 3048 Int32Constant(0), *effect_, *control_); |
| 3040 } | 3049 } |
| 3041 Return(val); | 3050 Return(val); |
| 3042 } | 3051 } |
| 3043 } | 3052 } |
| 3044 | 3053 |
| 3045 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { | 3054 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { |
| 3046 DCHECK(module_ && module_->instance); | 3055 DCHECK_NOT_NULL(module_); |
| 3056 uintptr_t mem_start = reinterpret_cast<uintptr_t>( |
| 3057 module_->instance ? module_->instance->mem_start : nullptr); |
| 3047 if (offset == 0) { | 3058 if (offset == 0) { |
| 3048 if (!mem_buffer_) { | 3059 if (!mem_buffer_) { |
| 3049 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( | 3060 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( |
| 3050 reinterpret_cast<uintptr_t>(module_->instance->mem_start), | 3061 mem_start, RelocInfo::WASM_MEMORY_REFERENCE); |
| 3051 RelocInfo::WASM_MEMORY_REFERENCE); | |
| 3052 } | 3062 } |
| 3053 return mem_buffer_; | 3063 return mem_buffer_; |
| 3054 } else { | 3064 } else { |
| 3055 return jsgraph()->RelocatableIntPtrConstant( | 3065 return jsgraph()->RelocatableIntPtrConstant( |
| 3056 reinterpret_cast<uintptr_t>(module_->instance->mem_start + offset), | 3066 mem_start + offset, RelocInfo::WASM_MEMORY_REFERENCE); |
| 3057 RelocInfo::WASM_MEMORY_REFERENCE); | |
| 3058 } | 3067 } |
| 3059 } | 3068 } |
| 3060 | 3069 |
| 3061 Node* WasmGraphBuilder::CurrentMemoryPages() { | 3070 Node* WasmGraphBuilder::CurrentMemoryPages() { |
| 3071 // CurrentMemoryPages will not be called from asm.js, hence we cannot be in |
| 3072 // lazy-compilation mode, hence the instance will be set. |
| 3073 DCHECK_EQ(wasm::kWasmOrigin, module_->module->origin); |
| 3074 DCHECK_NOT_NULL(module_); |
| 3075 DCHECK_NOT_NULL(module_->instance); |
| 3076 |
| 3062 Runtime::FunctionId function_id = Runtime::kWasmMemorySize; | 3077 Runtime::FunctionId function_id = Runtime::kWasmMemorySize; |
| 3063 const Runtime::Function* function = Runtime::FunctionForId(function_id); | 3078 const Runtime::Function* function = Runtime::FunctionForId(function_id); |
| 3064 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 3079 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
| 3065 jsgraph()->zone(), function_id, function->nargs, Operator::kNoThrow, | 3080 jsgraph()->zone(), function_id, function->nargs, Operator::kNoThrow, |
| 3066 CallDescriptor::kNoFlags); | 3081 CallDescriptor::kNoFlags); |
| 3067 Node* inputs[] = { | 3082 Node* inputs[] = { |
| 3068 jsgraph()->CEntryStubConstant(function->result_size), // C entry | 3083 jsgraph()->CEntryStubConstant(function->result_size), // C entry |
| 3069 jsgraph()->ExternalConstant( | 3084 jsgraph()->ExternalConstant( |
| 3070 ExternalReference(function_id, jsgraph()->isolate())), // ref | 3085 ExternalReference(function_id, jsgraph()->isolate())), // ref |
| 3071 jsgraph()->Int32Constant(function->nargs), // arity | 3086 jsgraph()->Int32Constant(function->nargs), // arity |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3085 DCHECK_NOT_NULL(module_); | 3100 DCHECK_NOT_NULL(module_); |
| 3086 if (mem_size_) return mem_size_; | 3101 if (mem_size_) return mem_size_; |
| 3087 uint32_t size = module_->instance ? module_->instance->mem_size : 0; | 3102 uint32_t size = module_->instance ? module_->instance->mem_size : 0; |
| 3088 mem_size_ = jsgraph()->RelocatableInt32Constant( | 3103 mem_size_ = jsgraph()->RelocatableInt32Constant( |
| 3089 size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 3104 size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
| 3090 return mem_size_; | 3105 return mem_size_; |
| 3091 } | 3106 } |
| 3092 | 3107 |
| 3093 void WasmGraphBuilder::EnsureFunctionTableNodes() { | 3108 void WasmGraphBuilder::EnsureFunctionTableNodes() { |
| 3094 if (function_tables_.size() > 0) return; | 3109 if (function_tables_.size() > 0) return; |
| 3095 size_t tables_size = module_->instance->function_tables.size(); | 3110 size_t tables_size = module_->module->function_tables.size(); |
| 3096 DCHECK(tables_size == module_->instance->signature_tables.size()); | 3111 if (module_->instance) { |
| 3112 DCHECK_EQ(tables_size, module_->instance->function_tables.size()); |
| 3113 DCHECK_EQ(tables_size, module_->instance->signature_tables.size()); |
| 3114 } |
| 3097 for (size_t i = 0; i < tables_size; ++i) { | 3115 for (size_t i = 0; i < tables_size; ++i) { |
| 3098 auto function_handle = module_->instance->function_tables[i]; | 3116 auto function_handle = module_->GetFunctionTableObj(i); |
| 3099 auto signature_handle = module_->instance->signature_tables[i]; | 3117 auto signature_handle = module_->GetSignatureTableObj(i); |
| 3100 DCHECK(!function_handle.is_null() && !signature_handle.is_null()); | 3118 DCHECK(!function_handle.is_null() && !signature_handle.is_null()); |
| 3101 function_tables_.push_back(HeapConstant(function_handle)); | 3119 function_tables_.push_back(HeapConstant(function_handle)); |
| 3102 signature_tables_.push_back(HeapConstant(signature_handle)); | 3120 signature_tables_.push_back(HeapConstant(signature_handle)); |
| 3103 uint32_t table_size = module_->module->function_tables[i].min_size; | 3121 uint32_t table_size = module_->module->function_tables[i].min_size; |
| 3104 function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant( | 3122 function_table_sizes_.push_back(jsgraph()->RelocatableInt32Constant( |
| 3105 static_cast<uint32_t>(table_size), | 3123 static_cast<uint32_t>(table_size), |
| 3106 RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE)); | 3124 RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE)); |
| 3107 } | 3125 } |
| 3108 } | 3126 } |
| 3109 | 3127 |
| 3110 Node* WasmGraphBuilder::GetGlobal(uint32_t index) { | 3128 Node* WasmGraphBuilder::GetGlobal(uint32_t index) { |
| 3111 MachineType mem_type = | 3129 MachineType mem_type = |
| 3112 wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); | 3130 wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); |
| 3131 byte* globals_start = |
| 3132 module_->instance ? module_->instance->globals_start : nullptr; |
| 3133 uintptr_t global_addr = reinterpret_cast<uintptr_t>( |
| 3134 globals_start + module_->module->globals[index].offset); |
| 3113 Node* addr = jsgraph()->RelocatableIntPtrConstant( | 3135 Node* addr = jsgraph()->RelocatableIntPtrConstant( |
| 3114 reinterpret_cast<uintptr_t>(module_->instance->globals_start + | 3136 global_addr, RelocInfo::WASM_GLOBAL_REFERENCE); |
| 3115 module_->module->globals[index].offset), | |
| 3116 RelocInfo::WASM_GLOBAL_REFERENCE); | |
| 3117 const Operator* op = jsgraph()->machine()->Load(mem_type); | 3137 const Operator* op = jsgraph()->machine()->Load(mem_type); |
| 3118 Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_, | 3138 Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), *effect_, |
| 3119 *control_); | 3139 *control_); |
| 3120 *effect_ = node; | 3140 *effect_ = node; |
| 3121 return node; | 3141 return node; |
| 3122 } | 3142 } |
| 3123 | 3143 |
| 3124 Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) { | 3144 Node* WasmGraphBuilder::SetGlobal(uint32_t index, Node* val) { |
| 3125 MachineType mem_type = | 3145 MachineType mem_type = |
| 3126 wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); | 3146 wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); |
| 3147 byte* globals_start = |
| 3148 module_->instance ? module_->instance->globals_start : 0; |
| 3127 Node* addr = jsgraph()->RelocatableIntPtrConstant( | 3149 Node* addr = jsgraph()->RelocatableIntPtrConstant( |
| 3128 reinterpret_cast<uintptr_t>(module_->instance->globals_start + | 3150 reinterpret_cast<uintptr_t>(globals_start + |
| 3129 module_->module->globals[index].offset), | 3151 module_->module->globals[index].offset), |
| 3130 RelocInfo::WASM_GLOBAL_REFERENCE); | 3152 RelocInfo::WASM_GLOBAL_REFERENCE); |
| 3131 const Operator* op = jsgraph()->machine()->Store( | 3153 const Operator* op = jsgraph()->machine()->Store( |
| 3132 StoreRepresentation(mem_type.representation(), kNoWriteBarrier)); | 3154 StoreRepresentation(mem_type.representation(), kNoWriteBarrier)); |
| 3133 Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val, | 3155 Node* node = graph()->NewNode(op, addr, jsgraph()->Int32Constant(0), val, |
| 3134 *effect_, *control_); | 3156 *effect_, *control_); |
| 3135 *effect_ = node; | 3157 *effect_ = node; |
| 3136 return node; | 3158 return node; |
| 3137 } | 3159 } |
| 3138 | 3160 |
| (...skipping 1096 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 |