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 1298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1309 // - If receiver is null -> jump to IC miss. | 1309 // - If receiver is null -> jump to IC miss. |
1310 // - If receiver is Smi -> load Smi class. | 1310 // - If receiver is Smi -> load Smi class. |
1311 // - If receiver is not-Smi -> load receiver's class. | 1311 // - If receiver is not-Smi -> load receiver's class. |
1312 // - Check if 'num_args' (including receiver) match any IC data group. | 1312 // - Check if 'num_args' (including receiver) match any IC data group. |
1313 // - Match found -> jump to target. | 1313 // - Match found -> jump to target. |
1314 // - Match not found -> jump to IC miss. | 1314 // - Match not found -> jump to IC miss. |
1315 void StubCode::GenerateNArgsCheckInlineCacheStub( | 1315 void StubCode::GenerateNArgsCheckInlineCacheStub( |
1316 Assembler* assembler, | 1316 Assembler* assembler, |
1317 intptr_t num_args, | 1317 intptr_t num_args, |
1318 const RuntimeEntry& handle_ic_miss, | 1318 const RuntimeEntry& handle_ic_miss, |
1319 Token::Kind kind) { | 1319 Token::Kind kind, |
1320 RangeCollectionMode range_collection_mode) { | |
1320 ASSERT(num_args > 0); | 1321 ASSERT(num_args > 0); |
1321 #if defined(DEBUG) | 1322 #if defined(DEBUG) |
1322 { Label ok; | 1323 { Label ok; |
1323 // Check that the IC data array has NumArgsTested() == num_args. | 1324 // Check that the IC data array has NumArgsTested() == num_args. |
1324 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1325 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
1325 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); | 1326 __ ldr(R6, FieldAddress(R5, ICData::state_bits_offset())); |
1326 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1327 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1327 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); | 1328 __ and_(R6, R6, Operand(ICData::NumArgsTestedMask())); |
1328 __ CompareImmediate(R6, num_args); | 1329 __ CompareImmediate(R6, num_args); |
1329 __ b(&ok, EQ); | 1330 __ b(&ok, EQ); |
1330 __ Stop("Incorrect stub for IC data"); | 1331 __ Stop("Incorrect stub for IC data"); |
1331 __ Bind(&ok); | 1332 __ Bind(&ok); |
1332 } | 1333 } |
1333 #endif // DEBUG | 1334 #endif // DEBUG |
1334 | 1335 |
1335 | 1336 |
1336 // Check single stepping. | 1337 // Check single stepping. |
1337 Label stepping, done_stepping; | 1338 Label stepping, done_stepping; |
1338 __ LoadIsolate(R6); | 1339 __ LoadIsolate(R6); |
1339 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); | 1340 __ ldrb(R6, Address(R6, Isolate::single_step_offset())); |
1340 __ CompareImmediate(R6, 0); | 1341 __ CompareImmediate(R6, 0); |
1341 __ b(&stepping, NE); | 1342 __ b(&stepping, NE); |
1342 __ Bind(&done_stepping); | 1343 __ Bind(&done_stepping); |
1343 | 1344 |
1345 Label not_smi_or_overflow; | |
zra
2014/12/11 04:29:33
What is the effect of this change on unoptimized c
Vyacheslav Egorov (Google)
2014/12/11 13:06:25
There are no visible regression on the dart2js com
| |
1346 if (range_collection_mode == kCollectRanges) { | |
1347 ASSERT((num_args == 1) || (num_args == 2)); | |
1348 if (num_args == 2) { | |
1349 __ ldr(R0, Address(SP, 1 * kWordSize)); | |
1350 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); | |
1351 } | |
1352 | |
1353 __ ldr(R0, Address(SP, 0 * kWordSize)); | |
1354 __ UpdateRangeFeedback(R0, num_args - 1, R5, R1, R4, ¬_smi_or_overflow); | |
1355 } | |
1344 if (kind != Token::kILLEGAL) { | 1356 if (kind != Token::kILLEGAL) { |
1345 Label not_smi_or_overflow; | |
1346 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1357 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
1347 __ Bind(¬_smi_or_overflow); | |
1348 } | 1358 } |
1359 __ Bind(¬_smi_or_overflow); | |
1349 | 1360 |
1350 // Load arguments descriptor into R4. | 1361 // Load arguments descriptor into R4. |
1351 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1362 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
1352 // Loop that checks if there is an IC data match. | 1363 // Loop that checks if there is an IC data match. |
1353 Label loop, update, test, found; | 1364 Label loop, update, test, found; |
1354 // R5: IC data object (preserved). | 1365 // R5: IC data object (preserved). |
1355 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1366 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
1356 // R6: ic_data_array with check entries: classes and target functions. | 1367 // R6: ic_data_array with check entries: classes and target functions. |
1357 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1368 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
1358 // R6: points directly to the first ic data array element. | 1369 // R6: points directly to the first ic data array element. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1440 // Update counter. | 1451 // Update counter. |
1441 __ LoadFromOffset(kWord, R1, R6, count_offset); | 1452 __ LoadFromOffset(kWord, R1, R6, count_offset); |
1442 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1453 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1443 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. | 1454 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. |
1444 __ StoreIntoSmiField(Address(R6, count_offset), R1); | 1455 __ StoreIntoSmiField(Address(R6, count_offset), R1); |
1445 | 1456 |
1446 __ Bind(&call_target_function); | 1457 __ Bind(&call_target_function); |
1447 // R0: target function. | 1458 // R0: target function. |
1448 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1459 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
1449 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 1460 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
1450 __ bx(R2); | 1461 if (range_collection_mode == kCollectRanges) { |
1462 __ ldr(R1, Address(SP, 0 * kWordSize)); | |
1463 if (num_args == 2) { | |
1464 __ ldr(R3, Address(SP, 1 * kWordSize)); | |
1465 } | |
1466 __ EnterStubFrame(); | |
1467 if (num_args == 2) { | |
1468 __ PushList((1 << R1) | (1 << R3) | (1 << R5)); | |
1469 } else { | |
1470 __ PushList((1 << R1) | (1 << R5)); | |
1471 } | |
1472 __ blx(R2); | |
1473 | |
1474 Label done; | |
1475 __ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize)); | |
1476 __ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done); | |
1477 __ Bind(&done); | |
1478 __ LeaveStubFrame(); | |
1479 __ Ret(); | |
1480 } else { | |
1481 __ bx(R2); | |
1482 } | |
1451 | 1483 |
1452 __ Bind(&stepping); | 1484 __ Bind(&stepping); |
1453 __ EnterStubFrame(); | 1485 __ EnterStubFrame(); |
1454 __ Push(R5); // Preserve IC data. | 1486 __ Push(R5); // Preserve IC data. |
1455 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1487 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1456 __ Pop(R5); | 1488 __ Pop(R5); |
1457 __ LeaveStubFrame(); | 1489 __ LeaveStubFrame(); |
1458 __ b(&done_stepping); | 1490 __ b(&done_stepping); |
1459 } | 1491 } |
1460 | 1492 |
1461 | 1493 |
1462 // Use inline cache data array to invoke the target or continue in inline | 1494 // Use inline cache data array to invoke the target or continue in inline |
1463 // cache miss handler. Stub for 1-argument check (receiver class). | 1495 // cache miss handler. Stub for 1-argument check (receiver class). |
1464 // LR: return address. | 1496 // LR: return address. |
1465 // R5: inline cache data object. | 1497 // R5: inline cache data object. |
1466 // Inline cache data object structure: | 1498 // Inline cache data object structure: |
1467 // 0: function-name | 1499 // 0: function-name |
1468 // 1: N, number of arguments checked. | 1500 // 1: N, number of arguments checked. |
1469 // 2 .. (length - 1): group of checks, each check containing: | 1501 // 2 .. (length - 1): group of checks, each check containing: |
1470 // - N classes. | 1502 // - N classes. |
1471 // - 1 target function. | 1503 // - 1 target function. |
1472 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1504 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1473 GenerateUsageCounterIncrement(assembler, R6); | 1505 GenerateUsageCounterIncrement(assembler, R6); |
1474 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1506 GenerateNArgsCheckInlineCacheStub(assembler, |
1475 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1507 1, |
1508 kInlineCacheMissHandlerOneArgRuntimeEntry, | |
1509 Token::kILLEGAL, | |
1510 kIgnoreRanges); | |
1476 } | 1511 } |
1477 | 1512 |
1478 | 1513 |
1479 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1514 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1480 GenerateUsageCounterIncrement(assembler, R6); | 1515 GenerateUsageCounterIncrement(assembler, R6); |
1481 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1516 GenerateNArgsCheckInlineCacheStub(assembler, |
1482 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); | 1517 2, |
1518 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | |
1519 Token::kILLEGAL, | |
1520 kIgnoreRanges); | |
1483 } | 1521 } |
1484 | 1522 |
1485 | 1523 |
1486 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1524 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
1487 GenerateUsageCounterIncrement(assembler, R6); | 1525 GenerateUsageCounterIncrement(assembler, R6); |
1488 GenerateNArgsCheckInlineCacheStub(assembler, 3, | 1526 GenerateNArgsCheckInlineCacheStub(assembler, |
1489 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL); | 1527 3, |
1528 kInlineCacheMissHandlerThreeArgsRuntimeEntry, | |
1529 Token::kILLEGAL, | |
1530 kIgnoreRanges); | |
1490 } | 1531 } |
1491 | 1532 |
1492 | 1533 |
1493 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { | 1534 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { |
1494 GenerateUsageCounterIncrement(assembler, R6); | 1535 GenerateUsageCounterIncrement(assembler, R6); |
1495 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1536 GenerateNArgsCheckInlineCacheStub(assembler, |
1496 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); | 1537 2, |
1538 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | |
1539 Token::kADD, | |
1540 kCollectRanges); | |
1497 } | 1541 } |
1498 | 1542 |
1499 | 1543 |
1500 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { | 1544 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { |
1501 GenerateUsageCounterIncrement(assembler, R6); | 1545 GenerateUsageCounterIncrement(assembler, R6); |
1502 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1546 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1503 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); | 1547 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB, |
1548 kCollectRanges); | |
1504 } | 1549 } |
1505 | 1550 |
1506 | 1551 |
1507 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { | 1552 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { |
1508 GenerateUsageCounterIncrement(assembler, R6); | 1553 GenerateUsageCounterIncrement(assembler, R6); |
1509 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1554 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1510 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); | 1555 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ, |
1556 kIgnoreRanges); | |
1511 } | 1557 } |
1512 | 1558 |
1513 | 1559 |
1560 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( | |
1561 Assembler* assembler) { | |
1562 GenerateUsageCounterIncrement(assembler, R6); | |
1563 GenerateNArgsCheckInlineCacheStub(assembler, 1, | |
1564 kInlineCacheMissHandlerOneArgRuntimeEntry, | |
1565 Token::kILLEGAL, | |
1566 kCollectRanges); | |
1567 } | |
1568 | |
1569 | |
1570 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( | |
1571 Assembler* assembler) { | |
1572 GenerateUsageCounterIncrement(assembler, R6); | |
1573 GenerateNArgsCheckInlineCacheStub(assembler, 2, | |
1574 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | |
1575 Token::kILLEGAL, | |
1576 kCollectRanges); | |
1577 } | |
1578 | |
1579 | |
1514 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1580 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1515 Assembler* assembler) { | 1581 Assembler* assembler) { |
1516 GenerateOptimizedUsageCounterIncrement(assembler); | 1582 GenerateOptimizedUsageCounterIncrement(assembler); |
1517 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1583 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1518 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1584 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
1585 kIgnoreRanges); | |
1519 } | 1586 } |
1520 | 1587 |
1521 | 1588 |
1522 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1589 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
1523 Assembler* assembler) { | 1590 Assembler* assembler) { |
1524 GenerateOptimizedUsageCounterIncrement(assembler); | 1591 GenerateOptimizedUsageCounterIncrement(assembler); |
1525 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1592 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1526 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); | 1593 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, |
1594 kIgnoreRanges); | |
1527 } | 1595 } |
1528 | 1596 |
1529 | 1597 |
1530 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( | 1598 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( |
1531 Assembler* assembler) { | 1599 Assembler* assembler) { |
1532 GenerateOptimizedUsageCounterIncrement(assembler); | 1600 GenerateOptimizedUsageCounterIncrement(assembler); |
1533 GenerateNArgsCheckInlineCacheStub(assembler, 3, | 1601 GenerateNArgsCheckInlineCacheStub(assembler, 3, |
1534 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL); | 1602 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL, |
1603 kIgnoreRanges); | |
1535 } | 1604 } |
1536 | 1605 |
1537 | 1606 |
1538 // Intermediary stub between a static call and its target. ICData contains | 1607 // Intermediary stub between a static call and its target. ICData contains |
1539 // the target function and the call count. | 1608 // the target function and the call count. |
1540 // R5: ICData | 1609 // R5: ICData |
1541 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1610 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1542 GenerateUsageCounterIncrement(assembler, R6); | 1611 GenerateUsageCounterIncrement(assembler, R6); |
1543 #if defined(DEBUG) | 1612 #if defined(DEBUG) |
1544 { Label ok; | 1613 { Label ok; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1594 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1663 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1595 __ Pop(R5); | 1664 __ Pop(R5); |
1596 __ LeaveStubFrame(); | 1665 __ LeaveStubFrame(); |
1597 __ b(&done_stepping); | 1666 __ b(&done_stepping); |
1598 } | 1667 } |
1599 | 1668 |
1600 | 1669 |
1601 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1670 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1602 GenerateUsageCounterIncrement(assembler, R6); | 1671 GenerateUsageCounterIncrement(assembler, R6); |
1603 GenerateNArgsCheckInlineCacheStub( | 1672 GenerateNArgsCheckInlineCacheStub( |
1604 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1673 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, |
1674 kIgnoreRanges); | |
1605 } | 1675 } |
1606 | 1676 |
1607 | 1677 |
1608 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1678 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1609 GenerateUsageCounterIncrement(assembler, R6); | 1679 GenerateUsageCounterIncrement(assembler, R6); |
1610 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1680 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1611 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); | 1681 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL, |
1682 kIgnoreRanges); | |
1612 } | 1683 } |
1613 | 1684 |
1614 | 1685 |
1615 // Stub for compiling a function and jumping to the compiled code. | 1686 // Stub for compiling a function and jumping to the compiled code. |
1616 // R5: IC-Data (for methods). | 1687 // R5: IC-Data (for methods). |
1617 // R4: Arguments descriptor. | 1688 // R4: Arguments descriptor. |
1618 // R0: Function. | 1689 // R0: Function. |
1619 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1690 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
1620 // Preserve arg desc. and IC data object. | 1691 // Preserve arg desc. and IC data object. |
1621 __ EnterStubFrame(); | 1692 __ EnterStubFrame(); |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1971 const Register right = R0; | 2042 const Register right = R0; |
1972 __ ldr(left, Address(SP, 1 * kWordSize)); | 2043 __ ldr(left, Address(SP, 1 * kWordSize)); |
1973 __ ldr(right, Address(SP, 0 * kWordSize)); | 2044 __ ldr(right, Address(SP, 0 * kWordSize)); |
1974 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2045 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
1975 __ Ret(); | 2046 __ Ret(); |
1976 } | 2047 } |
1977 | 2048 |
1978 } // namespace dart | 2049 } // namespace dart |
1979 | 2050 |
1980 #endif // defined TARGET_ARCH_ARM | 2051 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |