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 |