| 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 |