| 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 __ LoadClassOfObject(EAX, EAX, EDI); | 298 __ LoadClass(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 __ LoadClassOfObject(EAX, EDI, ECX); | 775 __ LoadClass(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 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1584 // 'num_args_tested' is stored as an untagged int. | 1584 // 'num_args_tested' is stored as an untagged int. |
| 1585 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1585 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1586 __ cmpl(EBX, Immediate(num_args)); | 1586 __ cmpl(EBX, Immediate(num_args)); |
| 1587 __ j(EQUAL, &ok, Assembler::kNearJump); | 1587 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1588 __ Stop("Incorrect stub for IC data"); | 1588 __ Stop("Incorrect stub for IC data"); |
| 1589 __ Bind(&ok); | 1589 __ Bind(&ok); |
| 1590 } | 1590 } |
| 1591 #endif // DEBUG | 1591 #endif // DEBUG |
| 1592 | 1592 |
| 1593 // Loop that checks if there is an IC data match. | 1593 // Loop that checks if there is an IC data match. |
| 1594 // EAX: receiver's class. | |
| 1595 // ECX: IC data object (preserved). | 1594 // ECX: IC data object (preserved). |
| 1596 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1595 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1597 // EBX: ic_data_array with check entries: classes and target functions. | 1596 // EBX: ic_data_array with check entries: classes and target functions. |
| 1598 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1597 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1599 // EBX: points directly to the first ic data array element. | 1598 // EBX: points directly to the first ic data array element. |
| 1600 Label loop, found; | 1599 Label loop, found; |
| 1601 if (num_args == 1) { | 1600 if (num_args == 1) { |
| 1602 __ call(&get_class); | 1601 __ call(&get_class); |
| 1603 // EAX: receiver's class | 1602 // EAX: receiver's class |
| 1604 __ Bind(&loop); | 1603 __ Bind(&loop); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 Label not_smi; | 1689 Label not_smi; |
| 1691 // Test if Smi -> load Smi class for comparison. | 1690 // Test if Smi -> load Smi class for comparison. |
| 1692 __ testl(EAX, Immediate(kSmiTagMask)); | 1691 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1693 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1692 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1694 const Class& smi_class = | 1693 const Class& smi_class = |
| 1695 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); | 1694 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); |
| 1696 __ LoadObject(EAX, smi_class); | 1695 __ LoadObject(EAX, smi_class); |
| 1697 __ ret(); | 1696 __ ret(); |
| 1698 | 1697 |
| 1699 __ Bind(¬_smi); | 1698 __ Bind(¬_smi); |
| 1700 __ LoadClassOfObject(EAX, EAX, EDI); | 1699 __ LoadClass(EAX, EAX, EDI); |
| 1701 __ ret(); | 1700 __ ret(); |
| 1702 } | 1701 } |
| 1703 | 1702 |
| 1704 | 1703 |
| 1705 // Use inline cache data array to invoke the target or continue in inline | 1704 // Use inline cache data array to invoke the target or continue in inline |
| 1706 // cache miss handler. Stub for 1-argument check (receiver class). | 1705 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1707 // ECX: Inline cache data array | 1706 // ECX: Inline cache data array |
| 1708 // EDX: Arguments array | 1707 // EDX: Arguments array |
| 1709 // TOS(0): return address | 1708 // TOS(0): return address |
| 1710 // Inline cache data array structure: | 1709 // Inline cache data array structure: |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1796 // TOS + 3: SubtypeTestCache. | 1795 // TOS + 3: SubtypeTestCache. |
| 1797 // Result in ECX: null -> not found, otherwise result (true or false). | 1796 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1798 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1797 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1799 ASSERT((1 <= n) && (n <= 3)); | 1798 ASSERT((1 <= n) && (n <= 3)); |
| 1800 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1799 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| 1801 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1800 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| 1802 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1801 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| 1803 const Immediate raw_null = | 1802 const Immediate raw_null = |
| 1804 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1803 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1805 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); | 1804 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); |
| 1806 __ LoadClassOfObject(ECX, EAX, EBX); | 1805 __ LoadClass(ECX, EAX, EBX); |
| 1807 // EAX: instance, ECX: instance-class. | 1806 // EAX: instance, ECX: instance-class. |
| 1808 // Get instance type arguments | 1807 // Get instance type arguments |
| 1809 if (n > 1) { | 1808 if (n > 1) { |
| 1810 // Compute instance type arguments into EBX. | 1809 // Compute instance type arguments into EBX. |
| 1811 Label has_no_type_arguments; | 1810 Label has_no_type_arguments; |
| 1812 __ movl(EBX, raw_null); | 1811 __ movl(EBX, raw_null); |
| 1813 __ movl(EDI, FieldAddress(ECX, | 1812 __ movl(EDI, FieldAddress(ECX, |
| 1814 Class::type_arguments_instance_field_offset_offset())); | 1813 Class::type_arguments_instance_field_offset_offset())); |
| 1815 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); | 1814 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); |
| 1816 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1815 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 // TOS + 2: instance. | 1891 // TOS + 2: instance. |
| 1893 // TOS + 3: cache array. | 1892 // TOS + 3: cache array. |
| 1894 // Result in ECX: null -> not found, otherwise result (true or false). | 1893 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1895 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1894 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1896 GenerateSubtypeNTestCacheStub(assembler, 3); | 1895 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1897 } | 1896 } |
| 1898 | 1897 |
| 1899 } // namespace dart | 1898 } // namespace dart |
| 1900 | 1899 |
| 1901 #endif // defined TARGET_ARCH_IA32 | 1900 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |