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

Side by Side Diff: runtime/vm/intrinsifier_arm.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.cc ('k') | runtime/vm/intrinsifier_arm64.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) 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" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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/cpu.h" 11 #include "vm/cpu.h"
12 #include "vm/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/symbols.h" 15 #include "vm/symbols.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 DECLARE_FLAG(bool, enable_type_checks); 19 DECLARE_FLAG(bool, enable_type_checks);
20 20
21 21
22 #define __ assembler-> 22 #define __ assembler->
23 23
24 24
25 void Intrinsifier::Array_getLength(Assembler* assembler) { 25 void Intrinsifier::ObjectArrayLength(Assembler* assembler) {
26 __ ldr(R0, Address(SP, 0 * kWordSize)); 26 __ ldr(R0, Address(SP, 0 * kWordSize));
27 __ ldr(R0, FieldAddress(R0, Array::length_offset())); 27 __ ldr(R0, FieldAddress(R0, Array::length_offset()));
28 __ Ret(); 28 __ Ret();
29 } 29 }
30 30
31 31
32 void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { 32 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) {
33 Array_getLength(assembler); 33 ObjectArrayLength(assembler);
34 } 34 }
35 35
36 36
37 void Intrinsifier::Array_getIndexed(Assembler* assembler) { 37 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) {
38 Label fall_through; 38 Label fall_through;
39 39
40 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index 40 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
41 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array 41 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
42 42
43 __ tst(R0, Operand(kSmiTagMask)); 43 __ tst(R0, Operand(kSmiTagMask));
44 __ b(&fall_through, NE); // Index is not an smi, fall through 44 __ b(&fall_through, NE); // Index is not an smi, fall through
45 45
46 // Range check. 46 // Range check.
47 __ ldr(R6, FieldAddress(R1, Array::length_offset())); 47 __ ldr(R6, FieldAddress(R1, Array::length_offset()));
48 __ cmp(R0, Operand(R6)); 48 __ cmp(R0, Operand(R6));
49 49
50 ASSERT(kSmiTagShift == 1); 50 ASSERT(kSmiTagShift == 1);
51 // array element at R1 + R0*2 + Array::data_offset - 1 51 // array element at R1 + R0*2 + Array::data_offset - 1
52 __ add(R6, R1, Operand(R0, LSL, 1), CC); 52 __ add(R6, R1, Operand(R0, LSL, 1), CC);
53 __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC); 53 __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC);
54 __ bx(LR, CC); 54 __ bx(LR, CC);
55 __ Bind(&fall_through); 55 __ Bind(&fall_through);
56 } 56 }
57 57
58 58
59 void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { 59 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) {
60 Array_getIndexed(assembler); 60 ObjectArrayGetIndexed(assembler);
61 } 61 }
62 62
63 63
64 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { 64 static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
65 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 65 const Library& core_lib = Library::Handle(Library::CoreLibrary());
66 const Class& cls = Class::Handle( 66 const Class& cls = Class::Handle(
67 core_lib.LookupClassAllowPrivate(Symbols::_List())); 67 core_lib.LookupClassAllowPrivate(Symbols::_List()));
68 ASSERT(!cls.IsNull()); 68 ASSERT(!cls.IsNull());
69 ASSERT(cls.NumTypeArguments() == 1); 69 ASSERT(cls.NumTypeArguments() == 1);
70 const intptr_t field_offset = cls.type_arguments_field_offset(); 70 const intptr_t field_offset = cls.type_arguments_field_offset();
71 ASSERT(field_offset != Class::kNoTypeArguments); 71 ASSERT(field_offset != Class::kNoTypeArguments);
72 return field_offset; 72 return field_offset;
73 } 73 }
74 74
75 75
76 // Intrinsify only for Smi value and index. Non-smi values need a store buffer 76 // Intrinsify only for Smi value and index. Non-smi values need a store buffer
77 // update. Array length is always a Smi. 77 // update. Array length is always a Smi.
78 void Intrinsifier::Array_setIndexed(Assembler* assembler) { 78 void Intrinsifier::ObjectArraySetIndexed(Assembler* assembler) {
79 Label fall_through; 79 Label fall_through;
80 80
81 if (FLAG_enable_type_checks) { 81 if (FLAG_enable_type_checks) {
82 const intptr_t type_args_field_offset = 82 const intptr_t type_args_field_offset =
83 ComputeObjectArrayTypeArgumentsOffset(); 83 ComputeObjectArrayTypeArgumentsOffset();
84 // Inline simple tests (Smi, null), fallthrough if not positive. 84 // Inline simple tests (Smi, null), fallthrough if not positive.
85 const int32_t raw_null = reinterpret_cast<intptr_t>(Object::null()); 85 const int32_t raw_null = reinterpret_cast<intptr_t>(Object::null());
86 Label checked_ok; 86 Label checked_ok;
87 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 87 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
88 88
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 __ add(R1, R0, Operand(R1, LSL, 1)); // R1 is Smi. 130 __ add(R1, R0, Operand(R1, LSL, 1)); // R1 is Smi.
131 __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), R2); 131 __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), 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); 149 __ TryAllocate(cls, &fall_through, R0, R1);
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); 168 __ LoadImmediate(R1, 0);
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 __ tst(R0, Operand(kSmiTagMask)); 197 __ tst(R0, Operand(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 203
204 ASSERT(kSmiTagShift == 1); 204 ASSERT(kSmiTagShift == 1);
205 // array element at R6 + R0 * 2 + Array::data_offset - 1 205 // array element at R6 + R0 * 2 + Array::data_offset - 1
206 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset()), CC); // data 206 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset()), CC); // data
207 __ add(R6, R6, Operand(R0, LSL, 1), CC); 207 __ add(R6, R6, Operand(R0, LSL, 1), CC);
208 __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC); 208 __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC);
209 __ bx(LR, CC); 209 __ bx(LR, CC);
210 __ Bind(&fall_through); 210 __ Bind(&fall_through);
211 } 211 }
212 212
213 213
214 // Set value into growable object array at specified index. 214 // Set value into growable object array at specified index.
215 // On stack: growable array (+2), index (+1), value (+0). 215 // On stack: growable array (+2), index (+1), value (+0).
216 void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { 216 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
217 if (FLAG_enable_type_checks) { 217 if (FLAG_enable_type_checks) {
218 return; 218 return;
219 } 219 }
220 Label fall_through; 220 Label fall_through;
221 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 221 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
222 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray. 222 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray.
223 __ tst(R1, Operand(kSmiTagMask)); 223 __ tst(R1, Operand(kSmiTagMask));
224 __ b(&fall_through, NE); // Non-smi index. 224 __ b(&fall_through, NE); // Non-smi index.
225 // Range check using _length field. 225 // Range check using _length field.
226 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset())); 226 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
227 __ cmp(R1, Operand(R2)); 227 __ cmp(R1, Operand(R2));
228 // Runtime throws exception. 228 // Runtime throws exception.
229 __ b(&fall_through, CS); 229 __ b(&fall_through, CS);
230 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data. 230 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data.
231 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 231 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
232 // Note that R1 is Smi, i.e, times 2. 232 // Note that R1 is Smi, i.e, times 2.
233 ASSERT(kSmiTagShift == 1); 233 ASSERT(kSmiTagShift == 1);
234 __ add(R1, R0, Operand(R1, LSL, 1)); 234 __ add(R1, R0, Operand(R1, LSL, 1));
235 __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), R2); 235 __ StoreIntoObject(R0, FieldAddress(R1, Array::data_offset()), R2);
236 __ Ret(); 236 __ Ret();
237 __ Bind(&fall_through); 237 __ Bind(&fall_through);
238 } 238 }
239 239
240 240
241 // Set length of growable object array. The length cannot 241 // Set length of growable object array. The length cannot
242 // be greater than the length of the data container. 242 // be greater than the length of the data container.
243 // On stack: growable array (+1), length (+0). 243 // On stack: growable array (+1), length (+0).
244 void Intrinsifier::GrowableList_setLength(Assembler* assembler) { 244 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
245 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 245 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
246 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value. 246 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value.
247 __ tst(R1, Operand(kSmiTagMask)); // Check for Smi. 247 __ tst(R1, Operand(kSmiTagMask)); // Check for Smi.
248 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()), EQ); 248 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()), EQ);
249 __ bx(LR, EQ); 249 __ bx(LR, EQ);
250 // Fall through on non-Smi. 250 // Fall through on non-Smi.
251 } 251 }
252 252
253 253
254 // Set data of growable object array. 254 // Set data of growable object array.
255 // On stack: growable array (+1), data (+0). 255 // On stack: growable array (+1), data (+0).
256 void Intrinsifier::GrowableList_setData(Assembler* assembler) { 256 void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
257 if (FLAG_enable_type_checks) { 257 if (FLAG_enable_type_checks) {
258 return; 258 return;
259 } 259 }
260 Label fall_through; 260 Label fall_through;
261 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data. 261 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data.
262 // Check that data is an ObjectArray. 262 // Check that data is an ObjectArray.
263 __ tst(R1, Operand(kSmiTagMask)); 263 __ tst(R1, Operand(kSmiTagMask));
264 __ b(&fall_through, EQ); // Data is Smi. 264 __ b(&fall_through, EQ); // Data is Smi.
265 __ CompareClassId(R1, kArrayCid, R0); 265 __ CompareClassId(R1, kArrayCid, R0);
266 __ b(&fall_through, NE); 266 __ b(&fall_through, NE);
267 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 267 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
268 __ StoreIntoObject(R0, 268 __ StoreIntoObject(R0,
269 FieldAddress(R0, GrowableObjectArray::data_offset()), 269 FieldAddress(R0, GrowableObjectArray::data_offset()),
270 R1); 270 R1);
271 __ Ret(); 271 __ Ret();
272 __ Bind(&fall_through); 272 __ Bind(&fall_through);
273 } 273 }
274 274
275 275
276 // Add an element to growable array if it doesn't need to grow, otherwise 276 // Add an element to growable array if it doesn't need to grow, otherwise
277 // call into regular code. 277 // call into regular code.
278 // On stack: growable array (+1), value (+0). 278 // On stack: growable array (+1), value (+0).
279 void Intrinsifier::GrowableList_add(Assembler* assembler) { 279 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
280 // In checked mode we need to type-check the incoming argument. 280 // In checked mode we need to type-check the incoming argument.
281 if (FLAG_enable_type_checks) { 281 if (FLAG_enable_type_checks) {
282 return; 282 return;
283 } 283 }
284 Label fall_through; 284 Label fall_through;
285 // R0: Array. 285 // R0: Array.
286 __ ldr(R0, Address(SP, 1 * kWordSize)); 286 __ ldr(R0, Address(SP, 1 * kWordSize));
287 // R1: length. 287 // R1: length.
288 __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 288 __ ldr(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
289 // R2: data. 289 // R2: data.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 __ cmp(R2, Operand(R1)); \ 386 __ cmp(R2, Operand(R1)); \
387 __ str(R3, Address(R2, 0), CC); \ 387 __ str(R3, Address(R2, 0), CC); \
388 __ add(R2, R2, Operand(kWordSize), CC); \ 388 __ add(R2, R2, Operand(kWordSize), CC); \
389 __ b(&init_loop, CC); \ 389 __ b(&init_loop, CC); \
390 \ 390 \
391 __ Ret(); \ 391 __ Ret(); \
392 __ Bind(&fall_through); \ 392 __ Bind(&fall_through); \
393 393
394 394
395 // Gets the length of a TypedData. 395 // Gets the length of a TypedData.
396 void Intrinsifier::TypedData_getLength(Assembler* assembler) { 396 void Intrinsifier::TypedDataLength(Assembler* assembler) {
397 __ ldr(R0, Address(SP, 0 * kWordSize)); 397 __ ldr(R0, Address(SP, 0 * kWordSize));
398 __ ldr(R0, FieldAddress(R0, TypedData::length_offset())); 398 __ ldr(R0, FieldAddress(R0, TypedData::length_offset()));
399 __ Ret(); 399 __ Ret();
400 } 400 }
401 401
402 402
403 void Intrinsifier::Uint8Array_getIndexed(Assembler* assembler) { 403 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) {
404 Label fall_through; 404 Label fall_through;
405 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index. 405 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
406 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array. 406 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
407 __ tst(R0, Operand(kSmiTagMask)); 407 __ tst(R0, Operand(kSmiTagMask));
408 __ b(&fall_through, NE); // Index is not a smi, fall through. 408 __ b(&fall_through, NE); // Index is not a smi, fall through.
409 409
410 // Range check. 410 // Range check.
411 __ ldr(R6, FieldAddress(R1, TypedData::length_offset())); 411 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
412 __ cmp(R0, Operand(R6)); 412 __ cmp(R0, Operand(R6));
413 __ b(&fall_through, CS); 413 __ b(&fall_through, CS);
414 414
415 __ SmiUntag(R0); 415 __ SmiUntag(R0);
416 __ AddImmediate(R1, TypedData::data_offset() - kHeapObjectTag); 416 __ AddImmediate(R1, TypedData::data_offset() - kHeapObjectTag);
417 __ ldrb(R0, Address(R1, R0)); 417 __ ldrb(R0, Address(R1, R0));
418 __ SmiTag(R0); 418 __ SmiTag(R0);
419 __ Ret(); 419 __ Ret();
420 __ Bind(&fall_through); 420 __ Bind(&fall_through);
421 } 421 }
422 422
423 423
424 void Intrinsifier::ExternalUint8Array_getIndexed(Assembler* assembler) { 424 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) {
425 Label fall_through; 425 Label fall_through;
426 426
427 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index. 427 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
428 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array. 428 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
429 __ tst(R0, Operand(kSmiTagMask)); 429 __ tst(R0, Operand(kSmiTagMask));
430 __ b(&fall_through, NE); // Index is not a smi, fall through. 430 __ b(&fall_through, NE); // Index is not a smi, fall through.
431 431
432 // Range check. 432 // Range check.
433 __ ldr(R6, FieldAddress(R1, TypedData::length_offset())); 433 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
434 __ cmp(R0, Operand(R6)); 434 __ cmp(R0, Operand(R6));
435 __ b(&fall_through, CS); 435 __ b(&fall_through, CS);
436 436
437 __ LoadFromOffset(kWord, R1, R1, 437 __ LoadFromOffset(kWord, R1, R1,
438 ExternalTypedData::data_offset() - kHeapObjectTag); 438 ExternalTypedData::data_offset() - kHeapObjectTag);
439 __ SmiUntag(R0); 439 __ SmiUntag(R0);
440 __ ldrb(R0, Address(R1, R0)); 440 __ ldrb(R0, Address(R1, R0));
441 __ SmiTag(R0); 441 __ SmiTag(R0);
442 __ Ret(); 442 __ Ret();
443 __ Bind(&fall_through); 443 __ Bind(&fall_through);
444 } 444 }
445 445
446 446
447 void Intrinsifier::Float64Array_getIndexed(Assembler* assembler) { 447 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) {
448 if (!TargetCPUFeatures::vfp_supported()) { 448 if (!TargetCPUFeatures::vfp_supported()) {
449 return; 449 return;
450 } 450 }
451 Label fall_through; 451 Label fall_through;
452 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index. 452 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
453 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array. 453 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
454 __ tst(R0, Operand(kSmiTagMask)); 454 __ tst(R0, Operand(kSmiTagMask));
455 __ b(&fall_through, NE); // Index is not a smi, fall through. 455 __ b(&fall_through, NE); // Index is not a smi, fall through.
456 456
457 // Range check. 457 // Range check.
(...skipping 17 matching lines...) Expand all
475 __ TryAllocate(double_class, 475 __ TryAllocate(double_class,
476 &fall_through, 476 &fall_through,
477 R0, // Result register. 477 R0, // Result register.
478 R1); 478 R1);
479 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag); 479 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
480 __ Ret(); 480 __ Ret();
481 __ Bind(&fall_through); 481 __ Bind(&fall_through);
482 } 482 }
483 483
484 484
485 void Intrinsifier::Float64Array_setIndexed(Assembler* assembler) { 485 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) {
486 if (!TargetCPUFeatures::vfp_supported()) { 486 if (!TargetCPUFeatures::vfp_supported()) {
487 return; 487 return;
488 } 488 }
489 Label fall_through; 489 Label fall_through;
490 __ ldr(R0, Address(SP, + 1 * kWordSize)); // Index. 490 __ ldr(R0, Address(SP, + 1 * kWordSize)); // Index.
491 __ ldr(R1, Address(SP, + 2 * kWordSize)); // Array. 491 __ ldr(R1, Address(SP, + 2 * kWordSize)); // Array.
492 __ tst(R0, Operand(kSmiTagMask)); 492 __ tst(R0, Operand(kSmiTagMask));
493 __ b(&fall_through, NE); // Index is not a smi, fall through. 493 __ b(&fall_through, NE); // Index is not a smi, fall through.
494 494
495 // Range check. 495 // Range check.
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 // Check for negative zero by looking at the sign bit. 1254 // Check for negative zero by looking at the sign bit.
1255 __ vmovrrd(R0, R1, D0); // R1:R0 <- D0, so sign bit is in bit 31 of R1. 1255 __ vmovrrd(R0, R1, D0); // R1:R0 <- D0, so sign bit is in bit 31 of R1.
1256 __ mov(R1, Operand(R1, LSR, 31)); 1256 __ mov(R1, Operand(R1, LSR, 31));
1257 __ tst(R1, Operand(1)); 1257 __ tst(R1, Operand(1));
1258 __ b(&is_true, NE); // Sign bit set. 1258 __ b(&is_true, NE); // Sign bit set.
1259 __ b(&is_false); 1259 __ b(&is_false);
1260 } 1260 }
1261 } 1261 }
1262 1262
1263 1263
1264 void Intrinsifier::Double_toInt(Assembler* assembler) { 1264 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
1265 if (TargetCPUFeatures::vfp_supported()) { 1265 if (TargetCPUFeatures::vfp_supported()) {
1266 Label fall_through; 1266 Label fall_through;
1267 1267
1268 __ ldr(R0, Address(SP, 0 * kWordSize)); 1268 __ ldr(R0, Address(SP, 0 * kWordSize));
1269 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag); 1269 __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
1270 1270
1271 // Explicit NaN check, since ARM gives an FPU exception if you try to 1271 // Explicit NaN check, since ARM gives an FPU exception if you try to
1272 // convert NaN to an int. 1272 // convert NaN to an int.
1273 __ vcmpd(D0, D0); 1273 __ vcmpd(D0, D0);
1274 __ vmstat(); 1274 __ vmstat();
1275 __ b(&fall_through, VS); 1275 __ b(&fall_through, VS);
1276 1276
1277 __ vcvtid(S0, D0); 1277 __ vcvtid(S0, D0);
1278 __ vmovrs(R0, S0); 1278 __ vmovrs(R0, S0);
1279 // Overflow is signaled with minint. 1279 // Overflow is signaled with minint.
1280 // Check for overflow and that it fits into Smi. 1280 // Check for overflow and that it fits into Smi.
1281 __ CompareImmediate(R0, 0xC0000000); 1281 __ CompareImmediate(R0, 0xC0000000);
1282 __ SmiTag(R0, PL); 1282 __ SmiTag(R0, PL);
1283 __ bx(LR, PL); 1283 __ bx(LR, PL);
1284 __ Bind(&fall_through); 1284 __ Bind(&fall_through);
1285 } 1285 }
1286 } 1286 }
1287 1287
1288 1288
1289 void Intrinsifier::Math_sqrt(Assembler* assembler) { 1289 void Intrinsifier::MathSqrt(Assembler* assembler) {
1290 if (TargetCPUFeatures::vfp_supported()) { 1290 if (TargetCPUFeatures::vfp_supported()) {
1291 Label fall_through, is_smi, double_op; 1291 Label fall_through, is_smi, double_op;
1292 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1292 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1293 // Argument is double and is in R0. 1293 // Argument is double and is in R0.
1294 __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag); 1294 __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
1295 __ Bind(&double_op); 1295 __ Bind(&double_op);
1296 __ vsqrtd(D0, D1); 1296 __ vsqrtd(D0, D1);
1297 const Class& double_class = Class::Handle( 1297 const Class& double_class = Class::Handle(
1298 Isolate::Current()->object_store()->double_class()); 1298 Isolate::Current()->object_store()->double_class());
1299 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register. 1299 __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 __ mov(R6, Operand(0)); // Zero extend unsigned _state[kSTATE_HI]. 1347 __ mov(R6, Operand(0)); // Zero extend unsigned _state[kSTATE_HI].
1348 // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3. 1348 // Unsigned 32-bit multiply and 64-bit accumulate into R6:R3.
1349 __ umlal(R3, R6, R0, R2); // R6:R3 <- R6:R3 + R0 * R2. 1349 __ umlal(R3, R6, R0, R2); // R6:R3 <- R6:R3 + R0 * R2.
1350 __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag); 1350 __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
1351 __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag); 1351 __ StoreToOffset(kWord, R6, R1, disp_1 - kHeapObjectTag);
1352 __ Ret(); 1352 __ Ret();
1353 } 1353 }
1354 } 1354 }
1355 1355
1356 1356
1357 void Intrinsifier::Object_equal(Assembler* assembler) { 1357 void Intrinsifier::ObjectEquals(Assembler* assembler) {
1358 __ ldr(R0, Address(SP, 0 * kWordSize)); 1358 __ ldr(R0, Address(SP, 0 * kWordSize));
1359 __ ldr(R1, Address(SP, 1 * kWordSize)); 1359 __ ldr(R1, Address(SP, 1 * kWordSize));
1360 __ cmp(R0, Operand(R1)); 1360 __ cmp(R0, Operand(R1));
1361 __ LoadObject(R0, Bool::False(), NE); 1361 __ LoadObject(R0, Bool::False(), NE);
1362 __ LoadObject(R0, Bool::True(), EQ); 1362 __ LoadObject(R0, Bool::True(), EQ);
1363 __ Ret(); 1363 __ Ret();
1364 } 1364 }
1365 1365
1366 1366
1367 void Intrinsifier::String_getHashCode(Assembler* assembler) { 1367 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1368 __ ldr(R0, Address(SP, 0 * kWordSize)); 1368 __ ldr(R0, Address(SP, 0 * kWordSize));
1369 __ ldr(R0, FieldAddress(R0, String::hash_offset())); 1369 __ ldr(R0, FieldAddress(R0, String::hash_offset()));
1370 __ cmp(R0, Operand(0)); 1370 __ cmp(R0, Operand(0));
1371 __ bx(LR, NE); // Hash not yet computed. 1371 __ bx(LR, NE); // Hash not yet computed.
1372 } 1372 }
1373 1373
1374 1374
1375 void Intrinsifier::String_getLength(Assembler* assembler) { 1375 void Intrinsifier::StringBaseLength(Assembler* assembler) {
1376 __ ldr(R0, Address(SP, 0 * kWordSize)); 1376 __ ldr(R0, Address(SP, 0 * kWordSize));
1377 __ ldr(R0, FieldAddress(R0, String::length_offset())); 1377 __ ldr(R0, FieldAddress(R0, String::length_offset()));
1378 __ Ret(); 1378 __ Ret();
1379 } 1379 }
1380 1380
1381 1381
1382 void Intrinsifier::String_codeUnitAt(Assembler* assembler) { 1382 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) {
1383 Label fall_through, try_two_byte_string; 1383 Label fall_through, try_two_byte_string;
1384 1384
1385 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1385 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1386 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1386 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1387 __ tst(R1, Operand(kSmiTagMask)); 1387 __ tst(R1, Operand(kSmiTagMask));
1388 __ b(&fall_through, NE); // Index is not a Smi. 1388 __ b(&fall_through, NE); // Index is not a Smi.
1389 // Range check. 1389 // Range check.
1390 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1390 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1391 __ cmp(R1, Operand(R2)); 1391 __ cmp(R1, Operand(R2));
1392 __ b(&fall_through, CS); // Runtime throws exception. 1392 __ b(&fall_through, CS); // Runtime throws exception.
(...skipping 11 matching lines...) Expand all
1404 ASSERT(kSmiTagShift == 1); 1404 ASSERT(kSmiTagShift == 1);
1405 __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag); 1405 __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag);
1406 __ ldrh(R0, Address(R0, R1)); 1406 __ ldrh(R0, Address(R0, R1));
1407 __ SmiTag(R0); 1407 __ SmiTag(R0);
1408 __ Ret(); 1408 __ Ret();
1409 1409
1410 __ Bind(&fall_through); 1410 __ Bind(&fall_through);
1411 } 1411 }
1412 1412
1413 1413
1414 void Intrinsifier::String_getIsEmpty(Assembler* assembler) { 1414 void Intrinsifier::StringBaseIsEmpty(Assembler* assembler) {
1415 __ ldr(R0, Address(SP, 0 * kWordSize)); 1415 __ ldr(R0, Address(SP, 0 * kWordSize));
1416 __ ldr(R0, FieldAddress(R0, String::length_offset())); 1416 __ ldr(R0, FieldAddress(R0, String::length_offset()));
1417 __ cmp(R0, Operand(Smi::RawValue(0))); 1417 __ cmp(R0, Operand(Smi::RawValue(0)));
1418 __ LoadObject(R0, Bool::True(), EQ); 1418 __ LoadObject(R0, Bool::True(), EQ);
1419 __ LoadObject(R0, Bool::False(), NE); 1419 __ LoadObject(R0, Bool::False(), NE);
1420 __ Ret(); 1420 __ Ret();
1421 } 1421 }
1422 1422
1423 1423
1424 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { 1424 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 __ strb(R1, FieldAddress(R7, OneByteString::data_offset())); 1609 __ strb(R1, FieldAddress(R7, OneByteString::data_offset()));
1610 __ AddImmediate(R7, 1); 1610 __ AddImmediate(R7, 1);
1611 __ b(&loop, GT); 1611 __ b(&loop, GT);
1612 1612
1613 __ Bind(&done); 1613 __ Bind(&done);
1614 __ Ret(); 1614 __ Ret();
1615 __ Bind(&fall_through); 1615 __ Bind(&fall_through);
1616 } 1616 }
1617 1617
1618 1618
1619 void Intrinsifier::OneByteString_setAt(Assembler* assembler) { 1619 void Intrinsifier::OneByteStringSetAt(Assembler* assembler) {
1620 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 1620 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
1621 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 1621 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
1622 __ ldr(R0, Address(SP, 2 * kWordSize)); // OneByteString. 1622 __ ldr(R0, Address(SP, 2 * kWordSize)); // OneByteString.
1623 __ SmiUntag(R1); 1623 __ SmiUntag(R1);
1624 __ SmiUntag(R2); 1624 __ SmiUntag(R2);
1625 __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag); 1625 __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag);
1626 __ strb(R2, Address(R3, R1)); 1626 __ strb(R2, Address(R3, R1));
1627 __ Ret(); 1627 __ Ret();
1628 } 1628 }
1629 1629
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 Isolate* isolate = Isolate::Current(); 1749 Isolate* isolate = Isolate::Current();
1750 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); 1750 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate));
1751 // Set return value to Isolate::current_tag_. 1751 // Set return value to Isolate::current_tag_.
1752 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); 1752 __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
1753 __ Ret(); 1753 __ Ret();
1754 } 1754 }
1755 1755
1756 } // namespace dart 1756 } // namespace dart
1757 1757
1758 #endif // defined TARGET_ARCH_ARM 1758 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier.cc ('k') | runtime/vm/intrinsifier_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698