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