OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 // miss-handler may return null. | 560 // miss-handler may return null. |
561 __ CompareObject(R0, Object::null_object()); | 561 __ CompareObject(R0, Object::null_object()); |
562 __ b(call_target_function, NE); | 562 __ b(call_target_function, NE); |
563 __ EnterStubFrame(); | 563 __ EnterStubFrame(); |
564 | 564 |
565 // Load the receiver. | 565 // Load the receiver. |
566 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset()); | 566 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset()); |
567 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi. | 567 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi. |
568 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize); | 568 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize); |
569 __ PushObject(Object::null_object()); | 569 __ PushObject(Object::null_object()); |
570 __ Push(R6); | 570 __ Push(R6); // Receiver. |
571 __ Push(R5); | 571 __ Push(R5); // ICData/MegamorphicCache. |
572 __ Push(R4); | 572 __ Push(R4); // Arguments descriptor. |
573 // R2: Smi-tagged arguments array length. | 573 // R2: Smi-tagged arguments array length. |
574 PushArgumentsArray(assembler); | 574 PushArgumentsArray(assembler); |
575 const intptr_t kNumArgs = 4; | 575 const intptr_t kNumArgs = 4; |
576 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); | 576 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); |
577 __ Drop(4); | 577 __ Drop(4); |
578 __ Pop(R0); // Return value. | 578 __ Pop(R0); // Return value. |
579 __ LeaveStubFrame(); | 579 __ LeaveStubFrame(); |
580 __ ret(); | 580 __ ret(); |
581 } | 581 } |
582 | 582 |
(...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2091 Assembler* assembler) { | 2091 Assembler* assembler) { |
2092 const Register left = R1; | 2092 const Register left = R1; |
2093 const Register right = R0; | 2093 const Register right = R0; |
2094 __ LoadFromOffset(left, SP, 1 * kWordSize); | 2094 __ LoadFromOffset(left, SP, 1 * kWordSize); |
2095 __ LoadFromOffset(right, SP, 0 * kWordSize); | 2095 __ LoadFromOffset(right, SP, 0 * kWordSize); |
2096 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2096 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2097 __ ret(); | 2097 __ ret(); |
2098 } | 2098 } |
2099 | 2099 |
2100 | 2100 |
2101 void StubCode::EmitMegamorphicLookup( | 2101 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
2102 Assembler* assembler, Register receiver, Register cache, Register target) { | 2102 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
2103 ASSERT((cache != R0) && (cache != R2)); | |
2104 __ LoadTaggedClassIdMayBeSmi(R0, receiver); | |
2105 // R0: class ID of the receiver (smi). | 2103 // R0: class ID of the receiver (smi). |
2106 __ LoadFieldFromOffset(R2, cache, MegamorphicCache::buckets_offset()); | 2104 __ ldr(R4, FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset())); |
2107 __ LoadFieldFromOffset(R1, cache, MegamorphicCache::mask_offset()); | 2105 __ ldr(R2, FieldAddress(R5, MegamorphicCache::buckets_offset())); |
| 2106 __ ldr(R1, FieldAddress(R5, MegamorphicCache::mask_offset())); |
2108 // R2: cache buckets array. | 2107 // R2: cache buckets array. |
2109 // R1: mask. | 2108 // R1: mask. |
2110 __ mov(R3, R0); | 2109 __ mov(R3, R0); |
| 2110 // R3: probe. |
2111 | 2111 |
2112 Label loop, update, call_target_function; | 2112 Label loop, update, load_target_function; |
2113 __ b(&loop); | 2113 __ b(&loop); |
2114 | 2114 |
2115 __ Bind(&update); | 2115 __ Bind(&update); |
2116 __ add(R3, R3, Operand(Smi::RawValue(1))); | 2116 __ add(R3, R3, Operand(Smi::RawValue(1))); |
2117 __ Bind(&loop); | 2117 __ Bind(&loop); |
2118 __ and_(R3, R3, Operand(R1)); | 2118 __ and_(R3, R3, Operand(R1)); |
2119 const intptr_t base = Array::data_offset(); | 2119 const intptr_t base = Array::data_offset(); |
2120 // R3 is smi tagged, but table entries are 16 bytes, so LSL 3. | 2120 // R3 is smi tagged, but table entries are 16 bytes, so LSL 3. |
2121 __ add(TMP, R2, Operand(R3, LSL, 3)); | 2121 __ add(TMP, R2, Operand(R3, LSL, 3)); |
2122 __ LoadFieldFromOffset(R4, TMP, base); | 2122 __ ldr(R6, FieldAddress(TMP, base)); |
2123 | 2123 |
2124 ASSERT(kIllegalCid == 0); | 2124 ASSERT(kIllegalCid == 0); |
2125 __ tst(R4, Operand(R4)); | 2125 __ tst(R6, Operand(R6)); |
2126 __ b(&call_target_function, EQ); | 2126 __ b(&load_target_function, EQ); |
2127 __ CompareRegisters(R4, R0); | 2127 __ CompareRegisters(R6, R0); |
2128 __ b(&update, NE); | 2128 __ b(&update, NE); |
2129 | 2129 |
2130 __ Bind(&call_target_function); | 2130 __ Bind(&load_target_function); |
2131 // Call the target found in the cache. For a class id match, this is a | 2131 // Call the target found in the cache. For a class id match, this is a |
2132 // proper target for the given name and arguments descriptor. If the | 2132 // proper target for the given name and arguments descriptor. If the |
2133 // illegal class id was found, the target is a cache miss handler that can | 2133 // illegal class id was found, the target is a cache miss handler that can |
2134 // be invoked as a normal Dart function. | 2134 // be invoked as a normal Dart function. |
2135 __ add(TMP, R2, Operand(R3, LSL, 3)); | 2135 __ add(TMP, R2, Operand(R3, LSL, 3)); |
2136 __ LoadFieldFromOffset(R0, TMP, base + kWordSize); | 2136 __ ldr(R0, FieldAddress(TMP, base + kWordSize)); |
2137 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); | 2137 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2138 __ LoadFieldFromOffset(R1, R0, Function::entry_point_offset()); | 2138 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2139 } | 2139 } |
2140 | 2140 |
2141 | 2141 |
2142 // Called from megamorphic calls. | 2142 // Called from megamorphic calls. |
2143 // R0: receiver. | 2143 // R0: receiver |
2144 // R1: lookup cache. | 2144 // R5: MegamorphicCache (preserved) |
2145 // Result: | 2145 // Result: |
2146 // R1: entry point. | 2146 // R1: target entry point |
| 2147 // CODE_REG: target Code |
| 2148 // R4: arguments descriptor |
2147 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2149 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2148 EmitMegamorphicLookup(assembler, R0, R1, R1); | 2150 EmitMegamorphicLookup(assembler); |
2149 __ ret(); | 2151 __ ret(); |
2150 } | 2152 } |
2151 | 2153 |
| 2154 |
| 2155 // Called from switchable IC calls. |
| 2156 // R0: receiver |
| 2157 // R5: ICData (preserved) |
| 2158 // Result: |
| 2159 // R1: target entry point |
| 2160 // CODE_REG: target Code object |
| 2161 // R4: arguments descriptor |
| 2162 void StubCode::GenerateICLookupStub(Assembler* assembler) { |
| 2163 Label loop, found, miss; |
| 2164 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 2165 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); |
| 2166 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); |
| 2167 // R8: first IC entry |
| 2168 __ LoadTaggedClassIdMayBeSmi(R1, R0); |
| 2169 // R1: receiver cid as Smi |
| 2170 |
| 2171 __ Bind(&loop); |
| 2172 __ ldr(R2, Address(R8, 0)); |
| 2173 __ cmp(R1, Operand(R2)); |
| 2174 __ b(&found, EQ); |
| 2175 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
| 2176 __ b(&miss, EQ); |
| 2177 |
| 2178 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
| 2179 __ AddImmediate(R8, R8, entry_length); // Next entry. |
| 2180 __ b(&loop); |
| 2181 |
| 2182 __ Bind(&found); |
| 2183 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; |
| 2184 __ ldr(R0, Address(R8, target_offset)); |
| 2185 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
| 2186 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 2187 __ ret(); |
| 2188 |
| 2189 __ Bind(&miss); |
| 2190 __ LoadIsolate(R2); |
| 2191 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
| 2192 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 2193 __ ret(); |
| 2194 } |
| 2195 |
2152 } // namespace dart | 2196 } // namespace dart |
2153 | 2197 |
2154 #endif // defined TARGET_ARCH_ARM64 | 2198 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |