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

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

Issue 251083007: Removes loads from PP from stubs on arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 // Save current Context pointer into Isolate structure. 157 // Save current Context pointer into Isolate structure.
158 __ StoreToOffset(CTX, R0, Isolate::top_context_offset()); 158 __ StoreToOffset(CTX, R0, Isolate::top_context_offset());
159 159
160 // Cache Isolate pointer into CTX while executing native code. 160 // Cache Isolate pointer into CTX while executing native code.
161 __ mov(CTX, R0); 161 __ mov(CTX, R0);
162 162
163 #if defined(DEBUG) 163 #if defined(DEBUG)
164 { Label ok; 164 { Label ok;
165 // Check that we are always entering from Dart code. 165 // Check that we are always entering from Dart code.
166 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset()); 166 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset());
167 __ CompareImmediate(R6, VMTag::kScriptTagId, PP); 167 __ CompareImmediate(R6, VMTag::kScriptTagId, kNoRegister);
168 __ b(&ok, EQ); 168 __ b(&ok, EQ);
169 __ Stop("Not coming from Dart code."); 169 __ Stop("Not coming from Dart code.");
170 __ Bind(&ok); 170 __ Bind(&ok);
171 } 171 }
172 #endif 172 #endif
173 173
174 // Mark that the isolate is executing Native code. 174 // Mark that the isolate is executing Native code.
175 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset()); 175 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset());
176 176
177 // Reserve space for the native arguments structure passed on the stack (the 177 // Reserve space for the native arguments structure passed on the stack (the
(...skipping 10 matching lines...) Expand all
188 // There are no native calls to closures, so we do not need to set the tag 188 // There are no native calls to closures, so we do not need to set the tag
189 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 189 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
190 ASSERT(argc_tag_offset == 1 * kWordSize); 190 ASSERT(argc_tag_offset == 1 * kWordSize);
191 // Set argc in NativeArguments: R1 already contains argc. 191 // Set argc in NativeArguments: R1 already contains argc.
192 192
193 ASSERT(argv_offset == 2 * kWordSize); 193 ASSERT(argv_offset == 2 * kWordSize);
194 // Set argv in NativeArguments: R2 already contains argv. 194 // Set argv in NativeArguments: R2 already contains argv.
195 195
196 // Set retval in NativeArgs. 196 // Set retval in NativeArgs.
197 ASSERT(retval_offset == 3 * kWordSize); 197 ASSERT(retval_offset == 3 * kWordSize);
198 __ AddImmediate(R3, FP, 2 * kWordSize, PP); 198 __ AddImmediate(R3, FP, 2 * kWordSize, kNoRegister);
199 199
200 // TODO(regis): Should we pass the structure by value as in runtime calls? 200 // TODO(regis): Should we pass the structure by value as in runtime calls?
201 // It would require changing Dart API for native functions. 201 // It would require changing Dart API for native functions.
202 // For now, space is reserved on the stack and we pass a pointer to it. 202 // For now, space is reserved on the stack and we pass a pointer to it.
203 __ StoreToOffset(R0, SP, isolate_offset); 203 __ StoreToOffset(R0, SP, isolate_offset);
204 __ StoreToOffset(R1, SP, argc_tag_offset); 204 __ StoreToOffset(R1, SP, argc_tag_offset);
205 __ StoreToOffset(R2, SP, argv_offset); 205 __ StoreToOffset(R2, SP, argv_offset);
206 __ StoreToOffset(R3, SP, retval_offset); 206 __ StoreToOffset(R3, SP, retval_offset);
207 __ mov(R0, SP); // Pass the pointer to the NativeArguments. 207 __ mov(R0, SP); // Pass the pointer to the NativeArguments.
208 208
209 // Call native function (setsup scope if not leaf function). 209 // Call native function (setsup scope if not leaf function).
210 Label leaf_call; 210 Label leaf_call;
211 Label done; 211 Label done;
212 __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask(), PP); 212 __ TestImmediate(R1, NativeArguments::AutoSetupScopeMask(), kNoRegister);
213 __ b(&leaf_call, EQ); 213 __ b(&leaf_call, EQ);
214 214
215 __ mov(R1, R5); // Pass the function entrypoint to call. 215 __ mov(R1, R5); // Pass the function entrypoint to call.
216 // Call native function invocation wrapper or redirection via simulator. 216 // Call native function invocation wrapper or redirection via simulator.
217 #if defined(USING_SIMULATOR) 217 #if defined(USING_SIMULATOR)
218 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper); 218 uword entry = reinterpret_cast<uword>(NativeEntry::NativeCallWrapper);
219 entry = Simulator::RedirectExternalReference( 219 entry = Simulator::RedirectExternalReference(
220 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments); 220 entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
221 __ LoadImmediate(R2, entry, PP); 221 __ LoadImmediate(R2, entry, kNoRegister);
222 __ blr(R2); 222 __ blr(R2);
223 #else 223 #else
224 __ BranchLink(&NativeEntry::NativeCallWrapperLabel()); 224 __ BranchLink(&NativeEntry::NativeCallWrapperLabel());
225 #endif 225 #endif
226 __ b(&done); 226 __ b(&done);
227 227
228 __ Bind(&leaf_call); 228 __ Bind(&leaf_call);
229 // Call native function or redirection via simulator. 229 // Call native function or redirection via simulator.
230 __ blr(R5); 230 __ blr(R5);
231 231
232 __ Bind(&done); 232 __ Bind(&done);
233 233
234 // Mark that the isolate is executing Dart code. 234 // Mark that the isolate is executing Dart code.
235 __ LoadImmediate(R2, VMTag::kScriptTagId, PP); 235 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoRegister);
236 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset()); 236 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset());
237 237
238 // Reset exit frame information in Isolate structure. 238 // Reset exit frame information in Isolate structure.
239 __ LoadImmediate(R2, 0, PP); 239 __ LoadImmediate(R2, 0, kNoRegister);
240 __ StoreToOffset(R2, CTX, Isolate::top_exit_frame_info_offset()); 240 __ StoreToOffset(R2, CTX, Isolate::top_exit_frame_info_offset());
241 241
242 // Load Context pointer from Isolate structure into R2. 242 // Load Context pointer from Isolate structure into R2.
243 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset()); 243 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset());
244 244
245 // Reset Context pointer in Isolate structure. 245 // Reset Context pointer in Isolate structure.
246 __ LoadObject(R3, Object::null_object(), PP); 246 __ LoadObject(R3, Object::null_object(), PP);
247 __ StoreToOffset(R3, CTX, Isolate::top_context_offset()); 247 __ StoreToOffset(R3, CTX, Isolate::top_context_offset());
248 248
249 // Cache Context pointer into CTX while executing Dart code. 249 // Cache Context pointer into CTX while executing Dart code.
(...skipping 29 matching lines...) Expand all
279 // Save current Context pointer into Isolate structure. 279 // Save current Context pointer into Isolate structure.
280 __ StoreToOffset(CTX, R0, Isolate::top_context_offset()); 280 __ StoreToOffset(CTX, R0, Isolate::top_context_offset());
281 281
282 // Cache Isolate pointer into CTX while executing native code. 282 // Cache Isolate pointer into CTX while executing native code.
283 __ mov(CTX, R0); 283 __ mov(CTX, R0);
284 284
285 #if defined(DEBUG) 285 #if defined(DEBUG)
286 { Label ok; 286 { Label ok;
287 // Check that we are always entering from Dart code. 287 // Check that we are always entering from Dart code.
288 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset()); 288 __ LoadFromOffset(R6, CTX, Isolate::vm_tag_offset());
289 __ CompareImmediate(R6, VMTag::kScriptTagId, PP); 289 __ CompareImmediate(R6, VMTag::kScriptTagId, kNoRegister);
290 __ b(&ok, EQ); 290 __ b(&ok, EQ);
291 __ Stop("Not coming from Dart code."); 291 __ Stop("Not coming from Dart code.");
292 __ Bind(&ok); 292 __ Bind(&ok);
293 } 293 }
294 #endif 294 #endif
295 295
296 // Mark that the isolate is executing Native code. 296 // Mark that the isolate is executing Native code.
297 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset()); 297 __ StoreToOffset(R5, CTX, Isolate::vm_tag_offset());
298 298
299 // Reserve space for the native arguments structure passed on the stack (the 299 // Reserve space for the native arguments structure passed on the stack (the
(...skipping 10 matching lines...) Expand all
310 // There are no native calls to closures, so we do not need to set the tag 310 // There are no native calls to closures, so we do not need to set the tag
311 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 311 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
312 ASSERT(argc_tag_offset == 1 * kWordSize); 312 ASSERT(argc_tag_offset == 1 * kWordSize);
313 // Set argc in NativeArguments: R1 already contains argc. 313 // Set argc in NativeArguments: R1 already contains argc.
314 314
315 ASSERT(argv_offset == 2 * kWordSize); 315 ASSERT(argv_offset == 2 * kWordSize);
316 // Set argv in NativeArguments: R2 already contains argv. 316 // Set argv in NativeArguments: R2 already contains argv.
317 317
318 // Set retval in NativeArgs. 318 // Set retval in NativeArgs.
319 ASSERT(retval_offset == 3 * kWordSize); 319 ASSERT(retval_offset == 3 * kWordSize);
320 __ AddImmediate(R3, FP, 2 * kWordSize, PP); 320 __ AddImmediate(R3, FP, 2 * kWordSize, kNoRegister);
321 321
322 // TODO(regis): Should we pass the structure by value as in runtime calls? 322 // TODO(regis): Should we pass the structure by value as in runtime calls?
323 // It would require changing Dart API for native functions. 323 // It would require changing Dart API for native functions.
324 // For now, space is reserved on the stack and we pass a pointer to it. 324 // For now, space is reserved on the stack and we pass a pointer to it.
325 __ StoreToOffset(R0, SP, isolate_offset); 325 __ StoreToOffset(R0, SP, isolate_offset);
326 __ StoreToOffset(R1, SP, argc_tag_offset); 326 __ StoreToOffset(R1, SP, argc_tag_offset);
327 __ StoreToOffset(R2, SP, argv_offset); 327 __ StoreToOffset(R2, SP, argv_offset);
328 __ StoreToOffset(R3, SP, retval_offset); 328 __ StoreToOffset(R3, SP, retval_offset);
329 __ mov(R0, SP); // Pass the pointer to the NativeArguments. 329 __ mov(R0, SP); // Pass the pointer to the NativeArguments.
330 330
331 // Call native function or redirection via simulator. 331 // Call native function or redirection via simulator.
332 __ blr(R5); 332 __ blr(R5);
333 333
334 // Mark that the isolate is executing Dart code. 334 // Mark that the isolate is executing Dart code.
335 __ LoadImmediate(R2, VMTag::kScriptTagId, PP); 335 __ LoadImmediate(R2, VMTag::kScriptTagId, kNoRegister);
336 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset()); 336 __ StoreToOffset(R2, CTX, Isolate::vm_tag_offset());
337 337
338 // Reset exit frame information in Isolate structure. 338 // Reset exit frame information in Isolate structure.
339 __ LoadImmediate(R2, 0, PP); 339 __ LoadImmediate(R2, 0, kNoRegister);
340 __ StoreToOffset(R2, CTX, Isolate::top_exit_frame_info_offset()); 340 __ StoreToOffset(R2, CTX, Isolate::top_exit_frame_info_offset());
341 341
342 // Load Context pointer from Isolate structure into R2. 342 // Load Context pointer from Isolate structure into R2.
343 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset()); 343 __ LoadFromOffset(R2, CTX, Isolate::top_context_offset());
344 344
345 // Reset Context pointer in Isolate structure. 345 // Reset Context pointer in Isolate structure.
346 __ LoadObject(R3, Object::null_object(), PP); 346 __ LoadObject(R3, Object::null_object(), PP);
347 __ StoreToOffset(R3, CTX, Isolate::top_context_offset()); 347 __ StoreToOffset(R3, CTX, Isolate::top_context_offset());
348 348
349 // Cache Context pointer into CTX while executing Dart code. 349 // Cache Context pointer into CTX while executing Dart code.
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 565
566 // Load the isolate out of the context. 566 // Load the isolate out of the context.
567 // Spilled: R1, R2, R3. 567 // Spilled: R1, R2, R3.
568 // R0: address being stored. 568 // R0: address being stored.
569 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset()); 569 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset());
570 570
571 // Load the StoreBuffer block out of the isolate. Then load top_ out of the 571 // Load the StoreBuffer block out of the isolate. Then load top_ out of the
572 // StoreBufferBlock and add the address to the pointers_. 572 // StoreBufferBlock and add the address to the pointers_.
573 // R1: isolate. 573 // R1: isolate.
574 __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset()); 574 __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset());
575 __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset()); 575 __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord);
576 __ add(R3, R1, Operand(R2, LSL, 3)); 576 __ add(R3, R1, Operand(R2, LSL, 3));
577 __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset()); 577 __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset());
578 578
579 // Increment top_ and check for overflow. 579 // Increment top_ and check for overflow.
580 // R2: top_. 580 // R2: top_.
581 // R1: StoreBufferBlock. 581 // R1: StoreBufferBlock.
582 Label L; 582 Label L;
583 __ add(R2, R2, Operand(1)); 583 __ add(R2, R2, Operand(1));
584 __ StoreToOffset(R2, R1, StoreBufferBlock::top_offset()); 584 __ StoreToOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord);
585 __ CompareImmediate(R2, StoreBufferBlock::kSize, PP); 585 __ CompareImmediate(R2, StoreBufferBlock::kSize, kNoRegister);
586 // Restore values. 586 // Restore values.
587 __ Pop(R3); 587 __ Pop(R3);
588 __ Pop(R2); 588 __ Pop(R2);
589 __ Pop(R1); 589 __ Pop(R1);
590 __ b(&L, EQ); 590 __ b(&L, EQ);
591 __ ret(); 591 __ ret();
592 592
593 // Handle overflow: Call the runtime leaf function. 593 // Handle overflow: Call the runtime leaf function.
594 __ Bind(&L); 594 __ Bind(&L);
595 // Setup frame, push callee-saved registers. 595 // Setup frame, push callee-saved registers.
(...skipping 26 matching lines...) Expand all
622 if (is_cls_parameterized) { 622 if (is_cls_parameterized) {
623 __ ldr(R1, Address(SP)); 623 __ ldr(R1, Address(SP));
624 // R1: instantiated type arguments. 624 // R1: instantiated type arguments.
625 } 625 }
626 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) { 626 if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size)) {
627 Label slow_case; 627 Label slow_case;
628 // Allocate the object and update top to point to 628 // Allocate the object and update top to point to
629 // next object start and initialize the allocated object. 629 // next object start and initialize the allocated object.
630 // R1: instantiated type arguments (if is_cls_parameterized). 630 // R1: instantiated type arguments (if is_cls_parameterized).
631 Heap* heap = Isolate::Current()->heap(); 631 Heap* heap = Isolate::Current()->heap();
632 __ LoadImmediate(R5, heap->TopAddress(), PP); 632 __ LoadImmediate(R5, heap->TopAddress(), kNoRegister);
633 __ ldr(R2, Address(R5)); 633 __ ldr(R2, Address(R5));
634 __ AddImmediate(R3, R2, instance_size, PP); 634 __ AddImmediate(R3, R2, instance_size, kNoRegister);
635 // Check if the allocation fits into the remaining space. 635 // Check if the allocation fits into the remaining space.
636 // R2: potential new object start. 636 // R2: potential new object start.
637 // R3: potential next object start. 637 // R3: potential next object start.
638 __ LoadImmediate(TMP, heap->EndAddress(), PP); 638 __ LoadImmediate(TMP, heap->EndAddress(), kNoRegister);
639 __ ldr(TMP, Address(TMP)); 639 __ ldr(TMP, Address(TMP));
640 __ CompareRegisters(R3, TMP); 640 __ CompareRegisters(R3, TMP);
641 if (FLAG_use_slow_path) { 641 if (FLAG_use_slow_path) {
642 __ b(&slow_case); 642 __ b(&slow_case);
643 } else { 643 } else {
644 __ b(&slow_case, CS); // Unsigned higher or equal. 644 __ b(&slow_case, CS); // Unsigned higher or equal.
645 } 645 }
646 __ str(R3, Address(R5)); 646 __ str(R3, Address(R5));
647 __ UpdateAllocationStats(cls.id(), R5); 647 __ UpdateAllocationStats(cls.id(), R5, kNoRegister);
648 648
649 // R2: new object start. 649 // R2: new object start.
650 // R3: next object start. 650 // R3: next object start.
651 // R1: new object type arguments (if is_cls_parameterized). 651 // R1: new object type arguments (if is_cls_parameterized).
652 // Set the tags. 652 // Set the tags.
653 uword tags = 0; 653 uword tags = 0;
654 tags = RawObject::SizeTag::update(instance_size, tags); 654 tags = RawObject::SizeTag::update(instance_size, tags);
655 ASSERT(cls.id() != kIllegalCid); 655 ASSERT(cls.id() != kIllegalCid);
656 tags = RawObject::ClassIdTag::update(cls.id(), tags); 656 tags = RawObject::ClassIdTag::update(cls.id(), tags);
657 __ LoadImmediate(R0, tags, PP); 657 __ LoadImmediate(R0, tags, kNoRegister);
658 __ StoreToOffset(R0, R2, Instance::tags_offset()); 658 __ StoreToOffset(R0, R2, Instance::tags_offset());
659 659
660 // Initialize the remaining words of the object. 660 // Initialize the remaining words of the object.
661 __ LoadObject(R0, Object::null_object(), PP); 661 __ LoadObject(R0, Object::null_object(), PP);
662 662
663 // R0: raw null. 663 // R0: raw null.
664 // R2: new object start. 664 // R2: new object start.
665 // R3: next object start. 665 // R3: next object start.
666 // R1: new object type arguments (if is_cls_parameterized). 666 // R1: new object type arguments (if is_cls_parameterized).
667 // First try inlining the initialization without a loop. 667 // First try inlining the initialization without a loop.
668 if (instance_size < (kInlineInstanceSize * kWordSize)) { 668 if (instance_size < (kInlineInstanceSize * kWordSize)) {
669 // Check if the object contains any non-header fields. 669 // Check if the object contains any non-header fields.
670 // Small objects are initialized using a consecutive set of writes. 670 // Small objects are initialized using a consecutive set of writes.
671 for (intptr_t current_offset = Instance::NextFieldOffset(); 671 for (intptr_t current_offset = Instance::NextFieldOffset();
672 current_offset < instance_size; 672 current_offset < instance_size;
673 current_offset += kWordSize) { 673 current_offset += kWordSize) {
674 __ StoreToOffset(R0, R2, current_offset); 674 __ StoreToOffset(R0, R2, current_offset);
675 } 675 }
676 } else { 676 } else {
677 __ AddImmediate(R4, R2, Instance::NextFieldOffset(), PP); 677 __ AddImmediate(R4, R2, Instance::NextFieldOffset(), kNoRegister);
678 // Loop until the whole object is initialized. 678 // Loop until the whole object is initialized.
679 // R0: raw null. 679 // R0: raw null.
680 // R2: new object. 680 // R2: new object.
681 // R3: next object start. 681 // R3: next object start.
682 // R4: next word to be initialized. 682 // R4: next word to be initialized.
683 // R1: new object type arguments (if is_cls_parameterized). 683 // R1: new object type arguments (if is_cls_parameterized).
684 Label init_loop; 684 Label init_loop;
685 Label done; 685 Label done;
686 __ Bind(&init_loop); 686 __ Bind(&init_loop);
687 __ CompareRegisters(R4, R3); 687 __ CompareRegisters(R4, R3);
688 __ b(&done, CS); 688 __ b(&done, CS);
689 __ str(R0, Address(R4)); 689 __ str(R0, Address(R4));
690 __ AddImmediate(R4, R4, kWordSize, PP); 690 __ AddImmediate(R4, R4, kWordSize, kNoRegister);
691 __ b(&init_loop); 691 __ b(&init_loop);
692 __ Bind(&done); 692 __ Bind(&done);
693 } 693 }
694 if (is_cls_parameterized) { 694 if (is_cls_parameterized) {
695 // R1: new object type arguments. 695 // R1: new object type arguments.
696 // Set the type arguments in the new object. 696 // Set the type arguments in the new object.
697 __ StoreToOffset(R1, R2, cls.type_arguments_field_offset()); 697 __ StoreToOffset(R1, R2, cls.type_arguments_field_offset());
698 } 698 }
699 // Done allocating and initializing the instance. 699 // Done allocating and initializing the instance.
700 // R2: new object still missing its heap tag. 700 // R2: new object still missing its heap tag.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 740
741 741
742 // Loads function into 'temp_reg'. 742 // Loads function into 'temp_reg'.
743 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 743 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
744 Register temp_reg) { 744 Register temp_reg) {
745 Register ic_reg = R5; 745 Register ic_reg = R5;
746 Register func_reg = temp_reg; 746 Register func_reg = temp_reg;
747 ASSERT(temp_reg == R6); 747 ASSERT(temp_reg == R6);
748 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset()); 748 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset());
749 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset()); 749 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset());
750 __ AddImmediate(R7, R7, 1, PP); 750 __ AddImmediate(R7, R7, 1, kNoRegister);
751 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset()); 751 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset());
752 } 752 }
753 753
754 754
755 // Generate inline cache check for 'num_args'. 755 // Generate inline cache check for 'num_args'.
756 // LR: return address. 756 // LR: return address.
757 // R5: inline cache data object. 757 // R5: inline cache data object.
758 // Control flow: 758 // Control flow:
759 // - If receiver is null -> jump to IC miss. 759 // - If receiver is null -> jump to IC miss.
760 // - If receiver is Smi -> load Smi class. 760 // - If receiver is Smi -> load Smi class.
761 // - If receiver is not-Smi -> load receiver's class. 761 // - If receiver is not-Smi -> load receiver's class.
762 // - Check if 'num_args' (including receiver) match any IC data group. 762 // - Check if 'num_args' (including receiver) match any IC data group.
763 // - Match found -> jump to target. 763 // - Match found -> jump to target.
764 // - Match not found -> jump to IC miss. 764 // - Match not found -> jump to IC miss.
765 void StubCode::GenerateNArgsCheckInlineCacheStub( 765 void StubCode::GenerateNArgsCheckInlineCacheStub(
766 Assembler* assembler, 766 Assembler* assembler,
767 intptr_t num_args, 767 intptr_t num_args,
768 const RuntimeEntry& handle_ic_miss) { 768 const RuntimeEntry& handle_ic_miss) {
769 ASSERT(num_args > 0); 769 ASSERT(num_args > 0);
770 #if defined(DEBUG) 770 #if defined(DEBUG)
771 { Label ok; 771 { Label ok;
772 // Check that the IC data array has NumArgsTested() == num_args. 772 // Check that the IC data array has NumArgsTested() == num_args.
773 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 773 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
774 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 774 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
775 kUnsignedWord); 775 kUnsignedWord);
776 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 776 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
777 __ andi(R6, R6, ICData::NumArgsTestedMask()); 777 __ andi(R6, R6, ICData::NumArgsTestedMask());
778 __ CompareImmediate(R6, num_args, PP); 778 __ CompareImmediate(R6, num_args, kNoRegister);
779 __ b(&ok, EQ); 779 __ b(&ok, EQ);
780 __ Stop("Incorrect stub for IC data"); 780 __ Stop("Incorrect stub for IC data");
781 __ Bind(&ok); 781 __ Bind(&ok);
782 } 782 }
783 #endif // DEBUG 783 #endif // DEBUG
784 784
785 // Check single stepping. 785 // Check single stepping.
786 Label not_stepping; 786 Label not_stepping;
787 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset()); 787 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset());
788 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte); 788 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte);
789 __ CompareImmediate(R6, 0, PP); 789 __ CompareImmediate(R6, 0, kNoRegister);
790 __ b(&not_stepping, EQ); 790 __ b(&not_stepping, EQ);
791 __ EnterStubFrame(); 791 __ EnterStubFrame();
792 __ Push(R5); // Preserve IC data. 792 __ Push(R5); // Preserve IC data.
793 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 793 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
794 __ Pop(R5); 794 __ Pop(R5);
795 __ LeaveStubFrame(); 795 __ LeaveStubFrame();
796 __ Bind(&not_stepping); 796 __ Bind(&not_stepping);
797 797
798 // Load arguments descriptor into R4. 798 // Load arguments descriptor into R4.
799 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); 799 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
800 // Loop that checks if there is an IC data match. 800 // Loop that checks if there is an IC data match.
801 Label loop, update, test, found, get_class_id_as_smi; 801 Label loop, update, test, found, get_class_id_as_smi;
802 // R5: IC data object (preserved). 802 // R5: IC data object (preserved).
803 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); 803 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
804 // R6: ic_data_array with check entries: classes and target functions. 804 // R6: ic_data_array with check entries: classes and target functions.
805 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, PP); 805 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoRegister);
806 // R6: points directly to the first ic data array element. 806 // R6: points directly to the first ic data array element.
807 807
808 // Get the receiver's class ID (first read number of arguments from 808 // Get the receiver's class ID (first read number of arguments from
809 // arguments descriptor array and then access the receiver from the stack). 809 // arguments descriptor array and then access the receiver from the stack).
810 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); 810 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset());
811 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode. 811 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode.
812 __ sub(R7, R7, Operand(1)); 812 __ sub(R7, R7, Operand(1));
813 813
814 // R0 <- [SP + (R7 << 3)] 814 // R0 <- [SP + (R7 << 3)]
815 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); 815 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
816 816
817 { 817 {
818 // TODO(zra): Put this code in a subroutine call as with other architectures 818 // TODO(zra): Put this code in a subroutine call as with other architectures
819 // when we have a bl(Label& l) instruction. 819 // when we have a bl(Label& l) instruction.
820 // Instance in R0, return its class-id in R0 as Smi. 820 // Instance in R0, return its class-id in R0 as Smi.
821 // Test if Smi -> load Smi class for comparison. 821 // Test if Smi -> load Smi class for comparison.
822 Label not_smi, done; 822 Label not_smi, done;
823 __ tsti(R0, kSmiTagMask); 823 __ tsti(R0, kSmiTagMask);
824 __ b(&not_smi, NE); 824 __ b(&not_smi, NE);
825 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP); 825 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoRegister);
826 __ b(&done); 826 __ b(&done);
827 827
828 __ Bind(&not_smi); 828 __ Bind(&not_smi);
829 __ LoadClassId(R0, R0); 829 __ LoadClassId(R0, R0);
830 __ SmiTag(R0); 830 __ SmiTag(R0);
831 __ Bind(&done); 831 __ Bind(&done);
832 } 832 }
833 833
834 // R7: argument_count - 1 (untagged). 834 // R7: argument_count - 1 (untagged).
835 // R0: receiver's class ID (smi). 835 // R0: receiver's class ID (smi).
836 __ ldr(R1, Address(R6)); // First class id (smi) to check. 836 __ ldr(R1, Address(R6)); // First class id (smi) to check.
837 __ b(&test); 837 __ b(&test);
838 838
839 __ Bind(&loop); 839 __ Bind(&loop);
840 for (int i = 0; i < num_args; i++) { 840 for (int i = 0; i < num_args; i++) {
841 if (i > 0) { 841 if (i > 0) {
842 // If not the first, load the next argument's class ID. 842 // If not the first, load the next argument's class ID.
843 __ AddImmediate(R0, R7, -i, PP); 843 __ AddImmediate(R0, R7, -i, kNoRegister);
844 // R0 <- [SP + (R0 << 3)] 844 // R0 <- [SP + (R0 << 3)]
845 __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled)); 845 __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled));
846 { 846 {
847 // Instance in R0, return its class-id in R0 as Smi. 847 // Instance in R0, return its class-id in R0 as Smi.
848 // Test if Smi -> load Smi class for comparison. 848 // Test if Smi -> load Smi class for comparison.
849 Label not_smi, done; 849 Label not_smi, done;
850 __ tsti(R0, kSmiTagMask); 850 __ tsti(R0, kSmiTagMask);
851 __ b(&not_smi, NE); 851 __ b(&not_smi, NE);
852 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP); 852 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoRegister);
853 __ b(&done); 853 __ b(&done);
854 854
855 __ Bind(&not_smi); 855 __ Bind(&not_smi);
856 __ LoadClassId(R0, R0); 856 __ LoadClassId(R0, R0);
857 __ SmiTag(R0); 857 __ SmiTag(R0);
858 __ Bind(&done); 858 __ Bind(&done);
859 } 859 }
860 // R0: next argument class ID (smi). 860 // R0: next argument class ID (smi).
861 __ LoadFromOffset(R1, R6, i * kWordSize); 861 __ LoadFromOffset(R1, R6, i * kWordSize);
862 // R1: next class ID to check (smi). 862 // R1: next class ID to check (smi).
863 } 863 }
864 __ CompareRegisters(R0, R1); // Class id match? 864 __ CompareRegisters(R0, R1); // Class id match?
865 if (i < (num_args - 1)) { 865 if (i < (num_args - 1)) {
866 __ b(&update, NE); // Continue. 866 __ b(&update, NE); // Continue.
867 } else { 867 } else {
868 // Last check, all checks before matched. 868 // Last check, all checks before matched.
869 __ b(&found, EQ); // Break. 869 __ b(&found, EQ); // Break.
870 } 870 }
871 } 871 }
872 __ Bind(&update); 872 __ Bind(&update);
873 // Reload receiver class ID. It has not been destroyed when num_args == 1. 873 // Reload receiver class ID. It has not been destroyed when num_args == 1.
874 if (num_args > 1) { 874 if (num_args > 1) {
875 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); 875 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled));
876 { 876 {
877 // Instance in R0, return its class-id in R0 as Smi. 877 // Instance in R0, return its class-id in R0 as Smi.
878 // Test if Smi -> load Smi class for comparison. 878 // Test if Smi -> load Smi class for comparison.
879 Label not_smi, done; 879 Label not_smi, done;
880 __ tsti(R0, kSmiTagMask); 880 __ tsti(R0, kSmiTagMask);
881 __ b(&not_smi, NE); 881 __ b(&not_smi, NE);
882 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), PP); 882 __ LoadImmediate(R0, Smi::RawValue(kSmiCid), kNoRegister);
883 __ b(&done); 883 __ b(&done);
884 884
885 __ Bind(&not_smi); 885 __ Bind(&not_smi);
886 __ LoadClassId(R0, R0); 886 __ LoadClassId(R0, R0);
887 __ SmiTag(R0); 887 __ SmiTag(R0);
888 __ Bind(&done); 888 __ Bind(&done);
889 } 889 }
890 } 890 }
891 891
892 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 892 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
893 __ AddImmediate(R6, R6, entry_size, PP); // Next entry. 893 __ AddImmediate(R6, R6, entry_size, kNoRegister); // Next entry.
894 __ ldr(R1, Address(R6)); // Next class ID. 894 __ ldr(R1, Address(R6)); // Next class ID.
895 895
896 __ Bind(&test); 896 __ Bind(&test);
897 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid), PP); // Done? 897 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid), kNoRegister); // Done?
898 __ b(&loop, NE); 898 __ b(&loop, NE);
899 899
900 // IC miss. 900 // IC miss.
901 // Compute address of arguments. 901 // Compute address of arguments.
902 // R7: argument_count - 1 (untagged). 902 // R7: argument_count - 1 (untagged).
903 // R7 <- SP + (R7 << 3) 903 // R7 <- SP + (R7 << 3)
904 __ add(R7, SP, Operand(R7, UXTX, 3)); // R7 is Untagged. 904 __ add(R7, SP, Operand(R7, UXTX, 3)); // R7 is Untagged.
905 // R7: address of receiver. 905 // R7: address of receiver.
906 // Create a stub frame as we are pushing some objects on the stack before 906 // Create a stub frame as we are pushing some objects on the stack before
907 // calling into the runtime. 907 // calling into the runtime.
(...skipping 25 matching lines...) Expand all
933 933
934 __ Bind(&found); 934 __ Bind(&found);
935 // R6: pointer to an IC data check group. 935 // R6: pointer to an IC data check group.
936 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 936 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
937 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 937 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
938 __ LoadFromOffset(R0, R6, target_offset); 938 __ LoadFromOffset(R0, R6, target_offset);
939 __ LoadFromOffset(R1, R6, count_offset); 939 __ LoadFromOffset(R1, R6, count_offset);
940 __ adds(R1, R1, Operand(Smi::RawValue(1))); 940 __ adds(R1, R1, Operand(Smi::RawValue(1)));
941 __ StoreToOffset(R1, R6, count_offset); 941 __ StoreToOffset(R1, R6, count_offset);
942 __ b(&call_target_function, VC); // No overflow. 942 __ b(&call_target_function, VC); // No overflow.
943 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), PP); 943 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), kNoRegister);
944 __ StoreToOffset(R1, R6, count_offset); 944 __ StoreToOffset(R1, R6, count_offset);
945 945
946 __ Bind(&call_target_function); 946 __ Bind(&call_target_function);
947 // R0: target function. 947 // R0: target function.
948 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 948 __ LoadFieldFromOffset(R2, R0, Function::code_offset());
949 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 949 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset());
950 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP); 950 __ AddImmediate(
951 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoRegister);
951 __ br(R2); 952 __ br(R2);
952 } 953 }
953 954
954 955
955 // Use inline cache data array to invoke the target or continue in inline 956 // Use inline cache data array to invoke the target or continue in inline
956 // cache miss handler. Stub for 1-argument check (receiver class). 957 // cache miss handler. Stub for 1-argument check (receiver class).
957 // LR: return address. 958 // LR: return address.
958 // R5: inline cache data object. 959 // R5: inline cache data object.
959 // Inline cache data object structure: 960 // Inline cache data object structure:
960 // 0: function-name 961 // 0: function-name
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1013 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1013 GenerateUsageCounterIncrement(assembler, R6); 1014 GenerateUsageCounterIncrement(assembler, R6);
1014 #if defined(DEBUG) 1015 #if defined(DEBUG)
1015 { Label ok; 1016 { Label ok;
1016 // Check that the IC data array has NumArgsTested() == 0. 1017 // Check that the IC data array has NumArgsTested() == 0.
1017 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1018 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1018 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 1019 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
1019 kUnsignedWord); 1020 kUnsignedWord);
1020 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1021 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1021 __ andi(R6, R6, ICData::NumArgsTestedMask()); 1022 __ andi(R6, R6, ICData::NumArgsTestedMask());
1022 __ CompareImmediate(R6, 0, PP); 1023 __ CompareImmediate(R6, 0, kNoRegister);
1023 __ b(&ok, EQ); 1024 __ b(&ok, EQ);
1024 __ Stop("Incorrect IC data for unoptimized static call"); 1025 __ Stop("Incorrect IC data for unoptimized static call");
1025 __ Bind(&ok); 1026 __ Bind(&ok);
1026 } 1027 }
1027 #endif // DEBUG 1028 #endif // DEBUG
1028 1029
1029 // Check single stepping. 1030 // Check single stepping.
1030 Label not_stepping; 1031 Label not_stepping;
1031 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset()); 1032 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset());
1032 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte); 1033 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte);
1033 __ CompareImmediate(R6, 0, PP); 1034 __ CompareImmediate(R6, 0, kNoRegister);
1034 __ b(&not_stepping, EQ); 1035 __ b(&not_stepping, EQ);
1035 __ EnterStubFrame(); 1036 __ EnterStubFrame();
1036 __ Push(R5); // Preserve IC data. 1037 __ Push(R5); // Preserve IC data.
1037 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1038 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1038 __ Pop(R5); 1039 __ Pop(R5);
1039 __ LeaveStubFrame(); 1040 __ LeaveStubFrame();
1040 __ Bind(&not_stepping); 1041 __ Bind(&not_stepping);
1041 1042
1042 // R5: IC data object (preserved). 1043 // R5: IC data object (preserved).
1043 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); 1044 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
1044 // R6: ic_data_array with entries: target functions and count. 1045 // R6: ic_data_array with entries: target functions and count.
1045 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, PP); 1046 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoRegister);
1046 // R6: points directly to the first ic data array element. 1047 // R6: points directly to the first ic data array element.
1047 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; 1048 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
1048 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; 1049 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
1049 1050
1050 // Increment count for this call. 1051 // Increment count for this call.
1051 Label increment_done; 1052 Label increment_done;
1052 __ LoadFromOffset(R1, R6, count_offset); 1053 __ LoadFromOffset(R1, R6, count_offset);
1053 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1054 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1054 __ StoreToOffset(R1, R6, count_offset); 1055 __ StoreToOffset(R1, R6, count_offset);
1055 __ b(&increment_done, VC); // No overflow. 1056 __ b(&increment_done, VC); // No overflow.
1056 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), PP); 1057 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), kNoRegister);
1057 __ StoreToOffset(R1, R6, count_offset); 1058 __ StoreToOffset(R1, R6, count_offset);
1058 __ Bind(&increment_done); 1059 __ Bind(&increment_done);
1059 1060
1060 // Load arguments descriptor into R4. 1061 // Load arguments descriptor into R4.
1061 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); 1062 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
1062 1063
1063 // Get function and call it, if possible. 1064 // Get function and call it, if possible.
1064 __ LoadFromOffset(R0, R6, target_offset); 1065 __ LoadFromOffset(R0, R6, target_offset);
1065 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 1066 __ LoadFieldFromOffset(R2, R0, Function::code_offset());
1066 1067
1067 // R0: function. 1068 // R0: function.
1068 // R2: target code. 1069 // R2: target code.
1069 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 1070 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset());
1070 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP); 1071 __ AddImmediate(
1072 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoRegister);
1071 __ br(R2); 1073 __ br(R2);
1072 } 1074 }
1073 1075
1074 1076
1075 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1077 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1076 __ Stop("GenerateTwoArgsUnoptimizedStaticCallStub"); 1078 __ Stop("GenerateTwoArgsUnoptimizedStaticCallStub");
1077 } 1079 }
1078 1080
1079 1081
1080 // Stub for compiling a function and jumping to the compiled code. 1082 // Stub for compiling a function and jumping to the compiled code.
1081 // R5: IC-Data (for methods). 1083 // R5: IC-Data (for methods).
1082 // R4: Arguments descriptor. 1084 // R4: Arguments descriptor.
1083 // R0: Function. 1085 // R0: Function.
1084 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1086 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1085 // Preserve arg desc. and IC data object. 1087 // Preserve arg desc. and IC data object.
1086 __ EnterStubFrame(); 1088 __ EnterStubFrame();
1087 __ Push(R5); // Save IC Data. 1089 __ Push(R5); // Save IC Data.
1088 __ Push(R4); // Save arg. desc. 1090 __ Push(R4); // Save arg. desc.
1089 __ Push(R0); // Pass function. 1091 __ Push(R0); // Pass function.
1090 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1092 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1091 __ Pop(R0); // Restore argument. 1093 __ Pop(R0); // Restore argument.
1092 __ Pop(R4); // Restore arg desc. 1094 __ Pop(R4); // Restore arg desc.
1093 __ Pop(R5); // Restore IC Data. 1095 __ Pop(R5); // Restore IC Data.
1094 __ LeaveStubFrame(); 1096 __ LeaveStubFrame();
1095 1097
1096 __ LoadFieldFromOffset(R2, R0, Function::code_offset()); 1098 __ LoadFieldFromOffset(R2, R0, Function::code_offset());
1097 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset()); 1099 __ LoadFieldFromOffset(R2, R2, Code::instructions_offset());
1098 __ AddImmediate(R2, R2, Instructions::HeaderSize() - kHeapObjectTag, PP); 1100 __ AddImmediate(
1101 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoRegister);
1099 __ br(R2); 1102 __ br(R2);
1100 } 1103 }
1101 1104
1102 1105
1103 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { 1106 void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) {
1104 __ Stop("GenerateBreakpointRuntimeStub"); 1107 __ Stop("GenerateBreakpointRuntimeStub");
1105 } 1108 }
1106 1109
1107 1110
1108 // Called only from unoptimized code. All relevant registers have been saved. 1111 // Called only from unoptimized code. All relevant registers have been saved.
1109 void StubCode::GenerateDebugStepCheckStub( 1112 void StubCode::GenerateDebugStepCheckStub(
1110 Assembler* assembler) { 1113 Assembler* assembler) {
1111 // Check single stepping. 1114 // Check single stepping.
1112 Label not_stepping; 1115 Label not_stepping;
1113 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset()); 1116 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset());
1114 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte); 1117 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte);
1115 __ CompareImmediate(R1, 0, PP); 1118 __ CompareImmediate(R1, 0, kNoRegister);
1116 __ b(&not_stepping, EQ); 1119 __ b(&not_stepping, EQ);
1117 __ EnterStubFrame(); 1120 __ EnterStubFrame();
1118 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1121 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1119 __ LeaveStubFrame(); 1122 __ LeaveStubFrame();
1120 __ Bind(&not_stepping); 1123 __ Bind(&not_stepping);
1121 __ ret(); 1124 __ ret();
1122 } 1125 }
1123 1126
1124 1127
1125 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { 1128 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 // LR: return address. 1225 // LR: return address.
1223 // SP + 4: left operand. 1226 // SP + 4: left operand.
1224 // SP + 0: right operand. 1227 // SP + 0: right operand.
1225 // Return Zero condition flag set if equal. 1228 // Return Zero condition flag set if equal.
1226 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( 1229 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
1227 Assembler* assembler) { 1230 Assembler* assembler) {
1228 // Check single stepping. 1231 // Check single stepping.
1229 Label not_stepping; 1232 Label not_stepping;
1230 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset()); 1233 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset());
1231 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte); 1234 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte);
1232 __ CompareImmediate(R1, 0, PP); 1235 __ CompareImmediate(R1, 0, kNoRegister);
1233 __ b(&not_stepping, EQ); 1236 __ b(&not_stepping, EQ);
1234 __ EnterStubFrame(); 1237 __ EnterStubFrame();
1235 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1238 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1236 __ LeaveStubFrame(); 1239 __ LeaveStubFrame();
1237 __ Bind(&not_stepping); 1240 __ Bind(&not_stepping);
1238 1241
1239 const Register left = R1; 1242 const Register left = R1;
1240 const Register right = R0; 1243 const Register right = R0;
1241 __ LoadFromOffset(left, SP, 1 * kWordSize); 1244 __ LoadFromOffset(left, SP, 1 * kWordSize);
1242 __ LoadFromOffset(right, SP, 0 * kWordSize); 1245 __ LoadFromOffset(right, SP, 0 * kWordSize);
1243 GenerateIdenticalWithNumberCheckStub(assembler, left, right); 1246 GenerateIdenticalWithNumberCheckStub(assembler, left, right);
1244 __ ret(); 1247 __ ret();
1245 } 1248 }
1246 1249
1247 1250
1248 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( 1251 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
1249 Assembler* assembler) { 1252 Assembler* assembler) {
1250 __ Stop("GenerateOptimizedIdenticalWithNumberCheckStub"); 1253 __ Stop("GenerateOptimizedIdenticalWithNumberCheckStub");
1251 } 1254 }
1252 1255
1253 } // namespace dart 1256 } // namespace dart
1254 1257
1255 #endif // defined TARGET_ARCH_ARM64 1258 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« runtime/vm/runtime_entry_arm64.cc ('K') | « runtime/vm/runtime_entry_arm64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698