OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 // - If receiver is Smi -> load Smi class. | 1317 // - If receiver is Smi -> load Smi class. |
1318 // - If receiver is not-Smi -> load receiver's class. | 1318 // - If receiver is not-Smi -> load receiver's class. |
1319 // - Check if 'num_args' (including receiver) match any IC data group. | 1319 // - Check if 'num_args' (including receiver) match any IC data group. |
1320 // - Match found -> jump to target. | 1320 // - Match found -> jump to target. |
1321 // - Match not found -> jump to IC miss. | 1321 // - Match not found -> jump to IC miss. |
1322 void StubCode::GenerateNArgsCheckInlineCacheStub( | 1322 void StubCode::GenerateNArgsCheckInlineCacheStub( |
1323 Assembler* assembler, | 1323 Assembler* assembler, |
1324 intptr_t num_args, | 1324 intptr_t num_args, |
1325 const RuntimeEntry& handle_ic_miss, | 1325 const RuntimeEntry& handle_ic_miss, |
1326 Token::Kind kind, | 1326 Token::Kind kind, |
1327 RangeCollectionMode range_collection_mode, | |
1328 bool optimized) { | 1327 bool optimized) { |
1329 __ CheckCodePointer(); | 1328 __ CheckCodePointer(); |
1330 ASSERT(num_args > 0); | 1329 ASSERT(num_args > 0); |
1331 #if defined(DEBUG) | 1330 #if defined(DEBUG) |
1332 { Label ok; | 1331 { Label ok; |
1333 // Check that the IC data array has NumArgsTested() == num_args. | 1332 // Check that the IC data array has NumArgsTested() == num_args. |
1334 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1333 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
1335 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); | 1334 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); |
1336 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1335 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1337 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); | 1336 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); |
1338 __ CompareImmediate(R8, num_args); | 1337 __ CompareImmediate(R8, num_args); |
1339 __ b(&ok, EQ); | 1338 __ b(&ok, EQ); |
1340 __ Stop("Incorrect stub for IC data"); | 1339 __ Stop("Incorrect stub for IC data"); |
1341 __ Bind(&ok); | 1340 __ Bind(&ok); |
1342 } | 1341 } |
1343 #endif // DEBUG | 1342 #endif // DEBUG |
1344 | 1343 |
1345 Label stepping, done_stepping; | 1344 Label stepping, done_stepping; |
1346 if (FLAG_support_debugger && !optimized) { | 1345 if (FLAG_support_debugger && !optimized) { |
1347 __ Comment("Check single stepping"); | 1346 __ Comment("Check single stepping"); |
1348 __ LoadIsolate(R8); | 1347 __ LoadIsolate(R8); |
1349 __ ldrb(R8, Address(R8, Isolate::single_step_offset())); | 1348 __ ldrb(R8, Address(R8, Isolate::single_step_offset())); |
1350 __ CompareImmediate(R8, 0); | 1349 __ CompareImmediate(R8, 0); |
1351 __ b(&stepping, NE); | 1350 __ b(&stepping, NE); |
1352 __ Bind(&done_stepping); | 1351 __ Bind(&done_stepping); |
1353 } | 1352 } |
1354 | 1353 |
1355 __ Comment("Range feedback collection"); | |
1356 Label not_smi_or_overflow; | 1354 Label not_smi_or_overflow; |
1357 if (range_collection_mode == kCollectRanges) { | |
1358 ASSERT((num_args == 1) || (num_args == 2)); | |
1359 if (num_args == 2) { | |
1360 __ ldr(R0, Address(SP, 1 * kWordSize)); | |
1361 __ UpdateRangeFeedback(R0, 0, R9, R1, R4, ¬_smi_or_overflow); | |
1362 } | |
1363 | |
1364 __ ldr(R0, Address(SP, 0 * kWordSize)); | |
1365 __ UpdateRangeFeedback(R0, num_args - 1, R9, R1, R4, ¬_smi_or_overflow); | |
1366 } | |
1367 if (kind != Token::kILLEGAL) { | 1355 if (kind != Token::kILLEGAL) { |
1368 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1356 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
1369 } | 1357 } |
1370 __ Bind(¬_smi_or_overflow); | 1358 __ Bind(¬_smi_or_overflow); |
1371 | 1359 |
1372 __ Comment("Extract ICData initial values and receiver cid"); | 1360 __ Comment("Extract ICData initial values and receiver cid"); |
1373 // Load arguments descriptor into R4. | 1361 // Load arguments descriptor into R4. |
1374 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); | 1362 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
1375 // Loop that checks if there is an IC data match. | 1363 // Loop that checks if there is an IC data match. |
1376 Label loop, update, test, found; | 1364 Label loop, update, test, found; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1471 __ LoadFromOffset(kWord, R1, R8, count_offset); | 1459 __ LoadFromOffset(kWord, R1, R8, count_offset); |
1472 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1460 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1473 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1461 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
1474 __ StoreIntoSmiField(Address(R8, count_offset), R1); | 1462 __ StoreIntoSmiField(Address(R8, count_offset), R1); |
1475 } | 1463 } |
1476 | 1464 |
1477 __ Comment("Call target"); | 1465 __ Comment("Call target"); |
1478 __ Bind(&call_target_function); | 1466 __ Bind(&call_target_function); |
1479 // R0: target function. | 1467 // R0: target function. |
1480 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 1468 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
1481 if (range_collection_mode == kCollectRanges) { | 1469 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
1482 __ ldr(R1, Address(SP, 0 * kWordSize)); | 1470 __ bx(R2); |
1483 if (num_args == 2) { | |
1484 __ ldr(R3, Address(SP, 1 * kWordSize)); | |
1485 } | |
1486 __ EnterStubFrame(); | |
1487 if (num_args == 2) { | |
1488 __ PushList((1 << R1) | (1 << R3) | (1 << R9)); | |
1489 } else { | |
1490 __ PushList((1 << R1) | (1 << R9)); | |
1491 } | |
1492 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | |
1493 __ blx(R2); | |
1494 | |
1495 Label done; | |
1496 __ ldr(R9, Address(FP, kFirstLocalSlotFromFp * kWordSize)); | |
1497 __ UpdateRangeFeedback(R0, 2, R9, R1, R4, &done); | |
1498 __ Bind(&done); | |
1499 __ RestoreCodePointer(); | |
1500 __ LeaveStubFrame(); | |
1501 __ Ret(); | |
1502 } else { | |
1503 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | |
1504 __ bx(R2); | |
1505 } | |
1506 | 1471 |
1507 if (FLAG_support_debugger && !optimized) { | 1472 if (FLAG_support_debugger && !optimized) { |
1508 __ Bind(&stepping); | 1473 __ Bind(&stepping); |
1509 __ EnterStubFrame(); | 1474 __ EnterStubFrame(); |
1510 __ Push(R9); // Preserve IC data. | 1475 __ Push(R9); // Preserve IC data. |
1511 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1476 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1512 __ Pop(R9); | 1477 __ Pop(R9); |
1513 __ RestoreCodePointer(); | 1478 __ RestoreCodePointer(); |
1514 __ LeaveStubFrame(); | 1479 __ LeaveStubFrame(); |
1515 __ b(&done_stepping); | 1480 __ b(&done_stepping); |
1516 } | 1481 } |
1517 } | 1482 } |
1518 | 1483 |
1519 | 1484 |
1520 // Use inline cache data array to invoke the target or continue in inline | 1485 // Use inline cache data array to invoke the target or continue in inline |
1521 // cache miss handler. Stub for 1-argument check (receiver class). | 1486 // cache miss handler. Stub for 1-argument check (receiver class). |
1522 // LR: return address. | 1487 // LR: return address. |
1523 // R9: inline cache data object. | 1488 // R9: inline cache data object. |
1524 // Inline cache data object structure: | 1489 // Inline cache data object structure: |
1525 // 0: function-name | 1490 // 0: function-name |
1526 // 1: N, number of arguments checked. | 1491 // 1: N, number of arguments checked. |
1527 // 2 .. (length - 1): group of checks, each check containing: | 1492 // 2 .. (length - 1): group of checks, each check containing: |
1528 // - N classes. | 1493 // - N classes. |
1529 // - 1 target function. | 1494 // - 1 target function. |
1530 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1495 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1531 GenerateUsageCounterIncrement(assembler, R8); | 1496 GenerateUsageCounterIncrement(assembler, R8); |
1532 GenerateNArgsCheckInlineCacheStub(assembler, | 1497 GenerateNArgsCheckInlineCacheStub(assembler, |
1533 1, | 1498 1, |
1534 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1499 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1535 Token::kILLEGAL, | 1500 Token::kILLEGAL); |
1536 kIgnoreRanges); | |
1537 } | 1501 } |
1538 | 1502 |
1539 | 1503 |
1540 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1504 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1541 GenerateUsageCounterIncrement(assembler, R8); | 1505 GenerateUsageCounterIncrement(assembler, R8); |
1542 GenerateNArgsCheckInlineCacheStub(assembler, | 1506 GenerateNArgsCheckInlineCacheStub(assembler, |
1543 2, | 1507 2, |
1544 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1508 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1545 Token::kILLEGAL, | 1509 Token::kILLEGAL); |
1546 kIgnoreRanges); | |
1547 } | 1510 } |
1548 | 1511 |
1549 | 1512 |
1550 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { | 1513 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { |
1551 GenerateUsageCounterIncrement(assembler, R8); | 1514 GenerateUsageCounterIncrement(assembler, R8); |
1552 GenerateNArgsCheckInlineCacheStub(assembler, | 1515 GenerateNArgsCheckInlineCacheStub(assembler, |
1553 2, | 1516 2, |
1554 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1517 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1555 Token::kADD, | 1518 Token::kADD); |
1556 kCollectRanges); | |
1557 } | 1519 } |
1558 | 1520 |
1559 | 1521 |
1560 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { | 1522 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { |
1561 GenerateUsageCounterIncrement(assembler, R8); | 1523 GenerateUsageCounterIncrement(assembler, R8); |
1562 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1524 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1563 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB, | 1525 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); |
1564 kCollectRanges); | |
1565 } | 1526 } |
1566 | 1527 |
1567 | 1528 |
1568 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { | 1529 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { |
1569 GenerateUsageCounterIncrement(assembler, R8); | 1530 GenerateUsageCounterIncrement(assembler, R8); |
1570 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1531 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1571 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ, | 1532 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); |
1572 kIgnoreRanges); | |
1573 } | 1533 } |
1574 | 1534 |
1575 | 1535 |
1576 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( | 1536 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( |
1577 Assembler* assembler) { | 1537 Assembler* assembler) { |
1578 GenerateUsageCounterIncrement(assembler, R8); | 1538 GenerateUsageCounterIncrement(assembler, R8); |
1579 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1539 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1580 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1540 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1581 Token::kILLEGAL, | 1541 Token::kILLEGAL); |
1582 kCollectRanges); | |
1583 } | 1542 } |
1584 | 1543 |
1585 | 1544 |
1586 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( | 1545 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( |
1587 Assembler* assembler) { | 1546 Assembler* assembler) { |
1588 GenerateUsageCounterIncrement(assembler, R8); | 1547 GenerateUsageCounterIncrement(assembler, R8); |
1589 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1548 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1590 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1549 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1591 Token::kILLEGAL, | 1550 Token::kILLEGAL); |
1592 kCollectRanges); | |
1593 } | 1551 } |
1594 | 1552 |
1595 | 1553 |
1596 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1554 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1597 Assembler* assembler) { | 1555 Assembler* assembler) { |
1598 GenerateOptimizedUsageCounterIncrement(assembler); | 1556 GenerateOptimizedUsageCounterIncrement(assembler); |
1599 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1557 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1600 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1558 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
1601 kIgnoreRanges, true /* optimized */); | 1559 true /* optimized */); |
1602 } | 1560 } |
1603 | 1561 |
1604 | 1562 |
1605 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1563 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
1606 Assembler* assembler) { | 1564 Assembler* assembler) { |
1607 GenerateOptimizedUsageCounterIncrement(assembler); | 1565 GenerateOptimizedUsageCounterIncrement(assembler); |
1608 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1566 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1609 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, | 1567 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, |
1610 kIgnoreRanges, true /* optimized */); | 1568 true /* optimized */); |
1611 } | 1569 } |
1612 | 1570 |
1613 | 1571 |
1614 // Intermediary stub between a static call and its target. ICData contains | 1572 // Intermediary stub between a static call and its target. ICData contains |
1615 // the target function and the call count. | 1573 // the target function and the call count. |
1616 // R9: ICData | 1574 // R9: ICData |
1617 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1575 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1618 GenerateUsageCounterIncrement(assembler, R8); | 1576 GenerateUsageCounterIncrement(assembler, R8); |
1619 #if defined(DEBUG) | 1577 #if defined(DEBUG) |
1620 { Label ok; | 1578 { Label ok; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 __ RestoreCodePointer(); | 1632 __ RestoreCodePointer(); |
1675 __ LeaveStubFrame(); | 1633 __ LeaveStubFrame(); |
1676 __ b(&done_stepping); | 1634 __ b(&done_stepping); |
1677 } | 1635 } |
1678 } | 1636 } |
1679 | 1637 |
1680 | 1638 |
1681 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1639 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1682 GenerateUsageCounterIncrement(assembler, R8); | 1640 GenerateUsageCounterIncrement(assembler, R8); |
1683 GenerateNArgsCheckInlineCacheStub( | 1641 GenerateNArgsCheckInlineCacheStub( |
1684 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, | 1642 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1685 kIgnoreRanges); | |
1686 } | 1643 } |
1687 | 1644 |
1688 | 1645 |
1689 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1646 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1690 GenerateUsageCounterIncrement(assembler, R8); | 1647 GenerateUsageCounterIncrement(assembler, R8); |
1691 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1648 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1692 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, | 1649 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); |
1693 kIgnoreRanges); | |
1694 } | 1650 } |
1695 | 1651 |
1696 | 1652 |
1697 // Stub for compiling a function and jumping to the compiled code. | 1653 // Stub for compiling a function and jumping to the compiled code. |
1698 // R9: IC-Data (for methods). | 1654 // R9: IC-Data (for methods). |
1699 // R4: Arguments descriptor. | 1655 // R4: Arguments descriptor. |
1700 // R0: Function. | 1656 // R0: Function. |
1701 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1657 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
1702 // Preserve arg desc. and IC data object. | 1658 // Preserve arg desc. and IC data object. |
1703 __ EnterStubFrame(); | 1659 __ EnterStubFrame(); |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2181 } | 2137 } |
2182 | 2138 |
2183 | 2139 |
2184 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { | 2140 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { |
2185 __ bkpt(0); | 2141 __ bkpt(0); |
2186 } | 2142 } |
2187 | 2143 |
2188 } // namespace dart | 2144 } // namespace dart |
2189 | 2145 |
2190 #endif // defined TARGET_ARCH_ARM | 2146 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |