OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 2026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2037 const Register temp = R2; | 2037 const Register temp = R2; |
2038 const Register left = R1; | 2038 const Register left = R1; |
2039 const Register right = R0; | 2039 const Register right = R0; |
2040 __ ldr(left, Address(SP, 1 * kWordSize)); | 2040 __ ldr(left, Address(SP, 1 * kWordSize)); |
2041 __ ldr(right, Address(SP, 0 * kWordSize)); | 2041 __ ldr(right, Address(SP, 0 * kWordSize)); |
2042 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2042 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
2043 __ Ret(); | 2043 __ Ret(); |
2044 } | 2044 } |
2045 | 2045 |
2046 | 2046 |
| 2047 // Called from megamorphic calls. |
| 2048 // R1: receiver |
| 2049 // R9: MegamorphicCache (preserved) |
| 2050 // Result: |
| 2051 // R1: target entry point |
| 2052 // CODE_REG: target Code |
| 2053 // R4: arguments descriptor |
2047 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { | 2054 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
2048 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 2055 __ LoadTaggedClassIdMayBeSmi(R0, R1); |
2049 // R0: receiver cid as Smi. | 2056 // R0: receiver cid as Smi. |
2050 __ ldr(R4, FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset())); | 2057 __ ldr(R4, FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset())); |
2051 __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset())); | 2058 __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset())); |
2052 __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset())); | 2059 __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset())); |
2053 // R2: cache buckets array. | 2060 // R2: cache buckets array. |
2054 // R1: mask. | 2061 // R1: mask. |
2055 __ mov(R3, Operand(R0)); | 2062 __ mov(R3, Operand(R0)); |
2056 // R3: probe. | 2063 // R3: probe. |
2057 | 2064 |
2058 Label loop, update, load_target_function; | 2065 Label loop, update, load_target_function; |
(...skipping 19 matching lines...) Expand all Loading... |
2078 // proper target for the given name and arguments descriptor. If the | 2085 // proper target for the given name and arguments descriptor. If the |
2079 // illegal class id was found, the target is a cache miss handler that can | 2086 // illegal class id was found, the target is a cache miss handler that can |
2080 // be invoked as a normal Dart function. | 2087 // be invoked as a normal Dart function. |
2081 __ add(IP, R2, Operand(R3, LSL, 2)); | 2088 __ add(IP, R2, Operand(R3, LSL, 2)); |
2082 __ ldr(R0, FieldAddress(IP, base + kWordSize)); | 2089 __ ldr(R0, FieldAddress(IP, base + kWordSize)); |
2083 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 2090 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2084 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2091 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2085 } | 2092 } |
2086 | 2093 |
2087 | 2094 |
2088 // Called from megamorphic calls. | |
2089 // R0: receiver | |
2090 // R9: MegamorphicCache (preserved) | |
2091 // Result: | |
2092 // R1: target entry point | |
2093 // CODE_REG: target Code | |
2094 // R4: arguments descriptor | |
2095 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2095 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2096 EmitMegamorphicLookup(assembler); | 2096 EmitMegamorphicLookup(assembler); |
2097 __ Ret(); | 2097 __ Ret(); |
2098 } | 2098 } |
2099 | 2099 |
2100 | 2100 |
2101 // Called from switchable IC calls. | 2101 // Called from switchable IC calls. |
2102 // R0: receiver | 2102 // R1: receiver |
2103 // R9: ICData (preserved) | 2103 // R9: ICData (preserved) |
2104 // Result: | 2104 // Result: |
2105 // R1: target entry point | 2105 // R1: target entry point |
2106 // CODE_REG: target Code object | 2106 // CODE_REG: target Code object |
2107 // R4: arguments descriptor | 2107 // R4: arguments descriptor |
2108 void StubCode::GenerateICLookupStub(Assembler* assembler) { | 2108 static void EmitICLookup(Assembler* assembler, |
| 2109 intptr_t args_checked, |
| 2110 Token::Kind kind) { |
| 2111 if (kind != Token::kILLEGAL) { |
| 2112 __ Comment("Fast Smi op"); |
| 2113 Label not_smi_or_overflow; |
| 2114 |
| 2115 // R1: receiver |
| 2116 __ ldr(R2, Address(SP, 0 * kWordSize)); |
| 2117 // R2: argument |
| 2118 __ orr(TMP, R1, Operand(R2)); |
| 2119 __ tst(TMP, Operand(kSmiTagMask)); |
| 2120 __ b(¬_smi_or_overflow, NE); |
| 2121 |
| 2122 switch (kind) { |
| 2123 case Token::kADD: { |
| 2124 __ adds(R0, R1, Operand(R2)); // Adds. |
| 2125 __ b(¬_smi_or_overflow, VS); // Branch if overflow. |
| 2126 break; |
| 2127 } |
| 2128 case Token::kSUB: { |
| 2129 __ subs(R0, R1, Operand(R2)); // Subtract. |
| 2130 __ b(¬_smi_or_overflow, VS); // Branch if overflow. |
| 2131 break; |
| 2132 } |
| 2133 case Token::kEQ: { |
| 2134 __ cmp(R1, Operand(R2)); |
| 2135 __ LoadObject(R0, Bool::True(), EQ); |
| 2136 __ LoadObject(R0, Bool::False(), NE); |
| 2137 break; |
| 2138 } |
| 2139 default: UNIMPLEMENTED(); |
| 2140 } |
| 2141 // Return past the call to lookup result. |
| 2142 __ add(LR, LR, Operand(Instr::kInstrSize)); |
| 2143 __ Ret(); |
| 2144 |
| 2145 __ Bind(¬_smi_or_overflow); |
| 2146 } |
| 2147 |
2109 Label loop, found, miss; | 2148 Label loop, found, miss; |
2110 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); | 2149 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
2111 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); | 2150 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
2112 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); | 2151 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); |
2113 // R8: first IC entry | 2152 // R8: first IC entry |
2114 __ LoadTaggedClassIdMayBeSmi(R1, R0); | 2153 __ LoadTaggedClassIdMayBeSmi(R0, R1); |
2115 // R1: receiver cid as Smi | 2154 // R0: receiver cid as Smi |
2116 | 2155 |
2117 __ Bind(&loop); | 2156 __ Bind(&loop); |
2118 __ ldr(R2, Address(R8, 0)); | 2157 __ ldr(R2, Address(R8, 0)); |
2119 __ cmp(R1, Operand(R2)); | 2158 __ cmp(R0, Operand(R2)); |
2120 __ b(&found, EQ); | 2159 __ b(&found, EQ); |
2121 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); | 2160 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
2122 __ b(&miss, EQ); | 2161 __ b(&miss, EQ); |
2123 | 2162 |
2124 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; | 2163 const intptr_t entry_length = |
| 2164 ICData::TestEntryLengthFor(args_checked) * kWordSize; |
2125 __ AddImmediate(R8, entry_length); // Next entry. | 2165 __ AddImmediate(R8, entry_length); // Next entry. |
2126 __ b(&loop); | 2166 __ b(&loop); |
2127 | 2167 |
2128 __ Bind(&found); | 2168 __ Bind(&found); |
2129 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; | 2169 const intptr_t target_offset = |
| 2170 ICData::TargetIndexFor(args_checked) * kWordSize; |
2130 __ LoadFromOffset(kWord, R0, R8, target_offset); | 2171 __ LoadFromOffset(kWord, R0, R8, target_offset); |
2131 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 2172 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2132 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2173 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2133 __ Ret(); | 2174 __ Ret(); |
2134 | 2175 |
2135 __ Bind(&miss); | 2176 __ Bind(&miss); |
2136 __ LoadIsolate(R2); | 2177 __ LoadIsolate(R2); |
2137 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); | 2178 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
2138 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2179 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
2139 __ Ret(); | 2180 __ Ret(); |
2140 } | 2181 } |
2141 | 2182 |
| 2183 |
| 2184 void StubCode::GenerateICLookupStub(Assembler* assembler) { |
| 2185 EmitICLookup(assembler, 1, Token::kILLEGAL); |
| 2186 } |
| 2187 |
| 2188 |
| 2189 void StubCode::GenerateICSmiAddLookupStub(Assembler* assembler) { |
| 2190 EmitICLookup(assembler, 2, Token::kADD); |
| 2191 } |
| 2192 |
| 2193 |
| 2194 void StubCode::GenerateICSmiSubLookupStub(Assembler* assembler) { |
| 2195 EmitICLookup(assembler, 2, Token::kSUB); |
| 2196 } |
| 2197 |
| 2198 |
| 2199 void StubCode::GenerateICSmiEqualLookupStub(Assembler* assembler) { |
| 2200 EmitICLookup(assembler, 2, Token::kEQ); |
| 2201 } |
| 2202 |
2142 } // namespace dart | 2203 } // namespace dart |
2143 | 2204 |
2144 #endif // defined TARGET_ARCH_ARM | 2205 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |