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 "src/isolate-inl.h" | 7 #include "src/isolate-inl.h" |
8 | 8 |
9 #include "src/base/platform/elapsed-timer.h" | 9 #include "src/base/platform/elapsed-timer.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 }; | 269 }; |
270 | 270 |
271 WasmGraphBuilder::WasmGraphBuilder( | 271 WasmGraphBuilder::WasmGraphBuilder( |
272 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature, | 272 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* function_signature, |
273 compiler::SourcePositionTable* source_position_table) | 273 compiler::SourcePositionTable* source_position_table) |
274 : zone_(zone), | 274 : zone_(zone), |
275 jsgraph_(jsgraph), | 275 jsgraph_(jsgraph), |
276 module_(nullptr), | 276 module_(nullptr), |
277 mem_buffer_(nullptr), | 277 mem_buffer_(nullptr), |
278 mem_size_(nullptr), | 278 mem_size_(nullptr), |
279 function_table_(nullptr), | 279 function_tables_(zone), |
280 control_(nullptr), | 280 control_(nullptr), |
281 effect_(nullptr), | 281 effect_(nullptr), |
282 cur_buffer_(def_buffer_), | 282 cur_buffer_(def_buffer_), |
283 cur_bufsize_(kDefaultBufferSize), | 283 cur_bufsize_(kDefaultBufferSize), |
284 trap_(new (zone) WasmTrapHelper(this)), | 284 trap_(new (zone) WasmTrapHelper(this)), |
285 function_signature_(function_signature), | 285 function_signature_(function_signature), |
286 source_position_table_(source_position_table) { | 286 source_position_table_(source_position_table) { |
287 DCHECK_NOT_NULL(jsgraph_); | 287 DCHECK_NOT_NULL(jsgraph_); |
288 } | 288 } |
289 | 289 |
(...skipping 1760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2050 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, | 2050 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, |
2051 wasm::WasmCodePosition position) { | 2051 wasm::WasmCodePosition position) { |
2052 DCHECK_NOT_NULL(args[0]); | 2052 DCHECK_NOT_NULL(args[0]); |
2053 DCHECK(module_ && module_->instance); | 2053 DCHECK(module_ && module_->instance); |
2054 | 2054 |
2055 MachineOperatorBuilder* machine = jsgraph()->machine(); | 2055 MachineOperatorBuilder* machine = jsgraph()->machine(); |
2056 | 2056 |
2057 // Compute the code object by loading it from the function table. | 2057 // Compute the code object by loading it from the function table. |
2058 Node* key = args[0]; | 2058 Node* key = args[0]; |
2059 | 2059 |
2060 // Assume only one table for now. | |
2061 DCHECK_EQ(module_->instance->function_tables.size(), 1); | |
2060 // Bounds check the index. | 2062 // Bounds check the index. |
2061 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2063 int table_size = |
2064 module_->IsValidTable(0) ? module_->GetTable(0)->max_size : 0; | |
2062 if (table_size > 0) { | 2065 if (table_size > 0) { |
2063 // Bounds check against the table size. | 2066 // Bounds check against the table size. |
2064 Node* size = Int32Constant(static_cast<int>(table_size)); | 2067 Node* size = Int32Constant(table_size); |
2065 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 2068 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
2066 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); | 2069 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); |
2067 } else { | 2070 } else { |
2068 // No function table. Generate a trap and return a constant. | 2071 // No function table. Generate a trap and return a constant. |
2069 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2072 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2070 return trap_->GetTrapValue(module_->GetSignature(index)); | 2073 return trap_->GetTrapValue(module_->GetSignature(index)); |
2071 } | 2074 } |
2072 Node* table = FunctionTable(); | 2075 Node* table = FunctionTable(0); |
2073 | 2076 |
2074 // Load signature from the table and check. | 2077 // Load signature from the table and check. |
2075 // The table is a FixedArray; signatures are encoded as SMIs. | 2078 // The table is a FixedArray; signatures are encoded as SMIs. |
2076 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 2079 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
2077 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 2080 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
2078 const int fixed_offset = access.header_size - access.tag(); | 2081 const int fixed_offset = access.header_size - access.tag(); |
2079 { | 2082 { |
2080 Node* load_sig = graph()->NewNode( | 2083 Node* load_sig = graph()->NewNode( |
2081 machine->Load(MachineType::AnyTagged()), table, | 2084 machine->Load(MachineType::AnyTagged()), table, |
2082 graph()->NewNode(machine->Int32Add(), | 2085 graph()->NewNode(machine->Int32Add(), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2122 trap_->AddTrapIfTrue(wasm::kTrapFuncInvalid, length_negative, position); | 2125 trap_->AddTrapIfTrue(wasm::kTrapFuncInvalid, length_negative, position); |
2123 | 2126 |
2124 Node* in_bounds = graph()->NewNode( | 2127 Node* in_bounds = graph()->NewNode( |
2125 machine->Uint32LessThanOrEqual(), | 2128 machine->Uint32LessThanOrEqual(), |
2126 graph()->NewNode(machine->Int32Add(), base, length), MemSize(0)); | 2129 graph()->NewNode(machine->Int32Add(), base, length), MemSize(0)); |
2127 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, in_bounds, position); | 2130 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, in_bounds, position); |
2128 } | 2131 } |
2129 | 2132 |
2130 // Bounds check the index. | 2133 // Bounds check the index. |
2131 { | 2134 { |
2132 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2135 // Assume only one table for now. |
2136 DCHECK_EQ(module_->instance->function_tables.size(), 1); | |
2137 int table_size = | |
2138 module_->IsValidTable(0) ? module_->GetTable(0)->max_size : 0; | |
2133 if (table_size > 0) { | 2139 if (table_size > 0) { |
2134 // Bounds check against the table size. | 2140 // Bounds check against the table size. |
2135 Node* size = Int32Constant(static_cast<int>(table_size)); | 2141 Node* size = Int32Constant(table_size); |
2136 Node* in_bounds = | 2142 Node* in_bounds = |
2137 graph()->NewNode(machine->Uint32LessThan(), index, size); | 2143 graph()->NewNode(machine->Uint32LessThan(), index, size); |
2138 trap_->AddTrapIfFalse(wasm::kTrapInvalidIndex, in_bounds, position); | 2144 trap_->AddTrapIfFalse(wasm::kTrapInvalidIndex, in_bounds, position); |
2139 } else { | 2145 } else { |
2140 // No function table. Generate a trap and return a constant. | 2146 // No function table. Generate a trap and return a constant. |
2141 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2147 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2142 return trap_->GetTrapValue(module_->GetSignature(sig_index)); | 2148 return trap_->GetTrapValue(module_->GetSignature(sig_index)); |
2143 } | 2149 } |
2144 } | 2150 } |
2145 | 2151 |
2146 const size_t runtime_input_params = 7; | 2152 const size_t runtime_input_params = 7; |
2147 const size_t runtime_env_params = 5; | 2153 const size_t runtime_env_params = 5; |
2148 | 2154 |
2149 Runtime::FunctionId f = Runtime::kJITSingleFunction; | 2155 Runtime::FunctionId f = Runtime::kJITSingleFunction; |
2150 const Runtime::Function* fun = Runtime::FunctionForId(f); | 2156 const Runtime::Function* fun = Runtime::FunctionForId(f); |
2151 // CEntryStubConstant nodes have to be created and cached in the main | 2157 // CEntryStubConstant nodes have to be created and cached in the main |
2152 // thread. At the moment this is only done for CEntryStubConstant(1). | 2158 // thread. At the moment this is only done for CEntryStubConstant(1). |
2153 DCHECK_EQ(1, fun->result_size); | 2159 DCHECK_EQ(1, fun->result_size); |
2154 const uint32_t return_count = static_cast<uint32_t>(sig->return_count()); | 2160 const uint32_t return_count = static_cast<uint32_t>(sig->return_count()); |
2155 const uint32_t parameter_count = | 2161 const uint32_t parameter_count = |
2156 static_cast<uint32_t>(sig->parameter_count()); | 2162 static_cast<uint32_t>(sig->parameter_count()); |
2157 | 2163 |
2158 const uint32_t inputs_size = runtime_input_params + runtime_env_params + | 2164 const uint32_t inputs_size = runtime_input_params + runtime_env_params + |
2159 return_count + parameter_count; | 2165 return_count + parameter_count; |
2160 Node** inputs = Buffer(inputs_size); | 2166 Node** inputs = Buffer(inputs_size); |
2161 inputs[0] = jsgraph()->CEntryStubConstant(fun->result_size); | 2167 inputs[0] = jsgraph()->CEntryStubConstant(fun->result_size); |
2162 inputs[1] = BuildChangeUint32ToSmi(base); | 2168 inputs[1] = BuildChangeUint32ToSmi(base); |
2163 inputs[2] = BuildChangeUint32ToSmi(length); | 2169 inputs[2] = BuildChangeUint32ToSmi(length); |
2164 inputs[3] = BuildChangeUint32ToSmi(index); | 2170 inputs[3] = BuildChangeUint32ToSmi(index); |
2165 inputs[4] = FunctionTable(); | 2171 inputs[4] = FunctionTable(0); |
2166 inputs[5] = Uint32Constant(sig_index); | 2172 inputs[5] = Uint32Constant(sig_index); |
2167 inputs[6] = BuildChangeUint32ToSmi(Uint32Constant(return_count)); | 2173 inputs[6] = BuildChangeUint32ToSmi(Uint32Constant(return_count)); |
2168 | 2174 |
2169 // Pass in parameters and return types in to the runtime function | 2175 // Pass in parameters and return types in to the runtime function |
2170 // to allow it to regenerate signature | 2176 // to allow it to regenerate signature |
2171 for (uint32_t i = 0; i < return_count; ++i) { | 2177 for (uint32_t i = 0; i < return_count; ++i) { |
2172 inputs[i + runtime_input_params] = BuildChangeUint32ToSmi( | 2178 inputs[i + runtime_input_params] = BuildChangeUint32ToSmi( |
2173 Uint32Constant(static_cast<int>(sig->GetReturn(i)))); | 2179 Uint32Constant(static_cast<int>(sig->GetReturn(i)))); |
2174 } | 2180 } |
2175 | 2181 |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2797 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 2803 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
2798 } | 2804 } |
2799 } | 2805 } |
2800 | 2806 |
2801 Node* WasmGraphBuilder::DefaultS128Value() { | 2807 Node* WasmGraphBuilder::DefaultS128Value() { |
2802 Node* zero = jsgraph()->Int32Constant(0); | 2808 Node* zero = jsgraph()->Int32Constant(0); |
2803 return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero, | 2809 return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero, |
2804 zero, zero); | 2810 zero, zero); |
2805 } | 2811 } |
2806 | 2812 |
2807 Node* WasmGraphBuilder::FunctionTable() { | 2813 Node* WasmGraphBuilder::FunctionTable(uint32_t index) { |
2808 DCHECK(module_ && module_->instance && | 2814 DCHECK(module_ && module_->instance && |
2809 !module_->instance->function_table.is_null()); | 2815 index < module_->instance->function_tables.size()); |
2810 if (!function_table_) { | 2816 if (index >= function_tables_.size()) { |
Mircea Trofin
2016/07/26 03:37:26
I think it'd be a bit more readable if you either:
ddchen
2016/07/26 05:44:43
I'll take the former approach; the module isn't av
| |
2811 function_table_ = HeapConstant(module_->instance->function_table); | 2817 for (size_t i = function_tables_.size(); i <= index; i++) { |
Mircea Trofin
2016/07/26 03:37:26
++i
ddchen
2016/07/26 05:44:44
Done.
| |
2818 DCHECK(!module_->instance->function_tables[i].is_null()); | |
2819 function_tables_.push_back( | |
2820 HeapConstant(module_->instance->function_tables[i])); | |
2821 } | |
2812 } | 2822 } |
2813 return function_table_; | 2823 return function_tables_[index]; |
2814 } | 2824 } |
2815 | 2825 |
2816 Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node, | 2826 Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node, |
2817 Runtime::FunctionId function_id, | 2827 Runtime::FunctionId function_id, |
2818 Signature<Conversion>* signature) { | 2828 Signature<Conversion>* signature) { |
2819 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); | 2829 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); |
2820 const Runtime::Function* function = Runtime::FunctionForId(function_id); | 2830 const Runtime::Function* function = Runtime::FunctionForId(function_id); |
2821 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 2831 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
2822 jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties, | 2832 jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties, |
2823 CallDescriptor::kNoFlags); | 2833 CallDescriptor::kNoFlags); |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3464 function_->code_start_offset), | 3474 function_->code_start_offset), |
3465 compile_ms); | 3475 compile_ms); |
3466 } | 3476 } |
3467 | 3477 |
3468 return code; | 3478 return code; |
3469 } | 3479 } |
3470 | 3480 |
3471 } // namespace compiler | 3481 } // namespace compiler |
3472 } // namespace internal | 3482 } // namespace internal |
3473 } // namespace v8 | 3483 } // namespace v8 |
OLD | NEW |