OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
(...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1469 if (tmp.IsRegister() && | 1469 if (tmp.IsRegister() && |
1470 !locs->live_registers()->ContainsRegister(tmp.reg())) { | 1470 !locs->live_registers()->ContainsRegister(tmp.reg())) { |
1471 __ movz(tmp.reg(), Immediate(0xf7), 0); | 1471 __ movz(tmp.reg(), Immediate(0xf7), 0); |
1472 } | 1472 } |
1473 } | 1473 } |
1474 } | 1474 } |
1475 #endif | 1475 #endif |
1476 | 1476 |
1477 | 1477 |
1478 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1478 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
1479 Register class_id_reg, | |
1480 intptr_t argument_count, | 1479 intptr_t argument_count, |
1481 const Array& argument_names, | 1480 const Array& argument_names, |
1482 Label* deopt, | 1481 Label* failed, |
| 1482 Label* match_found, |
1483 intptr_t deopt_id, | 1483 intptr_t deopt_id, |
1484 intptr_t token_index, | 1484 intptr_t token_index, |
1485 LocationSummary* locs) { | 1485 LocationSummary* locs) { |
1486 ASSERT(is_optimizing()); | 1486 ASSERT(is_optimizing()); |
1487 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0)); | 1487 |
1488 Label match_found; | 1488 __ Comment("EmitTestAndCall"); |
1489 const intptr_t len = ic_data.NumberOfChecks(); | |
1490 GrowableArray<CidTarget> sorted(len); | |
1491 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false); | |
1492 ASSERT(class_id_reg != R4); | |
1493 ASSERT(len > 0); // Why bother otherwise. | |
1494 const Array& arguments_descriptor = | 1489 const Array& arguments_descriptor = |
1495 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 1490 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
1496 argument_names)); | 1491 argument_names)); |
1497 StubCode* stub_code = isolate()->stub_code(); | 1492 StubCode* stub_code = isolate()->stub_code(); |
1498 | 1493 |
| 1494 // Load receiver into R0. |
| 1495 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize, PP); |
1499 __ LoadObject(R4, arguments_descriptor, PP); | 1496 __ LoadObject(R4, arguments_descriptor, PP); |
1500 for (intptr_t i = 0; i < len; i++) { | 1497 |
1501 const bool is_last_check = (i == (len - 1)); | 1498 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
| 1499 const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
| 1500 |
| 1501 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
| 1502 |
| 1503 Label after_smi_test; |
| 1504 __ tsti(R0, Immediate(kSmiTagMask)); |
| 1505 if (kFirstCheckIsSmi) { |
| 1506 // Jump if receiver is not Smi. |
| 1507 if (kNumChecks == 1) { |
| 1508 __ b(failed, NE); |
| 1509 } else { |
| 1510 __ b(&after_smi_test, NE); |
| 1511 } |
| 1512 // Do not use the code from the function, but let the code be patched so |
| 1513 // that we can record the outgoing edges to other code. |
| 1514 GenerateDartCall(deopt_id, |
| 1515 token_index, |
| 1516 &stub_code->CallStaticFunctionLabel(), |
| 1517 RawPcDescriptors::kOther, |
| 1518 locs); |
| 1519 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); |
| 1520 AddStaticCallTarget(function); |
| 1521 __ Drop(argument_count); |
| 1522 if (kNumChecks > 1) { |
| 1523 __ b(match_found); |
| 1524 } |
| 1525 } else { |
| 1526 // Receiver is Smi, but Smi is not a valid class therefore fail. |
| 1527 // (Smi class must be first in the list). |
| 1528 __ b(failed, EQ); |
| 1529 } |
| 1530 __ Bind(&after_smi_test); |
| 1531 |
| 1532 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
| 1533 GrowableArray<CidTarget> sorted(kNumChecks); |
| 1534 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); |
| 1535 |
| 1536 // Value is not Smi, |
| 1537 const intptr_t kSortedLen = sorted.length(); |
| 1538 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above |
| 1539 // will fail if there was only one check and receiver is not Smi. |
| 1540 if (kSortedLen == 0) return; |
| 1541 |
| 1542 __ LoadClassId(R2, R0, PP); |
| 1543 for (intptr_t i = 0; i < kSortedLen; i++) { |
| 1544 const bool kIsLastCheck = (i == (kSortedLen - 1)); |
| 1545 ASSERT(sorted[i].cid != kSmiCid); |
1502 Label next_test; | 1546 Label next_test; |
1503 __ CompareImmediate(class_id_reg, sorted[i].cid, PP); | 1547 __ CompareImmediate(R2, sorted[i].cid, PP); |
1504 if (is_last_check) { | 1548 if (kIsLastCheck) { |
1505 __ b(deopt, NE); | 1549 __ b(failed, NE); |
1506 } else { | 1550 } else { |
1507 __ b(&next_test, NE); | 1551 __ b(&next_test, NE); |
1508 } | 1552 } |
1509 // Do not use the code from the function, but let the code be patched so | 1553 // Do not use the code from the function, but let the code be patched so |
1510 // that we can record the outgoing edges to other code. | 1554 // that we can record the outgoing edges to other code. |
1511 GenerateDartCall(deopt_id, | 1555 GenerateDartCall(deopt_id, |
1512 token_index, | 1556 token_index, |
1513 &stub_code->CallStaticFunctionLabel(), | 1557 &stub_code->CallStaticFunctionLabel(), |
1514 RawPcDescriptors::kOther, | 1558 RawPcDescriptors::kOther, |
1515 locs); | 1559 locs); |
1516 const Function& function = *sorted[i].target; | 1560 const Function& function = *sorted[i].target; |
1517 AddStaticCallTarget(function); | 1561 AddStaticCallTarget(function); |
1518 __ Drop(argument_count); | 1562 __ Drop(argument_count); |
1519 if (!is_last_check) { | 1563 if (!kIsLastCheck) { |
1520 __ b(&match_found); | 1564 __ b(match_found); |
1521 } | 1565 } |
1522 __ Bind(&next_test); | 1566 __ Bind(&next_test); |
1523 } | 1567 } |
1524 __ Bind(&match_found); | |
1525 } | 1568 } |
1526 | 1569 |
1527 | 1570 |
1528 #undef __ | 1571 #undef __ |
1529 #define __ compiler_->assembler()-> | 1572 #define __ compiler_->assembler()-> |
1530 | 1573 |
1531 | 1574 |
1532 void ParallelMoveResolver::EmitMove(int index) { | 1575 void ParallelMoveResolver::EmitMove(int index) { |
1533 MoveOperands* move = moves_[index]; | 1576 MoveOperands* move = moves_[index]; |
1534 const Location source = move->src(); | 1577 const Location source = move->src(); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1804 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1847 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
1805 __ PopDouble(reg); | 1848 __ PopDouble(reg); |
1806 } | 1849 } |
1807 | 1850 |
1808 | 1851 |
1809 #undef __ | 1852 #undef __ |
1810 | 1853 |
1811 } // namespace dart | 1854 } // namespace dart |
1812 | 1855 |
1813 #endif // defined TARGET_ARCH_ARM64 | 1856 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |