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