Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 // Total number of args is the first Smi in args descriptor array (EDX). | 288 // Total number of args is the first Smi in args descriptor array (EDX). |
| 289 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 289 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 290 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi. | 290 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi. |
| 291 // TODO(srdjan): Remove the special casing below for null receiver, once | 291 // TODO(srdjan): Remove the special casing below for null receiver, once |
| 292 // NullClass is implemented. | 292 // NullClass is implemented. |
| 293 __ cmpl(EAX, raw_null); | 293 __ cmpl(EAX, raw_null); |
| 294 // Use Object class if receiver is null. | 294 // Use Object class if receiver is null. |
| 295 __ j(EQUAL, &null_receiver, Assembler::kNearJump); | 295 __ j(EQUAL, &null_receiver, Assembler::kNearJump); |
| 296 __ testl(EAX, Immediate(kSmiTagMask)); | 296 __ testl(EAX, Immediate(kSmiTagMask)); |
| 297 __ j(ZERO, &smi_receiver, Assembler::kNearJump); | 297 __ j(ZERO, &smi_receiver, Assembler::kNearJump); |
| 298 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); | 298 __ LoadClassOfObject(EAX, EAX, EDI); |
| 299 __ jmp(&class_in_eax, Assembler::kNearJump); | 299 __ jmp(&class_in_eax, Assembler::kNearJump); |
| 300 __ Bind(&smi_receiver); | 300 __ Bind(&smi_receiver); |
| 301 // For Smis we need to get the class from the isolate. | 301 // For Smis we need to get the class from the isolate. |
| 302 // Load current Isolate pointer from Context structure into EAX. | 302 // Load current Isolate pointer from Context structure into EAX. |
| 303 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 303 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
| 304 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); | 304 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); |
| 305 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset())); | 305 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset())); |
| 306 __ jmp(&class_in_eax, Assembler::kNearJump); | 306 __ jmp(&class_in_eax, Assembler::kNearJump); |
| 307 __ Bind(&null_receiver); | 307 __ Bind(&null_receiver); |
| 308 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); | 308 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 | 765 |
| 766 // Verify that EDI is a closure by checking its class. | 766 // Verify that EDI is a closure by checking its class. |
| 767 Label not_closure; | 767 Label not_closure; |
| 768 __ cmpl(EDI, raw_null); | 768 __ cmpl(EDI, raw_null); |
| 769 // Not a closure, but null object. | 769 // Not a closure, but null object. |
| 770 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 770 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 771 __ testl(EDI, Immediate(kSmiTagMask)); | 771 __ testl(EDI, Immediate(kSmiTagMask)); |
| 772 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. | 772 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. |
| 773 // Verify that the class of the object is a closure class by checking that | 773 // Verify that the class of the object is a closure class by checking that |
| 774 // class.signature_function() is not null. | 774 // class.signature_function() is not null. |
| 775 __ movl(EAX, FieldAddress(EDI, Object::class_offset())); | 775 __ LoadClassOfObject(EAX, EDI, ECX); |
| 776 __ movl(EAX, FieldAddress(EAX, Class::signature_function_offset())); | 776 __ movl(EAX, FieldAddress(EAX, Class::signature_function_offset())); |
| 777 __ cmpl(EAX, raw_null); | 777 __ cmpl(EAX, raw_null); |
| 778 // Actual class is not a closure class. | 778 // Actual class is not a closure class. |
| 779 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 779 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 780 | 780 |
| 781 // EAX is just the signature function. Load the actual closure function. | 781 // EAX is just the signature function. Load the actual closure function. |
| 782 __ movl(ECX, FieldAddress(EDI, Closure::function_offset())); | 782 __ movl(ECX, FieldAddress(EDI, Closure::function_offset())); |
| 783 | 783 |
| 784 // Load closure context in CTX; note that CTX has already been preserved. | 784 // Load closure context in CTX; note that CTX has already been preserved. |
| 785 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); | 785 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1569 __ Bind(¬_yet_hot); | 1569 __ Bind(¬_yet_hot); |
| 1570 } | 1570 } |
| 1571 | 1571 |
| 1572 ASSERT(num_args > 0); | 1572 ASSERT(num_args > 0); |
| 1573 // Get receiver (first read number of arguments from argument descriptor array | 1573 // Get receiver (first read number of arguments from argument descriptor array |
| 1574 // and then access the receiver from the stack). | 1574 // and then access the receiver from the stack). |
| 1575 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1575 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1576 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. | 1576 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. |
| 1577 | 1577 |
| 1578 Label get_class, ic_miss; | 1578 Label get_class, ic_miss; |
| 1579 __ call(&get_class); | |
| 1580 // EAX: receiver's class | |
| 1581 // ECX: IC data array. | 1579 // ECX: IC data array. |
| 1582 | 1580 |
| 1583 #if defined(DEBUG) | 1581 #if defined(DEBUG) |
| 1584 { Label ok; | 1582 { Label ok; |
| 1585 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1583 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1586 // 'num_args_tested' is stored as an untagged int. | 1584 // 'num_args_tested' is stored as an untagged int. |
| 1587 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1585 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1588 __ cmpl(EBX, Immediate(num_args)); | 1586 __ cmpl(EBX, Immediate(num_args)); |
| 1589 __ j(EQUAL, &ok, Assembler::kNearJump); | 1587 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1590 __ Stop("Incorrect stub for IC data"); | 1588 __ Stop("Incorrect stub for IC data"); |
| 1591 __ Bind(&ok); | 1589 __ Bind(&ok); |
| 1592 } | 1590 } |
| 1593 #endif // DEBUG | 1591 #endif // DEBUG |
| 1594 | 1592 |
| 1595 // Loop that checks if there is an IC data match. | 1593 // Loop that checks if there is an IC data match. |
| 1596 // EAX: receiver's class. | 1594 // EAX: receiver's class. |
|
Ivan Posva
2012/05/30 05:48:09
This comment is out of date.
| |
| 1597 // ECX: IC data object (preserved). | 1595 // ECX: IC data object (preserved). |
| 1598 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1596 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1599 // EBX: ic_data_array with check entries: classes and target functions. | 1597 // EBX: ic_data_array with check entries: classes and target functions. |
| 1600 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1598 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1601 // EBX: points directly to the first ic data array element. | 1599 // EBX: points directly to the first ic data array element. |
| 1602 Label loop, found; | 1600 Label loop, found; |
| 1603 if (num_args == 1) { | 1601 if (num_args == 1) { |
| 1602 __ call(&get_class); | |
| 1603 // EAX: receiver's class | |
| 1604 __ Bind(&loop); | 1604 __ Bind(&loop); |
| 1605 __ movl(EDI, Address(EBX, 0)); // Get class to check. | 1605 __ movl(EDI, Address(EBX, 0)); // Get class to check. |
| 1606 __ cmpl(EAX, EDI); // Match? | 1606 __ cmpl(EAX, EDI); // Match? |
| 1607 __ j(EQUAL, &found, Assembler::kNearJump); | 1607 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1608 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1608 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1609 __ cmpl(EDI, raw_null); // Done? | 1609 __ cmpl(EDI, raw_null); // Done? |
| 1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1611 } else if (num_args == 2) { | 1611 } else if (num_args == 2) { |
| 1612 // EDI: class to check. | 1612 // EDI: class to check. |
| 1613 Label no_match; | 1613 Label no_match; |
| 1614 __ Bind(&loop); | 1614 __ Bind(&loop); |
| 1615 // Get class from IC data to check. | 1615 // Get class from IC data to check. |
| 1616 __ movl(EDI, Address(EBX, 0)); | |
| 1617 // Get receiver using argument descriptor in EDX. | 1616 // Get receiver using argument descriptor in EDX. |
| 1618 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1617 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1619 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. | 1618 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. |
| 1620 __ call(&get_class); | 1619 __ call(&get_class); |
| 1620 // TODO(vegorov): switch IC data to store class index insted of class. | |
|
Ivan Posva
2012/05/30 05:48:09
instead
In general I think resolving this TODO is
| |
| 1621 __ movl(EDI, Address(EBX, 0)); | |
| 1621 __ cmpl(EAX, EDI); // Match? | 1622 __ cmpl(EAX, EDI); // Match? |
| 1622 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1623 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1623 // Check second class/argument. | 1624 // Check second class/argument. |
| 1624 // Get class from IC data to check. | 1625 // Get class from IC data to check. |
| 1625 __ movl(EDI, Address(EBX, kWordSize)); | |
| 1626 // Get next argument. | 1626 // Get next argument. |
| 1627 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1627 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1628 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); | 1628 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); |
| 1629 // EAX (argument count) is Smi. | 1629 // EAX (argument count) is Smi. |
| 1630 __ call(&get_class); | 1630 __ call(&get_class); |
| 1631 __ movl(EDI, Address(EBX, kWordSize)); | |
| 1631 __ cmpl(EAX, EDI); // Match? | 1632 __ cmpl(EAX, EDI); // Match? |
| 1632 __ j(EQUAL, &found, Assembler::kNearJump); | 1633 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1633 __ Bind(&no_match); | 1634 __ Bind(&no_match); |
| 1634 // Each test entry has (1 + num_args) array elements. | 1635 // Each test entry has (1 + num_args) array elements. |
| 1635 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1636 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1636 __ cmpl(EDI, raw_null); // Done? | 1637 __ cmpl(EDI, raw_null); // Done? |
| 1637 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1638 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1638 } | 1639 } |
| 1639 | 1640 |
| 1640 __ Bind(&ic_miss); | 1641 __ Bind(&ic_miss); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1689 Label not_smi; | 1690 Label not_smi; |
| 1690 // Test if Smi -> load Smi class for comparison. | 1691 // Test if Smi -> load Smi class for comparison. |
| 1691 __ testl(EAX, Immediate(kSmiTagMask)); | 1692 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1692 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1693 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1693 const Class& smi_class = | 1694 const Class& smi_class = |
| 1694 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); | 1695 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); |
| 1695 __ LoadObject(EAX, smi_class); | 1696 __ LoadObject(EAX, smi_class); |
| 1696 __ ret(); | 1697 __ ret(); |
| 1697 | 1698 |
| 1698 __ Bind(¬_smi); | 1699 __ Bind(¬_smi); |
| 1699 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); | 1700 __ LoadClassOfObject(EAX, EAX, EDI); |
| 1700 __ ret(); | 1701 __ ret(); |
| 1701 } | 1702 } |
| 1702 | 1703 |
| 1703 | 1704 |
| 1704 // Use inline cache data array to invoke the target or continue in inline | 1705 // Use inline cache data array to invoke the target or continue in inline |
| 1705 // cache miss handler. Stub for 1-argument check (receiver class). | 1706 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1706 // ECX: Inline cache data array | 1707 // ECX: Inline cache data array |
| 1707 // EDX: Arguments array | 1708 // EDX: Arguments array |
| 1708 // TOS(0): return address | 1709 // TOS(0): return address |
| 1709 // Inline cache data array structure: | 1710 // Inline cache data array structure: |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1795 // TOS + 3: SubtypeTestCache. | 1796 // TOS + 3: SubtypeTestCache. |
| 1796 // Result in ECX: null -> not found, otherwise result (true or false). | 1797 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1797 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1798 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1798 ASSERT((1 <= n) && (n <= 3)); | 1799 ASSERT((1 <= n) && (n <= 3)); |
| 1799 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1800 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| 1800 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1801 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| 1801 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1802 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| 1802 const Immediate raw_null = | 1803 const Immediate raw_null = |
| 1803 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1804 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1804 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); | 1805 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); |
| 1805 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1806 __ LoadClassOfObject(ECX, EAX, EBX); |
| 1806 // EAX: instance, ECX: instance-class. | 1807 // EAX: instance, ECX: instance-class. |
| 1807 // Get instance type arguments | 1808 // Get instance type arguments |
| 1808 if (n > 1) { | 1809 if (n > 1) { |
| 1809 // Compute instance type arguments into EBX. | 1810 // Compute instance type arguments into EBX. |
| 1810 Label has_no_type_arguments; | 1811 Label has_no_type_arguments; |
| 1811 __ movl(EBX, raw_null); | 1812 __ movl(EBX, raw_null); |
| 1812 __ movl(EDI, FieldAddress(ECX, | 1813 __ movl(EDI, FieldAddress(ECX, |
| 1813 Class::type_arguments_instance_field_offset_offset())); | 1814 Class::type_arguments_instance_field_offset_offset())); |
| 1814 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); | 1815 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); |
| 1815 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1816 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1891 // TOS + 2: instance. | 1892 // TOS + 2: instance. |
| 1892 // TOS + 3: cache array. | 1893 // TOS + 3: cache array. |
| 1893 // Result in ECX: null -> not found, otherwise result (true or false). | 1894 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1894 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1895 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1895 GenerateSubtypeNTestCacheStub(assembler, 3); | 1896 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1896 } | 1897 } |
| 1897 | 1898 |
| 1898 } // namespace dart | 1899 } // namespace dart |
| 1899 | 1900 |
| 1900 #endif // defined TARGET_ARCH_IA32 | 1901 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |