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 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1307 // Remove arguments. | 1307 // Remove arguments. |
1308 __ Drop(4); | 1308 __ Drop(4); |
1309 __ Pop(R0); // Get result into R0. | 1309 __ Pop(R0); // Get result into R0. |
1310 __ LeaveStubFrame(); | 1310 __ LeaveStubFrame(); |
1311 __ Ret(); | 1311 __ Ret(); |
1312 } | 1312 } |
1313 | 1313 |
1314 | 1314 |
1315 // R6: function object. | 1315 // R6: function object. |
1316 // R5: inline cache data object. | 1316 // R5: inline cache data object. |
1317 // R4: arguments descriptor array. | 1317 // Cannot use function object from ICData as it may be the inlined |
| 1318 // function and not the top-scope function. |
1318 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1319 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
1319 Register ic_reg = R5; | 1320 Register ic_reg = R5; |
1320 Register func_reg = R6; | 1321 Register func_reg = R6; |
1321 if (FLAG_trace_optimized_ic_calls) { | 1322 if (FLAG_trace_optimized_ic_calls) { |
1322 __ EnterStubFrame(); | 1323 __ EnterStubFrame(); |
1323 __ PushList((1 << R4) | (1 << R5) | (1 << R6)); // Preserve. | 1324 __ PushList((1 << R5) | (1 << R6)); // Preserve. |
1324 __ Push(ic_reg); // Argument. | 1325 __ Push(ic_reg); // Argument. |
1325 __ Push(func_reg); // Argument. | 1326 __ Push(func_reg); // Argument. |
1326 __ CallRuntime(kTraceICCallRuntimeEntry); | 1327 __ CallRuntime(kTraceICCallRuntimeEntry); |
1327 __ Drop(2); // Discard argument; | 1328 __ Drop(2); // Discard argument; |
1328 __ PushList((1 << R4) | (1 << R5) | (1 << R6)); // Restore. | 1329 __ PopList((1 << R5) | (1 << R6)); // Restore. |
1329 __ LeaveStubFrame(); | 1330 __ LeaveStubFrame(); |
1330 } | 1331 } |
1331 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1332 __ ldr(R7, FieldAddress(func_reg, Function::usage_counter_offset())); |
1332 Label is_hot; | 1333 Label is_hot; |
1333 if (FlowGraphCompiler::CanOptimize()) { | 1334 if (FlowGraphCompiler::CanOptimize()) { |
1334 ASSERT(FLAG_optimization_counter_threshold > 1); | 1335 ASSERT(FLAG_optimization_counter_threshold > 1); |
1335 __ CompareImmediate(R7, FLAG_optimization_counter_threshold); | 1336 __ CompareImmediate(R7, FLAG_optimization_counter_threshold); |
1336 __ b(&is_hot, GE); | 1337 __ b(&is_hot, GE); |
1337 // As long as VM has no OSR do not optimize in the middle of the function | 1338 // As long as VM has no OSR do not optimize in the middle of the function |
1338 // but only at exit so that we have collected all type feedback before | 1339 // but only at exit so that we have collected all type feedback before |
(...skipping 26 matching lines...) Expand all Loading... |
1365 } | 1366 } |
1366 __ add(R7, R7, ShifterOperand(1)); | 1367 __ add(R7, R7, ShifterOperand(1)); |
1367 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); | 1368 __ str(R7, FieldAddress(func_reg, Function::usage_counter_offset())); |
1368 __ Bind(&is_hot); | 1369 __ Bind(&is_hot); |
1369 } | 1370 } |
1370 | 1371 |
1371 | 1372 |
1372 // Generate inline cache check for 'num_args'. | 1373 // Generate inline cache check for 'num_args'. |
1373 // LR: return address. | 1374 // LR: return address. |
1374 // R5: inline cache data object. | 1375 // R5: inline cache data object. |
1375 // R4: arguments descriptor array. | |
1376 // Control flow: | 1376 // Control flow: |
1377 // - If receiver is null -> jump to IC miss. | 1377 // - If receiver is null -> jump to IC miss. |
1378 // - If receiver is Smi -> load Smi class. | 1378 // - If receiver is Smi -> load Smi class. |
1379 // - If receiver is not-Smi -> load receiver's class. | 1379 // - If receiver is not-Smi -> load receiver's class. |
1380 // - Check if 'num_args' (including receiver) match any IC data group. | 1380 // - Check if 'num_args' (including receiver) match any IC data group. |
1381 // - Match found -> jump to target. | 1381 // - Match found -> jump to target. |
1382 // - Match not found -> jump to IC miss. | 1382 // - Match not found -> jump to IC miss. |
1383 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1383 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
1384 intptr_t num_args) { | 1384 intptr_t num_args) { |
1385 ASSERT(num_args > 0); | 1385 ASSERT(num_args > 0); |
1386 #if defined(DEBUG) | 1386 #if defined(DEBUG) |
1387 { Label ok; | 1387 { Label ok; |
1388 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1388 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
1389 // 'num_args_tested' is stored as an untagged int. | 1389 // 'num_args_tested' is stored as an untagged int. |
1390 __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset())); | 1390 __ ldr(R6, FieldAddress(R5, ICData::num_args_tested_offset())); |
1391 __ CompareImmediate(R6, num_args); | 1391 __ CompareImmediate(R6, num_args); |
1392 __ b(&ok, EQ); | 1392 __ b(&ok, EQ); |
1393 __ Stop("Incorrect stub for IC data"); | 1393 __ Stop("Incorrect stub for IC data"); |
1394 __ Bind(&ok); | 1394 __ Bind(&ok); |
1395 } | 1395 } |
1396 #endif // DEBUG | 1396 #endif // DEBUG |
1397 | 1397 |
| 1398 // Load arguments descriptor into R4. |
| 1399 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
1398 // Preserve return address, since LR is needed for subroutine call. | 1400 // Preserve return address, since LR is needed for subroutine call. |
1399 __ mov(R8, ShifterOperand(LR)); | 1401 __ mov(R8, ShifterOperand(LR)); |
1400 // Loop that checks if there is an IC data match. | 1402 // Loop that checks if there is an IC data match. |
1401 Label loop, update, test, found, get_class_id_as_smi; | 1403 Label loop, update, test, found, get_class_id_as_smi; |
1402 // R5: IC data object (preserved). | 1404 // R5: IC data object (preserved). |
1403 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1405 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
1404 // R6: ic_data_array with check entries: classes and target functions. | 1406 // R6: ic_data_array with check entries: classes and target functions. |
1405 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1407 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
1406 // R6: points directly to the first ic data array element. | 1408 // R6: points directly to the first ic data array element. |
1407 | 1409 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 __ LoadClassId(R0, R0); | 1531 __ LoadClassId(R0, R0); |
1530 __ SmiTag(R0); | 1532 __ SmiTag(R0); |
1531 __ bx(LR); | 1533 __ bx(LR); |
1532 } | 1534 } |
1533 | 1535 |
1534 | 1536 |
1535 // Use inline cache data array to invoke the target or continue in inline | 1537 // Use inline cache data array to invoke the target or continue in inline |
1536 // cache miss handler. Stub for 1-argument check (receiver class). | 1538 // cache miss handler. Stub for 1-argument check (receiver class). |
1537 // LR: return address. | 1539 // LR: return address. |
1538 // R5: inline cache data object. | 1540 // R5: inline cache data object. |
1539 // R4: arguments descriptor array. | |
1540 // Inline cache data object structure: | 1541 // Inline cache data object structure: |
1541 // 0: function-name | 1542 // 0: function-name |
1542 // 1: N, number of arguments checked. | 1543 // 1: N, number of arguments checked. |
1543 // 2 .. (length - 1): group of checks, each check containing: | 1544 // 2 .. (length - 1): group of checks, each check containing: |
1544 // - N classes. | 1545 // - N classes. |
1545 // - 1 target function. | 1546 // - 1 target function. |
1546 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1547 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1547 GenerateUsageCounterIncrement(assembler, R6); | 1548 GenerateUsageCounterIncrement(assembler, R6); |
1548 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1549 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
1549 } | 1550 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 | 1632 |
1632 // Instead of returning to the patched Dart function, emulate the | 1633 // Instead of returning to the patched Dart function, emulate the |
1633 // smashed return code pattern and return to the function's caller. | 1634 // smashed return code pattern and return to the function's caller. |
1634 __ LeaveDartFrame(); | 1635 __ LeaveDartFrame(); |
1635 __ Ret(); | 1636 __ Ret(); |
1636 } | 1637 } |
1637 | 1638 |
1638 | 1639 |
1639 // LR: return address (Dart code). | 1640 // LR: return address (Dart code). |
1640 // R5: inline cache data array. | 1641 // R5: inline cache data array. |
1641 // R4: arguments descriptor array. | |
1642 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1642 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1643 // Create a stub frame as we are pushing some objects on the stack before | 1643 // Create a stub frame as we are pushing some objects on the stack before |
1644 // calling into the runtime. | 1644 // calling into the runtime. |
1645 __ EnterStubFrame(); | 1645 __ EnterStubFrame(); |
1646 __ PushList((1 << R4) | (1 << R5)); | 1646 __ Push(R5); |
1647 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1647 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
1648 __ PopList((1 << R4) | (1 << R5)); | 1648 __ Pop(R5); |
1649 __ LeaveStubFrame(); | 1649 __ LeaveStubFrame(); |
1650 | 1650 |
1651 // Find out which dispatch stub to call. | 1651 // Find out which dispatch stub to call. |
1652 __ ldr(IP, FieldAddress(R5, ICData::num_args_tested_offset())); | 1652 __ ldr(IP, FieldAddress(R5, ICData::num_args_tested_offset())); |
1653 __ cmp(IP, ShifterOperand(1)); | 1653 __ cmp(IP, ShifterOperand(1)); |
1654 __ Branch(&StubCode::OneArgCheckInlineCacheLabel(), EQ); | 1654 __ Branch(&StubCode::OneArgCheckInlineCacheLabel(), EQ); |
1655 __ cmp(IP, ShifterOperand(2)); | 1655 __ cmp(IP, ShifterOperand(2)); |
1656 __ Branch(&StubCode::TwoArgsCheckInlineCacheLabel(), EQ); | 1656 __ Branch(&StubCode::TwoArgsCheckInlineCacheLabel(), EQ); |
1657 __ cmp(IP, ShifterOperand(3)); | 1657 __ cmp(IP, ShifterOperand(3)); |
1658 __ Branch(&StubCode::ThreeArgsCheckInlineCacheLabel(), EQ); | 1658 __ Branch(&StubCode::ThreeArgsCheckInlineCacheLabel(), EQ); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1980 __ Bind(&reference_compare); | 1980 __ Bind(&reference_compare); |
1981 __ cmp(left, ShifterOperand(right)); | 1981 __ cmp(left, ShifterOperand(right)); |
1982 __ Bind(&done); | 1982 __ Bind(&done); |
1983 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); | 1983 __ PopList((1 << R0) | (1 << R1) | (1 << R2)); |
1984 __ Ret(); | 1984 __ Ret(); |
1985 } | 1985 } |
1986 | 1986 |
1987 } // namespace dart | 1987 } // namespace dart |
1988 | 1988 |
1989 #endif // defined TARGET_ARCH_ARM | 1989 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |