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/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 | 10 |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 | 291 |
292 WasmGraphBuilder::WasmGraphBuilder( | 292 WasmGraphBuilder::WasmGraphBuilder( |
293 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature, | 293 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature, |
294 compiler::SourcePositionTable* source_position_table) | 294 compiler::SourcePositionTable* source_position_table) |
295 : zone_(zone), | 295 : zone_(zone), |
296 jsgraph_(jsgraph), | 296 jsgraph_(jsgraph), |
297 module_(nullptr), | 297 module_(nullptr), |
298 mem_buffer_(nullptr), | 298 mem_buffer_(nullptr), |
299 mem_size_(nullptr), | 299 mem_size_(nullptr), |
300 function_tables_(zone), | 300 function_tables_(zone), |
301 function_table_sizes_(zone), | |
302 control_(nullptr), | 301 control_(nullptr), |
303 effect_(nullptr), | 302 effect_(nullptr), |
304 cur_buffer_(def_buffer_), | 303 cur_buffer_(def_buffer_), |
305 cur_bufsize_(kDefaultBufferSize), | 304 cur_bufsize_(kDefaultBufferSize), |
306 trap_(new (zone) WasmTrapHelper(this)), | 305 trap_(new (zone) WasmTrapHelper(this)), |
307 function_signature_(function_signature), | 306 function_signature_(function_signature), |
308 source_position_table_(source_position_table) { | 307 source_position_table_(source_position_table) { |
309 DCHECK_NOT_NULL(jsgraph_); | 308 DCHECK_NOT_NULL(jsgraph_); |
310 } | 309 } |
311 | 310 |
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1706 *effect_, *control_); | 1705 *effect_, *control_); |
1707 *effect_ = load; | 1706 *effect_ = load; |
1708 return load; | 1707 return load; |
1709 } | 1708 } |
1710 | 1709 |
1711 Node* WasmGraphBuilder::GrowMemory(Node* input) { | 1710 Node* WasmGraphBuilder::GrowMemory(Node* input) { |
1712 Diamond check_input_range( | 1711 Diamond check_input_range( |
1713 graph(), jsgraph()->common(), | 1712 graph(), jsgraph()->common(), |
1714 graph()->NewNode( | 1713 graph()->NewNode( |
1715 jsgraph()->machine()->Uint32LessThanOrEqual(), input, | 1714 jsgraph()->machine()->Uint32LessThanOrEqual(), input, |
1716 jsgraph()->Uint32Constant(wasm::WasmModule::kV8MaxPages)), | 1715 jsgraph()->Uint32Constant(wasm::WasmModule::kMaxMemPages)), |
1717 BranchHint::kTrue); | 1716 BranchHint::kTrue); |
1718 | 1717 |
1719 check_input_range.Chain(*control_); | 1718 check_input_range.Chain(*control_); |
1720 | 1719 |
1721 Runtime::FunctionId function_id = Runtime::kWasmGrowMemory; | 1720 Runtime::FunctionId function_id = Runtime::kWasmGrowMemory; |
1722 const Runtime::Function* function = Runtime::FunctionForId(function_id); | 1721 const Runtime::Function* function = Runtime::FunctionForId(function_id); |
1723 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 1722 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
1724 jsgraph()->zone(), function_id, function->nargs, Operator::kNoThrow, | 1723 jsgraph()->zone(), function_id, function->nargs, Operator::kNoThrow, |
1725 CallDescriptor::kNoFlags); | 1724 CallDescriptor::kNoFlags); |
1726 wasm::ModuleEnv* module = module_; | 1725 wasm::ModuleEnv* module = module_; |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2148 | 2147 |
2149 // Add code object as constant. | 2148 // Add code object as constant. |
2150 Handle<Code> code = module_->GetFunctionCode(index); | 2149 Handle<Code> code = module_->GetFunctionCode(index); |
2151 DCHECK(!code.is_null()); | 2150 DCHECK(!code.is_null()); |
2152 args[0] = HeapConstant(code); | 2151 args[0] = HeapConstant(code); |
2153 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); | 2152 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); |
2154 | 2153 |
2155 return BuildWasmCall(sig, args, rets, position); | 2154 return BuildWasmCall(sig, args, rets, position); |
2156 } | 2155 } |
2157 | 2156 |
2158 Node* WasmGraphBuilder::CallIndirect(uint32_t sig_index, Node** args, | 2157 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, Node*** rets, |
2159 Node*** rets, | |
2160 wasm::WasmCodePosition position) { | 2158 wasm::WasmCodePosition position) { |
2161 DCHECK_NOT_NULL(args[0]); | 2159 DCHECK_NOT_NULL(args[0]); |
2162 DCHECK(module_ && module_->instance); | 2160 DCHECK(module_ && module_->instance); |
2163 | 2161 |
| 2162 MachineOperatorBuilder* machine = jsgraph()->machine(); |
| 2163 |
| 2164 // Compute the code object by loading it from the function table. |
| 2165 Node* key = args[0]; |
| 2166 |
2164 // Assume only one table for now. | 2167 // Assume only one table for now. |
2165 uint32_t table_index = 0; | 2168 DCHECK_LE(module_->instance->function_tables.size(), 1u); |
2166 wasm::FunctionSig* sig = module_->GetSignature(sig_index); | 2169 // Bounds check the index. |
2167 | 2170 uint32_t table_size = |
2168 if (!module_->IsValidTable(table_index)) { | 2171 module_->IsValidTable(0) ? module_->GetTable(0)->max_size : 0; |
| 2172 wasm::FunctionSig* sig = module_->GetSignature(index); |
| 2173 if (table_size > 0) { |
| 2174 // Bounds check against the table size. |
| 2175 Node* size = Uint32Constant(table_size); |
| 2176 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
| 2177 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); |
| 2178 } else { |
2169 // No function table. Generate a trap and return a constant. | 2179 // No function table. Generate a trap and return a constant. |
2170 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2180 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2171 (*rets) = Buffer(sig->return_count()); | 2181 (*rets) = Buffer(sig->return_count()); |
2172 for (size_t i = 0; i < sig->return_count(); i++) { | 2182 for (size_t i = 0; i < sig->return_count(); i++) { |
2173 (*rets)[i] = trap_->GetTrapValue(sig->GetReturn(i)); | 2183 (*rets)[i] = trap_->GetTrapValue(sig->GetReturn(i)); |
2174 } | 2184 } |
2175 return trap_->GetTrapValue(sig); | 2185 return trap_->GetTrapValue(sig); |
2176 } | 2186 } |
2177 | 2187 Node* table = FunctionTable(0); |
2178 EnsureFunctionTableNodes(); | |
2179 MachineOperatorBuilder* machine = jsgraph()->machine(); | |
2180 Node* key = args[0]; | |
2181 | |
2182 // Bounds check against the table size. | |
2183 Node* size = function_table_sizes_[table_index]; | |
2184 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | |
2185 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); | |
2186 Node* table = function_tables_[table_index]; | |
2187 | 2188 |
2188 // Load signature from the table and check. | 2189 // Load signature from the table and check. |
2189 // The table is a FixedArray; signatures are encoded as SMIs. | 2190 // The table is a FixedArray; signatures are encoded as SMIs. |
2190 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 2191 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
2191 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 2192 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
2192 const int fixed_offset = access.header_size - access.tag(); | 2193 const int fixed_offset = access.header_size - access.tag(); |
2193 { | 2194 { |
2194 Node* load_sig = graph()->NewNode( | 2195 Node* load_sig = graph()->NewNode( |
2195 machine->Load(MachineType::AnyTagged()), table, | 2196 machine->Load(MachineType::AnyTagged()), table, |
2196 graph()->NewNode(machine->Int32Add(), | 2197 graph()->NewNode(machine->Int32Add(), |
2197 graph()->NewNode(machine->Word32Shl(), key, | 2198 graph()->NewNode(machine->Word32Shl(), key, |
2198 Int32Constant(kPointerSizeLog2)), | 2199 Int32Constant(kPointerSizeLog2)), |
2199 Int32Constant(fixed_offset)), | 2200 Int32Constant(fixed_offset)), |
2200 *effect_, *control_); | 2201 *effect_, *control_); |
2201 auto map = const_cast<wasm::SignatureMap&>( | 2202 auto map = const_cast<wasm::SignatureMap&>( |
2202 module_->module->function_tables[0].map); | 2203 module_->module->function_tables[0].map); |
2203 Node* sig_match = graph()->NewNode( | 2204 Node* sig_match = graph()->NewNode( |
2204 machine->WordEqual(), load_sig, | 2205 machine->WordEqual(), load_sig, |
2205 jsgraph()->SmiConstant(static_cast<int>(map.FindOrInsert(sig)))); | 2206 jsgraph()->SmiConstant(static_cast<int>(map.FindOrInsert(sig)))); |
2206 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); | 2207 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); |
2207 } | 2208 } |
2208 | 2209 |
2209 // Load code object from the table. | 2210 // Load code object from the table. |
2210 uint32_t table_size = module_->module->function_tables[table_index].min_size; | |
2211 uint32_t offset = fixed_offset + kPointerSize * table_size; | 2211 uint32_t offset = fixed_offset + kPointerSize * table_size; |
2212 Node* load_code = graph()->NewNode( | 2212 Node* load_code = graph()->NewNode( |
2213 machine->Load(MachineType::AnyTagged()), table, | 2213 machine->Load(MachineType::AnyTagged()), table, |
2214 graph()->NewNode(machine->Int32Add(), | 2214 graph()->NewNode(machine->Int32Add(), |
2215 graph()->NewNode(machine->Word32Shl(), key, | 2215 graph()->NewNode(machine->Word32Shl(), key, |
2216 Int32Constant(kPointerSizeLog2)), | 2216 Int32Constant(kPointerSizeLog2)), |
2217 Uint32Constant(offset)), | 2217 Uint32Constant(offset)), |
2218 *effect_, *control_); | 2218 *effect_, *control_); |
2219 | 2219 |
2220 args[0] = load_code; | 2220 args[0] = load_code; |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2847 if (!mem_size_) | 2847 if (!mem_size_) |
2848 mem_size_ = jsgraph()->RelocatableInt32Constant( | 2848 mem_size_ = jsgraph()->RelocatableInt32Constant( |
2849 size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 2849 size, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
2850 return mem_size_; | 2850 return mem_size_; |
2851 } else { | 2851 } else { |
2852 return jsgraph()->RelocatableInt32Constant( | 2852 return jsgraph()->RelocatableInt32Constant( |
2853 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 2853 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
2854 } | 2854 } |
2855 } | 2855 } |
2856 | 2856 |
2857 void WasmGraphBuilder::EnsureFunctionTableNodes() { | 2857 Node* WasmGraphBuilder::FunctionTable(uint32_t index) { |
2858 if (function_tables_.size() > 0) return; | 2858 DCHECK(module_ && module_->instance && |
2859 for (size_t i = 0; i < module_->instance->function_tables.size(); ++i) { | 2859 index < module_->instance->function_tables.size()); |
2860 auto handle = module_->instance->function_tables[i]; | 2860 if (!function_tables_.size()) { |
2861 DCHECK(!handle.is_null()); | 2861 for (size_t i = 0; i < module_->instance->function_tables.size(); ++i) { |
2862 function_tables_.push_back(HeapConstant(handle)); | 2862 DCHECK(!module_->instance->function_tables[i].is_null()); |
2863 uint32_t table_size = module_->module->function_tables[i].min_size; | 2863 function_tables_.push_back( |
2864 function_table_sizes_.push_back(Uint32Constant(table_size)); | 2864 HeapConstant(module_->instance->function_tables[i])); |
| 2865 } |
2865 } | 2866 } |
| 2867 return function_tables_[index]; |
2866 } | 2868 } |
2867 | 2869 |
2868 Node* WasmGraphBuilder::GetGlobal(uint32_t index) { | 2870 Node* WasmGraphBuilder::GetGlobal(uint32_t index) { |
2869 MachineType mem_type = | 2871 MachineType mem_type = |
2870 wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); | 2872 wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); |
2871 Node* addr = jsgraph()->RelocatableIntPtrConstant( | 2873 Node* addr = jsgraph()->RelocatableIntPtrConstant( |
2872 reinterpret_cast<uintptr_t>(module_->instance->globals_start + | 2874 reinterpret_cast<uintptr_t>(module_->instance->globals_start + |
2873 module_->module->globals[index].offset), | 2875 module_->module->globals[index].offset), |
2874 RelocInfo::WASM_GLOBAL_REFERENCE); | 2876 RelocInfo::WASM_GLOBAL_REFERENCE); |
2875 const Operator* op = jsgraph()->machine()->Load(mem_type); | 2877 const Operator* op = jsgraph()->machine()->Load(mem_type); |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3480 function_->code_start_offset), | 3482 function_->code_start_offset), |
3481 compile_ms); | 3483 compile_ms); |
3482 } | 3484 } |
3483 | 3485 |
3484 return code; | 3486 return code; |
3485 } | 3487 } |
3486 | 3488 |
3487 } // namespace compiler | 3489 } // namespace compiler |
3488 } // namespace internal | 3490 } // namespace internal |
3489 } // namespace v8 | 3491 } // namespace v8 |
OLD | NEW |