| 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_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 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/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 1458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1469 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1470 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); | 1470 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); |
| 1471 __ cmpq(RCX, Immediate(0)); | 1471 __ cmpq(RCX, Immediate(0)); |
| 1472 __ j(EQUAL, &ok, Assembler::kNearJump); | 1472 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1473 __ Stop("Incorrect IC data for unoptimized static call"); | 1473 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1474 __ Bind(&ok); | 1474 __ Bind(&ok); |
| 1475 } | 1475 } |
| 1476 #endif // DEBUG | 1476 #endif // DEBUG |
| 1477 | 1477 |
| 1478 // Check single stepping. | 1478 // Check single stepping. |
| 1479 Label not_stepping; | 1479 Label stepping, done_stepping; |
| 1480 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1480 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1481 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1481 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1482 __ cmpq(RAX, Immediate(0)); | 1482 __ cmpq(RAX, Immediate(0)); |
| 1483 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | 1483 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); |
| 1484 __ EnterStubFrame(); | 1484 __ Bind(&done_stepping); |
| 1485 __ pushq(RBX); // Preserve IC data object. | |
| 1486 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | |
| 1487 __ popq(RBX); | |
| 1488 __ LeaveStubFrame(); | |
| 1489 __ Bind(¬_stepping); | |
| 1490 | 1485 |
| 1491 // RBX: IC data object (preserved). | 1486 // RBX: IC data object (preserved). |
| 1492 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1487 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1493 // R12: ic_data_array with entries: target functions and count. | 1488 // R12: ic_data_array with entries: target functions and count. |
| 1494 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1489 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1495 // R12: points directly to the first ic data array element. | 1490 // R12: points directly to the first ic data array element. |
| 1496 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1491 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1497 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1492 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1498 | 1493 |
| 1499 // Increment count for this call. | 1494 // Increment count for this call. |
| 1500 Label increment_done; | 1495 __ movq(R8, Address(R12, count_offset)); |
| 1501 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); | 1496 __ addq(R8, Immediate(Smi::RawValue(1))); |
| 1502 __ j(NO_OVERFLOW, &increment_done, Assembler::kNearJump); | 1497 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1503 __ movq(Address(R12, count_offset), | 1498 __ cmovnoq(R9, R8); |
| 1504 Immediate(Smi::RawValue(Smi::kMaxValue))); | 1499 __ movq(Address(R12, count_offset), R9); |
| 1505 __ Bind(&increment_done); | |
| 1506 | 1500 |
| 1507 // Load arguments descriptor into R10. | 1501 // Load arguments descriptor into R10. |
| 1508 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1502 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
| 1509 | 1503 |
| 1510 // Get function and call it, if possible. | 1504 // Get function and call it, if possible. |
| 1511 __ movq(RAX, Address(R12, target_offset)); | 1505 __ movq(RAX, Address(R12, target_offset)); |
| 1512 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1506 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
| 1513 // RCX: Target instructions. | 1507 // RCX: Target instructions. |
| 1514 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1508 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1515 __ jmp(RCX); | 1509 __ jmp(RCX); |
| 1510 |
| 1511 __ Bind(&stepping); |
| 1512 __ EnterStubFrame(); |
| 1513 __ pushq(RBX); // Preserve IC data object. |
| 1514 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1515 __ popq(RBX); |
| 1516 __ LeaveStubFrame(); |
| 1517 __ jmp(&done_stepping, Assembler::kNearJump); |
| 1516 } | 1518 } |
| 1517 | 1519 |
| 1518 | 1520 |
| 1519 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1521 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
| 1520 GenerateUsageCounterIncrement(assembler, RCX); | 1522 GenerateUsageCounterIncrement(assembler, RCX); |
| 1521 GenerateNArgsCheckInlineCacheStub( | 1523 GenerateNArgsCheckInlineCacheStub( |
| 1522 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); | 1524 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); |
| 1523 } | 1525 } |
| 1524 | 1526 |
| 1525 | 1527 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1594 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); | 1596 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); |
| 1595 __ popq(RAX); // Address of original. | 1597 __ popq(RAX); // Address of original. |
| 1596 __ LeaveStubFrame(); | 1598 __ LeaveStubFrame(); |
| 1597 __ jmp(RAX); // Jump to original stub. | 1599 __ jmp(RAX); // Jump to original stub. |
| 1598 } | 1600 } |
| 1599 | 1601 |
| 1600 | 1602 |
| 1601 // Called only from unoptimized code. | 1603 // Called only from unoptimized code. |
| 1602 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { | 1604 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { |
| 1603 // Check single stepping. | 1605 // Check single stepping. |
| 1604 Label not_stepping; | 1606 Label stepping, done_stepping; |
| 1605 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1607 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1606 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1608 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1607 __ cmpq(RAX, Immediate(0)); | 1609 __ cmpq(RAX, Immediate(0)); |
| 1608 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | 1610 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); |
| 1611 __ Bind(&done_stepping); |
| 1612 __ ret(); |
| 1609 | 1613 |
| 1614 __ Bind(&stepping); |
| 1610 __ EnterStubFrame(); | 1615 __ EnterStubFrame(); |
| 1611 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1616 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1612 __ LeaveStubFrame(); | 1617 __ LeaveStubFrame(); |
| 1613 __ Bind(¬_stepping); | 1618 __ jmp(&done_stepping, Assembler::kNearJump); |
| 1614 | |
| 1615 __ ret(); | |
| 1616 } | 1619 } |
| 1617 | 1620 |
| 1618 | 1621 |
| 1619 // Used to check class and type arguments. Arguments passed on stack: | 1622 // Used to check class and type arguments. Arguments passed on stack: |
| 1620 // TOS + 0: return address. | 1623 // TOS + 0: return address. |
| 1621 // TOS + 1: instantiator type arguments (can be NULL). | 1624 // TOS + 1: instantiator type arguments (can be NULL). |
| 1622 // TOS + 2: instance. | 1625 // TOS + 2: instance. |
| 1623 // TOS + 3: SubtypeTestCache. | 1626 // TOS + 3: SubtypeTestCache. |
| 1624 // Result in RCX: null -> not found, otherwise result (true or false). | 1627 // Result in RCX: null -> not found, otherwise result (true or false). |
| 1625 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1628 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1860 | 1863 |
| 1861 | 1864 |
| 1862 // Called only from unoptimized code. All relevant registers have been saved. | 1865 // Called only from unoptimized code. All relevant registers have been saved. |
| 1863 // TOS + 0: return address | 1866 // TOS + 0: return address |
| 1864 // TOS + 1: right argument. | 1867 // TOS + 1: right argument. |
| 1865 // TOS + 2: left argument. | 1868 // TOS + 2: left argument. |
| 1866 // Returns ZF set. | 1869 // Returns ZF set. |
| 1867 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 1870 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 1868 Assembler* assembler) { | 1871 Assembler* assembler) { |
| 1869 // Check single stepping. | 1872 // Check single stepping. |
| 1870 Label not_stepping; | 1873 Label stepping, done_stepping; |
| 1871 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 1874 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 1872 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1875 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
| 1873 __ cmpq(RAX, Immediate(0)); | 1876 __ cmpq(RAX, Immediate(0)); |
| 1874 __ j(EQUAL, ¬_stepping, Assembler::kNearJump); | 1877 __ j(NOT_EQUAL, &stepping); |
| 1875 __ EnterStubFrame(); | 1878 __ Bind(&done_stepping); |
| 1876 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | |
| 1877 __ LeaveStubFrame(); | |
| 1878 __ Bind(¬_stepping); | |
| 1879 | 1879 |
| 1880 const Register left = RAX; | 1880 const Register left = RAX; |
| 1881 const Register right = RDX; | 1881 const Register right = RDX; |
| 1882 | 1882 |
| 1883 __ movq(left, Address(RSP, 2 * kWordSize)); | 1883 __ movq(left, Address(RSP, 2 * kWordSize)); |
| 1884 __ movq(right, Address(RSP, 1 * kWordSize)); | 1884 __ movq(right, Address(RSP, 1 * kWordSize)); |
| 1885 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1885 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 1886 __ ret(); | 1886 __ ret(); |
| 1887 |
| 1888 __ Bind(&stepping); |
| 1889 __ EnterStubFrame(); |
| 1890 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
| 1891 __ LeaveStubFrame(); |
| 1892 __ jmp(&done_stepping); |
| 1887 } | 1893 } |
| 1888 | 1894 |
| 1889 | 1895 |
| 1890 // Called from optimized code only. | 1896 // Called from optimized code only. |
| 1891 // TOS + 0: return address | 1897 // TOS + 0: return address |
| 1892 // TOS + 1: right argument. | 1898 // TOS + 1: right argument. |
| 1893 // TOS + 2: left argument. | 1899 // TOS + 2: left argument. |
| 1894 // Returns ZF set. | 1900 // Returns ZF set. |
| 1895 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( | 1901 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( |
| 1896 Assembler* assembler) { | 1902 Assembler* assembler) { |
| 1897 const Register left = RAX; | 1903 const Register left = RAX; |
| 1898 const Register right = RDX; | 1904 const Register right = RDX; |
| 1899 | 1905 |
| 1900 __ movq(left, Address(RSP, 2 * kWordSize)); | 1906 __ movq(left, Address(RSP, 2 * kWordSize)); |
| 1901 __ movq(right, Address(RSP, 1 * kWordSize)); | 1907 __ movq(right, Address(RSP, 1 * kWordSize)); |
| 1902 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1908 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 1903 __ ret(); | 1909 __ ret(); |
| 1904 } | 1910 } |
| 1905 | 1911 |
| 1906 } // namespace dart | 1912 } // namespace dart |
| 1907 | 1913 |
| 1908 #endif // defined TARGET_ARCH_X64 | 1914 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |