| 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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 } | 452 } |
| 453 | 453 |
| 454 DCHECK_NE(0u, input_count); | 454 DCHECK_NE(0u, input_count); |
| 455 DCHECK_NE(0u, output_count); | 455 DCHECK_NE(0u, output_count); |
| 456 DCHECK_GE(arraysize(inputs), input_count); | 456 DCHECK_GE(arraysize(inputs), input_count); |
| 457 DCHECK_GE(arraysize(outputs), output_count); | 457 DCHECK_GE(arraysize(outputs), output_count); |
| 458 | 458 |
| 459 opcode = cont->Encode(opcode); | 459 opcode = cont->Encode(opcode); |
| 460 if (cont->IsDeoptimize()) { | 460 if (cont->IsDeoptimize()) { |
| 461 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, | 461 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 462 cont->frame_state()); | 462 cont->reason(), cont->frame_state()); |
| 463 } else { | 463 } else { |
| 464 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 464 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 465 } | 465 } |
| 466 } | 466 } |
| 467 | 467 |
| 468 | 468 |
| 469 // Shared routine for multiple binary operations. | 469 // Shared routine for multiple binary operations. |
| 470 void VisitBinop(InstructionSelector* selector, Node* node, | 470 void VisitBinop(InstructionSelector* selector, Node* node, |
| 471 InstructionCode opcode) { | 471 InstructionCode opcode) { |
| 472 FlagsContinuation cont; | 472 FlagsContinuation cont; |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 opcode |= AddressingModeField::encode(addressing_mode); | 1171 opcode |= AddressingModeField::encode(addressing_mode); |
| 1172 opcode = cont->Encode(opcode); | 1172 opcode = cont->Encode(opcode); |
| 1173 inputs[input_count++] = right; | 1173 inputs[input_count++] = right; |
| 1174 | 1174 |
| 1175 if (cont->IsBranch()) { | 1175 if (cont->IsBranch()) { |
| 1176 inputs[input_count++] = g.Label(cont->true_block()); | 1176 inputs[input_count++] = g.Label(cont->true_block()); |
| 1177 inputs[input_count++] = g.Label(cont->false_block()); | 1177 inputs[input_count++] = g.Label(cont->false_block()); |
| 1178 selector->Emit(opcode, 0, nullptr, input_count, inputs); | 1178 selector->Emit(opcode, 0, nullptr, input_count, inputs); |
| 1179 } else if (cont->IsDeoptimize()) { | 1179 } else if (cont->IsDeoptimize()) { |
| 1180 selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, | 1180 selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs, |
| 1181 cont->frame_state()); | 1181 cont->reason(), cont->frame_state()); |
| 1182 } else { | 1182 } else { |
| 1183 DCHECK(cont->IsSet()); | 1183 DCHECK(cont->IsSet()); |
| 1184 InstructionOperand output = g.DefineAsRegister(cont->result()); | 1184 InstructionOperand output = g.DefineAsRegister(cont->result()); |
| 1185 selector->Emit(opcode, 1, &output, input_count, inputs); | 1185 selector->Emit(opcode, 1, &output, input_count, inputs); |
| 1186 } | 1186 } |
| 1187 } | 1187 } |
| 1188 | 1188 |
| 1189 // Shared routine for multiple compare operations. | 1189 // Shared routine for multiple compare operations. |
| 1190 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1190 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| 1191 InstructionOperand left, InstructionOperand right, | 1191 InstructionOperand left, InstructionOperand right, |
| 1192 FlagsContinuation* cont) { | 1192 FlagsContinuation* cont) { |
| 1193 X87OperandGenerator g(selector); | 1193 X87OperandGenerator g(selector); |
| 1194 opcode = cont->Encode(opcode); | 1194 opcode = cont->Encode(opcode); |
| 1195 if (cont->IsBranch()) { | 1195 if (cont->IsBranch()) { |
| 1196 selector->Emit(opcode, g.NoOutput(), left, right, | 1196 selector->Emit(opcode, g.NoOutput(), left, right, |
| 1197 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1197 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1198 } else if (cont->IsDeoptimize()) { | 1198 } else if (cont->IsDeoptimize()) { |
| 1199 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, | 1199 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(), |
| 1200 cont->frame_state()); | 1200 cont->frame_state()); |
| 1201 } else { | 1201 } else { |
| 1202 DCHECK(cont->IsSet()); | 1202 DCHECK(cont->IsSet()); |
| 1203 selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right); | 1203 selector->Emit(opcode, g.DefineAsByteRegister(cont->result()), left, right); |
| 1204 } | 1204 } |
| 1205 } | 1205 } |
| 1206 | 1206 |
| 1207 | 1207 |
| 1208 // Shared routine for multiple compare operations. | 1208 // Shared routine for multiple compare operations. |
| 1209 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 1209 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1252 FlagsContinuation* cont) { | 1252 FlagsContinuation* cont) { |
| 1253 X87OperandGenerator g(selector); | 1253 X87OperandGenerator g(selector); |
| 1254 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); | 1254 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(0))); |
| 1255 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); | 1255 selector->Emit(kX87PushFloat32, g.NoOutput(), g.Use(node->InputAt(1))); |
| 1256 if (cont->IsBranch()) { | 1256 if (cont->IsBranch()) { |
| 1257 selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), | 1257 selector->Emit(cont->Encode(kX87Float32Cmp), g.NoOutput(), |
| 1258 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1258 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1259 } else if (cont->IsDeoptimize()) { | 1259 } else if (cont->IsDeoptimize()) { |
| 1260 selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(), | 1260 selector->EmitDeoptimize(cont->Encode(kX87Float32Cmp), g.NoOutput(), |
| 1261 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), | 1261 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), |
| 1262 cont->frame_state()); | 1262 cont->reason(), cont->frame_state()); |
| 1263 } else { | 1263 } else { |
| 1264 DCHECK(cont->IsSet()); | 1264 DCHECK(cont->IsSet()); |
| 1265 selector->Emit(cont->Encode(kX87Float32Cmp), | 1265 selector->Emit(cont->Encode(kX87Float32Cmp), |
| 1266 g.DefineAsByteRegister(cont->result())); | 1266 g.DefineAsByteRegister(cont->result())); |
| 1267 } | 1267 } |
| 1268 } | 1268 } |
| 1269 | 1269 |
| 1270 | 1270 |
| 1271 // Shared routine for multiple float64 compare operations (inputs commuted). | 1271 // Shared routine for multiple float64 compare operations (inputs commuted). |
| 1272 void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 1272 void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
| 1273 FlagsContinuation* cont) { | 1273 FlagsContinuation* cont) { |
| 1274 X87OperandGenerator g(selector); | 1274 X87OperandGenerator g(selector); |
| 1275 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); | 1275 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(0))); |
| 1276 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); | 1276 selector->Emit(kX87PushFloat64, g.NoOutput(), g.Use(node->InputAt(1))); |
| 1277 if (cont->IsBranch()) { | 1277 if (cont->IsBranch()) { |
| 1278 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), | 1278 selector->Emit(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
| 1279 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1279 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1280 } else if (cont->IsDeoptimize()) { | 1280 } else if (cont->IsDeoptimize()) { |
| 1281 selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(), | 1281 selector->EmitDeoptimize(cont->Encode(kX87Float64Cmp), g.NoOutput(), |
| 1282 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), | 1282 g.Use(node->InputAt(0)), g.Use(node->InputAt(1)), |
| 1283 cont->frame_state()); | 1283 cont->reason(), cont->frame_state()); |
| 1284 } else { | 1284 } else { |
| 1285 DCHECK(cont->IsSet()); | 1285 DCHECK(cont->IsSet()); |
| 1286 selector->Emit(cont->Encode(kX87Float64Cmp), | 1286 selector->Emit(cont->Encode(kX87Float64Cmp), |
| 1287 g.DefineAsByteRegister(cont->result())); | 1287 g.DefineAsByteRegister(cont->result())); |
| 1288 } | 1288 } |
| 1289 } | 1289 } |
| 1290 | 1290 |
| 1291 // Shared routine for multiple word compare operations. | 1291 // Shared routine for multiple word compare operations. |
| 1292 void VisitWordCompare(InstructionSelector* selector, Node* node, | 1292 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 1293 InstructionCode opcode, FlagsContinuation* cont) { | 1293 InstructionCode opcode, FlagsContinuation* cont) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 ExternalReference js_stack_limit = | 1352 ExternalReference js_stack_limit = |
| 1353 ExternalReference::address_of_stack_limit(selector->isolate()); | 1353 ExternalReference::address_of_stack_limit(selector->isolate()); |
| 1354 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { | 1354 if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) { |
| 1355 // Compare(Load(js_stack_limit), LoadStackPointer) | 1355 // Compare(Load(js_stack_limit), LoadStackPointer) |
| 1356 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); | 1356 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); |
| 1357 InstructionCode opcode = cont->Encode(kX87StackCheck); | 1357 InstructionCode opcode = cont->Encode(kX87StackCheck); |
| 1358 if (cont->IsBranch()) { | 1358 if (cont->IsBranch()) { |
| 1359 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), | 1359 selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()), |
| 1360 g.Label(cont->false_block())); | 1360 g.Label(cont->false_block())); |
| 1361 } else if (cont->IsDeoptimize()) { | 1361 } else if (cont->IsDeoptimize()) { |
| 1362 selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, | 1362 selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr, cont->reason(), |
| 1363 cont->frame_state()); | 1363 cont->frame_state()); |
| 1364 } else { | 1364 } else { |
| 1365 DCHECK(cont->IsSet()); | 1365 DCHECK(cont->IsSet()); |
| 1366 selector->Emit(opcode, g.DefineAsRegister(cont->result())); | 1366 selector->Emit(opcode, g.DefineAsRegister(cont->result())); |
| 1367 } | 1367 } |
| 1368 return; | 1368 return; |
| 1369 } | 1369 } |
| 1370 } | 1370 } |
| 1371 VisitWordCompare(selector, node, kX87Cmp, cont); | 1371 VisitWordCompare(selector, node, kX87Cmp, cont); |
| 1372 } | 1372 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 } // namespace | 1467 } // namespace |
| 1468 | 1468 |
| 1469 | 1469 |
| 1470 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 1470 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 1471 BasicBlock* fbranch) { | 1471 BasicBlock* fbranch) { |
| 1472 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 1472 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| 1473 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); | 1473 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); |
| 1474 } | 1474 } |
| 1475 | 1475 |
| 1476 void InstructionSelector::VisitDeoptimizeIf(Node* node) { | 1476 void InstructionSelector::VisitDeoptimizeIf(Node* node) { |
| 1477 FlagsContinuation cont = | 1477 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( |
| 1478 FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1)); | 1478 kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); |
| 1479 VisitWordCompareZero(this, node, node->InputAt(0), &cont); | 1479 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1480 } | 1480 } |
| 1481 | 1481 |
| 1482 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { | 1482 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { |
| 1483 FlagsContinuation cont = | 1483 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( |
| 1484 FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1)); | 1484 kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); |
| 1485 VisitWordCompareZero(this, node, node->InputAt(0), &cont); | 1485 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 1486 } | 1486 } |
| 1487 | 1487 |
| 1488 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 1488 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
| 1489 X87OperandGenerator g(this); | 1489 X87OperandGenerator g(this); |
| 1490 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 1490 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
| 1491 | 1491 |
| 1492 // Emit either ArchTableSwitch or ArchLookupSwitch. | 1492 // Emit either ArchTableSwitch or ArchLookupSwitch. |
| 1493 size_t table_space_cost = 4 + sw.value_range; | 1493 size_t table_space_cost = 4 + sw.value_range; |
| 1494 size_t table_time_cost = 3; | 1494 size_t table_time_cost = 3; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1728 // static | 1728 // static |
| 1729 MachineOperatorBuilder::AlignmentRequirements | 1729 MachineOperatorBuilder::AlignmentRequirements |
| 1730 InstructionSelector::AlignmentRequirements() { | 1730 InstructionSelector::AlignmentRequirements() { |
| 1731 return MachineOperatorBuilder::AlignmentRequirements:: | 1731 return MachineOperatorBuilder::AlignmentRequirements:: |
| 1732 FullUnalignedAccessSupport(); | 1732 FullUnalignedAccessSupport(); |
| 1733 } | 1733 } |
| 1734 | 1734 |
| 1735 } // namespace compiler | 1735 } // namespace compiler |
| 1736 } // namespace internal | 1736 } // namespace internal |
| 1737 } // namespace v8 | 1737 } // namespace v8 |
| OLD | NEW |