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" // Needed here to get TARGET_ARCH_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
9 | 9 |
10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 __ b(&fall_through, NE); \ | 190 __ b(&fall_through, NE); \ |
191 __ CompareRegisters(R2, ZR); \ | 191 __ CompareRegisters(R2, ZR); \ |
192 __ b(&fall_through, LT); \ | 192 __ b(&fall_through, LT); \ |
193 __ SmiUntag(R2); \ | 193 __ SmiUntag(R2); \ |
194 /* Check for maximum allowed length. */ \ | 194 /* Check for maximum allowed length. */ \ |
195 /* R2: untagged array length. */ \ | 195 /* R2: untagged array length. */ \ |
196 __ CompareImmediate(R2, max_len); \ | 196 __ CompareImmediate(R2, max_len); \ |
197 __ b(&fall_through, GT); \ | 197 __ b(&fall_through, GT); \ |
198 __ LslImmediate(R2, R2, scale_shift); \ | 198 __ LslImmediate(R2, R2, scale_shift); \ |
199 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ | 199 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ |
200 __ AddImmediate(R2, R2, fixed_size); \ | 200 __ AddImmediate(R2, fixed_size); \ |
201 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \ | 201 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \ |
202 Heap::Space space = Heap::kNew; \ | 202 Heap::Space space = Heap::kNew; \ |
203 __ ldr(R3, Address(THR, Thread::heap_offset())); \ | 203 __ ldr(R3, Address(THR, Thread::heap_offset())); \ |
204 __ ldr(R0, Address(R3, Heap::TopOffset(space))); \ | 204 __ ldr(R0, Address(R3, Heap::TopOffset(space))); \ |
205 \ | 205 \ |
206 /* R2: allocation size. */ \ | 206 /* R2: allocation size. */ \ |
207 __ adds(R1, R0, Operand(R2)); \ | 207 __ adds(R1, R0, Operand(R2)); \ |
208 __ b(&fall_through, CS); /* Fail on unsigned overflow. */ \ | 208 __ b(&fall_through, CS); /* Fail on unsigned overflow. */ \ |
209 \ | 209 \ |
210 /* Check if the allocation fits into the remaining space. */ \ | 210 /* Check if the allocation fits into the remaining space. */ \ |
211 /* R0: potential new object start. */ \ | 211 /* R0: potential new object start. */ \ |
212 /* R1: potential next object start. */ \ | 212 /* R1: potential next object start. */ \ |
213 /* R2: allocation size. */ \ | 213 /* R2: allocation size. */ \ |
214 /* R3: heap. */ \ | 214 /* R3: heap. */ \ |
215 __ ldr(R6, Address(R3, Heap::EndOffset(space))); \ | 215 __ ldr(R6, Address(R3, Heap::EndOffset(space))); \ |
216 __ cmp(R1, Operand(R6)); \ | 216 __ cmp(R1, Operand(R6)); \ |
217 __ b(&fall_through, CS); \ | 217 __ b(&fall_through, CS); \ |
218 \ | 218 \ |
219 /* Successfully allocated the object(s), now update top to point to */ \ | 219 /* Successfully allocated the object(s), now update top to point to */ \ |
220 /* next object start and initialize the object. */ \ | 220 /* next object start and initialize the object. */ \ |
221 __ str(R1, Address(R3, Heap::TopOffset(space))); \ | 221 __ str(R1, Address(R3, Heap::TopOffset(space))); \ |
222 __ AddImmediate(R0, R0, kHeapObjectTag); \ | 222 __ AddImmediate(R0, kHeapObjectTag); \ |
223 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2, space)); \ | 223 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2, space)); \ |
224 /* Initialize the tags. */ \ | 224 /* Initialize the tags. */ \ |
225 /* R0: new object start as a tagged pointer. */ \ | 225 /* R0: new object start as a tagged pointer. */ \ |
226 /* R1: new object end address. */ \ | 226 /* R1: new object end address. */ \ |
227 /* R2: allocation size. */ \ | 227 /* R2: allocation size. */ \ |
228 { \ | 228 { \ |
229 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); \ | 229 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); \ |
230 __ LslImmediate(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2); \ | 230 __ LslImmediate(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2); \ |
231 __ csel(R2, ZR, R2, HI); \ | 231 __ csel(R2, ZR, R2, HI); \ |
232 \ | 232 \ |
(...skipping 1616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1849 // if (start < 0) return false; | 1849 // if (start < 0) return false; |
1850 __ cmp(R1, Operand(0)); | 1850 __ cmp(R1, Operand(0)); |
1851 __ b(return_false, LT); | 1851 __ b(return_false, LT); |
1852 | 1852 |
1853 // if (start + other.length > this.length) return false; | 1853 // if (start + other.length > this.length) return false; |
1854 __ add(R3, R1, Operand(R9)); | 1854 __ add(R3, R1, Operand(R9)); |
1855 __ cmp(R3, Operand(R8)); | 1855 __ cmp(R3, Operand(R8)); |
1856 __ b(return_false, GT); | 1856 __ b(return_false, GT); |
1857 | 1857 |
1858 if (receiver_cid == kOneByteStringCid) { | 1858 if (receiver_cid == kOneByteStringCid) { |
1859 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag); | 1859 __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag); |
1860 __ add(R0, R0, Operand(R1)); | 1860 __ add(R0, R0, Operand(R1)); |
1861 } else { | 1861 } else { |
1862 ASSERT(receiver_cid == kTwoByteStringCid); | 1862 ASSERT(receiver_cid == kTwoByteStringCid); |
1863 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); | 1863 __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag); |
1864 __ add(R0, R0, Operand(R1)); | 1864 __ add(R0, R0, Operand(R1)); |
1865 __ add(R0, R0, Operand(R1)); | 1865 __ add(R0, R0, Operand(R1)); |
1866 } | 1866 } |
1867 if (other_cid == kOneByteStringCid) { | 1867 if (other_cid == kOneByteStringCid) { |
1868 __ AddImmediate(R2, R2, OneByteString::data_offset() - kHeapObjectTag); | 1868 __ AddImmediate(R2, OneByteString::data_offset() - kHeapObjectTag); |
1869 } else { | 1869 } else { |
1870 ASSERT(other_cid == kTwoByteStringCid); | 1870 ASSERT(other_cid == kTwoByteStringCid); |
1871 __ AddImmediate(R2, R2, TwoByteString::data_offset() - kHeapObjectTag); | 1871 __ AddImmediate(R2, TwoByteString::data_offset() - kHeapObjectTag); |
1872 } | 1872 } |
1873 | 1873 |
1874 // i = 0 | 1874 // i = 0 |
1875 __ LoadImmediate(R3, 0); | 1875 __ LoadImmediate(R3, 0); |
1876 | 1876 |
1877 // do | 1877 // do |
1878 Label loop; | 1878 Label loop; |
1879 __ Bind(&loop); | 1879 __ Bind(&loop); |
1880 | 1880 |
1881 // this.codeUnitAt(i + start) | 1881 // this.codeUnitAt(i + start) |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1948 __ tsti(R1, Immediate(kSmiTagMask)); | 1948 __ tsti(R1, Immediate(kSmiTagMask)); |
1949 __ b(&fall_through, NE); // Index is not a Smi. | 1949 __ b(&fall_through, NE); // Index is not a Smi. |
1950 // Range check. | 1950 // Range check. |
1951 __ ldr(R2, FieldAddress(R0, String::length_offset())); | 1951 __ ldr(R2, FieldAddress(R0, String::length_offset())); |
1952 __ cmp(R1, Operand(R2)); | 1952 __ cmp(R1, Operand(R2)); |
1953 __ b(&fall_through, CS); // Runtime throws exception. | 1953 __ b(&fall_through, CS); // Runtime throws exception. |
1954 | 1954 |
1955 __ CompareClassId(R0, kOneByteStringCid); | 1955 __ CompareClassId(R0, kOneByteStringCid); |
1956 __ b(&try_two_byte_string, NE); | 1956 __ b(&try_two_byte_string, NE); |
1957 __ SmiUntag(R1); | 1957 __ SmiUntag(R1); |
1958 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag); | 1958 __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag); |
1959 __ ldr(R1, Address(R0, R1), kUnsignedByte); | 1959 __ ldr(R1, Address(R0, R1), kUnsignedByte); |
1960 __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols); | 1960 __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols); |
1961 __ b(&fall_through, GE); | 1961 __ b(&fall_through, GE); |
1962 __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset())); | 1962 __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset())); |
1963 __ AddImmediate(R0, R0, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1963 __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
1964 __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled)); | 1964 __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled)); |
1965 __ ret(); | 1965 __ ret(); |
1966 | 1966 |
1967 __ Bind(&try_two_byte_string); | 1967 __ Bind(&try_two_byte_string); |
1968 __ CompareClassId(R0, kTwoByteStringCid); | 1968 __ CompareClassId(R0, kTwoByteStringCid); |
1969 __ b(&fall_through, NE); | 1969 __ b(&fall_through, NE); |
1970 ASSERT(kSmiTagShift == 1); | 1970 ASSERT(kSmiTagShift == 1); |
1971 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag); | 1971 __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag); |
1972 __ ldr(R1, Address(R0, R1), kUnsignedHalfword); | 1972 __ ldr(R1, Address(R0, R1), kUnsignedHalfword); |
1973 __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols); | 1973 __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols); |
1974 __ b(&fall_through, GE); | 1974 __ b(&fall_through, GE); |
1975 __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset())); | 1975 __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset())); |
1976 __ AddImmediate(R0, R0, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1976 __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
1977 __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled)); | 1977 __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled)); |
1978 __ ret(); | 1978 __ ret(); |
1979 | 1979 |
1980 __ Bind(&fall_through); | 1980 __ Bind(&fall_through); |
1981 } | 1981 } |
1982 | 1982 |
1983 | 1983 |
1984 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { | 1984 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) { |
1985 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1985 __ ldr(R0, Address(SP, 0 * kWordSize)); |
1986 __ ldr(R0, FieldAddress(R0, String::length_offset())); | 1986 __ ldr(R0, FieldAddress(R0, String::length_offset())); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2059 static void TryAllocateOnebyteString(Assembler* assembler, | 2059 static void TryAllocateOnebyteString(Assembler* assembler, |
2060 Label* ok, | 2060 Label* ok, |
2061 Label* failure) { | 2061 Label* failure) { |
2062 const Register length_reg = R2; | 2062 const Register length_reg = R2; |
2063 Label fail; | 2063 Label fail; |
2064 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure)); | 2064 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure)); |
2065 __ mov(R6, length_reg); // Save the length register. | 2065 __ mov(R6, length_reg); // Save the length register. |
2066 // TODO(koda): Protect against negative length and overflow here. | 2066 // TODO(koda): Protect against negative length and overflow here. |
2067 __ SmiUntag(length_reg); | 2067 __ SmiUntag(length_reg); |
2068 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 2068 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; |
2069 __ AddImmediate(length_reg, length_reg, fixed_size); | 2069 __ AddImmediate(length_reg, fixed_size); |
2070 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1))); | 2070 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1))); |
2071 | 2071 |
2072 const intptr_t cid = kOneByteStringCid; | 2072 const intptr_t cid = kOneByteStringCid; |
2073 Heap::Space space = Heap::kNew; | 2073 Heap::Space space = Heap::kNew; |
2074 __ ldr(R3, Address(THR, Thread::heap_offset())); | 2074 __ ldr(R3, Address(THR, Thread::heap_offset())); |
2075 __ ldr(R0, Address(R3, Heap::TopOffset(space))); | 2075 __ ldr(R0, Address(R3, Heap::TopOffset(space))); |
2076 | 2076 |
2077 // length_reg: allocation size. | 2077 // length_reg: allocation size. |
2078 __ adds(R1, R0, Operand(length_reg)); | 2078 __ adds(R1, R0, Operand(length_reg)); |
2079 __ b(&fail, CS); // Fail on unsigned overflow. | 2079 __ b(&fail, CS); // Fail on unsigned overflow. |
2080 | 2080 |
2081 // Check if the allocation fits into the remaining space. | 2081 // Check if the allocation fits into the remaining space. |
2082 // R0: potential new object start. | 2082 // R0: potential new object start. |
2083 // R1: potential next object start. | 2083 // R1: potential next object start. |
2084 // R2: allocation size. | 2084 // R2: allocation size. |
2085 // R3: heap. | 2085 // R3: heap. |
2086 __ ldr(R7, Address(R3, Heap::EndOffset(space))); | 2086 __ ldr(R7, Address(R3, Heap::EndOffset(space))); |
2087 __ cmp(R1, Operand(R7)); | 2087 __ cmp(R1, Operand(R7)); |
2088 __ b(&fail, CS); | 2088 __ b(&fail, CS); |
2089 | 2089 |
2090 // Successfully allocated the object(s), now update top to point to | 2090 // Successfully allocated the object(s), now update top to point to |
2091 // next object start and initialize the object. | 2091 // next object start and initialize the object. |
2092 __ str(R1, Address(R3, Heap::TopOffset(space))); | 2092 __ str(R1, Address(R3, Heap::TopOffset(space))); |
2093 __ AddImmediate(R0, R0, kHeapObjectTag); | 2093 __ AddImmediate(R0, kHeapObjectTag); |
2094 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2, space)); | 2094 NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2, space)); |
2095 | 2095 |
2096 // Initialize the tags. | 2096 // Initialize the tags. |
2097 // R0: new object start as a tagged pointer. | 2097 // R0: new object start as a tagged pointer. |
2098 // R1: new object end address. | 2098 // R1: new object end address. |
2099 // R2: allocation size. | 2099 // R2: allocation size. |
2100 { | 2100 { |
2101 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; | 2101 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; |
2102 | 2102 |
2103 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); | 2103 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2143 __ sub(R2, R2, Operand(TMP)); | 2143 __ sub(R2, R2, Operand(TMP)); |
2144 TryAllocateOnebyteString(assembler, &ok, &fall_through); | 2144 TryAllocateOnebyteString(assembler, &ok, &fall_through); |
2145 __ Bind(&ok); | 2145 __ Bind(&ok); |
2146 // R0: new string as tagged pointer. | 2146 // R0: new string as tagged pointer. |
2147 // Copy string. | 2147 // Copy string. |
2148 __ ldr(R3, Address(SP, kStringOffset)); | 2148 __ ldr(R3, Address(SP, kStringOffset)); |
2149 __ ldr(R1, Address(SP, kStartIndexOffset)); | 2149 __ ldr(R1, Address(SP, kStartIndexOffset)); |
2150 __ SmiUntag(R1); | 2150 __ SmiUntag(R1); |
2151 __ add(R3, R3, Operand(R1)); | 2151 __ add(R3, R3, Operand(R1)); |
2152 // Calculate start address and untag (- 1). | 2152 // Calculate start address and untag (- 1). |
2153 __ AddImmediate(R3, R3, OneByteString::data_offset() - 1); | 2153 __ AddImmediate(R3, OneByteString::data_offset() - 1); |
2154 | 2154 |
2155 // R3: Start address to copy from (untagged). | 2155 // R3: Start address to copy from (untagged). |
2156 // R1: Untagged start index. | 2156 // R1: Untagged start index. |
2157 __ ldr(R2, Address(SP, kEndIndexOffset)); | 2157 __ ldr(R2, Address(SP, kEndIndexOffset)); |
2158 __ SmiUntag(R2); | 2158 __ SmiUntag(R2); |
2159 __ sub(R2, R2, Operand(R1)); | 2159 __ sub(R2, R2, Operand(R1)); |
2160 | 2160 |
2161 // R3: Start address to copy from (untagged). | 2161 // R3: Start address to copy from (untagged). |
2162 // R2: Untagged number of bytes to copy. | 2162 // R2: Untagged number of bytes to copy. |
2163 // R0: Tagged result string. | 2163 // R0: Tagged result string. |
2164 // R6: Pointer into R3. | 2164 // R6: Pointer into R3. |
2165 // R7: Pointer into R0. | 2165 // R7: Pointer into R0. |
2166 // R1: Scratch register. | 2166 // R1: Scratch register. |
2167 Label loop, done; | 2167 Label loop, done; |
2168 __ cmp(R2, Operand(0)); | 2168 __ cmp(R2, Operand(0)); |
2169 __ b(&done, LE); | 2169 __ b(&done, LE); |
2170 __ mov(R6, R3); | 2170 __ mov(R6, R3); |
2171 __ mov(R7, R0); | 2171 __ mov(R7, R0); |
2172 __ Bind(&loop); | 2172 __ Bind(&loop); |
2173 __ ldr(R1, Address(R6), kUnsignedByte); | 2173 __ ldr(R1, Address(R6), kUnsignedByte); |
2174 __ AddImmediate(R6, R6, 1); | 2174 __ AddImmediate(R6, 1); |
2175 __ sub(R2, R2, Operand(1)); | 2175 __ sub(R2, R2, Operand(1)); |
2176 __ cmp(R2, Operand(0)); | 2176 __ cmp(R2, Operand(0)); |
2177 __ str(R1, FieldAddress(R7, OneByteString::data_offset()), kUnsignedByte); | 2177 __ str(R1, FieldAddress(R7, OneByteString::data_offset()), kUnsignedByte); |
2178 __ AddImmediate(R7, R7, 1); | 2178 __ AddImmediate(R7, 1); |
2179 __ b(&loop, GT); | 2179 __ b(&loop, GT); |
2180 | 2180 |
2181 __ Bind(&done); | 2181 __ Bind(&done); |
2182 __ ret(); | 2182 __ ret(); |
2183 __ Bind(&fall_through); | 2183 __ Bind(&fall_through); |
2184 } | 2184 } |
2185 | 2185 |
2186 | 2186 |
2187 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) { | 2187 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) { |
2188 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. | 2188 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 __ cmp(R2, Operand(R3)); | 2231 __ cmp(R2, Operand(R3)); |
2232 __ b(&is_false, NE); | 2232 __ b(&is_false, NE); |
2233 | 2233 |
2234 // Check contents, no fall-through possible. | 2234 // Check contents, no fall-through possible. |
2235 // TODO(zra): try out other sequences. | 2235 // TODO(zra): try out other sequences. |
2236 ASSERT((string_cid == kOneByteStringCid) || | 2236 ASSERT((string_cid == kOneByteStringCid) || |
2237 (string_cid == kTwoByteStringCid)); | 2237 (string_cid == kTwoByteStringCid)); |
2238 const intptr_t offset = (string_cid == kOneByteStringCid) | 2238 const intptr_t offset = (string_cid == kOneByteStringCid) |
2239 ? OneByteString::data_offset() | 2239 ? OneByteString::data_offset() |
2240 : TwoByteString::data_offset(); | 2240 : TwoByteString::data_offset(); |
2241 __ AddImmediate(R0, R0, offset - kHeapObjectTag); | 2241 __ AddImmediate(R0, offset - kHeapObjectTag); |
2242 __ AddImmediate(R1, R1, offset - kHeapObjectTag); | 2242 __ AddImmediate(R1, offset - kHeapObjectTag); |
2243 __ SmiUntag(R2); | 2243 __ SmiUntag(R2); |
2244 __ Bind(&loop); | 2244 __ Bind(&loop); |
2245 __ AddImmediate(R2, R2, -1); | 2245 __ AddImmediate(R2, -1); |
2246 __ CompareRegisters(R2, ZR); | 2246 __ CompareRegisters(R2, ZR); |
2247 __ b(&is_true, LT); | 2247 __ b(&is_true, LT); |
2248 if (string_cid == kOneByteStringCid) { | 2248 if (string_cid == kOneByteStringCid) { |
2249 __ ldr(R3, Address(R0), kUnsignedByte); | 2249 __ ldr(R3, Address(R0), kUnsignedByte); |
2250 __ ldr(R4, Address(R1), kUnsignedByte); | 2250 __ ldr(R4, Address(R1), kUnsignedByte); |
2251 __ AddImmediate(R0, R0, 1); | 2251 __ AddImmediate(R0, 1); |
2252 __ AddImmediate(R1, R1, 1); | 2252 __ AddImmediate(R1, 1); |
2253 } else if (string_cid == kTwoByteStringCid) { | 2253 } else if (string_cid == kTwoByteStringCid) { |
2254 __ ldr(R3, Address(R0), kUnsignedHalfword); | 2254 __ ldr(R3, Address(R0), kUnsignedHalfword); |
2255 __ ldr(R4, Address(R1), kUnsignedHalfword); | 2255 __ ldr(R4, Address(R1), kUnsignedHalfword); |
2256 __ AddImmediate(R0, R0, 2); | 2256 __ AddImmediate(R0, 2); |
2257 __ AddImmediate(R1, R1, 2); | 2257 __ AddImmediate(R1, 2); |
2258 } else { | 2258 } else { |
2259 UNIMPLEMENTED(); | 2259 UNIMPLEMENTED(); |
2260 } | 2260 } |
2261 __ cmp(R3, Operand(R4)); | 2261 __ cmp(R3, Operand(R4)); |
2262 __ b(&is_false, NE); | 2262 __ b(&is_false, NE); |
2263 __ b(&loop); | 2263 __ b(&loop); |
2264 | 2264 |
2265 __ Bind(&is_true); | 2265 __ Bind(&is_true); |
2266 __ LoadObject(R0, Bool::True()); | 2266 __ LoadObject(R0, Bool::True()); |
2267 __ ret(); | 2267 __ ret(); |
(...skipping 27 matching lines...) Expand all Loading... |
2295 // Incoming registers: | 2295 // Incoming registers: |
2296 // R0: Function. (Will be reloaded with the specialized matcher function.) | 2296 // R0: Function. (Will be reloaded with the specialized matcher function.) |
2297 // R4: Arguments descriptor. (Will be preserved.) | 2297 // R4: Arguments descriptor. (Will be preserved.) |
2298 // R5: Unknown. (Must be GC safe on tail call.) | 2298 // R5: Unknown. (Must be GC safe on tail call.) |
2299 | 2299 |
2300 // Load the specialized function pointer into R0. Leverage the fact the | 2300 // Load the specialized function pointer into R0. Leverage the fact the |
2301 // string CIDs as well as stored function pointers are in sequence. | 2301 // string CIDs as well as stored function pointers are in sequence. |
2302 __ ldr(R2, Address(SP, kRegExpParamOffset)); | 2302 __ ldr(R2, Address(SP, kRegExpParamOffset)); |
2303 __ ldr(R1, Address(SP, kStringParamOffset)); | 2303 __ ldr(R1, Address(SP, kStringParamOffset)); |
2304 __ LoadClassId(R1, R1); | 2304 __ LoadClassId(R1, R1); |
2305 __ AddImmediate(R1, R1, -kOneByteStringCid); | 2305 __ AddImmediate(R1, -kOneByteStringCid); |
2306 __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2)); | 2306 __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2)); |
2307 __ ldr(R0, | 2307 __ ldr(R0, |
2308 FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky))); | 2308 FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky))); |
2309 | 2309 |
2310 // Registers are now set up for the lazy compile stub. It expects the function | 2310 // Registers are now set up for the lazy compile stub. It expects the function |
2311 // in R0, the argument descriptor in R4, and IC-Data in R5. | 2311 // in R0, the argument descriptor in R4, and IC-Data in R5. |
2312 __ eor(R5, R5, Operand(R5)); | 2312 __ eor(R5, R5, Operand(R5)); |
2313 | 2313 |
2314 // Tail-call the function. | 2314 // Tail-call the function. |
2315 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2315 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2377 | 2377 |
2378 void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler) { | 2378 void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler) { |
2379 __ ldr(R0, Address(THR, Thread::async_stack_trace_offset())); | 2379 __ ldr(R0, Address(THR, Thread::async_stack_trace_offset())); |
2380 __ LoadObject(R0, Object::null_object()); | 2380 __ LoadObject(R0, Object::null_object()); |
2381 __ ret(); | 2381 __ ret(); |
2382 } | 2382 } |
2383 | 2383 |
2384 } // namespace dart | 2384 } // namespace dart |
2385 | 2385 |
2386 #endif // defined TARGET_ARCH_ARM64 | 2386 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |