| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| (...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1558 __ popq(RBX); // Restore inline cache data object. | 1558 __ popq(RBX); // Restore inline cache data object. |
| 1559 __ LeaveFrame(); | 1559 __ LeaveFrame(); |
| 1560 __ Bind(¬_yet_hot); | 1560 __ Bind(¬_yet_hot); |
| 1561 } | 1561 } |
| 1562 ASSERT(num_args > 0); | 1562 ASSERT(num_args > 0); |
| 1563 // Get receiver (first read number of arguments from argument descriptor array | 1563 // Get receiver (first read number of arguments from argument descriptor array |
| 1564 // and then access the receiver from the stack). | 1564 // and then access the receiver from the stack). |
| 1565 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1565 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 1566 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. | 1566 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. |
| 1567 | 1567 |
| 1568 Label get_class, ic_miss; | 1568 Label get_class_id_as_smi, ic_miss; |
| 1569 // RBX: IC data array. | 1569 // RBX: IC data array. |
| 1570 | 1570 |
| 1571 #if defined(DEBUG) | 1571 #if defined(DEBUG) |
| 1572 { Label ok; | 1572 { Label ok; |
| 1573 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1573 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1574 // 'num_args_tested' is stored as an untagged int. | 1574 // 'num_args_tested' is stored as an untagged int. |
| 1575 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); | 1575 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); |
| 1576 __ cmpq(RCX, Immediate(num_args)); | 1576 __ cmpq(RCX, Immediate(num_args)); |
| 1577 __ j(EQUAL, &ok, Assembler::kNearJump); | 1577 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1578 __ Stop("Incorrect stub for IC data"); | 1578 __ Stop("Incorrect stub for IC data"); |
| 1579 __ Bind(&ok); | 1579 __ Bind(&ok); |
| 1580 } | 1580 } |
| 1581 #endif // DEBUG | 1581 #endif // DEBUG |
| 1582 | 1582 |
| 1583 // Loop that checks if there is an IC data match. | 1583 // Loop that checks if there is an IC data match. |
| 1584 // RBX: IC data object (preserved). | 1584 // RBX: IC data object (preserved). |
| 1585 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1585 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
| 1586 // R12: ic_data_array with check entries: classes and target functions. | 1586 // R12: ic_data_array with check entries: classes and target functions. |
| 1587 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1587 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
| 1588 // R12: points directly to the first ic data array element. | 1588 // R12: points directly to the first ic data array element. |
| 1589 const Immediate raw_null = | 1589 const Immediate raw_null = |
| 1590 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1590 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1591 Label loop, found; | 1591 Label loop, found; |
| 1592 if (num_args == 1) { | 1592 if (num_args == 1) { |
| 1593 __ call(&get_class); | 1593 __ call(&get_class_id_as_smi); |
| 1594 // RAX: receiver's class. | 1594 // RAX: receiver's class id as Smi. |
| 1595 __ Bind(&loop); | 1595 __ Bind(&loop); |
| 1596 __ movq(R13, Address(R12, 0)); // Get class to check. | 1596 __ movq(R13, Address(R12, 0)); // Get class if (Smi) to check. |
| 1597 __ cmpq(RAX, R13); // Match? | 1597 __ cmpq(RAX, R13); // Match? |
| 1598 __ j(EQUAL, &found, Assembler::kNearJump); | 1598 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1599 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). | 1599 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1600 __ cmpq(R13, raw_null); // Done? | 1600 __ cmpq(R13, raw_null); // Done? |
| 1601 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1601 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1602 } else if (num_args == 2) { | 1602 } else if (num_args == 2) { |
| 1603 Label no_match; | 1603 Label no_match; |
| 1604 __ Bind(&loop); | 1604 __ Bind(&loop); |
| 1605 // Get receiver. | 1605 // Get receiver. |
| 1606 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1606 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 1607 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. | 1607 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. |
| 1608 __ call(&get_class); | 1608 __ call(&get_class_id_as_smi); |
| 1609 // TODO(vegorov): switch IC data to store class index instead of class. | 1609 __ movq(R13, Address(R12, 0)); // Get class id from IC data to check. |
| 1610 __ movq(R13, Address(R12, 0)); // Get class from IC data to check. | 1610 __ cmpq(RAX, R13); // Class id match? |
| 1611 __ cmpq(RAX, R13); // Match? | |
| 1612 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1611 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1613 // Check second. | 1612 // Check second. |
| 1614 // Get next argument. | 1613 // Get next argument. |
| 1615 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 1614 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 1616 __ movq(RAX, Address(RSP, RAX, TIMES_4, -kWordSize)); // RAX is Smi. | 1615 __ movq(RAX, Address(RSP, RAX, TIMES_4, -kWordSize)); // RAX is Smi. |
| 1617 __ call(&get_class); | 1616 __ call(&get_class_id_as_smi); |
| 1618 __ movq(R13, Address(R12, kWordSize)); // Get class from IC data to check. | 1617 __ movq(R13, Address(R12, kWordSize)); // Get class id from IC data. |
| 1619 __ cmpq(RAX, R13); // Match? | 1618 __ cmpq(RAX, R13); // Class id match? |
| 1620 __ j(EQUAL, &found); | 1619 __ j(EQUAL, &found); |
| 1621 __ Bind(&no_match); | 1620 __ Bind(&no_match); |
| 1622 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. | 1621 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1623 __ cmpq(R13, raw_null); // Done? | 1622 __ cmpq(R13, raw_null); // Done? |
| 1624 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1623 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1625 } | 1624 } |
| 1626 | 1625 |
| 1627 __ Bind(&ic_miss); | 1626 __ Bind(&ic_miss); |
| 1628 // Compute address of arguments (first read number of arguments from argument | 1627 // Compute address of arguments (first read number of arguments from argument |
| 1629 // descriptor array and then compute address on the stack). | 1628 // descriptor array and then compute address on the stack). |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1663 // R12: Pointer to an IC data check group (classes + target) | 1662 // R12: Pointer to an IC data check group (classes + target) |
| 1664 __ movq(RAX, Address(R12, kWordSize * num_args)); // Target function. | 1663 __ movq(RAX, Address(R12, kWordSize * num_args)); // Target function. |
| 1665 | 1664 |
| 1666 __ Bind(&call_target_function); | 1665 __ Bind(&call_target_function); |
| 1667 // RAX: Target function. | 1666 // RAX: Target function. |
| 1668 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); | 1667 __ movq(RAX, FieldAddress(RAX, Function::code_offset())); |
| 1669 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); | 1668 __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); |
| 1670 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1669 __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1671 __ jmp(RAX); | 1670 __ jmp(RAX); |
| 1672 | 1671 |
| 1673 __ Bind(&get_class); | 1672 __ Bind(&get_class_id_as_smi); |
| 1674 Label not_smi; | 1673 Label not_smi; |
| 1675 // Test if Smi -> load Smi class for comparison. | 1674 // Test if Smi -> load Smi class for comparison. |
| 1676 __ testq(RAX, Immediate(kSmiTagMask)); | 1675 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1677 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1676 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1678 const Class& smi_class = | 1677 __ movq(RAX, Immediate(Smi::RawValue(kSmi))); |
| 1679 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); | |
| 1680 __ LoadObject(RAX, smi_class); | |
| 1681 __ ret(); | 1678 __ ret(); |
| 1682 | 1679 |
| 1683 __ Bind(¬_smi); | 1680 __ Bind(¬_smi); |
| 1684 __ LoadClass(RAX, RAX); | 1681 __ LoadClassId(RAX, RAX); |
| 1682 __ SmiTag(RAX); |
| 1685 __ ret(); | 1683 __ ret(); |
| 1686 } | 1684 } |
| 1687 | 1685 |
| 1688 | 1686 |
| 1689 // Use inline cache data array to invoke the target or continue in inline | 1687 // Use inline cache data array to invoke the target or continue in inline |
| 1690 // cache miss handler. Stub for 1-argument check (receiver class). | 1688 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1691 // RCX: Inline cache data array | 1689 // RCX: Inline cache data array |
| 1692 // RDX: Arguments array | 1690 // RDX: Arguments array |
| 1693 // TOS(0): return address | 1691 // TOS(0): return address |
| 1694 // Inline cache data array structure: | 1692 // Inline cache data array structure: |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1867 // TOS + 2: instance. | 1865 // TOS + 2: instance. |
| 1868 // TOS + 3: cache array. | 1866 // TOS + 3: cache array. |
| 1869 // Result in RCX: null -> not found, otherwise result (true or false). | 1867 // Result in RCX: null -> not found, otherwise result (true or false). |
| 1870 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1868 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1871 GenerateSubtypeNTestCacheStub(assembler, 3); | 1869 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1872 } | 1870 } |
| 1873 | 1871 |
| 1874 } // namespace dart | 1872 } // namespace dart |
| 1875 | 1873 |
| 1876 #endif // defined TARGET_ARCH_X64 | 1874 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |