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/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 1361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); | 1372 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); |
1373 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1373 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1374 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); | 1374 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); |
1375 __ CompareImmediate(R8, num_args); | 1375 __ CompareImmediate(R8, num_args); |
1376 __ b(&ok, EQ); | 1376 __ b(&ok, EQ); |
1377 __ Stop("Incorrect stub for IC data"); | 1377 __ Stop("Incorrect stub for IC data"); |
1378 __ Bind(&ok); | 1378 __ Bind(&ok); |
1379 } | 1379 } |
1380 #endif // DEBUG | 1380 #endif // DEBUG |
1381 | 1381 |
| 1382 #if !defined(PRODUCT) |
1382 Label stepping, done_stepping; | 1383 Label stepping, done_stepping; |
1383 if (FLAG_support_debugger && !optimized) { | 1384 if (!optimized) { |
1384 __ Comment("Check single stepping"); | 1385 __ Comment("Check single stepping"); |
1385 __ LoadIsolate(R8); | 1386 __ LoadIsolate(R8); |
1386 __ ldrb(R8, Address(R8, Isolate::single_step_offset())); | 1387 __ ldrb(R8, Address(R8, Isolate::single_step_offset())); |
1387 __ CompareImmediate(R8, 0); | 1388 __ CompareImmediate(R8, 0); |
1388 __ b(&stepping, NE); | 1389 __ b(&stepping, NE); |
1389 __ Bind(&done_stepping); | 1390 __ Bind(&done_stepping); |
1390 } | 1391 } |
| 1392 #endif |
1391 | 1393 |
1392 Label not_smi_or_overflow; | 1394 Label not_smi_or_overflow; |
1393 if (kind != Token::kILLEGAL) { | 1395 if (kind != Token::kILLEGAL) { |
1394 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1396 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
1395 } | 1397 } |
1396 __ Bind(¬_smi_or_overflow); | 1398 __ Bind(¬_smi_or_overflow); |
1397 | 1399 |
1398 __ Comment("Extract ICData initial values and receiver cid"); | 1400 __ Comment("Extract ICData initial values and receiver cid"); |
1399 // Load arguments descriptor into R4. | 1401 // Load arguments descriptor into R4. |
1400 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); | 1402 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1501 __ StoreIntoSmiField(Address(R8, kIcDataOffset + count_offset), R1); | 1503 __ StoreIntoSmiField(Address(R8, kIcDataOffset + count_offset), R1); |
1502 } | 1504 } |
1503 | 1505 |
1504 __ Comment("Call target"); | 1506 __ Comment("Call target"); |
1505 __ Bind(&call_target_function); | 1507 __ Bind(&call_target_function); |
1506 // R0: target function. | 1508 // R0: target function. |
1507 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 1509 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
1508 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 1510 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
1509 __ bx(R2); | 1511 __ bx(R2); |
1510 | 1512 |
1511 if (FLAG_support_debugger && !optimized) { | 1513 #if !defined(PRODUCT) |
| 1514 if (!optimized) { |
1512 __ Bind(&stepping); | 1515 __ Bind(&stepping); |
1513 __ EnterStubFrame(); | 1516 __ EnterStubFrame(); |
1514 __ Push(R9); // Preserve IC data. | 1517 __ Push(R9); // Preserve IC data. |
1515 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1518 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1516 __ Pop(R9); | 1519 __ Pop(R9); |
1517 __ RestoreCodePointer(); | 1520 __ RestoreCodePointer(); |
1518 __ LeaveStubFrame(); | 1521 __ LeaveStubFrame(); |
1519 __ b(&done_stepping); | 1522 __ b(&done_stepping); |
1520 } | 1523 } |
| 1524 #endif |
1521 } | 1525 } |
1522 | 1526 |
1523 // Use inline cache data array to invoke the target or continue in inline | 1527 // Use inline cache data array to invoke the target or continue in inline |
1524 // cache miss handler. Stub for 1-argument check (receiver class). | 1528 // cache miss handler. Stub for 1-argument check (receiver class). |
1525 // LR: return address. | 1529 // LR: return address. |
1526 // R9: inline cache data object. | 1530 // R9: inline cache data object. |
1527 // Inline cache data object structure: | 1531 // Inline cache data object structure: |
1528 // 0: function-name | 1532 // 0: function-name |
1529 // 1: N, number of arguments checked. | 1533 // 1: N, number of arguments checked. |
1530 // 2 .. (length - 1): group of checks, each check containing: | 1534 // 2 .. (length - 1): group of checks, each check containing: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1590 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); | 1594 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); |
1591 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1595 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1592 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); | 1596 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); |
1593 __ CompareImmediate(R8, 0); | 1597 __ CompareImmediate(R8, 0); |
1594 __ b(&ok, EQ); | 1598 __ b(&ok, EQ); |
1595 __ Stop("Incorrect IC data for unoptimized static call"); | 1599 __ Stop("Incorrect IC data for unoptimized static call"); |
1596 __ Bind(&ok); | 1600 __ Bind(&ok); |
1597 } | 1601 } |
1598 #endif // DEBUG | 1602 #endif // DEBUG |
1599 | 1603 |
| 1604 #if !defined(PRODUCT) |
1600 // Check single stepping. | 1605 // Check single stepping. |
1601 Label stepping, done_stepping; | 1606 Label stepping, done_stepping; |
1602 if (FLAG_support_debugger) { | 1607 __ LoadIsolate(R8); |
1603 __ LoadIsolate(R8); | 1608 __ ldrb(R8, Address(R8, Isolate::single_step_offset())); |
1604 __ ldrb(R8, Address(R8, Isolate::single_step_offset())); | 1609 __ CompareImmediate(R8, 0); |
1605 __ CompareImmediate(R8, 0); | 1610 __ b(&stepping, NE); |
1606 __ b(&stepping, NE); | 1611 __ Bind(&done_stepping); |
1607 __ Bind(&done_stepping); | 1612 #endif |
1608 } | |
1609 | 1613 |
1610 // R9: IC data object (preserved). | 1614 // R9: IC data object (preserved). |
1611 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); | 1615 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
1612 // R8: ic_data_array with entries: target functions and count. | 1616 // R8: ic_data_array with entries: target functions and count. |
1613 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); | 1617 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); |
1614 // R8: points directly to the first ic data array element. | 1618 // R8: points directly to the first ic data array element. |
1615 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1619 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1616 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1620 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1617 | 1621 |
1618 if (FLAG_optimization_counter_threshold >= 0) { | 1622 if (FLAG_optimization_counter_threshold >= 0) { |
1619 // Increment count for this call, ignore overflow. | 1623 // Increment count for this call, ignore overflow. |
1620 __ LoadFromOffset(kWord, R1, R8, count_offset); | 1624 __ LoadFromOffset(kWord, R1, R8, count_offset); |
1621 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1625 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1622 __ StoreIntoSmiField(Address(R8, count_offset), R1); | 1626 __ StoreIntoSmiField(Address(R8, count_offset), R1); |
1623 } | 1627 } |
1624 | 1628 |
1625 // Load arguments descriptor into R4. | 1629 // Load arguments descriptor into R4. |
1626 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); | 1630 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
1627 | 1631 |
1628 // Get function and call it, if possible. | 1632 // Get function and call it, if possible. |
1629 __ LoadFromOffset(kWord, R0, R8, target_offset); | 1633 __ LoadFromOffset(kWord, R0, R8, target_offset); |
1630 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 1634 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
1631 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 1635 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
1632 __ bx(R2); | 1636 __ bx(R2); |
1633 | 1637 |
1634 if (FLAG_support_debugger) { | 1638 #if !defined(PRODUCT) |
1635 __ Bind(&stepping); | 1639 __ Bind(&stepping); |
1636 __ EnterStubFrame(); | 1640 __ EnterStubFrame(); |
1637 __ Push(R9); // Preserve IC data. | 1641 __ Push(R9); // Preserve IC data. |
1638 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1642 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1639 __ Pop(R9); | 1643 __ Pop(R9); |
1640 __ RestoreCodePointer(); | 1644 __ RestoreCodePointer(); |
1641 __ LeaveStubFrame(); | 1645 __ LeaveStubFrame(); |
1642 __ b(&done_stepping); | 1646 __ b(&done_stepping); |
1643 } | 1647 #endif |
1644 } | 1648 } |
1645 | 1649 |
1646 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1650 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1647 GenerateUsageCounterIncrement(assembler, R8); | 1651 GenerateUsageCounterIncrement(assembler, R8); |
1648 GenerateNArgsCheckInlineCacheStub( | 1652 GenerateNArgsCheckInlineCacheStub( |
1649 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); | 1653 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); |
1650 } | 1654 } |
1651 | 1655 |
1652 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1656 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1653 GenerateUsageCounterIncrement(assembler, R8); | 1657 GenerateUsageCounterIncrement(assembler, R8); |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 __ Bind(&done); | 1998 __ Bind(&done); |
1995 } | 1999 } |
1996 | 2000 |
1997 // Called only from unoptimized code. All relevant registers have been saved. | 2001 // Called only from unoptimized code. All relevant registers have been saved. |
1998 // LR: return address. | 2002 // LR: return address. |
1999 // SP + 4: left operand. | 2003 // SP + 4: left operand. |
2000 // SP + 0: right operand. | 2004 // SP + 0: right operand. |
2001 // Return Zero condition flag set if equal. | 2005 // Return Zero condition flag set if equal. |
2002 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2006 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
2003 Assembler* assembler) { | 2007 Assembler* assembler) { |
| 2008 #if !defined(PRODUCT) |
2004 // Check single stepping. | 2009 // Check single stepping. |
2005 Label stepping, done_stepping; | 2010 Label stepping, done_stepping; |
2006 if (FLAG_support_debugger) { | 2011 __ LoadIsolate(R1); |
2007 __ LoadIsolate(R1); | 2012 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); |
2008 __ ldrb(R1, Address(R1, Isolate::single_step_offset())); | 2013 __ CompareImmediate(R1, 0); |
2009 __ CompareImmediate(R1, 0); | 2014 __ b(&stepping, NE); |
2010 __ b(&stepping, NE); | 2015 __ Bind(&done_stepping); |
2011 __ Bind(&done_stepping); | 2016 #endif |
2012 } | |
2013 | 2017 |
2014 const Register temp = R2; | 2018 const Register temp = R2; |
2015 const Register left = R1; | 2019 const Register left = R1; |
2016 const Register right = R0; | 2020 const Register right = R0; |
2017 __ ldr(left, Address(SP, 1 * kWordSize)); | 2021 __ ldr(left, Address(SP, 1 * kWordSize)); |
2018 __ ldr(right, Address(SP, 0 * kWordSize)); | 2022 __ ldr(right, Address(SP, 0 * kWordSize)); |
2019 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2023 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
2020 __ Ret(); | 2024 __ Ret(); |
2021 | 2025 |
2022 if (FLAG_support_debugger) { | 2026 #if !defined(PRODUCT) |
2023 __ Bind(&stepping); | 2027 __ Bind(&stepping); |
2024 __ EnterStubFrame(); | 2028 __ EnterStubFrame(); |
2025 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 2029 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
2026 __ RestoreCodePointer(); | 2030 __ RestoreCodePointer(); |
2027 __ LeaveStubFrame(); | 2031 __ LeaveStubFrame(); |
2028 __ b(&done_stepping); | 2032 __ b(&done_stepping); |
2029 } | 2033 #endif |
2030 } | 2034 } |
2031 | 2035 |
2032 // Called from optimized code only. | 2036 // Called from optimized code only. |
2033 // LR: return address. | 2037 // LR: return address. |
2034 // SP + 4: left operand. | 2038 // SP + 4: left operand. |
2035 // SP + 0: right operand. | 2039 // SP + 0: right operand. |
2036 // Return Zero condition flag set if equal. | 2040 // Return Zero condition flag set if equal. |
2037 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 2041 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
2038 Assembler* assembler) { | 2042 Assembler* assembler) { |
2039 const Register temp = R2; | 2043 const Register temp = R2; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 __ bkpt(0); | 2265 __ bkpt(0); |
2262 } | 2266 } |
2263 | 2267 |
2264 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2268 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
2265 __ bkpt(0); | 2269 __ bkpt(0); |
2266 } | 2270 } |
2267 | 2271 |
2268 } // namespace dart | 2272 } // namespace dart |
2269 | 2273 |
2270 #endif // defined TARGET_ARCH_ARM | 2274 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |