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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 }; | 271 }; |
272 | 272 |
273 WasmGraphBuilder::WasmGraphBuilder( | 273 WasmGraphBuilder::WasmGraphBuilder( |
274 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature, | 274 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature, |
275 compiler::SourcePositionTable* source_position_table) | 275 compiler::SourcePositionTable* source_position_table) |
276 : zone_(zone), | 276 : zone_(zone), |
277 jsgraph_(jsgraph), | 277 jsgraph_(jsgraph), |
278 module_(nullptr), | 278 module_(nullptr), |
279 mem_buffer_(nullptr), | 279 mem_buffer_(nullptr), |
280 mem_size_(nullptr), | 280 mem_size_(nullptr), |
281 function_table_(nullptr), | 281 function_tables_(zone), |
282 control_(nullptr), | 282 control_(nullptr), |
283 effect_(nullptr), | 283 effect_(nullptr), |
284 cur_buffer_(def_buffer_), | 284 cur_buffer_(def_buffer_), |
285 cur_bufsize_(kDefaultBufferSize), | 285 cur_bufsize_(kDefaultBufferSize), |
286 trap_(new (zone) WasmTrapHelper(this)), | 286 trap_(new (zone) WasmTrapHelper(this)), |
287 function_signature_(function_signature), | 287 function_signature_(function_signature), |
288 source_position_table_(source_position_table) { | 288 source_position_table_(source_position_table) { |
289 DCHECK_NOT_NULL(jsgraph_); | 289 DCHECK_NOT_NULL(jsgraph_); |
290 } | 290 } |
291 | 291 |
(...skipping 1760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2052 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, | 2052 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, |
2053 wasm::WasmCodePosition position) { | 2053 wasm::WasmCodePosition position) { |
2054 DCHECK_NOT_NULL(args[0]); | 2054 DCHECK_NOT_NULL(args[0]); |
2055 DCHECK(module_ && module_->instance); | 2055 DCHECK(module_ && module_->instance); |
2056 | 2056 |
2057 MachineOperatorBuilder* machine = jsgraph()->machine(); | 2057 MachineOperatorBuilder* machine = jsgraph()->machine(); |
2058 | 2058 |
2059 // Compute the code object by loading it from the function table. | 2059 // Compute the code object by loading it from the function table. |
2060 Node* key = args[0]; | 2060 Node* key = args[0]; |
2061 | 2061 |
| 2062 // Assume only one table for now. |
| 2063 DCHECK_LE(module_->instance->function_tables.size(), 1u); |
2062 // Bounds check the index. | 2064 // Bounds check the index. |
2063 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2065 uint32_t table_size = |
| 2066 module_->IsValidTable(0) ? module_->GetTable(0)->max_size : 0; |
2064 if (table_size > 0) { | 2067 if (table_size > 0) { |
2065 // Bounds check against the table size. | 2068 // Bounds check against the table size. |
2066 Node* size = Int32Constant(static_cast<int>(table_size)); | 2069 Node* size = Uint32Constant(table_size); |
2067 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 2070 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
2068 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); | 2071 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); |
2069 } else { | 2072 } else { |
2070 // No function table. Generate a trap and return a constant. | 2073 // No function table. Generate a trap and return a constant. |
2071 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2074 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2072 return trap_->GetTrapValue(module_->GetSignature(index)); | 2075 return trap_->GetTrapValue(module_->GetSignature(index)); |
2073 } | 2076 } |
2074 Node* table = FunctionTable(); | 2077 Node* table = FunctionTable(0); |
2075 | 2078 |
2076 // Load signature from the table and check. | 2079 // Load signature from the table and check. |
2077 // The table is a FixedArray; signatures are encoded as SMIs. | 2080 // The table is a FixedArray; signatures are encoded as SMIs. |
2078 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 2081 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
2079 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 2082 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
2080 const int fixed_offset = access.header_size - access.tag(); | 2083 const int fixed_offset = access.header_size - access.tag(); |
2081 { | 2084 { |
2082 Node* load_sig = graph()->NewNode( | 2085 Node* load_sig = graph()->NewNode( |
2083 machine->Load(MachineType::AnyTagged()), table, | 2086 machine->Load(MachineType::AnyTagged()), table, |
2084 graph()->NewNode(machine->Int32Add(), | 2087 graph()->NewNode(machine->Int32Add(), |
2085 graph()->NewNode(machine->Word32Shl(), key, | 2088 graph()->NewNode(machine->Word32Shl(), key, |
2086 Int32Constant(kPointerSizeLog2)), | 2089 Int32Constant(kPointerSizeLog2)), |
2087 Int32Constant(fixed_offset)), | 2090 Int32Constant(fixed_offset)), |
2088 *effect_, *control_); | 2091 *effect_, *control_); |
2089 Node* sig_match = | 2092 Node* sig_match = |
2090 graph()->NewNode(machine->Word32Equal(), | 2093 graph()->NewNode(machine->Word32Equal(), |
2091 BuildChangeSmiToInt32(load_sig), Int32Constant(index)); | 2094 BuildChangeSmiToInt32(load_sig), Int32Constant(index)); |
2092 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); | 2095 trap_->AddTrapIfFalse(wasm::kTrapFuncSigMismatch, sig_match, position); |
2093 } | 2096 } |
2094 | 2097 |
2095 // Load code object from the table. | 2098 // Load code object from the table. |
2096 int offset = fixed_offset + kPointerSize * table_size; | 2099 uint32_t offset = fixed_offset + kPointerSize * table_size; |
2097 Node* load_code = graph()->NewNode( | 2100 Node* load_code = graph()->NewNode( |
2098 machine->Load(MachineType::AnyTagged()), table, | 2101 machine->Load(MachineType::AnyTagged()), table, |
2099 graph()->NewNode(machine->Int32Add(), | 2102 graph()->NewNode(machine->Int32Add(), |
2100 graph()->NewNode(machine->Word32Shl(), key, | 2103 graph()->NewNode(machine->Word32Shl(), key, |
2101 Int32Constant(kPointerSizeLog2)), | 2104 Int32Constant(kPointerSizeLog2)), |
2102 Int32Constant(offset)), | 2105 Uint32Constant(offset)), |
2103 *effect_, *control_); | 2106 *effect_, *control_); |
2104 | 2107 |
2105 args[0] = load_code; | 2108 args[0] = load_code; |
2106 wasm::FunctionSig* sig = module_->GetSignature(index); | 2109 wasm::FunctionSig* sig = module_->GetSignature(index); |
2107 return BuildWasmCall(sig, args, position); | 2110 return BuildWasmCall(sig, args, position); |
2108 } | 2111 } |
2109 | 2112 |
2110 Node* WasmGraphBuilder::JITSingleFunction(Node* const base, Node* const length, | 2113 Node* WasmGraphBuilder::JITSingleFunction(Node* const base, Node* const length, |
2111 Node* const index, | 2114 Node* const index, |
2112 const uint32_t sig_index, | 2115 const uint32_t sig_index, |
(...skipping 11 matching lines...) Expand all Loading... |
2124 trap_->AddTrapIfTrue(wasm::kTrapFuncInvalid, length_negative, position); | 2127 trap_->AddTrapIfTrue(wasm::kTrapFuncInvalid, length_negative, position); |
2125 | 2128 |
2126 Node* in_bounds = graph()->NewNode( | 2129 Node* in_bounds = graph()->NewNode( |
2127 machine->Uint32LessThanOrEqual(), | 2130 machine->Uint32LessThanOrEqual(), |
2128 graph()->NewNode(machine->Int32Add(), base, length), MemSize(0)); | 2131 graph()->NewNode(machine->Int32Add(), base, length), MemSize(0)); |
2129 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, in_bounds, position); | 2132 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, in_bounds, position); |
2130 } | 2133 } |
2131 | 2134 |
2132 // Bounds check the index. | 2135 // Bounds check the index. |
2133 { | 2136 { |
2134 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2137 // Assume only one table for now. |
| 2138 DCHECK_LE(module_->instance->function_tables.size(), 1u); |
| 2139 uint32_t table_size = |
| 2140 module_->IsValidTable(0) ? module_->GetTable(0)->max_size : 0; |
2135 if (table_size > 0) { | 2141 if (table_size > 0) { |
2136 // Bounds check against the table size. | 2142 // Bounds check against the table size. |
2137 Node* size = Int32Constant(static_cast<int>(table_size)); | 2143 Node* size = Uint32Constant(table_size); |
2138 Node* in_bounds = | 2144 Node* in_bounds = |
2139 graph()->NewNode(machine->Uint32LessThan(), index, size); | 2145 graph()->NewNode(machine->Uint32LessThan(), index, size); |
2140 trap_->AddTrapIfFalse(wasm::kTrapInvalidIndex, in_bounds, position); | 2146 trap_->AddTrapIfFalse(wasm::kTrapInvalidIndex, in_bounds, position); |
2141 } else { | 2147 } else { |
2142 // No function table. Generate a trap and return a constant. | 2148 // No function table. Generate a trap and return a constant. |
2143 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2149 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2144 return trap_->GetTrapValue(module_->GetSignature(sig_index)); | 2150 return trap_->GetTrapValue(module_->GetSignature(sig_index)); |
2145 } | 2151 } |
2146 } | 2152 } |
2147 | 2153 |
2148 const size_t runtime_input_params = 7; | 2154 const size_t runtime_input_params = 7; |
2149 const size_t runtime_env_params = 5; | 2155 const size_t runtime_env_params = 5; |
2150 | 2156 |
2151 Runtime::FunctionId f = Runtime::kJITSingleFunction; | 2157 Runtime::FunctionId f = Runtime::kJITSingleFunction; |
2152 const Runtime::Function* fun = Runtime::FunctionForId(f); | 2158 const Runtime::Function* fun = Runtime::FunctionForId(f); |
2153 // CEntryStubConstant nodes have to be created and cached in the main | 2159 // CEntryStubConstant nodes have to be created and cached in the main |
2154 // thread. At the moment this is only done for CEntryStubConstant(1). | 2160 // thread. At the moment this is only done for CEntryStubConstant(1). |
2155 DCHECK_EQ(1, fun->result_size); | 2161 DCHECK_EQ(1, fun->result_size); |
2156 const uint32_t return_count = static_cast<uint32_t>(sig->return_count()); | 2162 const uint32_t return_count = static_cast<uint32_t>(sig->return_count()); |
2157 const uint32_t parameter_count = | 2163 const uint32_t parameter_count = |
2158 static_cast<uint32_t>(sig->parameter_count()); | 2164 static_cast<uint32_t>(sig->parameter_count()); |
2159 | 2165 |
2160 const uint32_t inputs_size = runtime_input_params + runtime_env_params + | 2166 const uint32_t inputs_size = runtime_input_params + runtime_env_params + |
2161 return_count + parameter_count; | 2167 return_count + parameter_count; |
2162 Node** inputs = Buffer(inputs_size); | 2168 Node** inputs = Buffer(inputs_size); |
2163 inputs[0] = jsgraph()->CEntryStubConstant(fun->result_size); | 2169 inputs[0] = jsgraph()->CEntryStubConstant(fun->result_size); |
2164 inputs[1] = BuildChangeUint32ToSmi(base); | 2170 inputs[1] = BuildChangeUint32ToSmi(base); |
2165 inputs[2] = BuildChangeUint32ToSmi(length); | 2171 inputs[2] = BuildChangeUint32ToSmi(length); |
2166 inputs[3] = BuildChangeUint32ToSmi(index); | 2172 inputs[3] = BuildChangeUint32ToSmi(index); |
2167 inputs[4] = FunctionTable(); | 2173 inputs[4] = FunctionTable(0); |
2168 inputs[5] = Uint32Constant(sig_index); | 2174 inputs[5] = Uint32Constant(sig_index); |
2169 inputs[6] = BuildChangeUint32ToSmi(Uint32Constant(return_count)); | 2175 inputs[6] = BuildChangeUint32ToSmi(Uint32Constant(return_count)); |
2170 | 2176 |
2171 // Pass in parameters and return types in to the runtime function | 2177 // Pass in parameters and return types in to the runtime function |
2172 // to allow it to regenerate signature | 2178 // to allow it to regenerate signature |
2173 for (uint32_t i = 0; i < return_count; ++i) { | 2179 for (uint32_t i = 0; i < return_count; ++i) { |
2174 inputs[i + runtime_input_params] = BuildChangeUint32ToSmi( | 2180 inputs[i + runtime_input_params] = BuildChangeUint32ToSmi( |
2175 Uint32Constant(static_cast<int>(sig->GetReturn(i)))); | 2181 Uint32Constant(static_cast<int>(sig->GetReturn(i)))); |
2176 } | 2182 } |
2177 | 2183 |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2799 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 2805 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
2800 } | 2806 } |
2801 } | 2807 } |
2802 | 2808 |
2803 Node* WasmGraphBuilder::DefaultS128Value() { | 2809 Node* WasmGraphBuilder::DefaultS128Value() { |
2804 Node* zero = jsgraph()->Int32Constant(0); | 2810 Node* zero = jsgraph()->Int32Constant(0); |
2805 return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero, | 2811 return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero, |
2806 zero, zero); | 2812 zero, zero); |
2807 } | 2813 } |
2808 | 2814 |
2809 Node* WasmGraphBuilder::FunctionTable() { | 2815 Node* WasmGraphBuilder::FunctionTable(uint32_t index) { |
2810 DCHECK(module_ && module_->instance && | 2816 DCHECK(module_ && module_->instance && |
2811 !module_->instance->function_table.is_null()); | 2817 index < module_->instance->function_tables.size()); |
2812 if (!function_table_) { | 2818 if (!function_tables_.size()) { |
2813 function_table_ = HeapConstant(module_->instance->function_table); | 2819 for (size_t i = 0; i < module_->instance->function_tables.size(); ++i) { |
| 2820 DCHECK(!module_->instance->function_tables[i].is_null()); |
| 2821 function_tables_.push_back( |
| 2822 HeapConstant(module_->instance->function_tables[i])); |
| 2823 } |
2814 } | 2824 } |
2815 return function_table_; | 2825 return function_tables_[index]; |
2816 } | 2826 } |
2817 | 2827 |
2818 Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node, | 2828 Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node, |
2819 Runtime::FunctionId function_id, | 2829 Runtime::FunctionId function_id, |
2820 Signature<Conversion>* signature) { | 2830 Signature<Conversion>* signature) { |
2821 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); | 2831 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); |
2822 const Runtime::Function* function = Runtime::FunctionForId(function_id); | 2832 const Runtime::Function* function = Runtime::FunctionForId(function_id); |
2823 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 2833 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
2824 jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties, | 2834 jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties, |
2825 CallDescriptor::kNoFlags); | 2835 CallDescriptor::kNoFlags); |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3466 function_->code_start_offset), | 3476 function_->code_start_offset), |
3467 compile_ms); | 3477 compile_ms); |
3468 } | 3478 } |
3469 | 3479 |
3470 return code; | 3480 return code; |
3471 } | 3481 } |
3472 | 3482 |
3473 } // namespace compiler | 3483 } // namespace compiler |
3474 } // namespace internal | 3484 } // namespace internal |
3475 } // namespace v8 | 3485 } // namespace v8 |
OLD | NEW |