| 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_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/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1647 __ j(EQUAL, &found, Assembler::kNearJump); // Break. | 1647 __ j(EQUAL, &found, Assembler::kNearJump); // Break. |
| 1648 } | 1648 } |
| 1649 } | 1649 } |
| 1650 __ Bind(&update); | 1650 __ Bind(&update); |
| 1651 // Reload receiver class ID. It has not been destroyed when num_args == 1. | 1651 // Reload receiver class ID. It has not been destroyed when num_args == 1. |
| 1652 if (num_args > 1) { | 1652 if (num_args > 1) { |
| 1653 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1653 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1654 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); | 1654 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); |
| 1655 __ call(&get_class_id_as_smi); | 1655 __ call(&get_class_id_as_smi); |
| 1656 } | 1656 } |
| 1657 // Each test entry has (1 + num_args) array elements. | 1657 |
| 1658 const intptr_t entry_size = (num_args + 1) * kWordSize; | 1658 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1659 __ addl(EBX, Immediate(entry_size)); // Next entry. | 1659 __ addl(EBX, Immediate(entry_size)); // Next entry. |
| 1660 __ movl(EDI, Address(EBX, 0)); // Next class ID. | 1660 __ movl(EDI, Address(EBX, 0)); // Next class ID. |
| 1661 | 1661 |
| 1662 __ Bind(&test); | 1662 __ Bind(&test); |
| 1663 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 1663 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 1664 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1664 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1665 | 1665 |
| 1666 // IC miss. | 1666 // IC miss. |
| 1667 const Immediate raw_null = | 1667 const Immediate raw_null = |
| 1668 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1668 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1701 Label call_target_function; | 1701 Label call_target_function; |
| 1702 __ cmpl(EAX, raw_null); | 1702 __ cmpl(EAX, raw_null); |
| 1703 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); | 1703 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); |
| 1704 // NoSuchMethod or closure. | 1704 // NoSuchMethod or closure. |
| 1705 // Mark IC call that it may be a closure call that does not collect | 1705 // Mark IC call that it may be a closure call that does not collect |
| 1706 // type feedback. | 1706 // type feedback. |
| 1707 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1)); | 1707 __ movb(FieldAddress(ECX, ICData::is_closure_call_offset()), Immediate(1)); |
| 1708 __ jmp(&StubCode::InstanceFunctionLookupLabel()); | 1708 __ jmp(&StubCode::InstanceFunctionLookupLabel()); |
| 1709 | 1709 |
| 1710 __ Bind(&found); | 1710 __ Bind(&found); |
| 1711 // EBX: Pointer to an IC data check group (classes + target) | 1711 // EBX: Pointer to an IC data check group. |
| 1712 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. | 1712 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1713 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1714 __ movl(EAX, Address(EBX, target_offset)); |
| 1715 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); |
| 1716 __ j(NO_OVERFLOW, &call_target_function); |
| 1717 __ movl(Address(EBX, count_offset), |
| 1718 Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 1713 | 1719 |
| 1714 __ Bind(&call_target_function); | 1720 __ Bind(&call_target_function); |
| 1715 // EAX: Target function. | 1721 // EAX: Target function. |
| 1716 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 1722 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
| 1717 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 1723 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 1718 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1724 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1719 __ jmp(EAX); | 1725 __ jmp(EAX); |
| 1720 | 1726 |
| 1721 // Instance in EAX, return its class-id in EAX as Smi. | 1727 // Instance in EAX, return its class-id in EAX as Smi. |
| 1722 __ Bind(&get_class_id_as_smi); | 1728 __ Bind(&get_class_id_as_smi); |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2043 | 2049 |
| 2044 // Implements equality operator when one of the arguments is null | 2050 // Implements equality operator when one of the arguments is null |
| 2045 // (identity check) and updates ICData if necessary. | 2051 // (identity check) and updates ICData if necessary. |
| 2046 // TOS + 0: return address | 2052 // TOS + 0: return address |
| 2047 // TOS + 1: right argument | 2053 // TOS + 1: right argument |
| 2048 // TOS + 2: left argument | 2054 // TOS + 2: left argument |
| 2049 // ECX: ICData. | 2055 // ECX: ICData. |
| 2050 // EAX: result. | 2056 // EAX: result. |
| 2051 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. | 2057 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. |
| 2052 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { | 2058 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { |
| 2059 static const intptr_t kNumArgsTested = 2; |
| 2053 #if defined(DEBUG) | 2060 #if defined(DEBUG) |
| 2054 { Label ok; | 2061 { Label ok; |
| 2055 __ movl(EAX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 2062 __ movl(EAX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 2056 __ cmpl(EAX, Immediate(2)); | 2063 __ cmpl(EAX, Immediate(kNumArgsTested)); |
| 2057 __ j(EQUAL, &ok, Assembler::kNearJump); | 2064 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 2058 __ Stop("Incorrect ICData for equality"); | 2065 __ Stop("Incorrect ICData for equality"); |
| 2059 __ Bind(&ok); | 2066 __ Bind(&ok); |
| 2060 } | 2067 } |
| 2061 #endif // DEBUG | 2068 #endif // DEBUG |
| 2062 // Check IC data, update if needed. | 2069 // Check IC data, update if needed. |
| 2063 // EBX: IC data object (preserved). | 2070 // EBX: IC data object (preserved). |
| 2064 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 2071 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 2065 // EBX: ic_data_array with check entries: classes and target functions. | 2072 // EBX: ic_data_array with check entries: classes and target functions. |
| 2066 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 2073 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 2067 // EBX: points directly to the first ic data array element. | 2074 // EBX: points directly to the first ic data array element. |
| 2068 | 2075 |
| 2069 Label get_class_id_as_smi, no_match, loop, compute_result; | 2076 Label get_class_id_as_smi, no_match, loop, compute_result, found; |
| 2070 __ Bind(&loop); | 2077 __ Bind(&loop); |
| 2071 // Check left. | 2078 // Check left. |
| 2072 __ movl(EAX, Address(ESP, 2 * kWordSize)); | 2079 __ movl(EAX, Address(ESP, 2 * kWordSize)); |
| 2073 __ call(&get_class_id_as_smi); | 2080 __ call(&get_class_id_as_smi); |
| 2074 __ movl(EDI, Address(EBX, 0 * kWordSize)); | 2081 __ movl(EDI, Address(EBX, 0 * kWordSize)); |
| 2075 __ cmpl(EAX, EDI); // Class id match? | 2082 __ cmpl(EAX, EDI); // Class id match? |
| 2076 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 2083 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 2077 // Check right. | 2084 // Check right. |
| 2078 __ movl(EAX, Address(ESP, 1 * kWordSize)); | 2085 __ movl(EAX, Address(ESP, 1 * kWordSize)); |
| 2079 __ call(&get_class_id_as_smi); | 2086 __ call(&get_class_id_as_smi); |
| 2080 __ movl(EDI, Address(EBX, 1 * kWordSize)); | 2087 __ movl(EDI, Address(EBX, 1 * kWordSize)); |
| 2081 __ cmpl(EAX, EDI); // Class id match? | 2088 __ cmpl(EAX, EDI); // Class id match? |
| 2082 __ j(EQUAL, &compute_result, Assembler::kNearJump); | 2089 __ j(EQUAL, &found, Assembler::kNearJump); |
| 2083 __ Bind(&no_match); | 2090 __ Bind(&no_match); |
| 2084 // Each test entry has (1 + 2) array elements (2 arguments, 1 target). | 2091 // Next check group. |
| 2085 __ addl(EBX, Immediate(kWordSize * (1 + 2))); // Next element. | 2092 __ addl(EBX, Immediate( |
| 2093 kWordSize * ICData::TestEntryLengthFor(kNumArgsTested))); |
| 2086 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? | 2094 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? |
| 2087 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 2095 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 2088 Label update_ic_data; | 2096 Label update_ic_data; |
| 2089 __ jmp(&update_ic_data); | 2097 __ jmp(&update_ic_data); |
| 2090 | 2098 |
| 2099 __ Bind(&found); |
| 2100 const intptr_t count_offset = |
| 2101 ICData::CountIndexFor(kNumArgsTested) * kWordSize; |
| 2102 __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); |
| 2103 __ j(NO_OVERFLOW, &compute_result); |
| 2104 __ movl(Address(EBX, count_offset), |
| 2105 Immediate(Smi::RawValue(Smi::kMaxValue))); |
| 2106 |
| 2091 __ Bind(&compute_result); | 2107 __ Bind(&compute_result); |
| 2092 Label true_label; | 2108 Label true_label; |
| 2093 __ movl(EAX, Address(ESP, 1 * kWordSize)); | 2109 __ movl(EAX, Address(ESP, 1 * kWordSize)); |
| 2094 __ cmpl(EAX, Address(ESP, 2 * kWordSize)); | 2110 __ cmpl(EAX, Address(ESP, 2 * kWordSize)); |
| 2095 __ j(EQUAL, &true_label, Assembler::kNearJump); | 2111 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 2096 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); | 2112 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); |
| 2097 __ ret(); | 2113 __ ret(); |
| 2098 __ Bind(&true_label); | 2114 __ Bind(&true_label); |
| 2099 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True())); | 2115 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True())); |
| 2100 __ ret(); | 2116 __ ret(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2141 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); | 2157 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); |
| 2142 __ popl(EDX); | 2158 __ popl(EDX); |
| 2143 __ popl(EAX); | 2159 __ popl(EAX); |
| 2144 __ LeaveFrame(); | 2160 __ LeaveFrame(); |
| 2145 __ ret(); | 2161 __ ret(); |
| 2146 } | 2162 } |
| 2147 | 2163 |
| 2148 } // namespace dart | 2164 } // namespace dart |
| 2149 | 2165 |
| 2150 #endif // defined TARGET_ARCH_IA32 | 2166 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |