Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: runtime/vm/intrinsifier_arm64.cc

Issue 468793004: VM: Improve performance of method recognizer and unify the it with the intrinsifier. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/symbols.h" 14 #include "vm/symbols.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 DECLARE_FLAG(bool, enable_type_checks); 18 DECLARE_FLAG(bool, enable_type_checks);
19 19
20 #define __ assembler-> 20 #define __ assembler->
21 21
22 22
23 void Intrinsifier::Array_getLength(Assembler* assembler) { 23 void Intrinsifier::ObjectArrayLength(Assembler* assembler) {
24 __ ldr(R0, Address(SP, 0 * kWordSize)); 24 __ ldr(R0, Address(SP, 0 * kWordSize));
25 __ ldr(R0, FieldAddress(R0, Array::length_offset())); 25 __ ldr(R0, FieldAddress(R0, Array::length_offset()));
26 __ ret(); 26 __ ret();
27 } 27 }
28 28
29 29
30 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { 30 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) {
31 Array_getLength(assembler); 31 ObjectArrayLength(assembler);
32 } 32 }
33 33
34 34
35 void Intrinsifier::Array_getIndexed(Assembler* assembler) { 35 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) {
36 Label fall_through; 36 Label fall_through;
37 37
38 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index 38 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
39 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array 39 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
40 40
41 __ tsti(R0, kSmiTagMask); 41 __ tsti(R0, kSmiTagMask);
42 __ b(&fall_through, NE); // Index is not an smi, fall through. 42 __ b(&fall_through, NE); // Index is not an smi, fall through.
43 43
44 // Range check. 44 // Range check.
45 __ ldr(R6, FieldAddress(R1, Array::length_offset())); 45 __ ldr(R6, FieldAddress(R1, Array::length_offset()));
46 __ cmp(R0, Operand(R6)); 46 __ cmp(R0, Operand(R6));
47 __ b(&fall_through, CS); 47 __ b(&fall_through, CS);
48 48
49 ASSERT(kSmiTagShift == 1); 49 ASSERT(kSmiTagShift == 1);
50 // array element at R1 + R0*4 + Array::data_offset - 1 50 // array element at R1 + R0*4 + Array::data_offset - 1
51 __ add(R6, R1, Operand(R0, LSL, 2)); 51 __ add(R6, R1, Operand(R0, LSL, 2));
52 __ ldr(R0, FieldAddress(R6, Array::data_offset())); 52 __ ldr(R0, FieldAddress(R6, Array::data_offset()));
53 __ ret(); 53 __ ret();
54 __ Bind(&fall_through); 54 __ Bind(&fall_through);
55 } 55 }
56 56
57 57
58 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { 58 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) {
59 Array_getIndexed(assembler); 59 ObjectArrayGetIndexed(assembler);
60 } 60 }
61 61
62 62
63 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { 63 static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
64 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 64 const Library& core_lib = Library::Handle(Library::CoreLibrary());
65 const Class& cls = Class::Handle( 65 const Class& cls = Class::Handle(
66 core_lib.LookupClassAllowPrivate(Symbols::_List())); 66 core_lib.LookupClassAllowPrivate(Symbols::_List()));
67 ASSERT(!cls.IsNull()); 67 ASSERT(!cls.IsNull());
68 ASSERT(cls.NumTypeArguments() == 1); 68 ASSERT(cls.NumTypeArguments() == 1);
69 const intptr_t field_offset = cls.type_arguments_field_offset(); 69 const intptr_t field_offset = cls.type_arguments_field_offset();
70 ASSERT(field_offset != Class::kNoTypeArguments); 70 ASSERT(field_offset != Class::kNoTypeArguments);
71 return field_offset; 71 return field_offset;
72 } 72 }
73 73
74 74
75 // Intrinsify only for Smi value and index. Non-smi values need a store buffer 75 // Intrinsify only for Smi value and index. Non-smi values need a store buffer
76 // update. Array length is always a Smi. 76 // update. Array length is always a Smi.
77 void Intrinsifier::Array_setIndexed(Assembler* assembler) { 77 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
78 Label fall_through; 78 Label fall_through;
79 79
80 if (FLAG_enable_type_checks) { 80 if (FLAG_enable_type_checks) {
81 const intptr_t type_args_field_offset = 81 const intptr_t type_args_field_offset =
82 ComputeObjectArrayTypeArgumentsOffset(); 82 ComputeObjectArrayTypeArgumentsOffset();
83 // Inline simple tests (Smi, null), fallthrough if not positive. 83 // Inline simple tests (Smi, null), fallthrough if not positive.
84 Label checked_ok; 84 Label checked_ok;
85 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 85 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
86 86
87 // Null value is valid for any type. 87 // Null value is valid for any type.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 FieldAddress(R1, Array::data_offset()), 130 FieldAddress(R1, Array::data_offset()),
131 R2); 131 R2);
132 // Caller is responsible for preserving the value if necessary. 132 // Caller is responsible for preserving the value if necessary.
133 __ ret(); 133 __ ret();
134 __ Bind(&fall_through); 134 __ Bind(&fall_through);
135 } 135 }
136 136
137 137
138 // Allocate a GrowableObjectArray using the backing array specified. 138 // Allocate a GrowableObjectArray using the backing array specified.
139 // On stack: type argument (+1), data (+0). 139 // On stack: type argument (+1), data (+0).
140 void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { 140 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
141 // The newly allocated object is returned in R0. 141 // The newly allocated object is returned in R0.
142 const intptr_t kTypeArgumentsOffset = 1 * kWordSize; 142 const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
143 const intptr_t kArrayOffset = 0 * kWordSize; 143 const intptr_t kArrayOffset = 0 * kWordSize;
144 Label fall_through; 144 Label fall_through;
145 145
146 // Try allocating in new space. 146 // Try allocating in new space.
147 const Class& cls = Class::Handle( 147 const Class& cls = Class::Handle(
148 Isolate::Current()->object_store()->growable_object_array_class()); 148 Isolate::Current()->object_store()->growable_object_array_class());
149 __ TryAllocate(cls, &fall_through, R0, R1, kNoPP); 149 __ TryAllocate(cls, &fall_through, R0, R1, kNoPP);
150 150
(...skipping 15 matching lines...) Expand all
166 166
167 // Set the length field in the growable array object to 0. 167 // Set the length field in the growable array object to 0.
168 __ LoadImmediate(R1, 0, kNoPP); 168 __ LoadImmediate(R1, 0, kNoPP);
169 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 169 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
170 __ ret(); // Returns the newly allocated object in R0. 170 __ ret(); // Returns the newly allocated object in R0.
171 171
172 __ Bind(&fall_through); 172 __ Bind(&fall_through);
173 } 173 }
174 174
175 175
176 void Intrinsifier::GrowableList_getLength(Assembler* assembler) { 176 void Intrinsifier::GrowableArrayLength(Assembler* assembler) {
177 __ ldr(R0, Address(SP, 0 * kWordSize)); 177 __ ldr(R0, Address(SP, 0 * kWordSize));
178 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); 178 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset()));
179 __ ret(); 179 __ ret();
180 } 180 }
181 181
182 182
183 void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { 183 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) {
184 __ ldr(R0, Address(SP, 0 * kWordSize)); 184 __ ldr(R0, Address(SP, 0 * kWordSize));
185 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); 185 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset()));
186 __ ldr(R0, FieldAddress(R0, Array::length_offset())); 186 __ ldr(R0, FieldAddress(R0, Array::length_offset()));
187 __ ret(); 187 __ ret();
188 } 188 }
189 189
190 190
191 void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { 191 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
192 Label fall_through; 192 Label fall_through;
193 193
194 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index 194 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
195 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array 195 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
196 196
197 __ tsti(R0, kSmiTagMask); 197 __ tsti(R0, kSmiTagMask);
198 __ b(&fall_through, NE); // Index is not an smi, fall through. 198 __ b(&fall_through, NE); // Index is not an smi, fall through.
199 199
200 // Range check. 200 // Range check.
201 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset())); 201 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
202 __ cmp(R0, Operand(R6)); 202 __ cmp(R0, Operand(R6));
203 __ b(&fall_through, CS); 203 __ b(&fall_through, CS);
204 204
205 ASSERT(kSmiTagShift == 1); 205 ASSERT(kSmiTagShift == 1);
206 // array element at R6 + R0 * 4 + Array::data_offset - 1 206 // array element at R6 + R0 * 4 + Array::data_offset - 1
207 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset())); // Data 207 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset())); // Data
208 __ add(R6, R6, Operand(R0, LSL, 2)); 208 __ add(R6, R6, Operand(R0, LSL, 2));
209 __ ldr(R0, FieldAddress(R6, Array::data_offset())); 209 __ ldr(R0, FieldAddress(R6, Array::data_offset()));
210 __ ret(); 210 __ ret();
211 __ Bind(&fall_through); 211 __ Bind(&fall_through);
212 } 212 }
213 213
214 214
215 // Set value into growable object array at specified index. 215 // Set value into growable object array at specified index.
216 // On stack: growable array (+2), index (+1), value (+0). 216 // On stack: growable array (+2), index (+1), value (+0).
217 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { 217 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
218 if (FLAG_enable_type_checks) { 218 if (FLAG_enable_type_checks) {
219 return; 219 return;
220 } 220 }
221 Label fall_through; 221 Label fall_through;
222 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 222 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
223 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray. 223 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray.
224 __ tsti(R1, kSmiTagMask); 224 __ tsti(R1, kSmiTagMask);
225 __ b(&fall_through, NE); // Non-smi index. 225 __ b(&fall_through, NE); // Non-smi index.
226 // Range check using _length field. 226 // Range check using _length field.
227 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset())); 227 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
228 __ cmp(R1, Operand(R2)); 228 __ cmp(R1, Operand(R2));
229 // Runtime throws exception. 229 // Runtime throws exception.
230 __ b(&fall_through, CS); 230 __ b(&fall_through, CS);
231 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data. 231 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data.
232 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 232 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
233 // Note that R1 is Smi, i.e, times 2. 233 // Note that R1 is Smi, i.e, times 2.
234 ASSERT(kSmiTagShift == 1); 234 ASSERT(kSmiTagShift == 1);
235 __ add(R1, R0, Operand(R1, LSL, 2)); 235 __ add(R1, R0, Operand(R1, LSL, 2));
236 __ StoreIntoObject(R0, 236 __ StoreIntoObject(R0,
237 FieldAddress(R1, Array::data_offset()), 237 FieldAddress(R1, Array::data_offset()),
238 R2); 238 R2);
239 __ ret(); 239 __ ret();
240 __ Bind(&fall_through); 240 __ Bind(&fall_through);
241 } 241 }
242 242
243 243
244 // Set length of growable object array. The length cannot 244 // Set length of growable object array. The length cannot
245 // be greater than the length of the data container. 245 // be greater than the length of the data container.
246 // On stack: growable array (+1), length (+0). 246 // On stack: growable array (+1), length (+0).
247 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { 247 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
248 Label fall_through; 248 Label fall_through;
249 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 249 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
250 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value. 250 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value.
251 __ tsti(R1, kSmiTagMask); // Check for Smi. 251 __ tsti(R1, kSmiTagMask); // Check for Smi.
252 __ b(&fall_through, NE); 252 __ b(&fall_through, NE);
253 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 253 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
254 __ ret(); 254 __ ret();
255 __ Bind(&fall_through); 255 __ Bind(&fall_through);
256 // Fall through on non-Smi. 256 // Fall through on non-Smi.
257 } 257 }
258 258
259 259
260 // Set data of growable object array. 260 // Set data of growable object array.
261 // On stack: growable array (+1), data (+0). 261 // On stack: growable array (+1), data (+0).
262 void Intrinsifier::GrowableList_setData(Assembler* assembler) { 262 void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
263 if (FLAG_enable_type_checks) { 263 if (FLAG_enable_type_checks) {
264 return; 264 return;
265 } 265 }
266 Label fall_through; 266 Label fall_through;
267 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data. 267 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data.
268 // Check that data is an ObjectArray. 268 // Check that data is an ObjectArray.
269 __ tsti(R1, kSmiTagMask); 269 __ tsti(R1, kSmiTagMask);
270 __ b(&fall_through, EQ); // Data is Smi. 270 __ b(&fall_through, EQ); // Data is Smi.
271 __ CompareClassId(R1, kArrayCid, kNoPP); 271 __ CompareClassId(R1, kArrayCid, kNoPP);
272 __ b(&fall_through, NE); 272 __ b(&fall_through, NE);
273 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 273 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
274 __ StoreIntoObject(R0, 274 __ StoreIntoObject(R0,
275 FieldAddress(R0, GrowableObjectArray::data_offset()), 275 FieldAddress(R0, GrowableObjectArray::data_offset()),
276 R1); 276 R1);
277 __ ret(); 277 __ ret();
278 __ Bind(&fall_through); 278 __ Bind(&fall_through);
279 } 279 }
280 280
281 281
282 // Add an element to growable array if it doesn't need to grow, otherwise 282 // Add an element to growable array if it doesn't need to grow, otherwise
283 // call into regular code. 283 // call into regular code.
284 // On stack: growable array (+1), value (+0). 284 // On stack: growable array (+1), value (+0).
285 void Intrinsifier::GrowableList_add(Assembler* assembler) { 285 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
286 // In checked mode we need to type-check the incoming argument. 286 // In checked mode we need to type-check the incoming argument.
287 if (FLAG_enable_type_checks) { 287 if (FLAG_enable_type_checks) {
288 return; 288 return;
289 } 289 }
290 Label fall_through; 290 Label fall_through;
291 // R0: Array. 291 // R0: Array.
292 __ ldr(R0, Address(SP, 1 * kWordSize)); 292 __ ldr(R0, Address(SP, 1 * kWordSize));
293 // R1: length. 293 // R1: length.
294 __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 294 __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
295 // R2: data. 295 // R2: data.
(...skipping 13 matching lines...) Expand all
309 __ StoreIntoObject(R2, 309 __ StoreIntoObject(R2,
310 FieldAddress(R1, Array::data_offset()), 310 FieldAddress(R1, Array::data_offset()),
311 R0); 311 R0);
312 __ LoadObject(R0, Object::null_object(), PP); 312 __ LoadObject(R0, Object::null_object(), PP);
313 __ ret(); 313 __ ret();
314 __ Bind(&fall_through); 314 __ Bind(&fall_through);
315 } 315 }
316 316
317 317
318 // Gets the length of a TypedData. 318 // Gets the length of a TypedData.
319 void Intrinsifier::TypedData_getLength(Assembler* assembler) { 319 void Intrinsifier::TypedDataLength(Assembler* assembler) {
320 __ ldr(R0, Address(SP, 0 * kWordSize)); 320 __ ldr(R0, Address(SP, 0 * kWordSize));
321 __ ldr(R0, FieldAddress(R0, TypedData::length_offset())); 321 __ ldr(R0, FieldAddress(R0, TypedData::length_offset()));
322 __ ret(); 322 __ ret();
323 } 323 }
324 324
325 325
326 void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) { 326 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) {
327 Label fall_through; 327 Label fall_through;
328 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index. 328 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
329 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array. 329 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
330 __ tsti(R0, kSmiTagMask); 330 __ tsti(R0, kSmiTagMask);
331 __ b(&fall_through, NE); // Index is not a smi, fall through. 331 __ b(&fall_through, NE); // Index is not a smi, fall through.
332 332
333 // Range check. 333 // Range check.
334 __ ldr(R6, FieldAddress(R1, TypedData::length_offset())); 334 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
335 __ cmp(R0, Operand(R6)); 335 __ cmp(R0, Operand(R6));
336 __ b(&fall_through, CS); 336 __ b(&fall_through, CS);
337 337
338 // Array element at R1 + R0 + TypedData::data_offset - 1. 338 // Array element at R1 + R0 + TypedData::data_offset - 1.
339 // Untag R0. 339 // Untag R0.
340 __ add(R1, R1, Operand(R0, LSR, 1)); 340 __ add(R1, R1, Operand(R0, LSR, 1));
341 __ ldr(R0, FieldAddress(R1, TypedData::data_offset()), kUnsignedByte); 341 __ ldr(R0, FieldAddress(R1, TypedData::data_offset()), kUnsignedByte);
342 __ SmiTag(R0); 342 __ SmiTag(R0);
343 __ ret(); 343 __ ret();
344 __ Bind(&fall_through); 344 __ Bind(&fall_through);
345 } 345 }
346 346
347 347
348 void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) { 348 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) {
349 Label fall_through; 349 Label fall_through;
350 350
351 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index. 351 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
352 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array. 352 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
353 __ tsti(R0, kSmiTagMask); 353 __ tsti(R0, kSmiTagMask);
354 __ b(&fall_through, NE); // Index is not a smi, fall through. 354 __ b(&fall_through, NE); // Index is not a smi, fall through.
355 355
356 // Range check. 356 // Range check.
357 __ ldr(R6, FieldAddress(R1, TypedData::length_offset())); 357 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
358 __ cmp(R0, Operand(R6)); 358 __ cmp(R0, Operand(R6));
359 __ b(&fall_through, CS); 359 __ b(&fall_through, CS);
360 360
361 __ ldr(R1, FieldAddress(R1, ExternalTypedData::data_offset())); 361 __ ldr(R1, FieldAddress(R1, ExternalTypedData::data_offset()));
362 362
363 // Untag R0. 363 // Untag R0.
364 __ add(R1, R1, Operand(R0, LSR, 1)); 364 __ add(R1, R1, Operand(R0, LSR, 1));
365 __ ldr(R0, Address(R1, 0), kUnsignedByte); 365 __ ldr(R0, Address(R1, 0), kUnsignedByte);
366 __ SmiTag(R0); 366 __ SmiTag(R0);
367 __ ret(); 367 __ ret();
368 __ Bind(&fall_through); 368 __ Bind(&fall_through);
369 } 369 }
370 370
371 371
372 void Intrinsifier::Float64Array_getIndexed(Assembler* assembler) { 372 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) {
373 Label fall_through; 373 Label fall_through;
374 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index. 374 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
375 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array. 375 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
376 __ tsti(R0, kSmiTagMask); 376 __ tsti(R0, kSmiTagMask);
377 __ b(&fall_through, NE); // Index is not a smi, fall through. 377 __ b(&fall_through, NE); // Index is not a smi, fall through.
378 378
379 // Range check. 379 // Range check.
380 __ ldr(R6, FieldAddress(R1, TypedData::length_offset())); 380 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
381 __ cmp(R0, Operand(R6)); 381 __ cmp(R0, Operand(R6));
382 __ b(&fall_through, CS); 382 __ b(&fall_through, CS);
(...skipping 14 matching lines...) Expand all
397 &fall_through, 397 &fall_through,
398 R0, // Result register. 398 R0, // Result register.
399 R1, // Temp register. 399 R1, // Temp register.
400 kNoPP); 400 kNoPP);
401 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); 401 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
402 __ ret(); 402 __ ret();
403 __ Bind(&fall_through); 403 __ Bind(&fall_through);
404 } 404 }
405 405
406 406
407 void Intrinsifier::Float64Array_setIndexed(Assembler* assembler) { 407 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) {
408 Label fall_through; 408 Label fall_through;
409 __ ldr(R0, Address(SP, + 1 * kWordSize)); // Index. 409 __ ldr(R0, Address(SP, + 1 * kWordSize)); // Index.
410 __ ldr(R1, Address(SP, + 2 * kWordSize)); // Array. 410 __ ldr(R1, Address(SP, + 2 * kWordSize)); // Array.
411 __ tsti(R0, kSmiTagMask); 411 __ tsti(R0, kSmiTagMask);
412 __ b(&fall_through, NE); // Index is not a smi, fall through. 412 __ b(&fall_through, NE); // Index is not a smi, fall through.
413 413
414 // Range check. 414 // Range check.
415 __ ldr(R6, FieldAddress(R1, TypedData::length_offset())); 415 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
416 __ cmp(R0, Operand(R6)); 416 __ cmp(R0, Operand(R6));
417 __ b(&fall_through, CS); 417 __ b(&fall_through, CS);
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 __ Bind(&is_zero); 1146 __ Bind(&is_zero);
1147 // Check for negative zero by looking at the sign bit. 1147 // Check for negative zero by looking at the sign bit.
1148 __ fmovrd(R1, V0); 1148 __ fmovrd(R1, V0);
1149 __ Lsr(R1, R1, 63); 1149 __ Lsr(R1, R1, 63);
1150 __ tsti(R1, 1); 1150 __ tsti(R1, 1);
1151 __ csel(R0, true_reg, false_reg, NE); // Sign bit set. 1151 __ csel(R0, true_reg, false_reg, NE); // Sign bit set.
1152 __ ret(); 1152 __ ret();
1153 } 1153 }
1154 1154
1155 1155
1156 void Intrinsifier::Double_toInt(Assembler* assembler) { 1156 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
1157 Label fall_through; 1157 Label fall_through;
1158 1158
1159 __ ldr(R0, Address(SP, 0 * kWordSize)); 1159 __ ldr(R0, Address(SP, 0 * kWordSize));
1160 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); 1160 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
1161 1161
1162 // Explicit NaN check, since ARM gives an FPU exception if you try to 1162 // Explicit NaN check, since ARM gives an FPU exception if you try to
1163 // convert NaN to an int. 1163 // convert NaN to an int.
1164 __ fcmpd(V0, V0); 1164 __ fcmpd(V0, V0);
1165 __ b(&fall_through, VS); 1165 __ b(&fall_through, VS);
1166 1166
1167 __ fcvtzds(R0, V0); 1167 __ fcvtzds(R0, V0);
1168 // Overflow is signaled with minint. 1168 // Overflow is signaled with minint.
1169 // Check for overflow and that it fits into Smi. 1169 // Check for overflow and that it fits into Smi.
1170 __ CompareImmediate(R0, 0xC000000000000000, kNoPP); 1170 __ CompareImmediate(R0, 0xC000000000000000, kNoPP);
1171 __ b(&fall_through, MI); 1171 __ b(&fall_through, MI);
1172 __ SmiTag(R0); 1172 __ SmiTag(R0);
1173 __ ret(); 1173 __ ret();
1174 __ Bind(&fall_through); 1174 __ Bind(&fall_through);
1175 } 1175 }
1176 1176
1177 1177
1178 void Intrinsifier::Math_sqrt(Assembler* assembler) { 1178 void Intrinsifier::MathSqrt(Assembler* assembler) {
1179 Label fall_through, is_smi, double_op; 1179 Label fall_through, is_smi, double_op;
1180 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1180 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1181 // Argument is double and is in R0. 1181 // Argument is double and is in R0.
1182 __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP); 1182 __ LoadDFieldFromOffset(V1, R0, Double::value_offset(), kNoPP);
1183 __ Bind(&double_op); 1183 __ Bind(&double_op);
1184 __ fsqrtd(V0, V1); 1184 __ fsqrtd(V0, V1);
1185 const Class& double_class = Class::Handle( 1185 const Class& double_class = Class::Handle(
1186 Isolate::Current()->object_store()->double_class()); 1186 Isolate::Current()->object_store()->double_class());
1187 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); 1187 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
1188 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); 1188 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 __ LoadFromOffset(R2, R1, disp, kNoPP); 1225 __ LoadFromOffset(R2, R1, disp, kNoPP);
1226 __ Lsr(R3, R2, 32); 1226 __ Lsr(R3, R2, 32);
1227 __ andi(R2, R2, 0xffffffff); 1227 __ andi(R2, R2, 0xffffffff);
1228 __ mul(R2, R0, R2); 1228 __ mul(R2, R0, R2);
1229 __ add(R2, R2, Operand(R3)); 1229 __ add(R2, R2, Operand(R3));
1230 __ StoreToOffset(R2, R1, disp, kNoPP); 1230 __ StoreToOffset(R2, R1, disp, kNoPP);
1231 __ ret(); 1231 __ ret();
1232 } 1232 }
1233 1233
1234 1234
1235 void Intrinsifier::Object_equal(Assembler* assembler) { 1235 void Intrinsifier::ObjectEquals(Assembler* assembler) {
1236 __ ldr(R0, Address(SP, 0 * kWordSize)); 1236 __ ldr(R0, Address(SP, 0 * kWordSize));
1237 __ ldr(R1, Address(SP, 1 * kWordSize)); 1237 __ ldr(R1, Address(SP, 1 * kWordSize));
1238 __ cmp(R0, Operand(R1)); 1238 __ cmp(R0, Operand(R1));
1239 __ LoadObject(R0, Bool::False(), PP); 1239 __ LoadObject(R0, Bool::False(), PP);
1240 __ LoadObject(TMP, Bool::True(), PP); 1240 __ LoadObject(TMP, Bool::True(), PP);
1241 __ csel(R0, TMP, R0, EQ); 1241 __ csel(R0, TMP, R0, EQ);
1242 __ ret(); 1242 __ ret();
1243 } 1243 }
1244 1244
1245 1245
1246 void Intrinsifier::String_getHashCode(Assembler* assembler) { 1246 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1247 Label fall_through; 1247 Label fall_through;
1248 __ ldr(R0, Address(SP, 0 * kWordSize)); 1248 __ ldr(R0, Address(SP, 0 * kWordSize));
1249 __ ldr(R0, FieldAddress(R0, String::hash_offset())); 1249 __ ldr(R0, FieldAddress(R0, String::hash_offset()));
1250 __ CompareRegisters(R0, ZR); 1250 __ CompareRegisters(R0, ZR);
1251 __ b(&fall_through, EQ); 1251 __ b(&fall_through, EQ);
1252 __ ret(); 1252 __ ret();
1253 // Hash not yet computed. 1253 // Hash not yet computed.
1254 __ Bind(&fall_through); 1254 __ Bind(&fall_through);
1255 } 1255 }
1256 1256
1257 1257
1258 void Intrinsifier::String_getLength(Assembler* assembler) { 1258 void Intrinsifier::StringBaseLength(Assembler* assembler) {
1259 __ ldr(R0, Address(SP, 0 * kWordSize)); 1259 __ ldr(R0, Address(SP, 0 * kWordSize));
1260 __ ldr(R0, FieldAddress(R0, String::length_offset())); 1260 __ ldr(R0, FieldAddress(R0, String::length_offset()));
1261 __ ret(); 1261 __ ret();
1262 } 1262 }
1263 1263
1264 1264
1265 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { 1265 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) {
1266 Label fall_through, try_two_byte_string; 1266 Label fall_through, try_two_byte_string;
1267 1267
1268 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1268 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1269 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1269 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1270 __ tsti(R1, kSmiTagMask); 1270 __ tsti(R1, kSmiTagMask);
1271 __ b(&fall_through, NE); // Index is not a Smi. 1271 __ b(&fall_through, NE); // Index is not a Smi.
1272 // Range check. 1272 // Range check.
1273 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1273 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1274 __ cmp(R1, Operand(R2)); 1274 __ cmp(R1, Operand(R2));
1275 __ b(&fall_through, CS); // Runtime throws exception. 1275 __ b(&fall_through, CS); // Runtime throws exception.
(...skipping 11 matching lines...) Expand all
1287 ASSERT(kSmiTagShift == 1); 1287 ASSERT(kSmiTagShift == 1);
1288 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag, kNoPP); 1288 __ AddImmediate(R0, R0, TwoByteString::data_offset() - kHeapObjectTag, kNoPP);
1289 __ ldr(R0, Address(R0, R1), kUnsignedHalfword); 1289 __ ldr(R0, Address(R0, R1), kUnsignedHalfword);
1290 __ SmiTag(R0); 1290 __ SmiTag(R0);
1291 __ ret(); 1291 __ ret();
1292 1292
1293 __ Bind(&fall_through); 1293 __ Bind(&fall_through);
1294 } 1294 }
1295 1295
1296 1296
1297 void Intrinsifier::String_getIsEmpty(Assembler* assembler) { 1297 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) {
1298 __ ldr(R0, Address(SP, 0 * kWordSize)); 1298 __ ldr(R0, Address(SP, 0 * kWordSize));
1299 __ ldr(R0, FieldAddress(R0, String::length_offset())); 1299 __ ldr(R0, FieldAddress(R0, String::length_offset()));
1300 __ cmp(R0, Operand(Smi::RawValue(0))); 1300 __ cmp(R0, Operand(Smi::RawValue(0)));
1301 __ LoadObject(R0, Bool::True(), PP); 1301 __ LoadObject(R0, Bool::True(), PP);
1302 __ LoadObject(TMP, Bool::False(), PP); 1302 __ LoadObject(TMP, Bool::False(), PP);
1303 __ csel(R0, TMP, R0, NE); 1303 __ csel(R0, TMP, R0, NE);
1304 __ ret(); 1304 __ ret();
1305 } 1305 }
1306 1306
1307 1307
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1495 __ str(R1, FieldAddress(R7, OneByteString::data_offset()), kUnsignedByte); 1495 __ str(R1, FieldAddress(R7, OneByteString::data_offset()), kUnsignedByte);
1496 __ AddImmediate(R7, R7, 1, kNoPP); 1496 __ AddImmediate(R7, R7, 1, kNoPP);
1497 __ b(&loop, GT); 1497 __ b(&loop, GT);
1498 1498
1499 __ Bind(&done); 1499 __ Bind(&done);
1500 __ ret(); 1500 __ ret();
1501 __ Bind(&fall_through); 1501 __ Bind(&fall_through);
1502 } 1502 }
1503 1503
1504 1504
1505 void Intrinsifier::OneByteString_setAt(Assembler* assembler) { 1505 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) {
1506 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 1506 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
1507 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 1507 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
1508 __ ldr(R0, Address(SP, 2 * kWordSize)); // OneByteString. 1508 __ ldr(R0, Address(SP, 2 * kWordSize)); // OneByteString.
1509 __ SmiUntag(R1); 1509 __ SmiUntag(R1);
1510 __ SmiUntag(R2); 1510 __ SmiUntag(R2);
1511 __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP); 1511 __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
1512 __ str(R2, Address(R3, R1), kUnsignedByte); 1512 __ str(R2, Address(R3, R1), kUnsignedByte);
1513 __ ret(); 1513 __ ret();
1514 } 1514 }
1515 1515
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 Isolate* isolate = Isolate::Current(); 1636 Isolate* isolate = Isolate::Current();
1637 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); 1637 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP);
1638 // Set return value to Isolate::current_tag_. 1638 // Set return value to Isolate::current_tag_.
1639 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); 1639 __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
1640 __ ret(); 1640 __ ret();
1641 } 1641 }
1642 1642
1643 } // namespace dart 1643 } // namespace dart
1644 1644
1645 #endif // defined TARGET_ARCH_ARM64 1645 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698