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

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

Issue 593363003: Expands the use of Immediate and Operand wrappers. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 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) 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 __ CompareObject(R1, Object::null_object(), PP); 59 __ CompareObject(R1, Object::null_object(), PP);
60 __ b(&checked_ok, EQ); 60 __ b(&checked_ok, EQ);
61 61
62 // Check if it's dynamic. 62 // Check if it's dynamic.
63 // Get type at index 0. 63 // Get type at index 0.
64 __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0))); 64 __ ldr(R0, FieldAddress(R1, TypeArguments::type_at_offset(0)));
65 __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()), PP); 65 __ CompareObject(R0, Type::ZoneHandle(Type::DynamicType()), PP);
66 __ b(&checked_ok, EQ); 66 __ b(&checked_ok, EQ);
67 67
68 // Check for int and num. 68 // Check for int and num.
69 __ tsti(R2, kSmiTagMask); // Value is Smi? 69 __ tsti(R2, Immediate(Immediate(kSmiTagMask))); // Value is Smi?
70 __ b(&fall_through, NE); // Non-smi value. 70 __ b(&fall_through, NE); // Non-smi value.
71 __ CompareObject(R0, Type::ZoneHandle(Type::IntType()), PP); 71 __ CompareObject(R0, Type::ZoneHandle(Type::IntType()), PP);
72 __ b(&checked_ok, EQ); 72 __ b(&checked_ok, EQ);
73 __ CompareObject(R0, Type::ZoneHandle(Type::Number()), PP); 73 __ CompareObject(R0, Type::ZoneHandle(Type::Number()), PP);
74 __ b(&fall_through, NE); 74 __ b(&fall_through, NE);
75 __ Bind(&checked_ok); 75 __ Bind(&checked_ok);
76 } 76 }
77 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 77 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
78 __ tsti(R1, kSmiTagMask); 78 __ tsti(R1, Immediate(kSmiTagMask));
79 // Index not Smi. 79 // Index not Smi.
80 __ b(&fall_through, NE); 80 __ b(&fall_through, NE);
81 __ ldr(R0, Address(SP, 2 * kWordSize)); // Array. 81 __ ldr(R0, Address(SP, 2 * kWordSize)); // Array.
82 82
83 // Range check. 83 // Range check.
84 __ ldr(R3, FieldAddress(R0, Array::length_offset())); // Array length. 84 __ ldr(R3, FieldAddress(R0, Array::length_offset())); // Array length.
85 __ cmp(R1, Operand(R3)); 85 __ cmp(R1, Operand(R3));
86 // Runtime throws exception. 86 // Runtime throws exception.
87 __ b(&fall_through, CS); 87 __ b(&fall_through, CS);
88 88
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 __ Bind(&fall_through); 136 __ Bind(&fall_through);
137 } 137 }
138 138
139 139
140 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { 140 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) {
141 Label fall_through; 141 Label fall_through;
142 142
143 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index 143 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index
144 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array 144 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Array
145 145
146 __ tsti(R0, kSmiTagMask); 146 __ tsti(R0, Immediate(kSmiTagMask));
147 __ b(&fall_through, NE); // Index is not an smi, fall through. 147 __ b(&fall_through, NE); // Index is not an smi, fall through.
148 148
149 // Range check. 149 // Range check.
150 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset())); 150 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::length_offset()));
151 __ cmp(R0, Operand(R6)); 151 __ cmp(R0, Operand(R6));
152 __ b(&fall_through, CS); 152 __ b(&fall_through, CS);
153 153
154 ASSERT(kSmiTagShift == 1); 154 ASSERT(kSmiTagShift == 1);
155 // array element at R6 + R0 * 4 + Array::data_offset - 1 155 // array element at R6 + R0 * 4 + Array::data_offset - 1
156 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset())); // Data 156 __ ldr(R6, FieldAddress(R1, GrowableObjectArray::data_offset())); // Data
157 __ add(R6, R6, Operand(R0, LSL, 2)); 157 __ add(R6, R6, Operand(R0, LSL, 2));
158 __ ldr(R0, FieldAddress(R6, Array::data_offset())); 158 __ ldr(R0, FieldAddress(R6, Array::data_offset()));
159 __ ret(); 159 __ ret();
160 __ Bind(&fall_through); 160 __ Bind(&fall_through);
161 } 161 }
162 162
163 163
164 // Set value into growable object array at specified index. 164 // Set value into growable object array at specified index.
165 // On stack: growable array (+2), index (+1), value (+0). 165 // On stack: growable array (+2), index (+1), value (+0).
166 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) { 166 void Intrinsifier::GrowableArraySetIndexed(Assembler* assembler) {
167 if (FLAG_enable_type_checks) { 167 if (FLAG_enable_type_checks) {
168 return; 168 return;
169 } 169 }
170 Label fall_through; 170 Label fall_through;
171 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index. 171 __ ldr(R1, Address(SP, 1 * kWordSize)); // Index.
172 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray. 172 __ ldr(R0, Address(SP, 2 * kWordSize)); // GrowableArray.
173 __ tsti(R1, kSmiTagMask); 173 __ tsti(R1, Immediate(kSmiTagMask));
174 __ b(&fall_through, NE); // Non-smi index. 174 __ b(&fall_through, NE); // Non-smi index.
175 // Range check using _length field. 175 // Range check using _length field.
176 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset())); 176 __ ldr(R2, FieldAddress(R0, GrowableObjectArray::length_offset()));
177 __ cmp(R1, Operand(R2)); 177 __ cmp(R1, Operand(R2));
178 // Runtime throws exception. 178 // Runtime throws exception.
179 __ b(&fall_through, CS); 179 __ b(&fall_through, CS);
180 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data. 180 __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); // data.
181 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value. 181 __ ldr(R2, Address(SP, 0 * kWordSize)); // Value.
182 // Note that R1 is Smi, i.e, times 2. 182 // Note that R1 is Smi, i.e, times 2.
183 ASSERT(kSmiTagShift == 1); 183 ASSERT(kSmiTagShift == 1);
184 __ add(R1, R0, Operand(R1, LSL, 2)); 184 __ add(R1, R0, Operand(R1, LSL, 2));
185 __ StoreIntoObject(R0, 185 __ StoreIntoObject(R0,
186 FieldAddress(R1, Array::data_offset()), 186 FieldAddress(R1, Array::data_offset()),
187 R2); 187 R2);
188 __ ret(); 188 __ ret();
189 __ Bind(&fall_through); 189 __ Bind(&fall_through);
190 } 190 }
191 191
192 192
193 // Set length of growable object array. The length cannot 193 // Set length of growable object array. The length cannot
194 // be greater than the length of the data container. 194 // be greater than the length of the data container.
195 // On stack: growable array (+1), length (+0). 195 // On stack: growable array (+1), length (+0).
196 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) { 196 void Intrinsifier::GrowableArraySetLength(Assembler* assembler) {
197 Label fall_through; 197 Label fall_through;
198 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 198 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
199 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value. 199 __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value.
200 __ tsti(R1, kSmiTagMask); // Check for Smi. 200 __ tsti(R1, Immediate(kSmiTagMask)); // Check for Smi.
201 __ b(&fall_through, NE); 201 __ b(&fall_through, NE);
202 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset())); 202 __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
203 __ ret(); 203 __ ret();
204 __ Bind(&fall_through); 204 __ Bind(&fall_through);
205 // Fall through on non-Smi. 205 // Fall through on non-Smi.
206 } 206 }
207 207
208 208
209 // Set data of growable object array. 209 // Set data of growable object array.
210 // On stack: growable array (+1), data (+0). 210 // On stack: growable array (+1), data (+0).
211 void Intrinsifier::GrowableArraySetData(Assembler* assembler) { 211 void Intrinsifier::GrowableArraySetData(Assembler* assembler) {
212 if (FLAG_enable_type_checks) { 212 if (FLAG_enable_type_checks) {
213 return; 213 return;
214 } 214 }
215 Label fall_through; 215 Label fall_through;
216 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data. 216 __ ldr(R1, Address(SP, 0 * kWordSize)); // Data.
217 // Check that data is an ObjectArray. 217 // Check that data is an ObjectArray.
218 __ tsti(R1, kSmiTagMask); 218 __ tsti(R1, Immediate(kSmiTagMask));
219 __ b(&fall_through, EQ); // Data is Smi. 219 __ b(&fall_through, EQ); // Data is Smi.
220 __ CompareClassId(R1, kArrayCid, kNoPP); 220 __ CompareClassId(R1, kArrayCid, kNoPP);
221 __ b(&fall_through, NE); 221 __ b(&fall_through, NE);
222 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. 222 __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array.
223 __ StoreIntoObject(R0, 223 __ StoreIntoObject(R0,
224 FieldAddress(R0, GrowableObjectArray::data_offset()), 224 FieldAddress(R0, GrowableObjectArray::data_offset()),
225 R1); 225 R1);
226 __ ret(); 226 __ ret();
227 __ Bind(&fall_through); 227 __ Bind(&fall_through);
228 } 228 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 return -1; 276 return -1;
277 } 277 }
278 278
279 279
280 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \ 280 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift) \
281 Label fall_through; \ 281 Label fall_through; \
282 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \ 282 const intptr_t kArrayLengthStackOffset = 0 * kWordSize; \
283 __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \ 283 __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \
284 /* Check that length is a positive Smi. */ \ 284 /* Check that length is a positive Smi. */ \
285 /* R2: requested array length argument. */ \ 285 /* R2: requested array length argument. */ \
286 __ tsti(R2, kSmiTagMask); \ 286 __ tsti(R2, Immediate(kSmiTagMask)); \
287 __ b(&fall_through, NE); \ 287 __ b(&fall_through, NE); \
288 __ CompareRegisters(R2, ZR); \ 288 __ CompareRegisters(R2, ZR); \
289 __ b(&fall_through, LT); \ 289 __ b(&fall_through, LT); \
290 __ SmiUntag(R2); \ 290 __ SmiUntag(R2); \
291 /* Check for maximum allowed length. */ \ 291 /* Check for maximum allowed length. */ \
292 /* R2: untagged array length. */ \ 292 /* R2: untagged array length. */ \
293 __ CompareImmediate(R2, max_len, kNoPP); \ 293 __ CompareImmediate(R2, max_len, kNoPP); \
294 __ b(&fall_through, GT); \ 294 __ b(&fall_through, GT); \
295 __ LslImmediate(R2, R2, scale_shift); \ 295 __ LslImmediate(R2, R2, scale_shift); \
296 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ 296 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \
297 __ AddImmediate(R2, R2, fixed_size, kNoPP); \ 297 __ AddImmediate(R2, R2, fixed_size, kNoPP); \
298 __ andi(R2, R2, ~(kObjectAlignment - 1)); \ 298 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \
299 Heap* heap = Isolate::Current()->heap(); \ 299 Heap* heap = Isolate::Current()->heap(); \
300 Heap::Space space = heap->SpaceForAllocation(cid); \ 300 Heap::Space space = heap->SpaceForAllocation(cid); \
301 __ LoadImmediate(R0, heap->TopAddress(space), kNoPP); \ 301 __ LoadImmediate(R0, heap->TopAddress(space), kNoPP); \
302 __ ldr(R0, Address(R0, 0)); \ 302 __ ldr(R0, Address(R0, 0)); \
303 \ 303 \
304 /* R2: allocation size. */ \ 304 /* R2: allocation size. */ \
305 __ add(R1, R0, Operand(R2)); \ 305 __ add(R1, R0, Operand(R2)); \
306 __ b(&fall_through, VS); \ 306 __ b(&fall_through, VS); \
307 \ 307 \
308 /* Check if the allocation fits into the remaining space. */ \ 308 /* Check if the allocation fits into the remaining space. */ \
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) 378 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
379 #undef TYPED_DATA_ALLOCATOR 379 #undef TYPED_DATA_ALLOCATOR
380 380
381 381
382 // Loads args from stack into R0 and R1 382 // Loads args from stack into R0 and R1
383 // Tests if they are smis, jumps to label not_smi if not. 383 // Tests if they are smis, jumps to label not_smi if not.
384 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 384 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
385 __ ldr(R0, Address(SP, + 0 * kWordSize)); 385 __ ldr(R0, Address(SP, + 0 * kWordSize));
386 __ ldr(R1, Address(SP, + 1 * kWordSize)); 386 __ ldr(R1, Address(SP, + 1 * kWordSize));
387 __ orr(TMP, R0, Operand(R1)); 387 __ orr(TMP, R0, Operand(R1));
388 __ tsti(TMP, kSmiTagMask); 388 __ tsti(TMP, Immediate(kSmiTagMask));
389 __ b(not_smi, NE); 389 __ b(not_smi, NE);
390 } 390 }
391 391
392 392
393 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 393 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
394 Label fall_through; 394 Label fall_through;
395 TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis. 395 TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis.
396 __ adds(R0, R0, Operand(R1)); // Adds. 396 __ adds(R0, R0, Operand(R1)); // Adds.
397 __ b(&fall_through, VS); // Fall-through on overflow. 397 __ b(&fall_through, VS); // Fall-through on overflow.
398 __ ret(); 398 __ ret();
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 // } else { 503 // } else {
504 // res = res + right; 504 // res = res + right;
505 // } 505 // }
506 // } 506 // }
507 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { 507 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
508 // Check to see if we have integer division 508 // Check to see if we have integer division
509 Label neg_remainder, fall_through; 509 Label neg_remainder, fall_through;
510 __ ldr(R1, Address(SP, + 0 * kWordSize)); 510 __ ldr(R1, Address(SP, + 0 * kWordSize));
511 __ ldr(R0, Address(SP, + 1 * kWordSize)); 511 __ ldr(R0, Address(SP, + 1 * kWordSize));
512 __ orr(TMP, R0, Operand(R1)); 512 __ orr(TMP, R0, Operand(R1));
513 __ tsti(TMP, kSmiTagMask); 513 __ tsti(TMP, Immediate(kSmiTagMask));
514 __ b(&fall_through, NE); 514 __ b(&fall_through, NE);
515 // R1: Tagged left (dividend). 515 // R1: Tagged left (dividend).
516 // R0: Tagged right (divisor). 516 // R0: Tagged right (divisor).
517 // Check if modulo by zero -> exception thrown in main function. 517 // Check if modulo by zero -> exception thrown in main function.
518 __ CompareRegisters(R0, ZR); 518 __ CompareRegisters(R0, ZR);
519 __ b(&fall_through, EQ); 519 __ b(&fall_through, EQ);
520 EmitRemainderOperation(assembler); 520 EmitRemainderOperation(assembler);
521 // Untagged right in R0. Untagged remainder result in R1. 521 // Untagged right in R0. Untagged remainder result in R1.
522 522
523 __ CompareRegisters(R1, ZR); 523 __ CompareRegisters(R1, ZR);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 __ b(&fall_through, EQ); 557 __ b(&fall_through, EQ);
558 __ SmiTag(R0); // Not equal. Okay to tag and return. 558 __ SmiTag(R0); // Not equal. Okay to tag and return.
559 __ ret(); // Return. 559 __ ret(); // Return.
560 __ Bind(&fall_through); 560 __ Bind(&fall_through);
561 } 561 }
562 562
563 563
564 void Intrinsifier::Integer_negate(Assembler* assembler) { 564 void Intrinsifier::Integer_negate(Assembler* assembler) {
565 Label fall_through; 565 Label fall_through;
566 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Grab first argument. 566 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Grab first argument.
567 __ tsti(R0, kSmiTagMask); // Test for Smi. 567 __ tsti(R0, Immediate(kSmiTagMask)); // Test for Smi.
568 __ b(&fall_through, NE); 568 __ b(&fall_through, NE);
569 __ negs(R0, R0); 569 __ negs(R0, R0);
570 __ b(&fall_through, VS); 570 __ b(&fall_through, VS);
571 __ ret(); 571 __ ret();
572 __ Bind(&fall_through); 572 __ Bind(&fall_through);
573 } 573 }
574 574
575 575
576 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 576 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
577 Label fall_through; 577 Label fall_through;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 // can be Smi, Mint, Bigint or double. 687 // can be Smi, Mint, Bigint or double.
688 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 688 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
689 Label fall_through, true_label, check_for_mint; 689 Label fall_through, true_label, check_for_mint;
690 // For integer receiver '===' check first. 690 // For integer receiver '===' check first.
691 __ ldr(R0, Address(SP, 0 * kWordSize)); 691 __ ldr(R0, Address(SP, 0 * kWordSize));
692 __ ldr(R1, Address(SP, 1 * kWordSize)); 692 __ ldr(R1, Address(SP, 1 * kWordSize));
693 __ cmp(R0, Operand(R1)); 693 __ cmp(R0, Operand(R1));
694 __ b(&true_label, EQ); 694 __ b(&true_label, EQ);
695 695
696 __ orr(R2, R0, Operand(R1)); 696 __ orr(R2, R0, Operand(R1));
697 __ tsti(R2, kSmiTagMask); 697 __ tsti(R2, Immediate(kSmiTagMask));
698 __ b(&check_for_mint, NE); // If R0 or R1 is not a smi do Mint checks. 698 __ b(&check_for_mint, NE); // If R0 or R1 is not a smi do Mint checks.
699 699
700 // Both arguments are smi, '===' is good enough. 700 // Both arguments are smi, '===' is good enough.
701 __ LoadObject(R0, Bool::False(), PP); 701 __ LoadObject(R0, Bool::False(), PP);
702 __ ret(); 702 __ ret();
703 __ Bind(&true_label); 703 __ Bind(&true_label);
704 __ LoadObject(R0, Bool::True(), PP); 704 __ LoadObject(R0, Bool::True(), PP);
705 __ ret(); 705 __ ret();
706 706
707 // At least one of the arguments was not Smi. 707 // At least one of the arguments was not Smi.
708 Label receiver_not_smi; 708 Label receiver_not_smi;
709 __ Bind(&check_for_mint); 709 __ Bind(&check_for_mint);
710 710
711 __ tsti(R1, kSmiTagMask); // Check receiver. 711 __ tsti(R1, Immediate(kSmiTagMask)); // Check receiver.
712 __ b(&receiver_not_smi, NE); 712 __ b(&receiver_not_smi, NE);
713 713
714 // Left (receiver) is Smi, return false if right is not Double. 714 // Left (receiver) is Smi, return false if right is not Double.
715 // Note that an instance of Mint or Bigint never contains a value that can be 715 // Note that an instance of Mint or Bigint never contains a value that can be
716 // represented by Smi. 716 // represented by Smi.
717 717
718 __ CompareClassId(R0, kDoubleCid, kNoPP); 718 __ CompareClassId(R0, kDoubleCid, kNoPP);
719 __ b(&fall_through, EQ); 719 __ b(&fall_through, EQ);
720 __ LoadObject(R0, Bool::False(), PP); // Smi == Mint -> false. 720 __ LoadObject(R0, Bool::False(), PP); // Smi == Mint -> false.
721 __ ret(); 721 __ ret();
722 722
723 __ Bind(&receiver_not_smi); 723 __ Bind(&receiver_not_smi);
724 // R1: receiver. 724 // R1: receiver.
725 725
726 __ CompareClassId(R1, kMintCid, kNoPP); 726 __ CompareClassId(R1, kMintCid, kNoPP);
727 __ b(&fall_through, NE); 727 __ b(&fall_through, NE);
728 // Receiver is Mint, return false if right is Smi. 728 // Receiver is Mint, return false if right is Smi.
729 __ tsti(R0, kSmiTagMask); 729 __ tsti(R0, Immediate(kSmiTagMask));
730 __ b(&fall_through, NE); 730 __ b(&fall_through, NE);
731 __ LoadObject(R0, Bool::False(), PP); 731 __ LoadObject(R0, Bool::False(), PP);
732 __ ret(); 732 __ ret();
733 // TODO(srdjan): Implement Mint == Mint comparison. 733 // TODO(srdjan): Implement Mint == Mint comparison.
734 734
735 __ Bind(&fall_through); 735 __ Bind(&fall_through);
736 } 736 }
737 737
738 738
739 void Intrinsifier::Integer_equal(Assembler* assembler) { 739 void Intrinsifier::Integer_equal(Assembler* assembler) {
(...skipping 20 matching lines...) Expand all
760 __ asrv(R0, R1, R0); 760 __ asrv(R0, R1, R0);
761 __ SmiTag(R0); 761 __ SmiTag(R0);
762 __ ret(); 762 __ ret();
763 __ Bind(&fall_through); 763 __ Bind(&fall_through);
764 } 764 }
765 765
766 766
767 void Intrinsifier::Smi_bitNegate(Assembler* assembler) { 767 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
768 __ ldr(R0, Address(SP, 0 * kWordSize)); 768 __ ldr(R0, Address(SP, 0 * kWordSize));
769 __ mvn(R0, R0); 769 __ mvn(R0, R0);
770 __ andi(R0, R0, ~kSmiTagMask); // Remove inverted smi-tag. 770 __ andi(R0, R0, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
771 __ ret(); 771 __ ret();
772 } 772 }
773 773
774 774
775 void Intrinsifier::Smi_bitLength(Assembler* assembler) { 775 void Intrinsifier::Smi_bitLength(Assembler* assembler) {
776 // TODO(sra): Implement as word-length - CLZ. 776 // TODO(sra): Implement as word-length - CLZ.
777 } 777 }
778 778
779 779
780 void Intrinsifier::Bigint_setNeg(Assembler* assembler) { 780 void Intrinsifier::Bigint_setNeg(Assembler* assembler) {
(...skipping 25 matching lines...) Expand all
806 } 806 }
807 807
808 808
809 // Check if the last argument is a double, jump to label 'is_smi' if smi 809 // Check if the last argument is a double, jump to label 'is_smi' if smi
810 // (easy to convert to double), otherwise jump to label 'not_double_smi', 810 // (easy to convert to double), otherwise jump to label 'not_double_smi',
811 // Returns the last argument in R0. 811 // Returns the last argument in R0.
812 static void TestLastArgumentIsDouble(Assembler* assembler, 812 static void TestLastArgumentIsDouble(Assembler* assembler,
813 Label* is_smi, 813 Label* is_smi,
814 Label* not_double_smi) { 814 Label* not_double_smi) {
815 __ ldr(R0, Address(SP, 0 * kWordSize)); 815 __ ldr(R0, Address(SP, 0 * kWordSize));
816 __ tsti(R0, kSmiTagMask); 816 __ tsti(R0, Immediate(kSmiTagMask));
817 __ b(is_smi, EQ); 817 __ b(is_smi, EQ);
818 __ CompareClassId(R0, kDoubleCid, kNoPP); 818 __ CompareClassId(R0, kDoubleCid, kNoPP);
819 __ b(not_double_smi, NE); 819 __ b(not_double_smi, NE);
820 // Fall through with Double in R0. 820 // Fall through with Double in R0.
821 } 821 }
822 822
823 823
824 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown 824 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown
825 // type. Return true or false object in the register R0. Any NaN argument 825 // type. Return true or false object in the register R0. Any NaN argument
826 // returns false. Any non-double arg1 causes control flow to fall through to the 826 // returns false. Any non-double arg1 causes control flow to fall through to the
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 void Intrinsifier::Double_div(Assembler* assembler) { 923 void Intrinsifier::Double_div(Assembler* assembler) {
924 DoubleArithmeticOperations(assembler, Token::kDIV); 924 DoubleArithmeticOperations(assembler, Token::kDIV);
925 } 925 }
926 926
927 927
928 // Left is double right is integer (Bigint, Mint or Smi) 928 // Left is double right is integer (Bigint, Mint or Smi)
929 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) { 929 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
930 Label fall_through; 930 Label fall_through;
931 // Only smis allowed. 931 // Only smis allowed.
932 __ ldr(R0, Address(SP, 0 * kWordSize)); 932 __ ldr(R0, Address(SP, 0 * kWordSize));
933 __ tsti(R0, kSmiTagMask); 933 __ tsti(R0, Immediate(kSmiTagMask));
934 __ b(&fall_through, NE); 934 __ b(&fall_through, NE);
935 // Is Smi. 935 // Is Smi.
936 __ SmiUntag(R0); 936 __ SmiUntag(R0);
937 __ scvtfd(V1, R0); 937 __ scvtfd(V1, R0);
938 __ ldr(R0, Address(SP, 1 * kWordSize)); 938 __ ldr(R0, Address(SP, 1 * kWordSize));
939 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); 939 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
940 __ fmuld(V0, V0, V1); 940 __ fmuld(V0, V0, V1);
941 const Class& double_class = Class::Handle( 941 const Class& double_class = Class::Handle(
942 Isolate::Current()->object_store()->double_class()); 942 Isolate::Current()->object_store()->double_class());
943 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); 943 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
944 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); 944 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
945 __ ret(); 945 __ ret();
946 __ Bind(&fall_through); 946 __ Bind(&fall_through);
947 } 947 }
948 948
949 949
950 void Intrinsifier::DoubleFromInteger(Assembler* assembler) { 950 void Intrinsifier::DoubleFromInteger(Assembler* assembler) {
951 Label fall_through; 951 Label fall_through;
952 952
953 __ ldr(R0, Address(SP, 0 * kWordSize)); 953 __ ldr(R0, Address(SP, 0 * kWordSize));
954 __ tsti(R0, kSmiTagMask); 954 __ tsti(R0, Immediate(kSmiTagMask));
955 __ b(&fall_through, NE); 955 __ b(&fall_through, NE);
956 // Is Smi. 956 // Is Smi.
957 __ SmiUntag(R0); 957 __ SmiUntag(R0);
958 __ scvtfd(V0, R0); 958 __ scvtfd(V0, R0);
959 const Class& double_class = Class::Handle( 959 const Class& double_class = Class::Handle(
960 Isolate::Current()->object_store()->double_class()); 960 Isolate::Current()->object_store()->double_class());
961 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP); 961 __ TryAllocate(double_class, &fall_through, R0, R1, kNoPP);
962 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP); 962 __ StoreDFieldToOffset(V0, R0, Double::value_offset(), kNoPP);
963 __ ret(); 963 __ ret();
964 __ Bind(&fall_through); 964 __ Bind(&fall_through);
(...skipping 29 matching lines...) Expand all
994 __ Bind(&is_true); 994 __ Bind(&is_true);
995 __ mov(R0, true_reg); 995 __ mov(R0, true_reg);
996 996
997 __ Bind(&is_false); 997 __ Bind(&is_false);
998 __ ret(); 998 __ ret();
999 999
1000 __ Bind(&is_zero); 1000 __ Bind(&is_zero);
1001 // Check for negative zero by looking at the sign bit. 1001 // Check for negative zero by looking at the sign bit.
1002 __ fmovrd(R1, V0); 1002 __ fmovrd(R1, V0);
1003 __ LsrImmediate(R1, R1, 63); 1003 __ LsrImmediate(R1, R1, 63);
1004 __ tsti(R1, 1); 1004 __ tsti(R1, Immediate(1));
1005 __ csel(R0, true_reg, false_reg, NE); // Sign bit set. 1005 __ csel(R0, true_reg, false_reg, NE); // Sign bit set.
1006 __ ret(); 1006 __ ret();
1007 } 1007 }
1008 1008
1009 1009
1010 void Intrinsifier::DoubleToInteger(Assembler* assembler) { 1010 void Intrinsifier::DoubleToInteger(Assembler* assembler) {
1011 Label fall_through; 1011 Label fall_through;
1012 1012
1013 __ ldr(R0, Address(SP, 0 * kWordSize)); 1013 __ ldr(R0, Address(SP, 0 * kWordSize));
1014 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP); 1014 __ LoadDFieldFromOffset(V0, R0, Double::value_offset(), kNoPP);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1071 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver. 1071 __ ldr(R0, Address(SP, 0 * kWordSize)); // Receiver.
1072 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'. 1072 __ ldr(R1, FieldAddress(R0, state_field.Offset())); // Field '_state'.
1073 1073
1074 // Addresses of _state[0]. 1074 // Addresses of _state[0].
1075 const int64_t disp = 1075 const int64_t disp =
1076 Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag; 1076 Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag;
1077 1077
1078 __ LoadImmediate(R0, a_int_value, kNoPP); 1078 __ LoadImmediate(R0, a_int_value, kNoPP);
1079 __ LoadFromOffset(R2, R1, disp, kNoPP); 1079 __ LoadFromOffset(R2, R1, disp, kNoPP);
1080 __ LsrImmediate(R3, R2, 32); 1080 __ LsrImmediate(R3, R2, 32);
1081 __ andi(R2, R2, 0xffffffff); 1081 __ andi(R2, R2, Immediate(0xffffffff));
1082 __ mul(R2, R0, R2); 1082 __ mul(R2, R0, R2);
1083 __ add(R2, R2, Operand(R3)); 1083 __ add(R2, R2, Operand(R3));
1084 __ StoreToOffset(R2, R1, disp, kNoPP); 1084 __ StoreToOffset(R2, R1, disp, kNoPP);
1085 __ ret(); 1085 __ ret();
1086 } 1086 }
1087 1087
1088 1088
1089 void Intrinsifier::ObjectEquals(Assembler* assembler) { 1089 void Intrinsifier::ObjectEquals(Assembler* assembler) {
1090 __ ldr(R0, Address(SP, 0 * kWordSize)); 1090 __ ldr(R0, Address(SP, 0 * kWordSize));
1091 __ ldr(R1, Address(SP, 1 * kWordSize)); 1091 __ ldr(R1, Address(SP, 1 * kWordSize));
(...skipping 15 matching lines...) Expand all
1107 // Hash not yet computed. 1107 // Hash not yet computed.
1108 __ Bind(&fall_through); 1108 __ Bind(&fall_through);
1109 } 1109 }
1110 1110
1111 1111
1112 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { 1112 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) {
1113 Label fall_through, try_two_byte_string; 1113 Label fall_through, try_two_byte_string;
1114 1114
1115 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1115 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1116 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1116 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1117 __ tsti(R1, kSmiTagMask); 1117 __ tsti(R1, Immediate(kSmiTagMask));
1118 __ b(&fall_through, NE); // Index is not a Smi. 1118 __ b(&fall_through, NE); // Index is not a Smi.
1119 // Range check. 1119 // Range check.
1120 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1120 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1121 __ cmp(R1, Operand(R2)); 1121 __ cmp(R1, Operand(R2));
1122 __ b(&fall_through, CS); // Runtime throws exception. 1122 __ b(&fall_through, CS); // Runtime throws exception.
1123 __ CompareClassId(R0, kOneByteStringCid, kNoPP); 1123 __ CompareClassId(R0, kOneByteStringCid, kNoPP);
1124 __ b(&try_two_byte_string, NE); 1124 __ b(&try_two_byte_string, NE);
1125 __ SmiUntag(R1); 1125 __ SmiUntag(R1);
1126 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP); 1126 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
1127 __ ldr(R0, Address(R0, R1), kUnsignedByte); 1127 __ ldr(R0, Address(R0, R1), kUnsignedByte);
(...skipping 11 matching lines...) Expand all
1139 1139
1140 __ Bind(&fall_through); 1140 __ Bind(&fall_through);
1141 } 1141 }
1142 1142
1143 1143
1144 void Intrinsifier::StringBaseCharAt(Assembler* assembler) { 1144 void Intrinsifier::StringBaseCharAt(Assembler* assembler) {
1145 Label fall_through, try_two_byte_string; 1145 Label fall_through, try_two_byte_string;
1146 1146
1147 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index. 1147 __ ldr(R1, Address(SP, 0 * kWordSize)); // Index.
1148 __ ldr(R0, Address(SP, 1 * kWordSize)); // String. 1148 __ ldr(R0, Address(SP, 1 * kWordSize)); // String.
1149 __ tsti(R1, kSmiTagMask); 1149 __ tsti(R1, Immediate(kSmiTagMask));
1150 __ b(&fall_through, NE); // Index is not a Smi. 1150 __ b(&fall_through, NE); // Index is not a Smi.
1151 // Range check. 1151 // Range check.
1152 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1152 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1153 __ cmp(R1, Operand(R2)); 1153 __ cmp(R1, Operand(R2));
1154 __ b(&fall_through, CS); // Runtime throws exception. 1154 __ b(&fall_through, CS); // Runtime throws exception.
1155 1155
1156 __ CompareClassId(R0, kOneByteStringCid, kNoPP); 1156 __ CompareClassId(R0, kOneByteStringCid, kNoPP);
1157 __ b(&try_two_byte_string, NE); 1157 __ b(&try_two_byte_string, NE);
1158 __ SmiUntag(R1); 1158 __ SmiUntag(R1);
1159 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP); 1159 __ AddImmediate(R0, R0, OneByteString::data_offset() - kHeapObjectTag, kNoPP);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 static void TryAllocateOnebyteString(Assembler* assembler, 1265 static void TryAllocateOnebyteString(Assembler* assembler,
1266 Label* ok, 1266 Label* ok,
1267 Label* failure) { 1267 Label* failure) {
1268 const Register length_reg = R2; 1268 const Register length_reg = R2;
1269 Label fail; 1269 Label fail;
1270 1270
1271 __ mov(R6, length_reg); // Save the length register. 1271 __ mov(R6, length_reg); // Save the length register.
1272 __ SmiUntag(length_reg); 1272 __ SmiUntag(length_reg);
1273 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; 1273 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1;
1274 __ AddImmediate(length_reg, length_reg, fixed_size, kNoPP); 1274 __ AddImmediate(length_reg, length_reg, fixed_size, kNoPP);
1275 __ andi(length_reg, length_reg, ~(kObjectAlignment - 1)); 1275 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1)));
1276 1276
1277 Isolate* isolate = Isolate::Current(); 1277 Isolate* isolate = Isolate::Current();
1278 Heap* heap = isolate->heap(); 1278 Heap* heap = isolate->heap();
1279 const intptr_t cid = kOneByteStringCid; 1279 const intptr_t cid = kOneByteStringCid;
1280 Heap::Space space = heap->SpaceForAllocation(cid); 1280 Heap::Space space = heap->SpaceForAllocation(cid);
1281 __ LoadImmediate(R3, heap->TopAddress(space), kNoPP); 1281 __ LoadImmediate(R3, heap->TopAddress(space), kNoPP);
1282 __ ldr(R0, Address(R3)); 1282 __ ldr(R0, Address(R3));
1283 1283
1284 // length_reg: allocation size. 1284 // length_reg: allocation size.
1285 __ adds(R1, R0, Operand(length_reg)); 1285 __ adds(R1, R0, Operand(length_reg));
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 // The indexes must be valid. 1339 // The indexes must be valid.
1340 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { 1340 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
1341 const intptr_t kStringOffset = 2 * kWordSize; 1341 const intptr_t kStringOffset = 2 * kWordSize;
1342 const intptr_t kStartIndexOffset = 1 * kWordSize; 1342 const intptr_t kStartIndexOffset = 1 * kWordSize;
1343 const intptr_t kEndIndexOffset = 0 * kWordSize; 1343 const intptr_t kEndIndexOffset = 0 * kWordSize;
1344 Label fall_through, ok; 1344 Label fall_through, ok;
1345 1345
1346 __ ldr(R2, Address(SP, kEndIndexOffset)); 1346 __ ldr(R2, Address(SP, kEndIndexOffset));
1347 __ ldr(TMP, Address(SP, kStartIndexOffset)); 1347 __ ldr(TMP, Address(SP, kStartIndexOffset));
1348 __ orr(R3, R2, Operand(TMP)); 1348 __ orr(R3, R2, Operand(TMP));
1349 __ tsti(R3, kSmiTagMask); 1349 __ tsti(R3, Immediate(kSmiTagMask));
1350 __ b(&fall_through, NE); // 'start', 'end' not Smi. 1350 __ b(&fall_through, NE); // 'start', 'end' not Smi.
1351 1351
1352 __ sub(R2, R2, Operand(TMP)); 1352 __ sub(R2, R2, Operand(TMP));
1353 TryAllocateOnebyteString(assembler, &ok, &fall_through); 1353 TryAllocateOnebyteString(assembler, &ok, &fall_through);
1354 __ Bind(&ok); 1354 __ Bind(&ok);
1355 // R0: new string as tagged pointer. 1355 // R0: new string as tagged pointer.
1356 // Copy string. 1356 // Copy string.
1357 __ ldr(R3, Address(SP, kStringOffset)); 1357 __ ldr(R3, Address(SP, kStringOffset));
1358 __ ldr(R1, Address(SP, kStartIndexOffset)); 1358 __ ldr(R1, Address(SP, kStartIndexOffset));
1359 __ SmiUntag(R1); 1359 __ SmiUntag(R1);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 void StringEquality(Assembler* assembler, intptr_t string_cid) { 1422 void StringEquality(Assembler* assembler, intptr_t string_cid) {
1423 Label fall_through, is_true, is_false, loop; 1423 Label fall_through, is_true, is_false, loop;
1424 __ ldr(R0, Address(SP, 1 * kWordSize)); // This. 1424 __ ldr(R0, Address(SP, 1 * kWordSize)); // This.
1425 __ ldr(R1, Address(SP, 0 * kWordSize)); // Other. 1425 __ ldr(R1, Address(SP, 0 * kWordSize)); // Other.
1426 1426
1427 // Are identical? 1427 // Are identical?
1428 __ cmp(R0, Operand(R1)); 1428 __ cmp(R0, Operand(R1));
1429 __ b(&is_true, EQ); 1429 __ b(&is_true, EQ);
1430 1430
1431 // Is other OneByteString? 1431 // Is other OneByteString?
1432 __ tsti(R1, kSmiTagMask); 1432 __ tsti(R1, Immediate(kSmiTagMask));
1433 __ b(&fall_through, EQ); 1433 __ b(&fall_through, EQ);
1434 __ CompareClassId(R1, string_cid, kNoPP); 1434 __ CompareClassId(R1, string_cid, kNoPP);
1435 __ b(&fall_through, NE); 1435 __ b(&fall_through, NE);
1436 1436
1437 // Have same length? 1437 // Have same length?
1438 __ ldr(R2, FieldAddress(R0, String::length_offset())); 1438 __ ldr(R2, FieldAddress(R0, String::length_offset()));
1439 __ ldr(R3, FieldAddress(R1, String::length_offset())); 1439 __ ldr(R3, FieldAddress(R1, String::length_offset()));
1440 __ cmp(R2, Operand(R3)); 1440 __ cmp(R2, Operand(R3));
1441 __ b(&is_false, NE); 1441 __ b(&is_false, NE);
1442 1442
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 Isolate* isolate = Isolate::Current(); 1527 Isolate* isolate = Isolate::Current();
1528 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP); 1528 __ LoadImmediate(R1, reinterpret_cast<uword>(isolate), kNoPP);
1529 // Set return value to Isolate::current_tag_. 1529 // Set return value to Isolate::current_tag_.
1530 __ ldr(R0, Address(R1, Isolate::current_tag_offset())); 1530 __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
1531 __ ret(); 1531 __ ret();
1532 } 1532 }
1533 1533
1534 } // namespace dart 1534 } // namespace dart
1535 1535
1536 #endif // defined TARGET_ARCH_ARM64 1536 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698