Chromium Code Reviews| 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 |