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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
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 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1482 | 1482 |
1483 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); | 1483 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry); |
1484 | 1484 |
1485 __ lw(V0, Address(SP, 4 * kWordSize)); // Get result into V0. | 1485 __ lw(V0, Address(SP, 4 * kWordSize)); // Get result into V0. |
1486 __ LeaveStubFrameAndReturn(); | 1486 __ LeaveStubFrameAndReturn(); |
1487 } | 1487 } |
1488 | 1488 |
1489 | 1489 |
1490 // T0: function object. | 1490 // T0: function object. |
1491 // S5: inline cache data object. | 1491 // S5: inline cache data object. |
1492 // S4: arguments descriptor array. | 1492 // Cannot use function object from ICData as it may be the inlined |
| 1493 // function and not the top-scope function. |
1493 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1494 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
1494 __ TraceSimMsg("OptimizedUsageCounterIncrement"); | 1495 __ TraceSimMsg("OptimizedUsageCounterIncrement"); |
1495 Register ic_reg = S5; | 1496 Register ic_reg = S5; |
1496 Register func_reg = T0; | 1497 Register func_reg = T0; |
1497 if (FLAG_trace_optimized_ic_calls) { | 1498 if (FLAG_trace_optimized_ic_calls) { |
1498 __ EnterStubFrame(); | 1499 __ EnterStubFrame(); |
1499 __ addiu(SP, SP, Immediate(-5 * kWordSize)); | 1500 __ addiu(SP, SP, Immediate(-4 * kWordSize)); |
1500 __ sw(T0, Address(SP, 4 * kWordSize)); | 1501 __ sw(T0, Address(SP, 3 * kWordSize)); |
1501 __ sw(S5, Address(SP, 3 * kWordSize)); | 1502 __ sw(S5, Address(SP, 2 * kWordSize)); |
1502 __ sw(S4, Address(SP, 2 * kWordSize)); // Preserve. | |
1503 __ sw(ic_reg, Address(SP, 1 * kWordSize)); // Argument. | 1503 __ sw(ic_reg, Address(SP, 1 * kWordSize)); // Argument. |
1504 __ sw(func_reg, Address(SP, 0 * kWordSize)); // Argument. | 1504 __ sw(func_reg, Address(SP, 0 * kWordSize)); // Argument. |
1505 __ CallRuntime(kTraceICCallRuntimeEntry); | 1505 __ CallRuntime(kTraceICCallRuntimeEntry); |
1506 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore. | 1506 __ lw(S5, Address(SP, 2 * kWordSize)); |
1507 __ lw(S5, Address(SP, 3 * kWordSize)); | 1507 __ lw(T0, Address(SP, 3 * kWordSize)); |
1508 __ lw(T0, Address(SP, 4 * kWordSize)); | 1508 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Discard argument; |
1509 __ addiu(SP, SP, Immediate(5 * kWordSize)); // Discard argument; | |
1510 __ LeaveStubFrame(); | 1509 __ LeaveStubFrame(); |
1511 } | 1510 } |
1512 __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1511 __ lw(T7, FieldAddress(func_reg, Function::usage_counter_offset())); |
1513 Label is_hot; | 1512 Label is_hot; |
1514 if (FlowGraphCompiler::CanOptimize()) { | 1513 if (FlowGraphCompiler::CanOptimize()) { |
1515 ASSERT(FLAG_optimization_counter_threshold > 1); | 1514 ASSERT(FLAG_optimization_counter_threshold > 1); |
1516 __ BranchSignedGreaterEqual(T7, FLAG_optimization_counter_threshold, | 1515 __ BranchSignedGreaterEqual(T7, FLAG_optimization_counter_threshold, |
1517 &is_hot); | 1516 &is_hot); |
1518 // As long as VM has no OSR do not optimize in the middle of the function | 1517 // As long as VM has no OSR do not optimize in the middle of the function |
1519 // but only at exit so that we have collected all type feedback before | 1518 // but only at exit so that we have collected all type feedback before |
(...skipping 26 matching lines...) Expand all Loading... |
1546 } | 1545 } |
1547 __ addiu(T1, T1, Immediate(1)); | 1546 __ addiu(T1, T1, Immediate(1)); |
1548 __ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); | 1547 __ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); |
1549 __ Bind(&is_hot); | 1548 __ Bind(&is_hot); |
1550 } | 1549 } |
1551 | 1550 |
1552 | 1551 |
1553 // Generate inline cache check for 'num_args'. | 1552 // Generate inline cache check for 'num_args'. |
1554 // RA: return address | 1553 // RA: return address |
1555 // S5: Inline cache data object. | 1554 // S5: Inline cache data object. |
1556 // S4: Arguments descriptor array. | |
1557 // Control flow: | 1555 // Control flow: |
1558 // - If receiver is null -> jump to IC miss. | 1556 // - If receiver is null -> jump to IC miss. |
1559 // - If receiver is Smi -> load Smi class. | 1557 // - If receiver is Smi -> load Smi class. |
1560 // - If receiver is not-Smi -> load receiver's class. | 1558 // - If receiver is not-Smi -> load receiver's class. |
1561 // - Check if 'num_args' (including receiver) match any IC data group. | 1559 // - Check if 'num_args' (including receiver) match any IC data group. |
1562 // - Match found -> jump to target. | 1560 // - Match found -> jump to target. |
1563 // - Match not found -> jump to IC miss. | 1561 // - Match not found -> jump to IC miss. |
1564 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1562 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
1565 intptr_t num_args) { | 1563 intptr_t num_args) { |
1566 __ TraceSimMsg("NArgsCheckInlineCacheStub"); | 1564 __ TraceSimMsg("NArgsCheckInlineCacheStub"); |
1567 ASSERT(num_args > 0); | 1565 ASSERT(num_args > 0); |
1568 #if defined(DEBUG) | 1566 #if defined(DEBUG) |
1569 { Label ok; | 1567 { Label ok; |
1570 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1568 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
1571 // 'num_args_tested' is stored as an untagged int. | 1569 // 'num_args_tested' is stored as an untagged int. |
1572 __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset())); | 1570 __ lw(T0, FieldAddress(S5, ICData::num_args_tested_offset())); |
1573 __ BranchEqual(T0, num_args, &ok); | 1571 __ BranchEqual(T0, num_args, &ok); |
1574 __ Stop("Incorrect stub for IC data"); | 1572 __ Stop("Incorrect stub for IC data"); |
1575 __ Bind(&ok); | 1573 __ Bind(&ok); |
1576 } | 1574 } |
1577 #endif // DEBUG | 1575 #endif // DEBUG |
1578 | 1576 |
| 1577 // Load argument descriptor into S4. |
| 1578 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
1579 // Preserve return address, since RA is needed for subroutine call. | 1579 // Preserve return address, since RA is needed for subroutine call. |
1580 __ mov(T2, RA); | 1580 __ mov(T2, RA); |
1581 // Loop that checks if there is an IC data match. | 1581 // Loop that checks if there is an IC data match. |
1582 Label loop, update, test, found, get_class_id_as_smi; | 1582 Label loop, update, test, found, get_class_id_as_smi; |
1583 // S5: IC data object (preserved). | 1583 // S5: IC data object (preserved). |
1584 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1584 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
1585 // T0: ic_data_array with check entries: classes and target functions. | 1585 // T0: ic_data_array with check entries: classes and target functions. |
1586 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1586 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
1587 // T0: points directly to the first ic data array element. | 1587 // T0: points directly to the first ic data array element. |
1588 | 1588 |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 __ LoadClassId(T3, T3); | 1736 __ LoadClassId(T3, T3); |
1737 __ jr(RA); | 1737 __ jr(RA); |
1738 __ delay_slot()->SmiTag(T3); | 1738 __ delay_slot()->SmiTag(T3); |
1739 } | 1739 } |
1740 | 1740 |
1741 | 1741 |
1742 // Use inline cache data array to invoke the target or continue in inline | 1742 // Use inline cache data array to invoke the target or continue in inline |
1743 // cache miss handler. Stub for 1-argument check (receiver class). | 1743 // cache miss handler. Stub for 1-argument check (receiver class). |
1744 // RA: Return address. | 1744 // RA: Return address. |
1745 // S5: Inline cache data object. | 1745 // S5: Inline cache data object. |
1746 // S4: Arguments descriptor array. | |
1747 // Inline cache data object structure: | 1746 // Inline cache data object structure: |
1748 // 0: function-name | 1747 // 0: function-name |
1749 // 1: N, number of arguments checked. | 1748 // 1: N, number of arguments checked. |
1750 // 2 .. (length - 1): group of checks, each check containing: | 1749 // 2 .. (length - 1): group of checks, each check containing: |
1751 // - N classes. | 1750 // - N classes. |
1752 // - 1 target function. | 1751 // - 1 target function. |
1753 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1752 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1754 GenerateUsageCounterIncrement(assembler, T0); | 1753 GenerateUsageCounterIncrement(assembler, T0); |
1755 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1754 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
1756 } | 1755 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1843 __ LeaveStubFrame(); | 1842 __ LeaveStubFrame(); |
1844 | 1843 |
1845 // Instead of returning to the patched Dart function, emulate the | 1844 // Instead of returning to the patched Dart function, emulate the |
1846 // smashed return code pattern and return to the function's caller. | 1845 // smashed return code pattern and return to the function's caller. |
1847 __ LeaveDartFrameAndReturn(); | 1846 __ LeaveDartFrameAndReturn(); |
1848 } | 1847 } |
1849 | 1848 |
1850 | 1849 |
1851 // RA: return address (Dart code). | 1850 // RA: return address (Dart code). |
1852 // S5: Inline cache data array. | 1851 // S5: Inline cache data array. |
1853 // S4: Arguments descriptor array. | |
1854 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1852 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1855 // Create a stub frame as we are pushing some objects on the stack before | 1853 // Create a stub frame as we are pushing some objects on the stack before |
1856 // calling into the runtime. | 1854 // calling into the runtime. |
1857 __ TraceSimMsg("BreakpointDynamicStub"); | 1855 __ TraceSimMsg("BreakpointDynamicStub"); |
1858 __ EnterStubFrame(); | 1856 __ EnterStubFrame(); |
1859 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1857 __ Push(S5); |
1860 __ sw(S5, Address(SP, 1 * kWordSize)); | |
1861 __ sw(S4, Address(SP, 0 * kWordSize)); | |
1862 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1858 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
1863 __ lw(S4, Address(SP, 0 * kWordSize)); | 1859 __ Pop(S5); |
1864 __ lw(S5, Address(SP, 1 * kWordSize)); | |
1865 __ addiu(SP, SP, Immediate(2 * kWordSize)); | |
1866 __ LeaveStubFrame(); | 1860 __ LeaveStubFrame(); |
1867 | 1861 |
1868 // Find out which dispatch stub to call. | 1862 // Find out which dispatch stub to call. |
1869 __ lw(TMP1, FieldAddress(S5, ICData::num_args_tested_offset())); | 1863 __ lw(TMP1, FieldAddress(S5, ICData::num_args_tested_offset())); |
1870 | 1864 |
1871 Label one_arg, two_args, three_args; | 1865 Label one_arg, two_args, three_args; |
1872 __ BranchEqual(TMP1, 1, &one_arg); | 1866 __ BranchEqual(TMP1, 1, &one_arg); |
1873 __ BranchEqual(TMP1, 2, &two_args); | 1867 __ BranchEqual(TMP1, 2, &two_args); |
1874 __ BranchEqual(TMP1, 3, &three_args); | 1868 __ BranchEqual(TMP1, 3, &three_args); |
1875 __ Stop("Unsupported number of arguments tested."); | 1869 __ Stop("Unsupported number of arguments tested."); |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 __ lw(left, Address(SP, 1 * kWordSize)); | 2245 __ lw(left, Address(SP, 1 * kWordSize)); |
2252 __ lw(temp2, Address(SP, 2 * kWordSize)); | 2246 __ lw(temp2, Address(SP, 2 * kWordSize)); |
2253 __ lw(temp1, Address(SP, 3 * kWordSize)); | 2247 __ lw(temp1, Address(SP, 3 * kWordSize)); |
2254 __ Ret(); | 2248 __ Ret(); |
2255 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); | 2249 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); |
2256 } | 2250 } |
2257 | 2251 |
2258 } // namespace dart | 2252 } // namespace dart |
2259 | 2253 |
2260 #endif // defined TARGET_ARCH_MIPS | 2254 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |