OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/base/adapters.h" | 5 #include "src/base/adapters.h" |
6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
(...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 opcode = cont->Encode(opcode); | 1217 opcode = cont->Encode(opcode); |
1218 inputs[input_count++] = right; | 1218 inputs[input_count++] = right; |
1219 | 1219 |
1220 if (cont->IsBranch()) { | 1220 if (cont->IsBranch()) { |
1221 inputs[input_count++] = g.Label(cont->true_block()); | 1221 inputs[input_count++] = g.Label(cont->true_block()); |
1222 inputs[input_count++] = g.Label(cont->false_block()); | 1222 inputs[input_count++] = g.Label(cont->false_block()); |
1223 selector->Emit(opcode, 0, nullptr, input_count, inputs); | 1223 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
1224 } else if (cont->IsDeoptimize()) { | 1224 } else if (cont->IsDeoptimize()) { |
1225 selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, | 1225 selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, |
1226 cont->reason(), cont->frame_state()); | 1226 cont->reason(), cont->frame_state()); |
1227 } else { | 1227 } else if (cont->IsSet()) { |
1228 DCHECK(cont->IsSet()); | |
1229 InstructionOperand output = g.DefineAsRegister(cont->result()); | 1228 InstructionOperand output = g.DefineAsRegister(cont->result()); |
1230 selector->Emit(opcode, 1, &output, input_count, inputs); | 1229 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1230 } else { |
| 1231 DCHECK(cont->IsTrap()); |
| 1232 inputs[input_count++] = g.UseImmediate(cont->trap_id()); |
| 1233 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
1231 } | 1234 } |
1232 } | 1235 } |
1233 | 1236 |
1234 // Shared routine for multiple compare operations. | 1237 // Shared routine for multiple compare operations. |
1235 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1238 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1236 InstructionOperand left, InstructionOperand right, | 1239 InstructionOperand left, InstructionOperand right, |
1237 FlagsContinuation* cont) { | 1240 FlagsContinuation* cont) { |
1238 X87OperandGenerator g(selector); | 1241 X87OperandGenerator g(selector); |
1239 opcode = cont->Encode(opcode); | 1242 opcode = cont->Encode(opcode); |
1240 if (cont->IsBranch()) { | 1243 if (cont->IsBranch()) { |
1241 selector->Emit(opcode, g.NoOutput(), left, right, | 1244 selector->Emit(opcode, g.NoOutput(), left, right, |
1242 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1245 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1243 } else if (cont->IsDeoptimize()) { | 1246 } else if (cont->IsDeoptimize()) { |
1244 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(), | 1247 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(), |
1245 cont->frame_state()); | 1248 cont->frame_state()); |
| 1249 } else if (cont->IsSet()) { |
| 1250 selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right); |
1246 } else { | 1251 } else { |
1247 DCHECK(cont->IsSet()); | 1252 DCHECK(cont->IsTrap()); |
1248 selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right); | 1253 selector->Emit(opcode, g.NoOutput(), left, right, |
| 1254 g.UseImmediate(cont->trap_id())); |
1249 } | 1255 } |
1250 } | 1256 } |
1251 | 1257 |
1252 | 1258 |
1253 // Shared routine for multiple compare operations. | 1259 // Shared routine for multiple compare operations. |
1254 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1260 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
1255 Node* left, Node* right, FlagsContinuation* cont, | 1261 Node* left, Node* right, FlagsContinuation* cont, |
1256 bool commutative) { | 1262 bool commutative) { |
1257 X87OperandGenerator g(selector); | 1263 X87OperandGenerator g(selector); |
1258 if (commutative && g.CanBeBetterLeftOperand(right)) { | 1264 if (commutative && g.CanBeBetterLeftOperand(right)) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 X87OperandGenerator g(selector); | 1354 X87OperandGenerator g(selector); |
1349 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); | 1355 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
1350 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); | 1356 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
1351 if (cont->IsBranch()) { | 1357 if (cont->IsBranch()) { |
1352 selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), | 1358 selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), |
1353 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1359 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1354 } else if (cont->IsDeoptimize()) { | 1360 } else if (cont->IsDeoptimize()) { |
1355 selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(), | 1361 selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(), |
1356 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), | 1362 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), |
1357 cont->reason(), cont->frame_state()); | 1363 cont->reason(), cont->frame_state()); |
1358 } else { | 1364 } else if (cont->IsSet()) { |
1359 DCHECK(cont->IsSet()); | |
1360 selector->Emit(cont->Encode(kX87Float32Cmp), | 1365 selector->Emit(cont->Encode(kX87Float32Cmp), |
1361 g.DefineAsByteRegister(cont->result())); | 1366 g.DefineAsByteRegister(cont->result())); |
| 1367 } else { |
| 1368 DCHECK(cont->IsTrap()); |
| 1369 selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), |
| 1370 g.UseImmediate(cont->trap_id())); |
1362 } | 1371 } |
1363 } | 1372 } |
1364 | 1373 |
1365 | 1374 |
1366 // Shared routine for multiple float64 compare operations (inputs commuted). | 1375 // Shared routine for multiple float64 compare operations (inputs commuted). |
1367 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1376 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
1368 FlagsContinuation* cont) { | 1377 FlagsContinuation* cont) { |
1369 X87OperandGenerator g(selector); | 1378 X87OperandGenerator g(selector); |
1370 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); | 1379 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
1371 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); | 1380 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
1372 if (cont->IsBranch()) { | 1381 if (cont->IsBranch()) { |
1373 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), | 1382 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
1374 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1383 g.Label(cont->true_block()), g.Label(cont->false_block())); |
1375 } else if (cont->IsDeoptimize()) { | 1384 } else if (cont->IsDeoptimize()) { |
1376 selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(), | 1385 selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
1377 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), | 1386 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), |
1378 cont->reason(), cont->frame_state()); | 1387 cont->reason(), cont->frame_state()); |
1379 } else { | 1388 } else if (cont->IsSet()) { |
1380 DCHECK(cont->IsSet()); | |
1381 selector->Emit(cont->Encode(kX87Float64Cmp), | 1389 selector->Emit(cont->Encode(kX87Float64Cmp), |
1382 g.DefineAsByteRegister(cont->result())); | 1390 g.DefineAsByteRegister(cont->result())); |
| 1391 } else { |
| 1392 DCHECK(cont->IsTrap()); |
| 1393 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
| 1394 g.UseImmediate(cont->trap_id())); |
1383 } | 1395 } |
1384 } | 1396 } |
1385 | 1397 |
1386 // Shared routine for multiple word compare operations. | 1398 // Shared routine for multiple word compare operations. |
1387 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1399 void VisitWordCompare(InstructionSelector* selector, Node* node, |
1388 InstructionCode opcode, FlagsContinuation* cont) { | 1400 InstructionCode opcode, FlagsContinuation* cont) { |
1389 X87OperandGenerator g(selector); | 1401 X87OperandGenerator g(selector); |
1390 Node* left = node->InputAt(0); | 1402 Node* left = node->InputAt(0); |
1391 Node* right = node->InputAt(1); | 1403 Node* right = node->InputAt(1); |
1392 | 1404 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1571 kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); | 1583 kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); |
1572 VisitWordCompareZero(this, node, node->InputAt(0), &cont); | 1584 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
1573 } | 1585 } |
1574 | 1586 |
1575 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { | 1587 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { |
1576 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( | 1588 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( |
1577 kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); | 1589 kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); |
1578 VisitWordCompareZero(this, node, node->InputAt(0), &cont); | 1590 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
1579 } | 1591 } |
1580 | 1592 |
1581 void InstructionSelector::VisitTrapIf(Node* node, Runtime::FunctionId func_id) { | 1593 void InstructionSelector::VisitTrapIf(Node* node) { |
1582 UNREACHABLE(); | 1594 FlagsContinuation cont = FlagsContinuation::ForTrap( |
| 1595 kNotEqual, OpParameter<Runtime::FunctionId>(node->op()), |
| 1596 node->InputAt(1)); |
| 1597 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
1583 } | 1598 } |
1584 | 1599 |
1585 void InstructionSelector::VisitTrapUnless(Node* node, | 1600 void InstructionSelector::VisitTrapUnless(Node* node) { |
1586 Runtime::FunctionId func_id) { | 1601 FlagsContinuation cont = FlagsContinuation::ForTrap( |
1587 UNREACHABLE(); | 1602 kEqual, OpParameter<Runtime::FunctionId>(node->op()), node->InputAt(1)); |
| 1603 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
1588 } | 1604 } |
1589 | 1605 |
1590 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 1606 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
1591 X87OperandGenerator g(this); | 1607 X87OperandGenerator g(this); |
1592 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 1608 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
1593 | 1609 |
1594 // Emit either ArchTableSwitch or ArchLookupSwitch. | 1610 // Emit either ArchTableSwitch or ArchLookupSwitch. |
1595 size_t table_space_cost = 4 + sw.value_range; | 1611 size_t table_space_cost = 4 + sw.value_range; |
1596 size_t table_time_cost = 3; | 1612 size_t table_time_cost = 3; |
1597 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 1613 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 // static | 1842 // static |
1827 MachineOperatorBuilder::AlignmentRequirements | 1843 MachineOperatorBuilder::AlignmentRequirements |
1828 InstructionSelector::AlignmentRequirements() { | 1844 InstructionSelector::AlignmentRequirements() { |
1829 return MachineOperatorBuilder::AlignmentRequirements:: | 1845 return MachineOperatorBuilder::AlignmentRequirements:: |
1830 FullUnalignedAccessSupport(); | 1846 FullUnalignedAccessSupport(); |
1831 } | 1847 } |
1832 | 1848 |
1833 } // namespace compiler | 1849 } // namespace compiler |
1834 } // namespace internal | 1850 } // namespace internal |
1835 } // namespace v8 | 1851 } // namespace v8 |
OLD | NEW |