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_table_(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 1761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 // Bounds check the index. | 2060 // Bounds check the index. |
2061 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2061 int table_size = 0; |
2062 if (table_size > 0) { | 2062 // Assume only one table for now. |
ahaas
2016/07/25 19:23:44
Could you add a DCHECK for this assumption?
ddchen
2016/07/25 22:17:36
Done.
| |
2063 if (module_->IsValidTable(0) && | |
2064 ((table_size = module_->GetTable(0)->max_size) > 0)) { | |
ahaas
2016/07/25 19:23:44
I personally don't like assignments in conditions.
ddchen
2016/07/25 22:17:36
Done.
| |
2063 // Bounds check against the table size. | 2065 // Bounds check against the table size. |
2064 Node* size = Int32Constant(static_cast<int>(table_size)); | 2066 Node* size = Int32Constant(table_size); |
2065 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 2067 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
2066 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); | 2068 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, in_bounds, position); |
2067 } else { | 2069 } else { |
2068 // No function table. Generate a trap and return a constant. | 2070 // No function table. Generate a trap and return a constant. |
2069 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2071 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2070 return trap_->GetTrapValue(module_->GetSignature(index)); | 2072 return trap_->GetTrapValue(module_->GetSignature(index)); |
2071 } | 2073 } |
2072 Node* table = FunctionTable(); | 2074 Node* table = FunctionTable(0); |
2073 | 2075 |
2074 // Load signature from the table and check. | 2076 // Load signature from the table and check. |
2075 // The table is a FixedArray; signatures are encoded as SMIs. | 2077 // The table is a FixedArray; signatures are encoded as SMIs. |
2076 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 2078 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
2077 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 2079 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
2078 const int fixed_offset = access.header_size - access.tag(); | 2080 const int fixed_offset = access.header_size - access.tag(); |
2079 { | 2081 { |
2080 Node* load_sig = graph()->NewNode( | 2082 Node* load_sig = graph()->NewNode( |
2081 machine->Load(MachineType::AnyTagged()), table, | 2083 machine->Load(MachineType::AnyTagged()), table, |
2082 graph()->NewNode(machine->Int32Add(), | 2084 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); | 2124 trap_->AddTrapIfTrue(wasm::kTrapFuncInvalid, length_negative, position); |
2123 | 2125 |
2124 Node* in_bounds = graph()->NewNode( | 2126 Node* in_bounds = graph()->NewNode( |
2125 machine->Uint32LessThanOrEqual(), | 2127 machine->Uint32LessThanOrEqual(), |
2126 graph()->NewNode(machine->Int32Add(), base, length), MemSize(0)); | 2128 graph()->NewNode(machine->Int32Add(), base, length), MemSize(0)); |
2127 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, in_bounds, position); | 2129 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, in_bounds, position); |
2128 } | 2130 } |
2129 | 2131 |
2130 // Bounds check the index. | 2132 // Bounds check the index. |
2131 { | 2133 { |
2132 int table_size = static_cast<int>(module_->FunctionTableSize()); | 2134 int table_size = 0; |
2133 if (table_size > 0) { | 2135 // Assume only one table for now. |
ahaas
2016/07/25 19:23:44
same here.
ddchen
2016/07/25 22:17:36
Done.
| |
2136 if (module_->IsValidTable(0) && | |
2137 ((table_size = module_->GetTable(0)->max_size) > 0)) { | |
2134 // Bounds check against the table size. | 2138 // Bounds check against the table size. |
2135 Node* size = Int32Constant(static_cast<int>(table_size)); | 2139 Node* size = Int32Constant(table_size); |
2136 Node* in_bounds = | 2140 Node* in_bounds = |
2137 graph()->NewNode(machine->Uint32LessThan(), index, size); | 2141 graph()->NewNode(machine->Uint32LessThan(), index, size); |
2138 trap_->AddTrapIfFalse(wasm::kTrapInvalidIndex, in_bounds, position); | 2142 trap_->AddTrapIfFalse(wasm::kTrapInvalidIndex, in_bounds, position); |
2139 } else { | 2143 } else { |
2140 // No function table. Generate a trap and return a constant. | 2144 // No function table. Generate a trap and return a constant. |
2141 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); | 2145 trap_->AddTrapIfFalse(wasm::kTrapFuncInvalid, Int32Constant(0), position); |
2142 return trap_->GetTrapValue(module_->GetSignature(sig_index)); | 2146 return trap_->GetTrapValue(module_->GetSignature(sig_index)); |
2143 } | 2147 } |
2144 } | 2148 } |
2145 | 2149 |
2146 const size_t runtime_input_params = 7; | 2150 const size_t runtime_input_params = 7; |
2147 const size_t runtime_env_params = 5; | 2151 const size_t runtime_env_params = 5; |
2148 | 2152 |
2149 Runtime::FunctionId f = Runtime::kJITSingleFunction; | 2153 Runtime::FunctionId f = Runtime::kJITSingleFunction; |
2150 const Runtime::Function* fun = Runtime::FunctionForId(f); | 2154 const Runtime::Function* fun = Runtime::FunctionForId(f); |
2151 // CEntryStubConstant nodes have to be created and cached in the main | 2155 // CEntryStubConstant nodes have to be created and cached in the main |
2152 // thread. At the moment this is only done for CEntryStubConstant(1). | 2156 // thread. At the moment this is only done for CEntryStubConstant(1). |
2153 DCHECK_EQ(1, fun->result_size); | 2157 DCHECK_EQ(1, fun->result_size); |
2154 const uint32_t return_count = static_cast<uint32_t>(sig->return_count()); | 2158 const uint32_t return_count = static_cast<uint32_t>(sig->return_count()); |
2155 const uint32_t parameter_count = | 2159 const uint32_t parameter_count = |
2156 static_cast<uint32_t>(sig->parameter_count()); | 2160 static_cast<uint32_t>(sig->parameter_count()); |
2157 | 2161 |
2158 const uint32_t inputs_size = runtime_input_params + runtime_env_params + | 2162 const uint32_t inputs_size = runtime_input_params + runtime_env_params + |
2159 return_count + parameter_count; | 2163 return_count + parameter_count; |
2160 Node** inputs = Buffer(inputs_size); | 2164 Node** inputs = Buffer(inputs_size); |
2161 inputs[0] = jsgraph()->CEntryStubConstant(fun->result_size); | 2165 inputs[0] = jsgraph()->CEntryStubConstant(fun->result_size); |
2162 inputs[1] = BuildChangeUint32ToSmi(base); | 2166 inputs[1] = BuildChangeUint32ToSmi(base); |
2163 inputs[2] = BuildChangeUint32ToSmi(length); | 2167 inputs[2] = BuildChangeUint32ToSmi(length); |
2164 inputs[3] = BuildChangeUint32ToSmi(index); | 2168 inputs[3] = BuildChangeUint32ToSmi(index); |
2165 inputs[4] = FunctionTable(); | 2169 inputs[4] = FunctionTable(0); |
2166 inputs[5] = Uint32Constant(sig_index); | 2170 inputs[5] = Uint32Constant(sig_index); |
2167 inputs[6] = BuildChangeUint32ToSmi(Uint32Constant(return_count)); | 2171 inputs[6] = BuildChangeUint32ToSmi(Uint32Constant(return_count)); |
2168 | 2172 |
2169 // Pass in parameters and return types in to the runtime function | 2173 // Pass in parameters and return types in to the runtime function |
2170 // to allow it to regenerate signature | 2174 // to allow it to regenerate signature |
2171 for (uint32_t i = 0; i < return_count; ++i) { | 2175 for (uint32_t i = 0; i < return_count; ++i) { |
2172 inputs[i + runtime_input_params] = BuildChangeUint32ToSmi( | 2176 inputs[i + runtime_input_params] = BuildChangeUint32ToSmi( |
2173 Uint32Constant(static_cast<int>(sig->GetReturn(i)))); | 2177 Uint32Constant(static_cast<int>(sig->GetReturn(i)))); |
2174 } | 2178 } |
2175 | 2179 |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2797 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); | 2801 size + offset, RelocInfo::WASM_MEMORY_SIZE_REFERENCE); |
2798 } | 2802 } |
2799 } | 2803 } |
2800 | 2804 |
2801 Node* WasmGraphBuilder::DefaultS128Value() { | 2805 Node* WasmGraphBuilder::DefaultS128Value() { |
2802 Node* zero = jsgraph()->Int32Constant(0); | 2806 Node* zero = jsgraph()->Int32Constant(0); |
2803 return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero, | 2807 return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero, |
2804 zero, zero); | 2808 zero, zero); |
2805 } | 2809 } |
2806 | 2810 |
2807 Node* WasmGraphBuilder::FunctionTable() { | 2811 Node* WasmGraphBuilder::FunctionTable(uint32_t index) { |
2808 DCHECK(module_ && module_->instance && | 2812 DCHECK(module_ && module_->instance && |
2809 !module_->instance->function_table.is_null()); | 2813 index < module_->instance->function_table.size()); |
2810 if (!function_table_) { | 2814 if (index >= function_table_.size()) { |
2811 function_table_ = HeapConstant(module_->instance->function_table); | 2815 for (uint32_t i = 0; i <= index; i++) { |
2816 if (i < function_table_.size() && function_table_[i]) { | |
2817 continue; | |
2818 } | |
2819 DCHECK(!module_->instance->function_table[index].is_null()); | |
ahaas
2016/07/25 19:23:44
Shouldn't this be {i} instead of {index}? If you r
| |
2820 function_table_.push_back( | |
ahaas
2016/07/25 19:23:44
Does {push_back} actually add the element at the r
ddchen
2016/07/25 22:17:36
This code was incorrect, it should be fixed now.
| |
2821 HeapConstant(module_->instance->function_table[index])); | |
2822 } | |
2812 } | 2823 } |
2813 return function_table_; | 2824 return function_table_[index]; |
2814 } | 2825 } |
2815 | 2826 |
2816 Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node, | 2827 Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node, |
2817 Runtime::FunctionId function_id, | 2828 Runtime::FunctionId function_id, |
2818 Signature<Conversion>* signature) { | 2829 Signature<Conversion>* signature) { |
2819 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); | 2830 SimplifiedOperatorBuilder simplified(jsgraph()->zone()); |
2820 const Runtime::Function* function = Runtime::FunctionForId(function_id); | 2831 const Runtime::Function* function = Runtime::FunctionForId(function_id); |
2821 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 2832 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
2822 jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties, | 2833 jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties, |
2823 CallDescriptor::kNoFlags); | 2834 CallDescriptor::kNoFlags); |
(...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3464 function_->code_start_offset), | 3475 function_->code_start_offset), |
3465 compile_ms); | 3476 compile_ms); |
3466 } | 3477 } |
3467 | 3478 |
3468 return code; | 3479 return code; |
3469 } | 3480 } |
3470 | 3481 |
3471 } // namespace compiler | 3482 } // namespace compiler |
3472 } // namespace internal | 3483 } // namespace internal |
3473 } // namespace v8 | 3484 } // namespace v8 |
OLD | NEW |