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

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

Issue 513213002: Generate some intrinsics using our IR. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 6 years, 3 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
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::ObjectArrayLength(Assembler* assembler) { 25 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; }
26 __ ldr(R0, Address(SP, 0 * kWordSize));
27 __ ldr(R0, FieldAddress(R0, Array::length_offset()));
28 __ Ret();
29 }
30
31
32 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) {
33 ObjectArrayLength(assembler);
34 }
35
36
37 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) {
38 Label fall_through;
39
40 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
41 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
42
43 __ tst(R0, Operand(kSmiTagMask));
44 __ b(&fall_through, NE); // Index is not an smi, fall through
45
46 // Range check.
47 __ ldr(R6, FieldAddress(R1, Array::length_offset()));
48 __ cmp(R0, Operand(R6));
49
50 ASSERT(kSmiTagShift == 1);
51 // array element at R1 + R0*2 + Array::data_offset - 1
52 __ add(R6, R1, Operand(R0, LSL, 1), CC);
53 __ ldr(R0, FieldAddress(R6, Array::data_offset()), CC);
54 __ bx(LR, CC);
55 __ Bind(&fall_through);
56 }
57
58
59 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) {
60 ObjectArrayGetIndexed(assembler);
61 }
62 26
63 27
64 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { 28 static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
65 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 29 const Library& core_lib = Library::Handle(Library::CoreLibrary());
66 const Class& cls = Class::Handle( 30 const Class& cls = Class::Handle(
67 core_lib.LookupClassAllowPrivate(Symbols::_List())); 31 core_lib.LookupClassAllowPrivate(Symbols::_List()));
68 ASSERT(!cls.IsNull()); 32 ASSERT(!cls.IsNull());
69 ASSERT(cls.NumTypeArguments() == 1); 33 ASSERT(cls.NumTypeArguments() == 1);
70 const intptr_t field_offset = cls.type_arguments_field_offset(); 34 const intptr_t field_offset = cls.type_arguments_field_offset();
71 ASSERT(field_offset != Class::kNoTypeArguments); 35 ASSERT(field_offset != Class::kNoTypeArguments);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 130
167 // Set the length field in the growable array object to 0. 131 // Set the length field in the growable array object to 0.
168 __ LoadImmediate(R1, 0); 132 __ LoadImmediate(R1, 0);
169 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 133 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
170 __ Ret(); // Returns the newly allocated object in R0. 134 __ Ret(); // Returns the newly allocated object in R0.
171 135
172 __ Bind(&fall_through); 136 __ Bind(&fall_through);
173 } 137 }
174 138
175 139
176 void Intrinsifier::GrowableArrayLength(Assembler* assembler) {
177 __ ldr(R0, Address(SP, 0 * kWordSize));
178 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset()));
179 __ Ret();
180 }
181
182
183 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) {
184 __ ldr(R0, Address(SP, 0 * kWordSize));
185 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset()));
186 __ ldr(R0, FieldAddress(R0, Array::length_offset()));
187 __ Ret();
188 }
189
190
191 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { 140 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
192 Label fall_through; 141 Label fall_through;
193 142
194 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index 143 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
195 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array 144 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
196 145
197 __ tst(R0, Operand(kSmiTagMask)); 146 __ tst(R0, Operand(kSmiTagMask));
198 __ b(&fall_through, NE); // Index is not an smi, fall through 147 __ b(&fall_through, NE); // Index is not an smi, fall through
199 148
200 // Range check. 149 // Range check.
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 __ Bind(&init_loop); \ 334 __ Bind(&init_loop); \
386 __ cmp(R2, Operand(R1)); \ 335 __ cmp(R2, Operand(R1)); \
387 __ str(R3, Address(R2, 0), CC); \ 336 __ str(R3, Address(R2, 0), CC); \
388 __ add(R2, R2, Operand(kWordSize), CC); \ 337 __ add(R2, R2, Operand(kWordSize), CC); \
389 __ b(&init_loop, CC); \ 338 __ b(&init_loop, CC); \
390 \ 339 \
391 __ Ret(); \ 340 __ Ret(); \
392 __ Bind(&fall_through); \ 341 __ Bind(&fall_through); \
393 342
394 343
395 // Gets the length of a TypedData.
396 void Intrinsifier::TypedDataLength(Assembler* assembler) {
397 __ ldr(R0, Address(SP, 0 * kWordSize));
398 __ ldr(R0, FieldAddress(R0, TypedData::length_offset()));
399 __ Ret();
400 }
401
402
403 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) {
404 Label fall_through;
405 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
406 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
407 __ tst(R0, Operand(kSmiTagMask));
408 __ b(&fall_through, NE); // Index is not a smi, fall through.
409
410 // Range check.
411 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
412 __ cmp(R0, Operand(R6));
413 __ b(&fall_through, CS);
414
415 __ SmiUntag(R0);
416 __ AddImmediate(R1, TypedData::data_offset() - kHeapObjectTag);
417 __ ldrb(R0, Address(R1, R0));
418 __ SmiTag(R0);
419 __ Ret();
420 __ Bind(&fall_through);
421 }
422
423
424 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) {
425 Label fall_through;
426
427 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
428 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
429 __ tst(R0, Operand(kSmiTagMask));
430 __ b(&fall_through, NE); // Index is not a smi, fall through.
431
432 // Range check.
433 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
434 __ cmp(R0, Operand(R6));
435 __ b(&fall_through, CS);
436
437 __ LoadFromOffset(kWord, R1, R1,
438 ExternalTypedData::data_offset() - kHeapObjectTag);
439 __ SmiUntag(R0);
440 __ ldrb(R0, Address(R1, R0));
441 __ SmiTag(R0);
442 __ Ret();
443 __ Bind(&fall_through);
444 }
445
446
447 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) {
448 if (!TargetCPUFeatures::vfp_supported()) {
449 return;
450 }
451 Label fall_through;
452 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index.
453 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array.
454 __ tst(R0, Operand(kSmiTagMask));
455 __ b(&fall_through, NE); // Index is not a smi, fall through.
456
457 // Range check.
458 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
459 __ cmp(R0, Operand(R6));
460 __ b(&fall_through, CS);
461
462
463 Address element_address =
464 __ ElementAddressForRegIndex(true, // Load.
465 false, // Not external.
466 kTypedDataFloat64ArrayCid, // Cid.
467 8, // Index scale.
468 R1, // Array.
469 R0); // Index.
470
471 __ vldrd(D0, element_address);
472
473 const Class& double_class = Class::Handle(
474 Isolate::Current()->object_store()->double_class());
475 __ TryAllocate(double_class,
476 &fall_through,
477 R0, // Result register.
478 R1);
479 __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
480 __ Ret();
481 __ Bind(&fall_through);
482 }
483
484
485 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) {
486 if (!TargetCPUFeatures::vfp_supported()) {
487 return;
488 }
489 Label fall_through;
490 __ ldr(R0, Address(SP, + 1 * kWordSize)); // Index.
491 __ ldr(R1, Address(SP, + 2 * kWordSize)); // Array.
492 __ tst(R0, Operand(kSmiTagMask));
493 __ b(&fall_through, NE); // Index is not a smi, fall through.
494
495 // Range check.
496 __ ldr(R6, FieldAddress(R1, TypedData::length_offset()));
497 __ cmp(R0, Operand(R6));
498 __ b(&fall_through, CS);
499
500 __ ldr(R2, Address(SP, + 0 * kWordSize)); // Value.
501 __ tst(R2, Operand(kSmiTagMask));
502 __ b(&fall_through, EQ); // Value is Smi, fall through.
503
504 __ LoadClassId(R3, R2);
505 __ CompareImmediate(R3, kDoubleCid);
506 __ b(&fall_through, NE); // Not a Double, fall through.
507
508 __ LoadDFromOffset(D0, R2, Double::value_offset() - kHeapObjectTag);
509
510 Address element_address =
511 __ ElementAddressForRegIndex(false, // Store.
512 false, // Not external.
513 kTypedDataFloat64ArrayCid, // Cid.
514 8, // Index scale.
515 R1, // Array.
516 R0); // Index.
517 __ vstrd(D0, element_address);
518 __ Ret();
519 __ Bind(&fall_through);
520 }
521
522
523 static int GetScaleFactor(intptr_t size) { 344 static int GetScaleFactor(intptr_t size) {
524 switch (size) { 345 switch (size) {
525 case 1: return 0; 346 case 1: return 0;
526 case 2: return 1; 347 case 2: return 1;
527 case 4: return 2; 348 case 4: return 2;
528 case 8: return 3; 349 case 8: return 3;
529 case 16: return 4; 350 case 16: return 4;
530 } 351 }
531 UNREACHABLE(); 352 UNREACHABLE();
532 return -1; 353 return -1;
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 1186
1366 1187
1367 void Intrinsifier::String_getHashCode(Assembler* assembler) { 1188 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1368 __ ldr(R0, Address(SP, 0 * kWordSize)); 1189 __ ldr(R0, Address(SP, 0 * kWordSize));
1369 __ ldr(R0, FieldAddress(R0, String::hash_offset())); 1190 __ ldr(R0, FieldAddress(R0, String::hash_offset()));
1370 __ cmp(R0, Operand(0)); 1191 __ cmp(R0, Operand(0));
1371 __ bx(LR, NE); // Hash not yet computed. 1192 __ bx(LR, NE); // Hash not yet computed.
1372 } 1193 }
1373 1194
1374 1195
1375 void Intrinsifier::StringBaseLength(Assembler* assembler) {
1376 __ ldr(R0, Address(SP, 0 * kWordSize));
1377 __ ldr(R0, FieldAddress(R0, String::length_offset()));
1378 __ Ret();
1379 }
1380
1381
1382 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { 1196 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) {
1383 Label fall_through, try_two_byte_string; 1197 Label fall_through, try_two_byte_string;
1384 1198
1385 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1199 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1386 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1200 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1387 __ tst(R1, Operand(kSmiTagMask)); 1201 __ tst(R1, Operand(kSmiTagMask));
1388 __ b(&fall_through, NE); // Index is not a Smi. 1202 __ b(&fall_through, NE); // Index is not a Smi.
1389 // Range check. 1203 // Range check.
1390 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1204 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1391 __ cmp(R1, Operand(R2)); 1205 __ cmp(R1, Operand(R2));
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 Isolate* isolate = Isolate::Current(); 1606 Isolate* isolate = Isolate::Current();
1793 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate)); 1607 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate));
1794 // Set return value to Isolate::current_tag_. 1608 // Set return value to Isolate::current_tag_.
1795 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); 1609 __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
1796 __ Ret(); 1610 __ Ret();
1797 } 1611 }
1798 1612
1799 } // namespace dart 1613 } // namespace dart
1800 1614
1801 #endif // defined TARGET_ARCH_ARM 1615 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698