| 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/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 // Generate inline cache check for 'num_args'. | 1355 // Generate inline cache check for 'num_args'. |
| 1356 // LR: return address. | 1356 // LR: return address. |
| 1357 // R5: inline cache data object. | 1357 // R5: inline cache data object. |
| 1358 // Control flow: | 1358 // Control flow: |
| 1359 // - If receiver is null -> jump to IC miss. | 1359 // - If receiver is null -> jump to IC miss. |
| 1360 // - If receiver is Smi -> load Smi class. | 1360 // - If receiver is Smi -> load Smi class. |
| 1361 // - If receiver is not-Smi -> load receiver's class. | 1361 // - If receiver is not-Smi -> load receiver's class. |
| 1362 // - Check if 'num_args' (including receiver) match any IC data group. | 1362 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1363 // - Match found -> jump to target. | 1363 // - Match found -> jump to target. |
| 1364 // - Match not found -> jump to IC miss. | 1364 // - Match not found -> jump to IC miss. |
| 1365 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1365 void StubCode::GenerateNArgsCheckInlineCacheStub( |
| 1366 intptr_t num_args) { | 1366 Assembler* assembler, |
| 1367 intptr_t num_args, |
| 1368 const RuntimeEntry& handle_ic_miss) { |
| 1367 ASSERT(num_args > 0); | 1369 ASSERT(num_args > 0); |
| 1368 #if defined(DEBUG) | 1370 #if defined(DEBUG) |
| 1369 { Label ok; | 1371 { Label ok; |
| 1370 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1372 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1371 // 'num_args_tested' is stored as an untagged int. | 1373 // 'num_args_tested' is stored as an untagged int. |
| 1372 __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset())); | 1374 __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset())); |
| 1373 __ CompareImmediate(R6, num_args); | 1375 __ CompareImmediate(R6, num_args); |
| 1374 __ b(&ok, EQ); | 1376 __ b(&ok, EQ); |
| 1375 __ Stop("Incorrect stub for IC data"); | 1377 __ Stop("Incorrect stub for IC data"); |
| 1376 __ Bind(&ok); | 1378 __ Bind(&ok); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1463 // Preserve IC data object and arguments descriptor array and | 1465 // Preserve IC data object and arguments descriptor array and |
| 1464 // setup space on stack for result (target code object). | 1466 // setup space on stack for result (target code object). |
| 1465 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); | 1467 __ PushList((1 << R0) | (1 << R4) | (1 << R5)); |
| 1466 // Push call arguments. | 1468 // Push call arguments. |
| 1467 for (intptr_t i = 0; i < num_args; i++) { | 1469 for (intptr_t i = 0; i < num_args; i++) { |
| 1468 __ LoadFromOffset(kWord, IP, R7, -i * kWordSize); | 1470 __ LoadFromOffset(kWord, IP, R7, -i * kWordSize); |
| 1469 __ Push(IP); | 1471 __ Push(IP); |
| 1470 } | 1472 } |
| 1471 // Pass IC data object. | 1473 // Pass IC data object. |
| 1472 __ Push(R5); | 1474 __ Push(R5); |
| 1473 | 1475 __ CallRuntime(handle_ic_miss); |
| 1474 if (num_args == 1) { | |
| 1475 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); | |
| 1476 } else if (num_args == 2) { | |
| 1477 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); | |
| 1478 } else if (num_args == 3) { | |
| 1479 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); | |
| 1480 } else { | |
| 1481 UNIMPLEMENTED(); | |
| 1482 } | |
| 1483 // Remove the call arguments pushed earlier, including the IC data object. | 1476 // Remove the call arguments pushed earlier, including the IC data object. |
| 1484 __ Drop(num_args + 1); | 1477 __ Drop(num_args + 1); |
| 1485 // Pop returned code object into R0 (null if not found). | 1478 // Pop returned code object into R0 (null if not found). |
| 1486 // Restore arguments descriptor array and IC data array. | 1479 // Restore arguments descriptor array and IC data array. |
| 1487 __ PopList((1 << R0) | (1 << R4) | (1 << R5)); | 1480 __ PopList((1 << R0) | (1 << R4) | (1 << R5)); |
| 1488 __ LeaveStubFrame(); | 1481 __ LeaveStubFrame(); |
| 1489 Label call_target_function; | 1482 Label call_target_function; |
| 1490 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); | 1483 __ CompareImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); |
| 1491 __ b(&call_target_function, NE); | 1484 __ b(&call_target_function, NE); |
| 1492 // NoSuchMethod or closure. | 1485 // NoSuchMethod or closure. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1533 // LR: return address. | 1526 // LR: return address. |
| 1534 // R5: inline cache data object. | 1527 // R5: inline cache data object. |
| 1535 // Inline cache data object structure: | 1528 // Inline cache data object structure: |
| 1536 // 0: function-name | 1529 // 0: function-name |
| 1537 // 1: N, number of arguments checked. | 1530 // 1: N, number of arguments checked. |
| 1538 // 2 .. (length - 1): group of checks, each check containing: | 1531 // 2 .. (length - 1): group of checks, each check containing: |
| 1539 // - N classes. | 1532 // - N classes. |
| 1540 // - 1 target function. | 1533 // - 1 target function. |
| 1541 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1534 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
| 1542 GenerateUsageCounterIncrement(assembler, R6); | 1535 GenerateUsageCounterIncrement(assembler, R6); |
| 1543 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1536 GenerateNArgsCheckInlineCacheStub( |
| 1537 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1544 } | 1538 } |
| 1545 | 1539 |
| 1546 | 1540 |
| 1547 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1541 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1548 GenerateUsageCounterIncrement(assembler, R6); | 1542 GenerateUsageCounterIncrement(assembler, R6); |
| 1549 GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1543 GenerateNArgsCheckInlineCacheStub( |
| 1544 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1550 } | 1545 } |
| 1551 | 1546 |
| 1552 | 1547 |
| 1553 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1548 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
| 1554 GenerateUsageCounterIncrement(assembler, R6); | 1549 GenerateUsageCounterIncrement(assembler, R6); |
| 1555 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1550 GenerateNArgsCheckInlineCacheStub( |
| 1551 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); |
| 1556 } | 1552 } |
| 1557 | 1553 |
| 1558 | 1554 |
| 1559 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1555 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
| 1560 Assembler* assembler) { | 1556 Assembler* assembler) { |
| 1561 GenerateOptimizedUsageCounterIncrement(assembler); | 1557 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1562 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1558 GenerateNArgsCheckInlineCacheStub( |
| 1559 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1563 } | 1560 } |
| 1564 | 1561 |
| 1565 | 1562 |
| 1566 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1563 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
| 1567 Assembler* assembler) { | 1564 Assembler* assembler) { |
| 1568 GenerateOptimizedUsageCounterIncrement(assembler); | 1565 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1569 GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1566 GenerateNArgsCheckInlineCacheStub( |
| 1567 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); |
| 1570 } | 1568 } |
| 1571 | 1569 |
| 1572 | 1570 |
| 1573 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( | 1571 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( |
| 1574 Assembler* assembler) { | 1572 Assembler* assembler) { |
| 1575 GenerateOptimizedUsageCounterIncrement(assembler); | 1573 GenerateOptimizedUsageCounterIncrement(assembler); |
| 1576 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1574 GenerateNArgsCheckInlineCacheStub( |
| 1575 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); |
| 1577 } | 1576 } |
| 1578 | 1577 |
| 1579 | 1578 |
| 1580 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { | 1579 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { |
| 1581 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1580 GenerateNArgsCheckInlineCacheStub( |
| 1581 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1582 } | 1582 } |
| 1583 | 1583 |
| 1584 | 1584 |
| 1585 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { | 1585 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { |
| 1586 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1586 GenerateNArgsCheckInlineCacheStub( |
| 1587 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); |
| 1587 } | 1588 } |
| 1588 | 1589 |
| 1589 | 1590 |
| 1590 // Intermediary stub between a static call and its target. ICData contains | 1591 // Intermediary stub between a static call and its target. ICData contains |
| 1591 // the target function and the call count. | 1592 // the target function and the call count. |
| 1592 // R5: ICData | 1593 // R5: ICData |
| 1593 void StubCode::GenerateUnoptimizedStaticCallStub(Assembler* assembler) { | 1594 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1594 GenerateUsageCounterIncrement(assembler, R6); | 1595 GenerateUsageCounterIncrement(assembler, R6); |
| 1595 #if defined(DEBUG) | 1596 #if defined(DEBUG) |
| 1596 { Label ok; | 1597 { Label ok; |
| 1597 // Check that the IC data array has NumberOfArgumentsChecked() == 0. | 1598 // Check that the IC data array has NumberOfArgumentsChecked() == 0. |
| 1598 // 'num_args_tested' is stored as an untagged int. | 1599 // 'num_args_tested' is stored as an untagged int. |
| 1599 __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset())); | 1600 __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset())); |
| 1600 __ CompareImmediate(R6, 0); | 1601 __ CompareImmediate(R6, 0); |
| 1601 __ b(&ok, EQ); | 1602 __ b(&ok, EQ); |
| 1602 __ Stop("Incorrect IC data for unoptimized static call"); | 1603 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1603 __ Bind(&ok); | 1604 __ Bind(&ok); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 __ Bind(&target_is_compiled); | 1658 __ Bind(&target_is_compiled); |
| 1658 // R0: target code. | 1659 // R0: target code. |
| 1659 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); | 1660 __ ldr(R0, FieldAddress(R0, Code::instructions_offset())); |
| 1660 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); | 1661 __ AddImmediate(R0, Instructions::HeaderSize() - kHeapObjectTag); |
| 1661 // Load arguments descriptor into R4. | 1662 // Load arguments descriptor into R4. |
| 1662 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1663 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1663 __ bx(R0); | 1664 __ bx(R0); |
| 1664 } | 1665 } |
| 1665 | 1666 |
| 1666 | 1667 |
| 1668 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1669 GenerateUsageCounterIncrement(assembler, R6); |
| 1670 GenerateNArgsCheckInlineCacheStub( |
| 1671 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1672 } |
| 1673 |
| 1674 |
| 1667 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { | 1675 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { |
| 1668 __ Unimplemented("BreakpointRuntime stub"); | 1676 __ Unimplemented("BreakpointRuntime stub"); |
| 1669 } | 1677 } |
| 1670 | 1678 |
| 1671 | 1679 |
| 1672 // LR: return address (Dart code). | 1680 // LR: return address (Dart code). |
| 1673 // R5: IC data (unoptimized static call). | 1681 // R5: IC data (unoptimized static call). |
| 1674 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { | 1682 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { |
| 1675 // Create a stub frame as we are pushing some objects on the stack before | 1683 // Create a stub frame as we are pushing some objects on the stack before |
| 1676 // calling into the runtime. | 1684 // calling into the runtime. |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2090 __ ldr(left, Address(SP, 4 * kWordSize)); | 2098 __ ldr(left, Address(SP, 4 * kWordSize)); |
| 2091 __ ldr(right, Address(SP, 3 * kWordSize)); | 2099 __ ldr(right, Address(SP, 3 * kWordSize)); |
| 2092 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2100 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2093 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 2101 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
| 2094 __ Ret(); | 2102 __ Ret(); |
| 2095 } | 2103 } |
| 2096 | 2104 |
| 2097 } // namespace dart | 2105 } // namespace dart |
| 2098 | 2106 |
| 2099 #endif // defined TARGET_ARCH_ARM | 2107 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |