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/platform.h" | 9 #include "src/base/platform/platform.h" |
10 | 10 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 explicit WasmTrapHelper(WasmGraphBuilder* builder) | 98 explicit WasmTrapHelper(WasmGraphBuilder* builder) |
99 : builder_(builder), | 99 : builder_(builder), |
100 jsgraph_(builder->jsgraph()), | 100 jsgraph_(builder->jsgraph()), |
101 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { | 101 graph_(builder->jsgraph() ? builder->jsgraph()->graph() : nullptr) { |
102 for (int i = 0; i < kTrapCount; i++) traps_[i] = nullptr; | 102 for (int i = 0; i < kTrapCount; i++) traps_[i] = nullptr; |
103 } | 103 } |
104 | 104 |
105 // Make the current control path trap to unreachable. | 105 // Make the current control path trap to unreachable. |
106 void Unreachable() { ConnectTrap(kTrapUnreachable); } | 106 void Unreachable() { ConnectTrap(kTrapUnreachable); } |
107 | 107 |
| 108 // Always trap with the given reason. |
| 109 void TrapAlways(TrapReason reason) { ConnectTrap(reason); } |
| 110 |
108 // Add a check that traps if {node} is equal to {val}. | 111 // Add a check that traps if {node} is equal to {val}. |
109 Node* TrapIfEq32(TrapReason reason, Node* node, int32_t val) { | 112 Node* TrapIfEq32(TrapReason reason, Node* node, int32_t val) { |
110 Int32Matcher m(node); | 113 Int32Matcher m(node); |
111 if (m.HasValue() && !m.Is(val)) return graph()->start(); | 114 if (m.HasValue() && !m.Is(val)) return graph()->start(); |
112 if (val == 0) { | 115 if (val == 0) { |
113 AddTrapIfFalse(reason, node); | 116 AddTrapIfFalse(reason, node); |
114 } else { | 117 } else { |
115 AddTrapIfTrue(reason, | 118 AddTrapIfTrue(reason, |
116 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, | 119 graph()->NewNode(jsgraph()->machine()->Word32Equal(), node, |
117 jsgraph()->Int32Constant(val))); | 120 jsgraph()->Int32Constant(val))); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); | 161 Node* branch = graph()->NewNode(common()->Branch(hint), cond, *control_ptr); |
159 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 162 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
160 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 163 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
161 | 164 |
162 *control_ptr = iftrue ? if_true : if_false; | 165 *control_ptr = iftrue ? if_true : if_false; |
163 ConnectTrap(reason); | 166 ConnectTrap(reason); |
164 *control_ptr = iftrue ? if_false : if_true; | 167 *control_ptr = iftrue ? if_false : if_true; |
165 *effect_ptr = before; | 168 *effect_ptr = before; |
166 } | 169 } |
167 | 170 |
| 171 Node* GetTrapValue(wasm::FunctionSig* sig) { |
| 172 if (sig->return_count() > 0) { |
| 173 switch (sig->GetReturn()) { |
| 174 case wasm::kAstI32: |
| 175 return jsgraph()->Int32Constant(0xdeadbeef); |
| 176 case wasm::kAstI64: |
| 177 return jsgraph()->Int64Constant(0xdeadbeefdeadbeef); |
| 178 case wasm::kAstF32: |
| 179 return jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef)); |
| 180 case wasm::kAstF64: |
| 181 return jsgraph()->Float64Constant( |
| 182 bit_cast<double>(0xdeadbeefdeadbeef)); |
| 183 break; |
| 184 default: |
| 185 UNREACHABLE(); |
| 186 return nullptr; |
| 187 } |
| 188 } else { |
| 189 return jsgraph()->Int32Constant(0xdeadbeef); |
| 190 } |
| 191 } |
| 192 |
168 private: | 193 private: |
169 WasmGraphBuilder* builder_; | 194 WasmGraphBuilder* builder_; |
170 JSGraph* jsgraph_; | 195 JSGraph* jsgraph_; |
171 Graph* graph_; | 196 Graph* graph_; |
172 Node* traps_[kTrapCount]; | 197 Node* traps_[kTrapCount]; |
173 Node* effects_[kTrapCount]; | 198 Node* effects_[kTrapCount]; |
174 | 199 |
175 JSGraph* jsgraph() { return jsgraph_; } | 200 JSGraph* jsgraph() { return jsgraph_; } |
176 Graph* graph() { return jsgraph_->graph(); } | 201 Graph* graph() { return jsgraph_->graph(); } |
177 CommonOperatorBuilder* common() { return jsgraph()->common(); } | 202 CommonOperatorBuilder* common() { return jsgraph()->common(); } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 *effect_ptr = node; | 245 *effect_ptr = node; |
221 } | 246 } |
222 if (false) { | 247 if (false) { |
223 // End the control flow with a throw | 248 // End the control flow with a throw |
224 Node* thrw = | 249 Node* thrw = |
225 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), | 250 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), |
226 *effect_ptr, *control_ptr); | 251 *effect_ptr, *control_ptr); |
227 end = thrw; | 252 end = thrw; |
228 } else { | 253 } else { |
229 // End the control flow with returning 0xdeadbeef | 254 // End the control flow with returning 0xdeadbeef |
230 Node* ret_value; | 255 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); |
231 if (builder_->GetFunctionSignature()->return_count() > 0) { | |
232 switch (builder_->GetFunctionSignature()->GetReturn()) { | |
233 case wasm::kAstI32: | |
234 ret_value = jsgraph()->Int32Constant(0xdeadbeef); | |
235 break; | |
236 case wasm::kAstI64: | |
237 ret_value = jsgraph()->Int64Constant(0xdeadbeefdeadbeef); | |
238 break; | |
239 case wasm::kAstF32: | |
240 ret_value = jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef)); | |
241 break; | |
242 case wasm::kAstF64: | |
243 ret_value = jsgraph()->Float64Constant( | |
244 bit_cast<double>(0xdeadbeefdeadbeef)); | |
245 break; | |
246 default: | |
247 UNREACHABLE(); | |
248 ret_value = nullptr; | |
249 } | |
250 } else { | |
251 ret_value = jsgraph()->Int32Constant(0xdeadbeef); | |
252 } | |
253 end = graph()->NewNode(jsgraph()->common()->Return(), ret_value, | 256 end = graph()->NewNode(jsgraph()->common()->Return(), ret_value, |
254 *effect_ptr, *control_ptr); | 257 *effect_ptr, *control_ptr); |
255 } | 258 } |
256 | 259 |
257 MergeControlToEnd(jsgraph(), end); | 260 MergeControlToEnd(jsgraph(), end); |
258 } | 261 } |
259 }; | 262 }; |
260 | 263 |
261 | 264 |
262 WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph, | 265 WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph, |
(...skipping 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 // Add code object as constant. | 1461 // Add code object as constant. |
1459 args[0] = Constant(module_->GetFunctionCode(index)); | 1462 args[0] = Constant(module_->GetFunctionCode(index)); |
1460 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); | 1463 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); |
1461 | 1464 |
1462 return BuildWasmCall(sig, args); | 1465 return BuildWasmCall(sig, args); |
1463 } | 1466 } |
1464 | 1467 |
1465 | 1468 |
1466 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args) { | 1469 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args) { |
1467 DCHECK_NOT_NULL(args[0]); | 1470 DCHECK_NOT_NULL(args[0]); |
| 1471 DCHECK(module_ && module_->instance); |
1468 | 1472 |
1469 MachineOperatorBuilder* machine = jsgraph()->machine(); | 1473 MachineOperatorBuilder* machine = jsgraph()->machine(); |
1470 | 1474 |
1471 // Compute the code object by loading it from the function table. | 1475 // Compute the code object by loading it from the function table. |
1472 Node* key = args[0]; | 1476 Node* key = args[0]; |
1473 Node* table = FunctionTable(); | |
1474 | 1477 |
1475 // Bounds check the index. | 1478 // Bounds check the index. |
1476 int table_size = static_cast<int>(module_->FunctionTableSize()); | 1479 int table_size = static_cast<int>(module_->FunctionTableSize()); |
1477 { | 1480 if (table_size > 0) { |
| 1481 // Bounds check against the table size. |
1478 Node* size = Int32Constant(static_cast<int>(table_size)); | 1482 Node* size = Int32Constant(static_cast<int>(table_size)); |
1479 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); | 1483 Node* in_bounds = graph()->NewNode(machine->Uint32LessThan(), key, size); |
1480 trap_->AddTrapIfFalse(kTrapFuncInvalid, in_bounds); | 1484 trap_->AddTrapIfFalse(kTrapFuncInvalid, in_bounds); |
| 1485 } else { |
| 1486 // No function table. Generate a trap and return a constant. |
| 1487 trap_->AddTrapIfFalse(kTrapFuncInvalid, Int32Constant(0)); |
| 1488 return trap_->GetTrapValue(module_->GetSignature(index)); |
1481 } | 1489 } |
| 1490 Node* table = FunctionTable(); |
1482 | 1491 |
1483 // Load signature from the table and check. | 1492 // Load signature from the table and check. |
1484 // The table is a FixedArray; signatures are encoded as SMIs. | 1493 // The table is a FixedArray; signatures are encoded as SMIs. |
1485 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] | 1494 // [sig1, sig2, sig3, ...., code1, code2, code3 ...] |
1486 ElementAccess access = AccessBuilder::ForFixedArrayElement(); | 1495 ElementAccess access = AccessBuilder::ForFixedArrayElement(); |
1487 const int fixed_offset = access.header_size - access.tag(); | 1496 const int fixed_offset = access.header_size - access.tag(); |
1488 { | 1497 { |
1489 Node* load_sig = graph()->NewNode( | 1498 Node* load_sig = graph()->NewNode( |
1490 machine->Load(MachineType::AnyTagged()), table, | 1499 machine->Load(MachineType::AnyTagged()), table, |
1491 graph()->NewNode(machine->Int32Add(), | 1500 graph()->NewNode(machine->Int32Add(), |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2101 code->Disassemble(buffer.start(), os); | 2110 code->Disassemble(buffer.start(), os); |
2102 } | 2111 } |
2103 #endif | 2112 #endif |
2104 return code; | 2113 return code; |
2105 } | 2114 } |
2106 | 2115 |
2107 | 2116 |
2108 } // namespace compiler | 2117 } // namespace compiler |
2109 } // namespace internal | 2118 } // namespace internal |
2110 } // namespace v8 | 2119 } // namespace v8 |
OLD | NEW |