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

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

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 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
« no previous file with comments | « runtime/vm/stub_code_arm.cc ('k') | runtime/vm/stub_code_arm64_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 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/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 __ LoadImmediate(R2, VMTag::kDartTagId); 116 __ LoadImmediate(R2, VMTag::kDartTagId);
117 __ StoreToOffset(R2, THR, Thread::vm_tag_offset()); 117 __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
118 118
119 // Reset exit frame information in Isolate structure. 119 // Reset exit frame information in Isolate structure.
120 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset()); 120 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
121 121
122 __ LeaveStubFrame(); 122 __ LeaveStubFrame();
123 __ ret(); 123 __ ret();
124 } 124 }
125 125
126
127 // Print the stop message. 126 // Print the stop message.
128 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) { 127 DEFINE_LEAF_RUNTIME_ENTRY(void, PrintStopMessage, 1, const char* message) {
129 OS::Print("Stop message: %s\n", message); 128 OS::Print("Stop message: %s\n", message);
130 } 129 }
131 END_LEAF_RUNTIME_ENTRY 130 END_LEAF_RUNTIME_ENTRY
132 131
133
134 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) { 132 void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
135 __ Stop("GeneratePrintStopMessageStub"); 133 __ Stop("GeneratePrintStopMessageStub");
136 } 134 }
137 135
138
139 // Input parameters: 136 // Input parameters:
140 // LR : return address. 137 // LR : return address.
141 // SP : address of return value. 138 // SP : address of return value.
142 // R5 : address of the native function to call. 139 // R5 : address of the native function to call.
143 // R2 : address of first argument in argument array. 140 // R2 : address of first argument in argument array.
144 // R1 : argc_tag including number of arguments and function kind. 141 // R1 : argc_tag including number of arguments and function kind.
145 static void GenerateCallNativeWithWrapperStub(Assembler* assembler, 142 static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
146 Address wrapper) { 143 Address wrapper) {
147 const intptr_t thread_offset = NativeArguments::thread_offset(); 144 const intptr_t thread_offset = NativeArguments::thread_offset();
148 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 145 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 __ LoadImmediate(R2, VMTag::kDartTagId); 220 __ LoadImmediate(R2, VMTag::kDartTagId);
224 __ StoreToOffset(R2, THR, Thread::vm_tag_offset()); 221 __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
225 222
226 // Reset exit frame information in Isolate structure. 223 // Reset exit frame information in Isolate structure.
227 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset()); 224 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
228 225
229 __ LeaveStubFrame(); 226 __ LeaveStubFrame();
230 __ ret(); 227 __ ret();
231 } 228 }
232 229
233
234 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) { 230 void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) {
235 GenerateCallNativeWithWrapperStub( 231 GenerateCallNativeWithWrapperStub(
236 assembler, 232 assembler,
237 Address(THR, Thread::no_scope_native_wrapper_entry_point_offset())); 233 Address(THR, Thread::no_scope_native_wrapper_entry_point_offset()));
238 } 234 }
239 235
240
241 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) { 236 void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
242 GenerateCallNativeWithWrapperStub( 237 GenerateCallNativeWithWrapperStub(
243 assembler, 238 assembler,
244 Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset())); 239 Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset()));
245 } 240 }
246 241
247
248 // Input parameters: 242 // Input parameters:
249 // LR : return address. 243 // LR : return address.
250 // SP : address of return value. 244 // SP : address of return value.
251 // R5 : address of the native function to call. 245 // R5 : address of the native function to call.
252 // R2 : address of first argument in argument array. 246 // R2 : address of first argument in argument array.
253 // R1 : argc_tag including number of arguments and function kind. 247 // R1 : argc_tag including number of arguments and function kind.
254 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) { 248 void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) {
255 const intptr_t thread_offset = NativeArguments::thread_offset(); 249 const intptr_t thread_offset = NativeArguments::thread_offset();
256 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 250 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
257 const intptr_t argv_offset = NativeArguments::argv_offset(); 251 const intptr_t argv_offset = NativeArguments::argv_offset();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 __ LoadImmediate(R2, VMTag::kDartTagId); 322 __ LoadImmediate(R2, VMTag::kDartTagId);
329 __ StoreToOffset(R2, THR, Thread::vm_tag_offset()); 323 __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
330 324
331 // Reset exit frame information in Isolate structure. 325 // Reset exit frame information in Isolate structure.
332 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset()); 326 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
333 327
334 __ LeaveStubFrame(); 328 __ LeaveStubFrame();
335 __ ret(); 329 __ ret();
336 } 330 }
337 331
338
339 // Input parameters: 332 // Input parameters:
340 // R4: arguments descriptor array. 333 // R4: arguments descriptor array.
341 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 334 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
342 // Create a stub frame as we are pushing some objects on the stack before 335 // Create a stub frame as we are pushing some objects on the stack before
343 // calling into the runtime. 336 // calling into the runtime.
344 __ EnterStubFrame(); 337 __ EnterStubFrame();
345 // Setup space on stack for return value and preserve arguments descriptor. 338 // Setup space on stack for return value and preserve arguments descriptor.
346 __ Push(R4); 339 __ Push(R4);
347 __ Push(ZR); 340 __ Push(ZR);
348 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 341 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
349 // Get Code object result and restore arguments descriptor array. 342 // Get Code object result and restore arguments descriptor array.
350 __ Pop(CODE_REG); 343 __ Pop(CODE_REG);
351 __ Pop(R4); 344 __ Pop(R4);
352 // Remove the stub frame. 345 // Remove the stub frame.
353 __ LeaveStubFrame(); 346 __ LeaveStubFrame();
354 // Jump to the dart function. 347 // Jump to the dart function.
355 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 348 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
356 __ br(R0); 349 __ br(R0);
357 } 350 }
358 351
359
360 // Called from a static call only when an invalid code has been entered 352 // Called from a static call only when an invalid code has been entered
361 // (invalid because its function was optimized or deoptimized). 353 // (invalid because its function was optimized or deoptimized).
362 // R4: arguments descriptor array. 354 // R4: arguments descriptor array.
363 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 355 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
364 // Load code pointer to this stub from the thread: 356 // Load code pointer to this stub from the thread:
365 // The one that is passed in, is not correct - it points to the code object 357 // The one that is passed in, is not correct - it points to the code object
366 // that needs to be replaced. 358 // that needs to be replaced.
367 __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset())); 359 __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
368 // Create a stub frame as we are pushing some objects on the stack before 360 // Create a stub frame as we are pushing some objects on the stack before
369 // calling into the runtime. 361 // calling into the runtime.
370 __ EnterStubFrame(); 362 __ EnterStubFrame();
371 // Setup space on stack for return value and preserve arguments descriptor. 363 // Setup space on stack for return value and preserve arguments descriptor.
372 __ Push(R4); 364 __ Push(R4);
373 __ Push(ZR); 365 __ Push(ZR);
374 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 366 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
375 // Get Code object result and restore arguments descriptor array. 367 // Get Code object result and restore arguments descriptor array.
376 __ Pop(CODE_REG); 368 __ Pop(CODE_REG);
377 __ Pop(R4); 369 __ Pop(R4);
378 // Remove the stub frame. 370 // Remove the stub frame.
379 __ LeaveStubFrame(); 371 __ LeaveStubFrame();
380 // Jump to the dart function. 372 // Jump to the dart function.
381 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 373 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
382 __ br(R0); 374 __ br(R0);
383 } 375 }
384 376
385
386 // Called from object allocate instruction when the allocation stub has been 377 // Called from object allocate instruction when the allocation stub has been
387 // disabled. 378 // disabled.
388 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { 379 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
389 // Load code pointer to this stub from the thread: 380 // Load code pointer to this stub from the thread:
390 // The one that is passed in, is not correct - it points to the code object 381 // The one that is passed in, is not correct - it points to the code object
391 // that needs to be replaced. 382 // that needs to be replaced.
392 __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset())); 383 __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
393 __ EnterStubFrame(); 384 __ EnterStubFrame();
394 // Setup space on stack for return value. 385 // Setup space on stack for return value.
395 __ Push(ZR); 386 __ Push(ZR);
396 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); 387 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
397 // Get Code object result. 388 // Get Code object result.
398 __ Pop(CODE_REG); 389 __ Pop(CODE_REG);
399 // Remove the stub frame. 390 // Remove the stub frame.
400 __ LeaveStubFrame(); 391 __ LeaveStubFrame();
401 // Jump to the dart function. 392 // Jump to the dart function.
402 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 393 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
403 __ br(R0); 394 __ br(R0);
404 } 395 }
405 396
406
407 // Input parameters: 397 // Input parameters:
408 // R2: smi-tagged argument count, may be zero. 398 // R2: smi-tagged argument count, may be zero.
409 // FP[kParamEndSlotFromFp + 1]: last argument. 399 // FP[kParamEndSlotFromFp + 1]: last argument.
410 static void PushArgumentsArray(Assembler* assembler) { 400 static void PushArgumentsArray(Assembler* assembler) {
411 // Allocate array to store arguments of caller. 401 // Allocate array to store arguments of caller.
412 __ LoadObject(R1, Object::null_object()); 402 __ LoadObject(R1, Object::null_object());
413 // R1: null element type for raw Array. 403 // R1: null element type for raw Array.
414 // R2: smi-tagged argument count, may be zero. 404 // R2: smi-tagged argument count, may be zero.
415 __ BranchLink(*StubCode::AllocateArray_entry()); 405 __ BranchLink(*StubCode::AllocateArray_entry());
416 // R0: newly allocated array. 406 // R0: newly allocated array.
(...skipping 11 matching lines...) Expand all
428 __ Bind(&loop); 418 __ Bind(&loop);
429 __ ldr(R7, Address(R1)); 419 __ ldr(R7, Address(R1));
430 __ AddImmediate(R1, -kWordSize); 420 __ AddImmediate(R1, -kWordSize);
431 __ AddImmediate(R3, kWordSize); 421 __ AddImmediate(R3, kWordSize);
432 __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1)); 422 __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1));
433 __ str(R7, Address(R3, -kWordSize)); 423 __ str(R7, Address(R3, -kWordSize));
434 __ b(&loop, GE); 424 __ b(&loop, GE);
435 __ Bind(&loop_exit); 425 __ Bind(&loop_exit);
436 } 426 }
437 427
438
439 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. 428 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary.
440 // This stub translates optimized frame into unoptimized frame. The optimized 429 // This stub translates optimized frame into unoptimized frame. The optimized
441 // frame can contain values in registers and on stack, the unoptimized 430 // frame can contain values in registers and on stack, the unoptimized
442 // frame contains all values on stack. 431 // frame contains all values on stack.
443 // Deoptimization occurs in following steps: 432 // Deoptimization occurs in following steps:
444 // - Push all registers that can contain values. 433 // - Push all registers that can contain values.
445 // - Call C routine to copy the stack and saved registers into temporary buffer. 434 // - Call C routine to copy the stack and saved registers into temporary buffer.
446 // - Adjust caller's frame to correct unoptimized frame size. 435 // - Adjust caller's frame to correct unoptimized frame size.
447 // - Fill the unoptimized frame. 436 // - Fill the unoptimized frame.
448 // - Materialize objects that require allocation (e.g. Double instances). 437 // - Materialize objects that require allocation (e.g. Double instances).
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 } else if (kind == kLazyDeoptFromThrow) { 558 } else if (kind == kLazyDeoptFromThrow) {
570 __ Pop(R1); // Restore stacktrace. 559 __ Pop(R1); // Restore stacktrace.
571 __ Pop(R0); // Restore exception. 560 __ Pop(R0); // Restore exception.
572 } 561 }
573 __ LeaveStubFrame(); 562 __ LeaveStubFrame();
574 // Remove materialization arguments. 563 // Remove materialization arguments.
575 __ add(SP, SP, Operand(R2)); 564 __ add(SP, SP, Operand(R2));
576 // The caller is responsible for emitting the return instruction. 565 // The caller is responsible for emitting the return instruction.
577 } 566 }
578 567
579
580 // R0: result, must be preserved 568 // R0: result, must be preserved
581 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { 569 void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
582 // Push zap value instead of CODE_REG for lazy deopt. 570 // Push zap value instead of CODE_REG for lazy deopt.
583 __ LoadImmediate(TMP, kZapCodeReg); 571 __ LoadImmediate(TMP, kZapCodeReg);
584 __ Push(TMP); 572 __ Push(TMP);
585 // Return address for "call" to deopt stub. 573 // Return address for "call" to deopt stub.
586 __ LoadImmediate(LR, kZapReturnAddress); 574 __ LoadImmediate(LR, kZapReturnAddress);
587 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); 575 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset()));
588 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); 576 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
589 __ ret(); 577 __ ret();
590 } 578 }
591 579
592
593 // R0: exception, must be preserved 580 // R0: exception, must be preserved
594 // R1: stacktrace, must be preserved 581 // R1: stacktrace, must be preserved
595 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { 582 void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
596 // Push zap value instead of CODE_REG for lazy deopt. 583 // Push zap value instead of CODE_REG for lazy deopt.
597 __ LoadImmediate(TMP, kZapCodeReg); 584 __ LoadImmediate(TMP, kZapCodeReg);
598 __ Push(TMP); 585 __ Push(TMP);
599 // Return address for "call" to deopt stub. 586 // Return address for "call" to deopt stub.
600 __ LoadImmediate(LR, kZapReturnAddress); 587 __ LoadImmediate(LR, kZapReturnAddress);
601 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); 588 __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset()));
602 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); 589 GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
603 __ ret(); 590 __ ret();
604 } 591 }
605 592
606
607 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 593 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
608 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 594 GenerateDeoptimizationSequence(assembler, kEagerDeopt);
609 __ ret(); 595 __ ret();
610 } 596 }
611 597
612
613 static void GenerateDispatcherCode(Assembler* assembler, 598 static void GenerateDispatcherCode(Assembler* assembler,
614 Label* call_target_function) { 599 Label* call_target_function) {
615 __ Comment("NoSuchMethodDispatch"); 600 __ Comment("NoSuchMethodDispatch");
616 // When lazily generated invocation dispatchers are disabled, the 601 // When lazily generated invocation dispatchers are disabled, the
617 // miss-handler may return null. 602 // miss-handler may return null.
618 __ CompareObject(R0, Object::null_object()); 603 __ CompareObject(R0, Object::null_object());
619 __ b(call_target_function, NE); 604 __ b(call_target_function, NE);
620 __ EnterStubFrame(); 605 __ EnterStubFrame();
621 606
622 // Load the receiver. 607 // Load the receiver.
(...skipping 14 matching lines...) Expand all
637 // R2: Smi-tagged arguments array length. 622 // R2: Smi-tagged arguments array length.
638 PushArgumentsArray(assembler); 623 PushArgumentsArray(assembler);
639 const intptr_t kNumArgs = 4; 624 const intptr_t kNumArgs = 4;
640 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); 625 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
641 __ Drop(4); 626 __ Drop(4);
642 __ Pop(R0); // Return value. 627 __ Pop(R0); // Return value.
643 __ LeaveStubFrame(); 628 __ LeaveStubFrame();
644 __ ret(); 629 __ ret();
645 } 630 }
646 631
647
648 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 632 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
649 __ EnterStubFrame(); 633 __ EnterStubFrame();
650 634
651 // Load the receiver. 635 // Load the receiver.
652 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset()); 636 __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
653 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi. 637 __ add(TMP, FP, Operand(R2, LSL, 2)); // R2 is Smi.
654 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize); 638 __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
655 639
656 // Preserve IC data and arguments descriptor. 640 // Preserve IC data and arguments descriptor.
657 __ Push(R5); 641 __ Push(R5);
(...skipping 24 matching lines...) Expand all
682 GenerateDispatcherCode(assembler, &call_target_function); 666 GenerateDispatcherCode(assembler, &call_target_function);
683 __ Bind(&call_target_function); 667 __ Bind(&call_target_function);
684 } 668 }
685 669
686 // Tail-call to target function. 670 // Tail-call to target function.
687 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); 671 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
688 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); 672 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
689 __ br(R2); 673 __ br(R2);
690 } 674 }
691 675
692
693 // Called for inline allocation of arrays. 676 // Called for inline allocation of arrays.
694 // Input parameters: 677 // Input parameters:
695 // LR: return address. 678 // LR: return address.
696 // R2: array length as Smi. 679 // R2: array length as Smi.
697 // R1: array element type (either NULL or an instantiated type). 680 // R1: array element type (either NULL or an instantiated type).
698 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved. 681 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
699 // The newly allocated object is returned in R0. 682 // The newly allocated object is returned in R0.
700 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { 683 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
701 Label slow_case; 684 Label slow_case;
702 // Compute the size to be allocated, it is based on the array length 685 // Compute the size to be allocated, it is based on the array length
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 __ Push(R1); 810 __ Push(R1);
828 __ CallRuntime(kAllocateArrayRuntimeEntry, 2); 811 __ CallRuntime(kAllocateArrayRuntimeEntry, 2);
829 // Pop arguments; result is popped in IP. 812 // Pop arguments; result is popped in IP.
830 __ Pop(R1); 813 __ Pop(R1);
831 __ Pop(R2); 814 __ Pop(R2);
832 __ Pop(R0); 815 __ Pop(R0);
833 __ LeaveStubFrame(); 816 __ LeaveStubFrame();
834 __ ret(); 817 __ ret();
835 } 818 }
836 819
837
838 // Called when invoking Dart code from C++ (VM code). 820 // Called when invoking Dart code from C++ (VM code).
839 // Input parameters: 821 // Input parameters:
840 // LR : points to return address. 822 // LR : points to return address.
841 // R0 : code object of the Dart function to call. 823 // R0 : code object of the Dart function to call.
842 // R1 : arguments descriptor array. 824 // R1 : arguments descriptor array.
843 // R2 : arguments array. 825 // R2 : arguments array.
844 // R3 : current thread. 826 // R3 : current thread.
845 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 827 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
846 __ Comment("InvokeDartCodeStub"); 828 __ Comment("InvokeDartCodeStub");
847 829
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
960 // using it as the stack pointer. 942 // using it as the stack pointer.
961 __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex)); 943 __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
962 } 944 }
963 945
964 // Restore the frame pointer and C stack pointer and return. 946 // Restore the frame pointer and C stack pointer and return.
965 __ LeaveFrame(); 947 __ LeaveFrame();
966 __ RestoreCSP(); 948 __ RestoreCSP();
967 __ ret(); 949 __ ret();
968 } 950 }
969 951
970
971 // Called for inline allocation of contexts. 952 // Called for inline allocation of contexts.
972 // Input: 953 // Input:
973 // R1: number of context variables. 954 // R1: number of context variables.
974 // Output: 955 // Output:
975 // R0: new allocated RawContext object. 956 // R0: new allocated RawContext object.
976 void StubCode::GenerateAllocateContextStub(Assembler* assembler) { 957 void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
977 if (FLAG_inline_alloc) { 958 if (FLAG_inline_alloc) {
978 Label slow_case; 959 Label slow_case;
979 // First compute the rounded instance size. 960 // First compute the rounded instance size.
980 // R1: number of context variables. 961 // R1: number of context variables.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 __ Push(R1); 1056 __ Push(R1);
1076 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context. 1057 __ CallRuntime(kAllocateContextRuntimeEntry, 1); // Allocate context.
1077 __ Drop(1); // Pop number of context variables argument. 1058 __ Drop(1); // Pop number of context variables argument.
1078 __ Pop(R0); // Pop the new context object. 1059 __ Pop(R0); // Pop the new context object.
1079 // R0: new object 1060 // R0: new object
1080 // Restore the frame pointer. 1061 // Restore the frame pointer.
1081 __ LeaveStubFrame(); 1062 __ LeaveStubFrame();
1082 __ ret(); 1063 __ ret();
1083 } 1064 }
1084 1065
1085
1086 // Helper stub to implement Assembler::StoreIntoObject. 1066 // Helper stub to implement Assembler::StoreIntoObject.
1087 // Input parameters: 1067 // Input parameters:
1088 // R0: Address being stored 1068 // R0: Address being stored
1089 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) { 1069 void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
1090 Label add_to_buffer; 1070 Label add_to_buffer;
1091 // Check whether this object has already been remembered. Skip adding to the 1071 // Check whether this object has already been remembered. Skip adding to the
1092 // store buffer if the object is in the store buffer already. 1072 // store buffer if the object is in the store buffer already.
1093 __ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kWord); 1073 __ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kWord);
1094 __ tsti(TMP, Immediate(1 << RawObject::kRememberedBit)); 1074 __ tsti(TMP, Immediate(1 << RawObject::kRememberedBit));
1095 __ b(&add_to_buffer, EQ); 1075 __ b(&add_to_buffer, EQ);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 // Setup frame, push callee-saved registers. 1121 // Setup frame, push callee-saved registers.
1142 1122
1143 __ EnterCallRuntimeFrame(0 * kWordSize); 1123 __ EnterCallRuntimeFrame(0 * kWordSize);
1144 __ mov(R0, THR); 1124 __ mov(R0, THR);
1145 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); 1125 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
1146 // Restore callee-saved registers, tear down frame. 1126 // Restore callee-saved registers, tear down frame.
1147 __ LeaveCallRuntimeFrame(); 1127 __ LeaveCallRuntimeFrame();
1148 __ ret(); 1128 __ ret();
1149 } 1129 }
1150 1130
1151
1152 // Called for inline allocation of objects. 1131 // Called for inline allocation of objects.
1153 // Input parameters: 1132 // Input parameters:
1154 // LR : return address. 1133 // LR : return address.
1155 // SP + 0 : type arguments object (only if class is parameterized). 1134 // SP + 0 : type arguments object (only if class is parameterized).
1156 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, 1135 void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
1157 const Class& cls) { 1136 const Class& cls) {
1158 // The generated code is different if the class is parameterized. 1137 // The generated code is different if the class is parameterized.
1159 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1138 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1160 ASSERT(!is_cls_parameterized || 1139 ASSERT(!is_cls_parameterized ||
1161 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1140 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 } 1247 }
1269 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. 1248 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object.
1270 __ Drop(2); // Pop arguments. 1249 __ Drop(2); // Pop arguments.
1271 __ Pop(R0); // Pop result (newly allocated object). 1250 __ Pop(R0); // Pop result (newly allocated object).
1272 // R0: new object 1251 // R0: new object
1273 // Restore the frame pointer. 1252 // Restore the frame pointer.
1274 __ LeaveStubFrame(); 1253 __ LeaveStubFrame();
1275 __ ret(); 1254 __ ret();
1276 } 1255 }
1277 1256
1278
1279 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function 1257 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
1280 // from the entry code of a dart function after an error in passed argument 1258 // from the entry code of a dart function after an error in passed argument
1281 // name or number is detected. 1259 // name or number is detected.
1282 // Input parameters: 1260 // Input parameters:
1283 // LR : return address. 1261 // LR : return address.
1284 // SP : address of last argument. 1262 // SP : address of last argument.
1285 // R4: arguments descriptor array. 1263 // R4: arguments descriptor array.
1286 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) { 1264 void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
1287 __ EnterStubFrame(); 1265 __ EnterStubFrame();
1288 1266
(...skipping 17 matching lines...) Expand all
1306 1284
1307 // R2: Smi-tagged arguments array length. 1285 // R2: Smi-tagged arguments array length.
1308 PushArgumentsArray(assembler); 1286 PushArgumentsArray(assembler);
1309 1287
1310 const intptr_t kNumArgs = 3; 1288 const intptr_t kNumArgs = 3;
1311 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs); 1289 __ CallRuntime(kInvokeClosureNoSuchMethodRuntimeEntry, kNumArgs);
1312 // noSuchMethod on closures always throws an error, so it will never return. 1290 // noSuchMethod on closures always throws an error, so it will never return.
1313 __ brk(0); 1291 __ brk(0);
1314 } 1292 }
1315 1293
1316
1317 // R6: function object. 1294 // R6: function object.
1318 // R5: inline cache data object. 1295 // R5: inline cache data object.
1319 // Cannot use function object from ICData as it may be the inlined 1296 // Cannot use function object from ICData as it may be the inlined
1320 // function and not the top-scope function. 1297 // function and not the top-scope function.
1321 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 1298 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1322 Register ic_reg = R5; 1299 Register ic_reg = R5;
1323 Register func_reg = R6; 1300 Register func_reg = R6;
1324 if (FLAG_trace_optimized_ic_calls) { 1301 if (FLAG_trace_optimized_ic_calls) {
1325 __ EnterStubFrame(); 1302 __ EnterStubFrame();
1326 __ Push(R6); // Preserve. 1303 __ Push(R6); // Preserve.
1327 __ Push(R5); // Preserve. 1304 __ Push(R5); // Preserve.
1328 __ Push(ic_reg); // Argument. 1305 __ Push(ic_reg); // Argument.
1329 __ Push(func_reg); // Argument. 1306 __ Push(func_reg); // Argument.
1330 __ CallRuntime(kTraceICCallRuntimeEntry, 2); 1307 __ CallRuntime(kTraceICCallRuntimeEntry, 2);
1331 __ Drop(2); // Discard argument; 1308 __ Drop(2); // Discard argument;
1332 __ Pop(R5); // Restore. 1309 __ Pop(R5); // Restore.
1333 __ Pop(R6); // Restore. 1310 __ Pop(R6); // Restore.
1334 __ LeaveStubFrame(); 1311 __ LeaveStubFrame();
1335 } 1312 }
1336 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), kWord); 1313 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), kWord);
1337 __ add(R7, R7, Operand(1)); 1314 __ add(R7, R7, Operand(1));
1338 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), kWord); 1315 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), kWord);
1339 } 1316 }
1340 1317
1341
1342 // Loads function into 'temp_reg'. 1318 // Loads function into 'temp_reg'.
1343 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, 1319 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
1344 Register temp_reg) { 1320 Register temp_reg) {
1345 if (FLAG_optimization_counter_threshold >= 0) { 1321 if (FLAG_optimization_counter_threshold >= 0) {
1346 Register ic_reg = R5; 1322 Register ic_reg = R5;
1347 Register func_reg = temp_reg; 1323 Register func_reg = temp_reg;
1348 ASSERT(temp_reg == R6); 1324 ASSERT(temp_reg == R6);
1349 __ Comment("Increment function counter"); 1325 __ Comment("Increment function counter");
1350 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset()); 1326 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset());
1351 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), 1327 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(),
1352 kWord); 1328 kWord);
1353 __ AddImmediate(R7, 1); 1329 __ AddImmediate(R7, 1);
1354 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), 1330 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(),
1355 kWord); 1331 kWord);
1356 } 1332 }
1357 } 1333 }
1358 1334
1359
1360 // Note: R5 must be preserved. 1335 // Note: R5 must be preserved.
1361 // Attempt a quick Smi operation for known operations ('kind'). The ICData 1336 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1362 // must have been primed with a Smi/Smi check that will be used for counting 1337 // must have been primed with a Smi/Smi check that will be used for counting
1363 // the invocations. 1338 // the invocations.
1364 static void EmitFastSmiOp(Assembler* assembler, 1339 static void EmitFastSmiOp(Assembler* assembler,
1365 Token::Kind kind, 1340 Token::Kind kind,
1366 intptr_t num_args, 1341 intptr_t num_args,
1367 Label* not_smi_or_overflow) { 1342 Label* not_smi_or_overflow) {
1368 __ Comment("Fast Smi op"); 1343 __ Comment("Fast Smi op");
1369 __ ldr(R0, Address(SP, +0 * kWordSize)); // Right. 1344 __ ldr(R0, Address(SP, +0 * kWordSize)); // Right.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1391 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1417 // Update counter, ignore overflow. 1392 // Update counter, ignore overflow.
1418 __ LoadFromOffset(R1, R6, count_offset); 1393 __ LoadFromOffset(R1, R6, count_offset);
1419 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1394 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1420 __ StoreToOffset(R1, R6, count_offset); 1395 __ StoreToOffset(R1, R6, count_offset);
1421 } 1396 }
1422 1397
1423 __ ret(); 1398 __ ret();
1424 } 1399 }
1425 1400
1426
1427 // Generate inline cache check for 'num_args'. 1401 // Generate inline cache check for 'num_args'.
1428 // LR: return address. 1402 // LR: return address.
1429 // R5: inline cache data object. 1403 // R5: inline cache data object.
1430 // Control flow: 1404 // Control flow:
1431 // - If receiver is null -> jump to IC miss. 1405 // - If receiver is null -> jump to IC miss.
1432 // - If receiver is Smi -> load Smi class. 1406 // - If receiver is Smi -> load Smi class.
1433 // - If receiver is not-Smi -> load receiver's class. 1407 // - If receiver is not-Smi -> load receiver's class.
1434 // - Check if 'num_args' (including receiver) match any IC data group. 1408 // - Check if 'num_args' (including receiver) match any IC data group.
1435 // - Match found -> jump to target. 1409 // - Match found -> jump to target.
1436 // - Match not found -> jump to IC miss. 1410 // - Match not found -> jump to IC miss.
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 __ EnterStubFrame(); 1572 __ EnterStubFrame();
1599 __ Push(R5); // Preserve IC data. 1573 __ Push(R5); // Preserve IC data.
1600 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1574 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1601 __ Pop(R5); 1575 __ Pop(R5);
1602 __ RestoreCodePointer(); 1576 __ RestoreCodePointer();
1603 __ LeaveStubFrame(); 1577 __ LeaveStubFrame();
1604 __ b(&done_stepping); 1578 __ b(&done_stepping);
1605 } 1579 }
1606 } 1580 }
1607 1581
1608
1609 // Use inline cache data array to invoke the target or continue in inline 1582 // Use inline cache data array to invoke the target or continue in inline
1610 // cache miss handler. Stub for 1-argument check (receiver class). 1583 // cache miss handler. Stub for 1-argument check (receiver class).
1611 // LR: return address. 1584 // LR: return address.
1612 // R5: inline cache data object. 1585 // R5: inline cache data object.
1613 // Inline cache data object structure: 1586 // Inline cache data object structure:
1614 // 0: function-name 1587 // 0: function-name
1615 // 1: N, number of arguments checked. 1588 // 1: N, number of arguments checked.
1616 // 2 .. (length - 1): group of checks, each check containing: 1589 // 2 .. (length - 1): group of checks, each check containing:
1617 // - N classes. 1590 // - N classes.
1618 // - 1 target function. 1591 // - 1 target function.
1619 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1592 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1620 GenerateUsageCounterIncrement(assembler, R6); 1593 GenerateUsageCounterIncrement(assembler, R6);
1621 GenerateNArgsCheckInlineCacheStub( 1594 GenerateNArgsCheckInlineCacheStub(
1622 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); 1595 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1623 } 1596 }
1624 1597
1625
1626 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1598 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1627 GenerateUsageCounterIncrement(assembler, R6); 1599 GenerateUsageCounterIncrement(assembler, R6);
1628 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1600 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1629 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1601 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1630 Token::kILLEGAL); 1602 Token::kILLEGAL);
1631 } 1603 }
1632 1604
1633
1634 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { 1605 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1635 GenerateUsageCounterIncrement(assembler, R6); 1606 GenerateUsageCounterIncrement(assembler, R6);
1636 GenerateNArgsCheckInlineCacheStub( 1607 GenerateNArgsCheckInlineCacheStub(
1637 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD); 1608 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1638 } 1609 }
1639 1610
1640
1641 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { 1611 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1642 GenerateUsageCounterIncrement(assembler, R6); 1612 GenerateUsageCounterIncrement(assembler, R6);
1643 GenerateNArgsCheckInlineCacheStub( 1613 GenerateNArgsCheckInlineCacheStub(
1644 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB); 1614 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1645 } 1615 }
1646 1616
1647
1648 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { 1617 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1649 GenerateUsageCounterIncrement(assembler, R6); 1618 GenerateUsageCounterIncrement(assembler, R6);
1650 GenerateNArgsCheckInlineCacheStub( 1619 GenerateNArgsCheckInlineCacheStub(
1651 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ); 1620 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1652 } 1621 }
1653 1622
1654
1655 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1623 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1656 Assembler* assembler) { 1624 Assembler* assembler) {
1657 GenerateOptimizedUsageCounterIncrement(assembler); 1625 GenerateOptimizedUsageCounterIncrement(assembler);
1658 GenerateNArgsCheckInlineCacheStub(assembler, 1, 1626 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1659 kInlineCacheMissHandlerOneArgRuntimeEntry, 1627 kInlineCacheMissHandlerOneArgRuntimeEntry,
1660 Token::kILLEGAL, true /* optimized */); 1628 Token::kILLEGAL, true /* optimized */);
1661 } 1629 }
1662 1630
1663
1664 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1631 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1665 Assembler* assembler) { 1632 Assembler* assembler) {
1666 GenerateOptimizedUsageCounterIncrement(assembler); 1633 GenerateOptimizedUsageCounterIncrement(assembler);
1667 GenerateNArgsCheckInlineCacheStub(assembler, 2, 1634 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1668 kInlineCacheMissHandlerTwoArgsRuntimeEntry, 1635 kInlineCacheMissHandlerTwoArgsRuntimeEntry,
1669 Token::kILLEGAL, true /* optimized */); 1636 Token::kILLEGAL, true /* optimized */);
1670 } 1637 }
1671 1638
1672
1673 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1639 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1674 GenerateUsageCounterIncrement(assembler, R6); 1640 GenerateUsageCounterIncrement(assembler, R6);
1675 #if defined(DEBUG) 1641 #if defined(DEBUG)
1676 { 1642 {
1677 Label ok; 1643 Label ok;
1678 // Check that the IC data array has NumArgsTested() == 0. 1644 // Check that the IC data array has NumArgsTested() == 0.
1679 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1645 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1680 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 1646 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
1681 kUnsignedWord); 1647 kUnsignedWord);
1682 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1648 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1727 __ EnterStubFrame(); 1693 __ EnterStubFrame();
1728 __ Push(R5); // Preserve IC data. 1694 __ Push(R5); // Preserve IC data.
1729 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1695 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1730 __ Pop(R5); 1696 __ Pop(R5);
1731 __ RestoreCodePointer(); 1697 __ RestoreCodePointer();
1732 __ LeaveStubFrame(); 1698 __ LeaveStubFrame();
1733 __ b(&done_stepping); 1699 __ b(&done_stepping);
1734 } 1700 }
1735 } 1701 }
1736 1702
1737
1738 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1703 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1739 GenerateUsageCounterIncrement(assembler, R6); 1704 GenerateUsageCounterIncrement(assembler, R6);
1740 GenerateNArgsCheckInlineCacheStub( 1705 GenerateNArgsCheckInlineCacheStub(
1741 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL); 1706 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1742 } 1707 }
1743 1708
1744
1745 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1709 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1746 GenerateUsageCounterIncrement(assembler, R6); 1710 GenerateUsageCounterIncrement(assembler, R6);
1747 GenerateNArgsCheckInlineCacheStub( 1711 GenerateNArgsCheckInlineCacheStub(
1748 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL); 1712 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1749 } 1713 }
1750 1714
1751
1752 // Stub for compiling a function and jumping to the compiled code. 1715 // Stub for compiling a function and jumping to the compiled code.
1753 // R5: IC-Data (for methods). 1716 // R5: IC-Data (for methods).
1754 // R4: Arguments descriptor. 1717 // R4: Arguments descriptor.
1755 // R0: Function. 1718 // R0: Function.
1756 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1719 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1757 // Preserve arg desc. and IC data object. 1720 // Preserve arg desc. and IC data object.
1758 __ EnterStubFrame(); 1721 __ EnterStubFrame();
1759 __ Push(R5); // Save IC Data. 1722 __ Push(R5); // Save IC Data.
1760 __ Push(R4); // Save arg. desc. 1723 __ Push(R4); // Save arg. desc.
1761 __ Push(R0); // Pass function. 1724 __ Push(R0); // Pass function.
1762 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1725 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1763 __ Pop(R0); // Restore argument. 1726 __ Pop(R0); // Restore argument.
1764 __ Pop(R4); // Restore arg desc. 1727 __ Pop(R4); // Restore arg desc.
1765 __ Pop(R5); // Restore IC Data. 1728 __ Pop(R5); // Restore IC Data.
1766 __ LeaveStubFrame(); 1729 __ LeaveStubFrame();
1767 1730
1768 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); 1731 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
1769 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); 1732 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
1770 __ br(R2); 1733 __ br(R2);
1771 } 1734 }
1772 1735
1773
1774 // R5: Contains an ICData. 1736 // R5: Contains an ICData.
1775 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { 1737 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
1776 __ EnterStubFrame(); 1738 __ EnterStubFrame();
1777 __ Push(R5); 1739 __ Push(R5);
1778 __ Push(ZR); // Space for result. 1740 __ Push(ZR); // Space for result.
1779 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1741 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1780 __ Pop(CODE_REG); 1742 __ Pop(CODE_REG);
1781 __ Pop(R5); 1743 __ Pop(R5);
1782 __ LeaveStubFrame(); 1744 __ LeaveStubFrame();
1783 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 1745 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
1784 __ br(R0); 1746 __ br(R0);
1785 } 1747 }
1786 1748
1787
1788 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { 1749 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
1789 __ EnterStubFrame(); 1750 __ EnterStubFrame();
1790 __ Push(ZR); // Space for result. 1751 __ Push(ZR); // Space for result.
1791 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1752 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1792 __ Pop(CODE_REG); 1753 __ Pop(CODE_REG);
1793 __ LeaveStubFrame(); 1754 __ LeaveStubFrame();
1794 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 1755 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
1795 __ br(R0); 1756 __ br(R0);
1796 } 1757 }
1797 1758
1798 // Called only from unoptimized code. All relevant registers have been saved. 1759 // Called only from unoptimized code. All relevant registers have been saved.
1799 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) { 1760 void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
1800 // Check single stepping. 1761 // Check single stepping.
1801 Label stepping, done_stepping; 1762 Label stepping, done_stepping;
1802 __ LoadIsolate(R1); 1763 __ LoadIsolate(R1);
1803 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte); 1764 __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte);
1804 __ CompareImmediate(R1, 0); 1765 __ CompareImmediate(R1, 0);
1805 __ b(&stepping, NE); 1766 __ b(&stepping, NE);
1806 __ Bind(&done_stepping); 1767 __ Bind(&done_stepping);
1807 1768
1808 __ ret(); 1769 __ ret();
1809 1770
1810 __ Bind(&stepping); 1771 __ Bind(&stepping);
1811 __ EnterStubFrame(); 1772 __ EnterStubFrame();
1812 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1773 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1813 __ LeaveStubFrame(); 1774 __ LeaveStubFrame();
1814 __ b(&done_stepping); 1775 __ b(&done_stepping);
1815 } 1776 }
1816 1777
1817
1818 // Used to check class and type arguments. Arguments passed in registers: 1778 // Used to check class and type arguments. Arguments passed in registers:
1819 // LR: return address. 1779 // LR: return address.
1820 // R0: instance (must be preserved). 1780 // R0: instance (must be preserved).
1821 // R1: instantiator type arguments (only if n == 4, can be raw_null). 1781 // R1: instantiator type arguments (only if n == 4, can be raw_null).
1822 // R2: function type arguments (only if n == 4, can be raw_null). 1782 // R2: function type arguments (only if n == 4, can be raw_null).
1823 // R3: SubtypeTestCache. 1783 // R3: SubtypeTestCache.
1824 // Result in R1: null -> not found, otherwise result (true or false). 1784 // Result in R1: null -> not found, otherwise result (true or false).
1825 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1785 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1826 ASSERT((n == 1) || (n == 2) || (n == 4)); 1786 ASSERT((n == 1) || (n == 2) || (n == 4));
1827 if (n > 1) { 1787 if (n > 1) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1893 // Fall through to not found. 1853 // Fall through to not found.
1894 __ Bind(&not_found); 1854 __ Bind(&not_found);
1895 __ LoadObject(R1, Object::null_object()); 1855 __ LoadObject(R1, Object::null_object());
1896 __ ret(); 1856 __ ret();
1897 1857
1898 __ Bind(&found); 1858 __ Bind(&found);
1899 __ LoadFromOffset(R1, R3, kWordSize * SubtypeTestCache::kTestResult); 1859 __ LoadFromOffset(R1, R3, kWordSize * SubtypeTestCache::kTestResult);
1900 __ ret(); 1860 __ ret();
1901 } 1861 }
1902 1862
1903
1904 // Used to check class and type arguments. Arguments passed on stack: 1863 // Used to check class and type arguments. Arguments passed on stack:
1905 // LR: return address. 1864 // LR: return address.
1906 // R0: instance (must be preserved). 1865 // R0: instance (must be preserved).
1907 // R1: unused. 1866 // R1: unused.
1908 // R2: unused. 1867 // R2: unused.
1909 // R3: SubtypeTestCache. 1868 // R3: SubtypeTestCache.
1910 // Result in R1: null -> not found, otherwise result (true or false). 1869 // Result in R1: null -> not found, otherwise result (true or false).
1911 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) { 1870 void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
1912 GenerateSubtypeNTestCacheStub(assembler, 1); 1871 GenerateSubtypeNTestCacheStub(assembler, 1);
1913 } 1872 }
1914 1873
1915
1916 // Used to check class and type arguments. Arguments passed in registers: 1874 // Used to check class and type arguments. Arguments passed in registers:
1917 // LR: return address. 1875 // LR: return address.
1918 // R0: instance (must be preserved). 1876 // R0: instance (must be preserved).
1919 // R1: unused. 1877 // R1: unused.
1920 // R2: unused. 1878 // R2: unused.
1921 // R3: SubtypeTestCache. 1879 // R3: SubtypeTestCache.
1922 // Result in R1: null -> not found, otherwise result (true or false). 1880 // Result in R1: null -> not found, otherwise result (true or false).
1923 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) { 1881 void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
1924 GenerateSubtypeNTestCacheStub(assembler, 2); 1882 GenerateSubtypeNTestCacheStub(assembler, 2);
1925 } 1883 }
1926 1884
1927
1928 // Used to check class and type arguments. Arguments passed on stack: 1885 // Used to check class and type arguments. Arguments passed on stack:
1929 // LR: return address. 1886 // LR: return address.
1930 // R0: instance (must be preserved). 1887 // R0: instance (must be preserved).
1931 // R1: instantiator type arguments (can be raw_null). 1888 // R1: instantiator type arguments (can be raw_null).
1932 // R2: function type arguments (can be raw_null). 1889 // R2: function type arguments (can be raw_null).
1933 // R3: SubtypeTestCache. 1890 // R3: SubtypeTestCache.
1934 // Result in R1: null -> not found, otherwise result (true or false). 1891 // Result in R1: null -> not found, otherwise result (true or false).
1935 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) { 1892 void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) {
1936 GenerateSubtypeNTestCacheStub(assembler, 4); 1893 GenerateSubtypeNTestCacheStub(assembler, 4);
1937 } 1894 }
1938 1895
1939
1940 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) { 1896 void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) {
1941 __ mov(R0, CSP); 1897 __ mov(R0, CSP);
1942 __ ret(); 1898 __ ret();
1943 } 1899 }
1944 1900
1945
1946 // Jump to a frame on the call stack. 1901 // Jump to a frame on the call stack.
1947 // LR: return address. 1902 // LR: return address.
1948 // R0: program_counter. 1903 // R0: program_counter.
1949 // R1: stack_pointer. 1904 // R1: stack_pointer.
1950 // R2: frame_pointer. 1905 // R2: frame_pointer.
1951 // R3: thread. 1906 // R3: thread.
1952 // Does not return. 1907 // Does not return.
1953 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) { 1908 void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
1954 ASSERT(kExceptionObjectReg == R0); 1909 ASSERT(kExceptionObjectReg == R0);
1955 ASSERT(kStackTraceObjectReg == R1); 1910 ASSERT(kStackTraceObjectReg == R1);
1956 __ mov(LR, R0); // Program counter. 1911 __ mov(LR, R0); // Program counter.
1957 __ mov(SP, R1); // Stack pointer. 1912 __ mov(SP, R1); // Stack pointer.
1958 __ mov(FP, R2); // Frame_pointer. 1913 __ mov(FP, R2); // Frame_pointer.
1959 __ mov(THR, R3); 1914 __ mov(THR, R3);
1960 // Set the tag. 1915 // Set the tag.
1961 __ LoadImmediate(R2, VMTag::kDartTagId); 1916 __ LoadImmediate(R2, VMTag::kDartTagId);
1962 __ StoreToOffset(R2, THR, Thread::vm_tag_offset()); 1917 __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
1963 // Clear top exit frame. 1918 // Clear top exit frame.
1964 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset()); 1919 __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
1965 // Restore the pool pointer. 1920 // Restore the pool pointer.
1966 __ RestoreCodePointer(); 1921 __ RestoreCodePointer();
1967 __ LoadPoolPointer(); 1922 __ LoadPoolPointer();
1968 __ ret(); // Jump to continuation point. 1923 __ ret(); // Jump to continuation point.
1969 } 1924 }
1970 1925
1971
1972 // Run an exception handler. Execution comes from JumpToFrame 1926 // Run an exception handler. Execution comes from JumpToFrame
1973 // stub or from the simulator. 1927 // stub or from the simulator.
1974 // 1928 //
1975 // The arguments are stored in the Thread object. 1929 // The arguments are stored in the Thread object.
1976 // Does not return. 1930 // Does not return.
1977 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { 1931 void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
1978 __ LoadFromOffset(LR, THR, Thread::resume_pc_offset()); 1932 __ LoadFromOffset(LR, THR, Thread::resume_pc_offset());
1979 __ LoadImmediate(R2, 0); 1933 __ LoadImmediate(R2, 0);
1980 1934
1981 // Exception object. 1935 // Exception object.
1982 __ LoadFromOffset(R0, THR, Thread::active_exception_offset()); 1936 __ LoadFromOffset(R0, THR, Thread::active_exception_offset());
1983 __ StoreToOffset(R2, THR, Thread::active_exception_offset()); 1937 __ StoreToOffset(R2, THR, Thread::active_exception_offset());
1984 1938
1985 // StackTrace object. 1939 // StackTrace object.
1986 __ LoadFromOffset(R1, THR, Thread::active_stacktrace_offset()); 1940 __ LoadFromOffset(R1, THR, Thread::active_stacktrace_offset());
1987 __ StoreToOffset(R2, THR, Thread::active_stacktrace_offset()); 1941 __ StoreToOffset(R2, THR, Thread::active_stacktrace_offset());
1988 1942
1989 __ ret(); // Jump to the exception handler code. 1943 __ ret(); // Jump to the exception handler code.
1990 } 1944 }
1991 1945
1992
1993 // Deoptimize a frame on the call stack before rewinding. 1946 // Deoptimize a frame on the call stack before rewinding.
1994 // The arguments are stored in the Thread object. 1947 // The arguments are stored in the Thread object.
1995 // No result. 1948 // No result.
1996 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { 1949 void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
1997 // Push zap value instead of CODE_REG. 1950 // Push zap value instead of CODE_REG.
1998 __ LoadImmediate(TMP, kZapCodeReg); 1951 __ LoadImmediate(TMP, kZapCodeReg);
1999 __ Push(TMP); 1952 __ Push(TMP);
2000 1953
2001 // Load the deopt pc into LR. 1954 // Load the deopt pc into LR.
2002 __ LoadFromOffset(LR, THR, Thread::resume_pc_offset()); 1955 __ LoadFromOffset(LR, THR, Thread::resume_pc_offset());
2003 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 1956 GenerateDeoptimizationSequence(assembler, kEagerDeopt);
2004 1957
2005 // After we have deoptimized, jump to the correct frame. 1958 // After we have deoptimized, jump to the correct frame.
2006 __ EnterStubFrame(); 1959 __ EnterStubFrame();
2007 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); 1960 __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0);
2008 __ LeaveStubFrame(); 1961 __ LeaveStubFrame();
2009 __ brk(0); 1962 __ brk(0);
2010 } 1963 }
2011 1964
2012
2013 // Calls to the runtime to optimize the given function. 1965 // Calls to the runtime to optimize the given function.
2014 // R6: function to be re-optimized. 1966 // R6: function to be re-optimized.
2015 // R4: argument descriptor (preserved). 1967 // R4: argument descriptor (preserved).
2016 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1968 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
2017 __ EnterStubFrame(); 1969 __ EnterStubFrame();
2018 __ Push(R4); 1970 __ Push(R4);
2019 // Setup space on stack for the return value. 1971 // Setup space on stack for the return value.
2020 __ Push(ZR); 1972 __ Push(ZR);
2021 __ Push(R6); 1973 __ Push(R6);
2022 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 1974 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
2023 __ Pop(R0); // Discard argument. 1975 __ Pop(R0); // Discard argument.
2024 __ Pop(R0); // Get Function object 1976 __ Pop(R0); // Get Function object
2025 __ Pop(R4); // Restore argument descriptor. 1977 __ Pop(R4); // Restore argument descriptor.
2026 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); 1978 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
2027 __ LoadFieldFromOffset(R1, R0, Function::entry_point_offset()); 1979 __ LoadFieldFromOffset(R1, R0, Function::entry_point_offset());
2028 __ LeaveStubFrame(); 1980 __ LeaveStubFrame();
2029 __ br(R1); 1981 __ br(R1);
2030 __ brk(0); 1982 __ brk(0);
2031 } 1983 }
2032 1984
2033
2034 // Does identical check (object references are equal or not equal) with special 1985 // Does identical check (object references are equal or not equal) with special
2035 // checks for boxed numbers. 1986 // checks for boxed numbers.
2036 // Left and right are pushed on stack. 1987 // Left and right are pushed on stack.
2037 // Return Zero condition flag set if equal. 1988 // Return Zero condition flag set if equal.
2038 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint 1989 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
2039 // cannot contain a value that fits in Mint or Smi. 1990 // cannot contain a value that fits in Mint or Smi.
2040 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler, 1991 static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
2041 const Register left, 1992 const Register left,
2042 const Register right) { 1993 const Register right) {
2043 Label reference_compare, done, check_mint, check_bigint; 1994 Label reference_compare, done, check_mint, check_bigint;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 // Result in R0, 0 means equal. 2032 // Result in R0, 0 means equal.
2082 __ LeaveStubFrame(); 2033 __ LeaveStubFrame();
2083 __ cmp(R0, Operand(0)); 2034 __ cmp(R0, Operand(0));
2084 __ b(&done); 2035 __ b(&done);
2085 2036
2086 __ Bind(&reference_compare); 2037 __ Bind(&reference_compare);
2087 __ CompareRegisters(left, right); 2038 __ CompareRegisters(left, right);
2088 __ Bind(&done); 2039 __ Bind(&done);
2089 } 2040 }
2090 2041
2091
2092 // Called only from unoptimized code. All relevant registers have been saved. 2042 // Called only from unoptimized code. All relevant registers have been saved.
2093 // LR: return address. 2043 // LR: return address.
2094 // SP + 4: left operand. 2044 // SP + 4: left operand.
2095 // SP + 0: right operand. 2045 // SP + 0: right operand.
2096 // Return Zero condition flag set if equal. 2046 // Return Zero condition flag set if equal.
2097 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( 2047 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
2098 Assembler* assembler) { 2048 Assembler* assembler) {
2099 // Check single stepping. 2049 // Check single stepping.
2100 Label stepping, done_stepping; 2050 Label stepping, done_stepping;
2101 if (FLAG_support_debugger) { 2051 if (FLAG_support_debugger) {
(...skipping 14 matching lines...) Expand all
2116 if (FLAG_support_debugger) { 2066 if (FLAG_support_debugger) {
2117 __ Bind(&stepping); 2067 __ Bind(&stepping);
2118 __ EnterStubFrame(); 2068 __ EnterStubFrame();
2119 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 2069 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2120 __ RestoreCodePointer(); 2070 __ RestoreCodePointer();
2121 __ LeaveStubFrame(); 2071 __ LeaveStubFrame();
2122 __ b(&done_stepping); 2072 __ b(&done_stepping);
2123 } 2073 }
2124 } 2074 }
2125 2075
2126
2127 // Called from optimized code only. 2076 // Called from optimized code only.
2128 // LR: return address. 2077 // LR: return address.
2129 // SP + 4: left operand. 2078 // SP + 4: left operand.
2130 // SP + 0: right operand. 2079 // SP + 0: right operand.
2131 // Return Zero condition flag set if equal. 2080 // Return Zero condition flag set if equal.
2132 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub( 2081 void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
2133 Assembler* assembler) { 2082 Assembler* assembler) {
2134 const Register left = R1; 2083 const Register left = R1;
2135 const Register right = R0; 2084 const Register right = R0;
2136 __ LoadFromOffset(left, SP, 1 * kWordSize); 2085 __ LoadFromOffset(left, SP, 1 * kWordSize);
2137 __ LoadFromOffset(right, SP, 0 * kWordSize); 2086 __ LoadFromOffset(right, SP, 0 * kWordSize);
2138 GenerateIdenticalWithNumberCheckStub(assembler, left, right); 2087 GenerateIdenticalWithNumberCheckStub(assembler, left, right);
2139 __ ret(); 2088 __ ret();
2140 } 2089 }
2141 2090
2142
2143 // Called from megamorphic calls. 2091 // Called from megamorphic calls.
2144 // R0: receiver 2092 // R0: receiver
2145 // R5: MegamorphicCache (preserved) 2093 // R5: MegamorphicCache (preserved)
2146 // Passed to target: 2094 // Passed to target:
2147 // CODE_REG: target Code 2095 // CODE_REG: target Code
2148 // R4: arguments descriptor 2096 // R4: arguments descriptor
2149 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) { 2097 void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
2150 // Jump if receiver is a smi. 2098 // Jump if receiver is a smi.
2151 Label smi_case; 2099 Label smi_case;
2152 __ TestImmediate(R0, kSmiTagMask); 2100 __ TestImmediate(R0, kSmiTagMask);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 // Try next extry in the table. 2153 // Try next extry in the table.
2206 __ AddImmediate(R3, Smi::RawValue(1)); 2154 __ AddImmediate(R3, Smi::RawValue(1));
2207 __ b(&loop); 2155 __ b(&loop);
2208 2156
2209 // Load cid for the Smi case. 2157 // Load cid for the Smi case.
2210 __ Bind(&smi_case); 2158 __ Bind(&smi_case);
2211 __ LoadImmediate(R0, kSmiCid); 2159 __ LoadImmediate(R0, kSmiCid);
2212 __ b(&cid_loaded); 2160 __ b(&cid_loaded);
2213 } 2161 }
2214 2162
2215
2216 // Called from switchable IC calls. 2163 // Called from switchable IC calls.
2217 // R0: receiver 2164 // R0: receiver
2218 // R5: ICData (preserved) 2165 // R5: ICData (preserved)
2219 // Passed to target: 2166 // Passed to target:
2220 // CODE_REG: target Code object 2167 // CODE_REG: target Code object
2221 // R4: arguments descriptor 2168 // R4: arguments descriptor
2222 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { 2169 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) {
2223 Label loop, found, miss; 2170 Label loop, found, miss;
2224 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); 2171 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
2225 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); 2172 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
(...skipping 20 matching lines...) Expand all
2246 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); 2193 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
2247 __ br(R1); 2194 __ br(R1);
2248 2195
2249 __ Bind(&miss); 2196 __ Bind(&miss);
2250 __ LoadIsolate(R2); 2197 __ LoadIsolate(R2);
2251 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); 2198 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
2252 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); 2199 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
2253 __ br(R1); 2200 __ br(R1);
2254 } 2201 }
2255 2202
2256
2257 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { 2203 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) {
2258 Label loop, found, miss; 2204 Label loop, found, miss;
2259 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); 2205 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
2260 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); 2206 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
2261 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); 2207 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
2262 // R8: first IC entry 2208 // R8: first IC entry
2263 __ LoadTaggedClassIdMayBeSmi(R1, R0); 2209 __ LoadTaggedClassIdMayBeSmi(R1, R0);
2264 // R1: receiver cid as Smi 2210 // R1: receiver cid as Smi
2265 2211
2266 __ Bind(&loop); 2212 __ Bind(&loop);
(...skipping 14 matching lines...) Expand all
2281 __ ldr(CODE_REG, Address(R8, code_offset)); 2227 __ ldr(CODE_REG, Address(R8, code_offset));
2282 __ br(R1); 2228 __ br(R1);
2283 2229
2284 __ Bind(&miss); 2230 __ Bind(&miss);
2285 __ LoadIsolate(R2); 2231 __ LoadIsolate(R2);
2286 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); 2232 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
2287 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); 2233 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
2288 __ br(R1); 2234 __ br(R1);
2289 } 2235 }
2290 2236
2291
2292 // Called from switchable IC calls. 2237 // Called from switchable IC calls.
2293 // R0: receiver 2238 // R0: receiver
2294 // R5: SingleTargetCache 2239 // R5: SingleTargetCache
2295 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) { 2240 void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
2296 __ EnterStubFrame(); 2241 __ EnterStubFrame();
2297 __ Push(R0); // Preserve receiver. 2242 __ Push(R0); // Preserve receiver.
2298 2243
2299 __ Push(ZR); // Result slot. 2244 __ Push(ZR); // Result slot.
2300 __ Push(R0); // Arg0: Receiver 2245 __ Push(R0); // Arg0: Receiver
2301 __ Push(R5); // Arg1: UnlinkedCall 2246 __ Push(R5); // Arg1: UnlinkedCall
2302 __ CallRuntime(kUnlinkedCallRuntimeEntry, 2); 2247 __ CallRuntime(kUnlinkedCallRuntimeEntry, 2);
2303 __ Drop(2); 2248 __ Drop(2);
2304 __ Pop(R5); // result = IC 2249 __ Pop(R5); // result = IC
2305 2250
2306 __ Pop(R0); // Restore receiver. 2251 __ Pop(R0); // Restore receiver.
2307 __ LeaveStubFrame(); 2252 __ LeaveStubFrame();
2308 2253
2309 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); 2254 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
2310 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); 2255 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
2311 __ br(R1); 2256 __ br(R1);
2312 } 2257 }
2313 2258
2314
2315 // Called from switchable IC calls. 2259 // Called from switchable IC calls.
2316 // R0: receiver 2260 // R0: receiver
2317 // R5: SingleTargetCache 2261 // R5: SingleTargetCache
2318 // Passed to target: 2262 // Passed to target:
2319 // CODE_REG: target Code object 2263 // CODE_REG: target Code object
2320 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) { 2264 void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
2321 Label miss; 2265 Label miss;
2322 __ LoadClassIdMayBeSmi(R1, R0); 2266 __ LoadClassIdMayBeSmi(R1, R0);
2323 __ ldr(R2, FieldAddress(R5, SingleTargetCache::lower_limit_offset()), 2267 __ ldr(R2, FieldAddress(R5, SingleTargetCache::lower_limit_offset()),
2324 kUnsignedHalfword); 2268 kUnsignedHalfword);
(...skipping 20 matching lines...) Expand all
2345 __ Pop(R5); // result = IC 2289 __ Pop(R5); // result = IC
2346 2290
2347 __ Pop(R0); // Restore receiver. 2291 __ Pop(R0); // Restore receiver.
2348 __ LeaveStubFrame(); 2292 __ LeaveStubFrame();
2349 2293
2350 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); 2294 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
2351 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); 2295 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
2352 __ br(R1); 2296 __ br(R1);
2353 } 2297 }
2354 2298
2355
2356 // Called from the monomorphic checked entry. 2299 // Called from the monomorphic checked entry.
2357 // R0: receiver 2300 // R0: receiver
2358 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) { 2301 void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) {
2359 __ ldr(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset())); 2302 __ ldr(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset()));
2360 __ EnterStubFrame(); 2303 __ EnterStubFrame();
2361 __ Push(R0); // Preserve receiver. 2304 __ Push(R0); // Preserve receiver.
2362 2305
2363 __ Push(ZR); // Result slot. 2306 __ Push(ZR); // Result slot.
2364 __ Push(R0); // Arg0: Receiver 2307 __ Push(R0); // Arg0: Receiver
2365 __ CallRuntime(kMonomorphicMissRuntimeEntry, 1); 2308 __ CallRuntime(kMonomorphicMissRuntimeEntry, 1);
2366 __ Drop(1); 2309 __ Drop(1);
2367 __ Pop(R5); // result = IC 2310 __ Pop(R5); // result = IC
2368 2311
2369 __ Pop(R0); // Restore receiver. 2312 __ Pop(R0); // Restore receiver.
2370 __ LeaveStubFrame(); 2313 __ LeaveStubFrame();
2371 2314
2372 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset())); 2315 __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
2373 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset())); 2316 __ ldr(R1, FieldAddress(CODE_REG, Code::checked_entry_point_offset()));
2374 __ br(R1); 2317 __ br(R1);
2375 } 2318 }
2376 2319
2377
2378 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2320 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2379 __ brk(0); 2321 __ brk(0);
2380 } 2322 }
2381 2323
2382
2383 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { 2324 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
2384 __ brk(0); 2325 __ brk(0);
2385 } 2326 }
2386 2327
2387 } // namespace dart 2328 } // namespace dart
2388 2329
2389 #endif // defined TARGET_ARCH_ARM64 2330 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_arm.cc ('k') | runtime/vm/stub_code_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698