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 2080 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 // Called from megamorphic calls. |
| 2102 // R1: receiver |
| 2103 // R5: MegamorphicCache (preserved) |
| 2104 // Result: |
| 2105 // R1: target entry point |
| 2106 // CODE_REG: target Code |
| 2107 // R4: arguments descriptor |
2101 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { | 2108 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
2102 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 2109 __ LoadTaggedClassIdMayBeSmi(R0, R1); |
2103 // R0: class ID of the receiver (smi). | 2110 // R0: class ID of the receiver (smi). |
2104 __ ldr(R4, FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset())); | 2111 __ ldr(R4, FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset())); |
2105 __ ldr(R2, FieldAddress(R5, MegamorphicCache::buckets_offset())); | 2112 __ ldr(R2, FieldAddress(R5, MegamorphicCache::buckets_offset())); |
2106 __ ldr(R1, FieldAddress(R5, MegamorphicCache::mask_offset())); | 2113 __ ldr(R1, FieldAddress(R5, MegamorphicCache::mask_offset())); |
2107 // R2: cache buckets array. | 2114 // R2: cache buckets array. |
2108 // R1: mask. | 2115 // R1: mask. |
2109 __ mov(R3, R0); | 2116 __ mov(R3, R0); |
2110 // R3: probe. | 2117 // R3: probe. |
2111 | 2118 |
2112 Label loop, update, load_target_function; | 2119 Label loop, update, load_target_function; |
(...skipping 19 matching lines...) Expand all Loading... |
2132 // proper target for the given name and arguments descriptor. If the | 2139 // 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 | 2140 // illegal class id was found, the target is a cache miss handler that can |
2134 // be invoked as a normal Dart function. | 2141 // be invoked as a normal Dart function. |
2135 __ add(TMP, R2, Operand(R3, LSL, 3)); | 2142 __ add(TMP, R2, Operand(R3, LSL, 3)); |
2136 __ ldr(R0, FieldAddress(TMP, base + kWordSize)); | 2143 __ ldr(R0, FieldAddress(TMP, base + kWordSize)); |
2137 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 2144 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2138 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2145 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2139 } | 2146 } |
2140 | 2147 |
2141 | 2148 |
2142 // Called from megamorphic calls. | |
2143 // R0: receiver | |
2144 // R5: MegamorphicCache (preserved) | |
2145 // Result: | |
2146 // R1: target entry point | |
2147 // CODE_REG: target Code | |
2148 // R4: arguments descriptor | |
2149 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2149 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2150 EmitMegamorphicLookup(assembler); | 2150 EmitMegamorphicLookup(assembler); |
2151 __ ret(); | 2151 __ ret(); |
2152 } | 2152 } |
2153 | 2153 |
2154 | 2154 |
2155 // Called from switchable IC calls. | 2155 // Called from switchable IC calls. |
2156 // R0: receiver | 2156 // R1: receiver |
2157 // R5: ICData (preserved) | 2157 // R5: ICData (preserved) |
2158 // Result: | 2158 // Result: |
2159 // R1: target entry point | 2159 // R1: target entry point |
2160 // CODE_REG: target Code object | 2160 // CODE_REG: target Code object |
2161 // R4: arguments descriptor | 2161 // R4: arguments descriptor |
2162 void StubCode::GenerateICLookupStub(Assembler* assembler) { | 2162 static void EmitICLookup(Assembler* assembler, |
| 2163 intptr_t args_checked, |
| 2164 Token::Kind kind) { |
| 2165 if (kind != Token::kILLEGAL) { |
| 2166 __ Comment("Fast Smi op"); |
| 2167 Label not_smi_or_overflow; |
| 2168 |
| 2169 // R1: Receiver. |
| 2170 __ ldr(R2, Address(SP, + 0 * kWordSize)); |
| 2171 // R2: Argument. |
| 2172 __ orr(TMP, R1, Operand(R2)); |
| 2173 __ tsti(TMP, Immediate(kSmiTagMask)); |
| 2174 __ b(¬_smi_or_overflow, NE); |
| 2175 switch (kind) { |
| 2176 case Token::kADD: { |
| 2177 __ adds(R0, R1, Operand(R2)); // Adds. |
| 2178 __ b(¬_smi_or_overflow, VS); // Branch if overflow. |
| 2179 break; |
| 2180 } |
| 2181 case Token::kSUB: { |
| 2182 __ subs(R0, R1, Operand(R2)); // Subtract. |
| 2183 __ b(¬_smi_or_overflow, VS); // Branch if overflow. |
| 2184 break; |
| 2185 } |
| 2186 case Token::kEQ: { |
| 2187 __ CompareRegisters(R1, R2); |
| 2188 __ LoadObject(R0, Bool::True()); |
| 2189 __ LoadObject(R1, Bool::False()); |
| 2190 __ csel(R0, R1, R0, NE); |
| 2191 break; |
| 2192 } |
| 2193 default: UNIMPLEMENTED(); |
| 2194 } |
| 2195 // Return past the call to lookup result. |
| 2196 __ add(LR, LR, Operand(Instr::kInstrSize)); |
| 2197 __ ret(); |
| 2198 |
| 2199 __ Bind(¬_smi_or_overflow); |
| 2200 } |
| 2201 |
2163 Label loop, found, miss; | 2202 Label loop, found, miss; |
2164 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 2203 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
2165 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); | 2204 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); |
2166 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); | 2205 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); |
2167 // R8: first IC entry | 2206 // R8: first IC entry |
2168 __ LoadTaggedClassIdMayBeSmi(R1, R0); | 2207 __ LoadTaggedClassIdMayBeSmi(R0, R1); |
2169 // R1: receiver cid as Smi | 2208 // R1: receiver cid as Smi |
2170 | 2209 |
2171 __ Bind(&loop); | 2210 __ Bind(&loop); |
2172 __ ldr(R2, Address(R8, 0)); | 2211 __ ldr(R2, Address(R8, 0)); |
2173 __ cmp(R1, Operand(R2)); | 2212 __ cmp(R0, Operand(R2)); |
2174 __ b(&found, EQ); | 2213 __ b(&found, EQ); |
2175 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); | 2214 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
2176 __ b(&miss, EQ); | 2215 __ b(&miss, EQ); |
2177 | 2216 |
2178 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; | 2217 const intptr_t entry_length = |
| 2218 ICData::TestEntryLengthFor(args_checked) * kWordSize; |
2179 __ AddImmediate(R8, R8, entry_length); // Next entry. | 2219 __ AddImmediate(R8, R8, entry_length); // Next entry. |
2180 __ b(&loop); | 2220 __ b(&loop); |
2181 | 2221 |
2182 __ Bind(&found); | 2222 __ Bind(&found); |
2183 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; | 2223 const intptr_t target_offset = |
| 2224 ICData::TargetIndexFor(args_checked) * kWordSize; |
2184 __ ldr(R0, Address(R8, target_offset)); | 2225 __ ldr(R0, Address(R8, target_offset)); |
2185 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 2226 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2186 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2227 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2187 __ ret(); | 2228 __ ret(); |
2188 | 2229 |
2189 __ Bind(&miss); | 2230 __ Bind(&miss); |
2190 __ LoadIsolate(R2); | 2231 __ LoadIsolate(R2); |
2191 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); | 2232 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
2192 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2233 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
2193 __ ret(); | 2234 __ ret(); |
2194 } | 2235 } |
2195 | 2236 |
| 2237 |
| 2238 void StubCode::GenerateICLookupStub(Assembler* assembler) { |
| 2239 EmitICLookup(assembler, 1, Token::kILLEGAL); |
| 2240 } |
| 2241 |
| 2242 |
| 2243 void StubCode::GenerateICSmiAddLookupStub(Assembler* assembler) { |
| 2244 EmitICLookup(assembler, 2, Token::kADD); |
| 2245 } |
| 2246 |
| 2247 |
| 2248 void StubCode::GenerateICSmiSubLookupStub(Assembler* assembler) { |
| 2249 EmitICLookup(assembler, 2, Token::kSUB); |
| 2250 } |
| 2251 |
| 2252 |
| 2253 void StubCode::GenerateICSmiEqualLookupStub(Assembler* assembler) { |
| 2254 EmitICLookup(assembler, 2, Token::kEQ); |
| 2255 } |
| 2256 |
2196 } // namespace dart | 2257 } // namespace dart |
2197 | 2258 |
2198 #endif // defined TARGET_ARCH_ARM64 | 2259 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |