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

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

Issue 1343373003: Revert "VM: New calling convention for generated code." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/stub_code_arm.cc ('k') | runtime/vm/stub_code_ia32.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/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 23 matching lines...) Expand all
34 // SP : address of last argument in argument array. 34 // SP : address of last argument in argument array.
35 // SP + 8*R4 - 8 : address of first argument in argument array. 35 // SP + 8*R4 - 8 : address of first argument in argument array.
36 // SP + 8*R4 : address of return value. 36 // SP + 8*R4 : address of return value.
37 // R5 : address of the runtime function to call. 37 // R5 : address of the runtime function to call.
38 // R4 : number of arguments to the call. 38 // R4 : number of arguments to the call.
39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { 39 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
40 const intptr_t thread_offset = NativeArguments::thread_offset(); 40 const intptr_t thread_offset = NativeArguments::thread_offset();
41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset(); 41 const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
42 const intptr_t argv_offset = NativeArguments::argv_offset(); 42 const intptr_t argv_offset = NativeArguments::argv_offset();
43 const intptr_t retval_offset = NativeArguments::retval_offset(); 43 const intptr_t retval_offset = NativeArguments::retval_offset();
44 const intptr_t exitframe_last_param_slot_from_fp = 1;
44 45
45 __ SetPrologueOffset(); 46 __ SetPrologueOffset();
46 __ Comment("CallToRuntimeStub"); 47 __ Comment("CallToRuntimeStub");
47 __ EnterStubFrame(); 48 __ EnterStubFrame();
48 49
49 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0); 50 COMPILE_ASSERT((kAbiPreservedCpuRegs & (1 << R28)) != 0);
50 __ LoadIsolate(R28); 51 __ LoadIsolate(R28);
51 52
52 // Save exit frame information to enable stack walking as we are about 53 // Save exit frame information to enable stack walking as we are about
53 // to transition to Dart VM C++ code. 54 // to transition to Dart VM C++ code.
(...skipping 29 matching lines...) Expand all
83 84
84 // There are no runtime calls to closures, so we do not need to set the tag 85 // There are no runtime calls to closures, so we do not need to set the tag
85 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. 86 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
86 ASSERT(argc_tag_offset == 1 * kWordSize); 87 ASSERT(argc_tag_offset == 1 * kWordSize);
87 __ mov(R1, R4); // Set argc in NativeArguments. 88 __ mov(R1, R4); // Set argc in NativeArguments.
88 89
89 ASSERT(argv_offset == 2 * kWordSize); 90 ASSERT(argv_offset == 2 * kWordSize);
90 __ add(R2, ZR, Operand(R4, LSL, 3)); 91 __ add(R2, ZR, Operand(R4, LSL, 3));
91 __ add(R2, FP, Operand(R2)); // Compute argv. 92 __ add(R2, FP, Operand(R2)); // Compute argv.
92 // Set argv in NativeArguments. 93 // Set argv in NativeArguments.
93 __ AddImmediate(R2, R2, kParamEndSlotFromFp * kWordSize); 94 __ AddImmediate(R2, R2, exitframe_last_param_slot_from_fp * kWordSize);
94 95
95 ASSERT(retval_offset == 3 * kWordSize); 96 ASSERT(retval_offset == 3 * kWordSize);
96 __ AddImmediate(R3, R2, kWordSize); 97 __ AddImmediate(R3, R2, kWordSize);
97 98
98 __ StoreToOffset(R0, SP, thread_offset); 99 __ StoreToOffset(R0, SP, thread_offset);
99 __ StoreToOffset(R1, SP, argc_tag_offset); 100 __ StoreToOffset(R1, SP, argc_tag_offset);
100 __ StoreToOffset(R2, SP, argv_offset); 101 __ StoreToOffset(R2, SP, argv_offset);
101 __ StoreToOffset(R3, SP, retval_offset); 102 __ StoreToOffset(R3, SP, retval_offset);
102 __ mov(R0, SP); // Pass the pointer to the NativeArguments. 103 __ mov(R0, SP); // Pass the pointer to the NativeArguments.
103 104
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 // R4: arguments descriptor array. 339 // R4: arguments descriptor array.
339 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 340 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
340 // Create a stub frame as we are pushing some objects on the stack before 341 // Create a stub frame as we are pushing some objects on the stack before
341 // calling into the runtime. 342 // calling into the runtime.
342 __ EnterStubFrame(); 343 __ EnterStubFrame();
343 // Setup space on stack for return value and preserve arguments descriptor. 344 // Setup space on stack for return value and preserve arguments descriptor.
344 __ Push(R4); 345 __ Push(R4);
345 __ PushObject(Object::null_object()); 346 __ PushObject(Object::null_object());
346 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); 347 __ CallRuntime(kPatchStaticCallRuntimeEntry, 0);
347 // Get Code object result and restore arguments descriptor array. 348 // Get Code object result and restore arguments descriptor array.
348 __ Pop(CODE_REG); 349 __ Pop(R0);
349 __ Pop(R4); 350 __ Pop(R4);
350 // Remove the stub frame. 351 // Remove the stub frame.
351 __ LeaveStubFrame(); 352 __ LeaveStubFrame();
352 // Jump to the dart function. 353 // Jump to the dart function.
353 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 354 __ LoadFieldFromOffset(R0, R0, Code::entry_point_offset());
354 __ br(R0); 355 __ br(R0);
355 } 356 }
356 357
357 358
358 // Called from a static call only when an invalid code has been entered 359 // Called from a static call only when an invalid code has been entered
359 // (invalid because its function was optimized or deoptimized). 360 // (invalid because its function was optimized or deoptimized).
360 // R4: arguments descriptor array. 361 // R4: arguments descriptor array.
361 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 362 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
362 // Load code pointer to this stub from the thread:
363 // The one that is passed in, is not correct - it points to the code object
364 // that needs to be replaced.
365 __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
366 // Create a stub frame as we are pushing some objects on the stack before 363 // Create a stub frame as we are pushing some objects on the stack before
367 // calling into the runtime. 364 // calling into the runtime.
368 __ EnterStubFrame(); 365 __ EnterStubFrame();
369 // Setup space on stack for return value and preserve arguments descriptor. 366 // Setup space on stack for return value and preserve arguments descriptor.
370 __ Push(R4); 367 __ Push(R4);
371 __ PushObject(Object::null_object()); 368 __ PushObject(Object::null_object());
372 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); 369 __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
373 // Get Code object result and restore arguments descriptor array. 370 // Get Code object result and restore arguments descriptor array.
374 __ Pop(CODE_REG); 371 __ Pop(R0);
375 __ Pop(R4); 372 __ Pop(R4);
376 // Remove the stub frame. 373 // Remove the stub frame.
377 __ LeaveStubFrame(); 374 __ LeaveStubFrame();
378 // Jump to the dart function. 375 // Jump to the dart function.
379 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 376 __ LoadFieldFromOffset(R0, R0, Code::entry_point_offset());
380 __ br(R0); 377 __ br(R0);
381 } 378 }
382 379
383 380
384 // Called from object allocate instruction when the allocation stub has been 381 // Called from object allocate instruction when the allocation stub has been
385 // disabled. 382 // disabled.
386 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) { 383 void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
387 // Load code pointer to this stub from the thread:
388 // The one that is passed in, is not correct - it points to the code object
389 // that needs to be replaced.
390 __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
391 __ EnterStubFrame(); 384 __ EnterStubFrame();
392 // Setup space on stack for return value. 385 // Setup space on stack for return value.
393 __ PushObject(Object::null_object()); 386 __ PushObject(Object::null_object());
394 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0); 387 __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
395 // Get Code object result. 388 // Get Code object result.
396 __ Pop(CODE_REG); 389 __ Pop(R0);
397 // Remove the stub frame. 390 // Remove the stub frame.
398 __ LeaveStubFrame(); 391 __ LeaveStubFrame();
399 // Jump to the dart function. 392 // Jump to the dart function.
400 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 393 __ LoadFieldFromOffset(R0, R0, Code::entry_point_offset());
401 __ br(R0); 394 __ br(R0);
402 } 395 }
403 396
404 397
405 // Input parameters: 398 // Input parameters:
406 // R2: smi-tagged argument count, may be zero. 399 // R2: smi-tagged argument count, may be zero.
407 // FP[kParamEndSlotFromFp + 1]: last argument. 400 // FP[kParamEndSlotFromFp + 1]: last argument.
408 static void PushArgumentsArray(Assembler* assembler) { 401 static void PushArgumentsArray(Assembler* assembler) {
409 // Allocate array to store arguments of caller. 402 // Allocate array to store arguments of caller.
410 __ LoadObject(R1, Object::null_object()); 403 __ LoadObject(R1, Object::null_object());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 // Stack after TagAndPushPP() below: 441 // Stack after TagAndPushPP() below:
449 // +------------------+ 442 // +------------------+
450 // | Saved PP | <- PP 443 // | Saved PP | <- PP
451 // +------------------+ 444 // +------------------+
452 // | PC marker | <- TOS 445 // | PC marker | <- TOS
453 // +------------------+ 446 // +------------------+
454 // | Saved FP | <- FP of stub 447 // | Saved FP | <- FP of stub
455 // +------------------+ 448 // +------------------+
456 // | return-address | (deoptimization point) 449 // | return-address | (deoptimization point)
457 // +------------------+ 450 // +------------------+
458 // | Saved CODE_REG |
459 // +------------------+
460 // | ... | <- SP of optimized frame 451 // | ... | <- SP of optimized frame
461 // 452 //
462 // Parts of the code cannot GC, part of the code can GC. 453 // Parts of the code cannot GC, part of the code can GC.
463 static void GenerateDeoptimizationSequence(Assembler* assembler, 454 static void GenerateDeoptimizationSequence(Assembler* assembler,
464 DeoptStubKind kind) { 455 bool preserve_result) {
465 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 456 // DeoptimizeCopyFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
466 // is no need to set the correct PC marker or load PP, since they get patched. 457 // is no need to set the correct PC marker or load PP, since they get patched.
467 __ EnterStubFrame(); 458 __ EnterStubFrame();
468 459
469 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry 460 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
470 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. 461 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls.
471 const intptr_t saved_result_slot_from_fp = 462 const intptr_t saved_result_slot_from_fp =
472 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0); 463 kFirstLocalSlotFromFp + 1 - (kNumberOfCpuRegisters - R0);
473 // Result in R0 is preserved as part of pushing all registers below. 464 // Result in R0 is preserved as part of pushing all registers below.
474 465
475 // Push registers in their enumeration order: lowest register number at 466 // Push registers in their enumeration order: lowest register number at
476 // lowest address. 467 // lowest address.
477 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { 468 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
478 const Register r = static_cast<Register>(i); 469 const Register r = static_cast<Register>(i);
479 if (r == CODE_REG) { 470 __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
480 // Save the original value of CODE_REG pushed before invoking this stub
481 // instead of the value used to call this stub.
482 COMPILE_ASSERT(R25 > CODE_REG);
483 __ ldr(R25, Address(FP, 2 * kWordSize));
484 __ str(R25, Address(SP, -1 * kWordSize, Address::PreIndex));
485 } else {
486 __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
487 }
488 } 471 }
489 472
490 for (intptr_t reg_idx = kNumberOfVRegisters - 1; reg_idx >= 0; reg_idx--) { 473 for (intptr_t reg_idx = kNumberOfVRegisters - 1; reg_idx >= 0; reg_idx--) {
491 VRegister vreg = static_cast<VRegister>(reg_idx); 474 VRegister vreg = static_cast<VRegister>(reg_idx);
492 __ PushQuad(vreg); 475 __ PushQuad(vreg);
493 } 476 }
494 477
495 __ mov(R0, SP); // Pass address of saved registers block. 478 __ mov(R0, SP); // Pass address of saved registers block.
496 __ LoadImmediate(R1, kind == kLazyDeopt ? 1 : 0);
497 __ ReserveAlignedFrameSpace(0); 479 __ ReserveAlignedFrameSpace(0);
498 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2); 480 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1);
499 // Result (R0) is stack-size (FP - SP) in bytes. 481 // Result (R0) is stack-size (FP - SP) in bytes.
500 482
501 const bool preserve_result = (kind == kLazyDeopt);
502 if (preserve_result) { 483 if (preserve_result) {
503 // Restore result into R1 temporarily. 484 // Restore result into R1 temporarily.
504 __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize); 485 __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize);
505 } 486 }
506 487
507 // There is a Dart Frame on the stack. We must restore PP and leave frame. 488 // There is a Dart Frame on the stack. We must restore PP and leave frame.
508 __ RestoreCodePointer();
509 __ LeaveStubFrame(); 489 __ LeaveStubFrame();
510 __ sub(SP, FP, Operand(R0)); 490 __ sub(SP, FP, Operand(R0));
511 491
512 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there 492 // DeoptimizeFillFrame expects a Dart frame, i.e. EnterDartFrame(0), but there
513 // is no need to set the correct PC marker or load PP, since they get patched. 493 // is no need to set the correct PC marker or load PP, since they get patched.
514 __ EnterStubFrame(); 494 __ EnterStubFrame();
515 495
516 if (preserve_result) { 496 if (preserve_result) {
517 __ Push(R1); // Preserve result as first local. 497 __ Push(R1); // Preserve result as first local.
518 } 498 }
519 __ ReserveAlignedFrameSpace(0); 499 __ ReserveAlignedFrameSpace(0);
520 __ mov(R0, FP); // Pass last FP as parameter in R0. 500 __ mov(R0, FP); // Pass last FP as parameter in R0.
521 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1); 501 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
522 if (preserve_result) { 502 if (preserve_result) {
523 // Restore result into R1. 503 // Restore result into R1.
524 __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize); 504 __ LoadFromOffset(R1, FP, kFirstLocalSlotFromFp * kWordSize);
525 } 505 }
526 // Code above cannot cause GC. 506 // Code above cannot cause GC.
527 // There is a Dart Frame on the stack. We must restore PP and leave frame. 507 // There is a Dart Frame on the stack. We must restore PP and leave frame.
528 __ RestoreCodePointer();
529 __ LeaveStubFrame(); 508 __ LeaveStubFrame();
530 509
531 // Frame is fully rewritten at this point and it is safe to perform a GC. 510 // Frame is fully rewritten at this point and it is safe to perform a GC.
532 // Materialize any objects that were deferred by FillFrame because they 511 // Materialize any objects that were deferred by FillFrame because they
533 // require allocation. 512 // require allocation.
534 // Enter stub frame with loading PP. The caller's PP is not materialized yet. 513 // Enter stub frame with loading PP. The caller's PP is not materialized yet.
535 __ EnterStubFrame(); 514 __ EnterStubFrame();
536 if (preserve_result) { 515 if (preserve_result) {
537 __ Push(R1); // Preserve result, it will be GC-d here. 516 __ Push(R1); // Preserve result, it will be GC-d here.
538 } 517 }
539 __ Push(ZR); // Space for the result. 518 __ Push(ZR); // Space for the result.
540 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0); 519 __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
541 // Result tells stub how many bytes to remove from the expression stack 520 // Result tells stub how many bytes to remove from the expression stack
542 // of the bottom-most frame. They were used as materialization arguments. 521 // of the bottom-most frame. They were used as materialization arguments.
543 __ Pop(R1); 522 __ Pop(R1);
544 __ SmiUntag(R1); 523 __ SmiUntag(R1);
545 if (preserve_result) { 524 if (preserve_result) {
546 __ Pop(R0); // Restore result. 525 __ Pop(R0); // Restore result.
547 } 526 }
548 __ LeaveStubFrame(); 527 __ LeaveStubFrame();
549 // Remove materialization arguments. 528 // Remove materialization arguments.
550 __ add(SP, SP, Operand(R1)); 529 __ add(SP, SP, Operand(R1));
551 __ ret(); 530 __ ret();
552 } 531 }
553 532
554 533
555 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { 534 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
556 // Correct return address to point just after the call that is being 535 // Correct return address to point just after the call that is being
557 // deoptimized. 536 // deoptimized.
558 __ AddImmediate(LR, LR, -CallPattern::kDeoptCallLengthInBytes); 537 __ AddImmediate(LR, LR, -CallPattern::kLengthInBytes);
559 // Push zap value instead of CODE_REG for lazy deopt. 538 GenerateDeoptimizationSequence(assembler, true); // Preserve R0.
560 __ LoadImmediate(TMP, 0xf1f1f1f1);
561 __ Push(TMP);
562 GenerateDeoptimizationSequence(assembler, kLazyDeopt);
563 } 539 }
564 540
565 541
566 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 542 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
567 GenerateDeoptimizationSequence(assembler, kEagerDeopt); 543 GenerateDeoptimizationSequence(assembler, false); // Don't preserve R0.
568 } 544 }
569 545
570 546
571 static void GenerateDispatcherCode(Assembler* assembler, 547 static void GenerateDispatcherCode(Assembler* assembler,
572 Label* call_target_function) { 548 Label* call_target_function) {
573 __ Comment("NoSuchMethodDispatch"); 549 __ Comment("NoSuchMethodDispatch");
574 // When lazily generated invocation dispatchers are disabled, the 550 // When lazily generated invocation dispatchers are disabled, the
575 // miss-handler may return null. 551 // miss-handler may return null.
576 __ CompareObject(R0, Object::null_object()); 552 __ CompareObject(R0, Object::null_object());
577 __ b(call_target_function, NE); 553 __ b(call_target_function, NE);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 __ Push(R4); 594 __ Push(R4);
619 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3); 595 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry, 3);
620 // Remove arguments. 596 // Remove arguments.
621 __ Drop(3); 597 __ Drop(3);
622 __ Pop(R0); // Get result into R0 (target function). 598 __ Pop(R0); // Get result into R0 (target function).
623 599
624 // Restore IC data and arguments descriptor. 600 // Restore IC data and arguments descriptor.
625 __ Pop(R4); 601 __ Pop(R4);
626 __ Pop(R5); 602 __ Pop(R5);
627 603
628 __ RestoreCodePointer();
629 __ LeaveStubFrame(); 604 __ LeaveStubFrame();
630 605
631 if (!FLAG_lazy_dispatchers) { 606 if (!FLAG_lazy_dispatchers) {
632 Label call_target_function; 607 Label call_target_function;
633 GenerateDispatcherCode(assembler, &call_target_function); 608 GenerateDispatcherCode(assembler, &call_target_function);
634 __ Bind(&call_target_function); 609 __ Bind(&call_target_function);
635 } 610 }
636 611
637 // Tail-call to target function. 612 // Tail-call to target function.
638 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
639 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); 613 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
640 __ br(R2); 614 __ br(R2);
641 } 615 }
642 616
643 617
644 // Called for inline allocation of arrays. 618 // Called for inline allocation of arrays.
645 // Input parameters: 619 // Input parameters:
646 // LR: return address. 620 // LR: return address.
647 // R2: array length as Smi. 621 // R2: array length as Smi.
648 // R1: array element type (either NULL or an instantiated type). 622 // R1: array element type (either NULL or an instantiated type).
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 __ Pop(R2); 759 __ Pop(R2);
786 __ Pop(R0); 760 __ Pop(R0);
787 __ LeaveStubFrame(); 761 __ LeaveStubFrame();
788 __ ret(); 762 __ ret();
789 } 763 }
790 764
791 765
792 // Called when invoking Dart code from C++ (VM code). 766 // Called when invoking Dart code from C++ (VM code).
793 // Input parameters: 767 // Input parameters:
794 // LR : points to return address. 768 // LR : points to return address.
795 // R0 : code object of the Dart function to call. 769 // R0 : entrypoint of the Dart function to call.
796 // R1 : arguments descriptor array. 770 // R1 : arguments descriptor array.
797 // R2 : arguments array. 771 // R2 : arguments array.
798 // R3 : current thread. 772 // R3 : current thread.
799 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) { 773 void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
800 __ Comment("InvokeDartCodeStub"); 774 __ Comment("InvokeDartCodeStub");
801 775
802 // Copy the C stack pointer (R31) into the stack pointer we'll actually use 776 // Copy the C stack pointer (R31) into the stack pointer we'll actually use
803 // to access the stack, and put the C stack pointer at the stack limit. 777 // to access the stack, and put the C stack pointer at the stack limit.
804 __ SetupDartSP(Isolate::GetSpecifiedStackSize()); 778 __ SetupDartSP(Isolate::GetSpecifiedStackSize());
805 __ EnterFrame(0); 779 __ EnterFrame(0);
806 780
807 // Save the callee-saved registers. 781 // Save the callee-saved registers.
808 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) { 782 for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
809 const Register r = static_cast<Register>(i); 783 const Register r = static_cast<Register>(i);
810 // We use str instead of the Push macro because we will be pushing the PP 784 // We use str instead of the Push macro because we will be pushing the PP
811 // register when it is not holding a pool-pointer since we are coming from 785 // register when it is not holding a pool-pointer since we are coming from
812 // C++ code. 786 // C++ code.
813 __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex)); 787 __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
814 } 788 }
815 789
816 // Save the bottom 64-bits of callee-saved V registers. 790 // Save the bottom 64-bits of callee-saved V registers.
817 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) { 791 for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
818 const VRegister r = static_cast<VRegister>(i); 792 const VRegister r = static_cast<VRegister>(i);
819 __ PushDouble(r); 793 __ PushDouble(r);
820 } 794 }
821 795
796 // We now load the pool pointer(PP) as we are about to invoke dart code and we
797 // could potentially invoke some intrinsic functions which need the PP to be
798 // set up.
799 __ LoadPoolPointer();
800
822 // Set up THR, which caches the current thread in Dart code. 801 // Set up THR, which caches the current thread in Dart code.
823 if (THR != R3) { 802 if (THR != R3) {
824 __ mov(THR, R3); 803 __ mov(THR, R3);
825 } 804 }
826 // Load Isolate pointer into temporary register R5. 805 // Load Isolate pointer into temporary register R5.
827 __ LoadIsolate(R5); 806 __ LoadIsolate(R5);
828 807
829 // Save the current VMTag on the stack. 808 // Save the current VMTag on the stack.
830 __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset()); 809 __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset());
831 __ Push(R4); 810 __ Push(R4);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 __ LoadImmediate(R1, 0); 843 __ LoadImmediate(R1, 0);
865 __ Bind(&push_arguments); 844 __ Bind(&push_arguments);
866 __ ldr(R3, Address(R2)); 845 __ ldr(R3, Address(R2));
867 __ Push(R3); 846 __ Push(R3);
868 __ add(R1, R1, Operand(1)); 847 __ add(R1, R1, Operand(1));
869 __ add(R2, R2, Operand(kWordSize)); 848 __ add(R2, R2, Operand(kWordSize));
870 __ cmp(R1, Operand(R5)); 849 __ cmp(R1, Operand(R5));
871 __ b(&push_arguments, LT); 850 __ b(&push_arguments, LT);
872 __ Bind(&done_push_arguments); 851 __ Bind(&done_push_arguments);
873 852
874 // We now load the pool pointer(PP) with a GC safe value as we are about to
875 // invoke dart code. We don't need a real object pool here.
876 // Smi zero does not work because ARM64 assumes PP to be untagged.
877 __ LoadObject(PP, Object::null_object());
878
879 // Call the Dart code entrypoint. 853 // Call the Dart code entrypoint.
880 __ ldr(CODE_REG, Address(R0, VMHandles::kOffsetOfRawPtrInHandle));
881 __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
882 __ blr(R0); // R4 is the arguments descriptor array. 854 __ blr(R0); // R4 is the arguments descriptor array.
883 __ Comment("InvokeDartCodeStub return"); 855 __ Comment("InvokeDartCodeStub return");
884 856
857 // Restore constant pool pointer after return.
858 __ LoadPoolPointer();
859
885 // Get rid of arguments pushed on the stack. 860 // Get rid of arguments pushed on the stack.
886 __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize); 861 __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
887 862
888 __ LoadIsolate(R28); 863 __ LoadIsolate(R28);
889 864
890 // Restore the saved top exit frame info and top resource back into the 865 // Restore the saved top exit frame info and top resource back into the
891 // Isolate structure. Uses R6 as a temporary register for this. 866 // Isolate structure. Uses R6 as a temporary register for this.
892 __ Pop(R6); 867 __ Pop(R6);
893 __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset()); 868 __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset());
894 __ Pop(R6); 869 __ Pop(R6);
(...skipping 11 matching lines...) Expand all
906 881
907 // Restore C++ ABI callee-saved registers. 882 // Restore C++ ABI callee-saved registers.
908 for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) { 883 for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
909 Register r = static_cast<Register>(i); 884 Register r = static_cast<Register>(i);
910 // We use ldr instead of the Pop macro because we will be popping the PP 885 // We use ldr instead of the Pop macro because we will be popping the PP
911 // register when it is not holding a pool-pointer since we are returning to 886 // register when it is not holding a pool-pointer since we are returning to
912 // C++ code. We also skip the dart stack pointer SP, since we are still 887 // C++ code. We also skip the dart stack pointer SP, since we are still
913 // using it as the stack pointer. 888 // using it as the stack pointer.
914 __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex)); 889 __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
915 } 890 }
891 __ set_constant_pool_allowed(false);
916 892
917 // Restore the frame pointer and C stack pointer and return. 893 // Restore the frame pointer and C stack pointer and return.
918 __ LeaveFrame(); 894 __ LeaveFrame();
919 __ mov(CSP, SP); 895 __ mov(CSP, SP);
920 __ ret(); 896 __ ret();
921 } 897 }
922 898
923 899
924 // Called for inline allocation of contexts. 900 // Called for inline allocation of contexts.
925 // Input: 901 // Input:
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 // Restore callee-saved registers, tear down frame. 1067 // Restore callee-saved registers, tear down frame.
1092 __ LeaveCallRuntimeFrame(); 1068 __ LeaveCallRuntimeFrame();
1093 __ ret(); 1069 __ ret();
1094 } 1070 }
1095 1071
1096 1072
1097 // Called for inline allocation of objects. 1073 // Called for inline allocation of objects.
1098 // Input parameters: 1074 // Input parameters:
1099 // LR : return address. 1075 // LR : return address.
1100 // SP + 0 : type arguments object (only if class is parameterized). 1076 // SP + 0 : type arguments object (only if class is parameterized).
1101 void StubCode::GenerateAllocationStubForClass(Assembler* assembler, 1077 void StubCode::GenerateAllocationStubForClass(
1102 const Class& cls) { 1078 Assembler* assembler, const Class& cls,
1079 uword* entry_patch_offset, uword* patch_code_pc_offset) {
1080 *entry_patch_offset = assembler->CodeSize();
1103 // The generated code is different if the class is parameterized. 1081 // The generated code is different if the class is parameterized.
1104 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 1082 const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
1105 ASSERT(!is_cls_parameterized || 1083 ASSERT(!is_cls_parameterized ||
1106 (cls.type_arguments_field_offset() != Class::kNoTypeArguments)); 1084 (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
1107 // kInlineInstanceSize is a constant used as a threshold for determining 1085 // kInlineInstanceSize is a constant used as a threshold for determining
1108 // when the object initialization should be done as a loop or as 1086 // when the object initialization should be done as a loop or as
1109 // straight line code. 1087 // straight line code.
1110 const int kInlineInstanceSize = 12; 1088 const int kInlineInstanceSize = 12;
1111 const intptr_t instance_size = cls.instance_size(); 1089 const intptr_t instance_size = cls.instance_size();
1112 ASSERT(instance_size > 0); 1090 ASSERT(instance_size > 0);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 // Push null type arguments. 1190 // Push null type arguments.
1213 __ PushObject(Object::null_object()); 1191 __ PushObject(Object::null_object());
1214 } 1192 }
1215 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object. 1193 __ CallRuntime(kAllocateObjectRuntimeEntry, 2); // Allocate object.
1216 __ Drop(2); // Pop arguments. 1194 __ Drop(2); // Pop arguments.
1217 __ Pop(R0); // Pop result (newly allocated object). 1195 __ Pop(R0); // Pop result (newly allocated object).
1218 // R0: new object 1196 // R0: new object
1219 // Restore the frame pointer. 1197 // Restore the frame pointer.
1220 __ LeaveStubFrame(); 1198 __ LeaveStubFrame();
1221 __ ret(); 1199 __ ret();
1200 *patch_code_pc_offset = assembler->CodeSize();
1201 __ BranchPatchable(*StubCode::FixAllocationStubTarget_entry());
1222 } 1202 }
1223 1203
1224 1204
1225 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function 1205 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
1226 // from the entry code of a dart function after an error in passed argument 1206 // from the entry code of a dart function after an error in passed argument
1227 // name or number is detected. 1207 // name or number is detected.
1228 // Input parameters: 1208 // Input parameters:
1229 // LR : return address. 1209 // LR : return address.
1230 // SP : address of last argument. 1210 // SP : address of last argument.
1231 // R4: arguments descriptor array. 1211 // R4: arguments descriptor array.
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 // Pass IC data object. 1508 // Pass IC data object.
1529 __ Push(R5); 1509 __ Push(R5);
1530 __ CallRuntime(handle_ic_miss, num_args + 1); 1510 __ CallRuntime(handle_ic_miss, num_args + 1);
1531 // Remove the call arguments pushed earlier, including the IC data object. 1511 // Remove the call arguments pushed earlier, including the IC data object.
1532 __ Drop(num_args + 1); 1512 __ Drop(num_args + 1);
1533 // Pop returned function object into R0. 1513 // Pop returned function object into R0.
1534 // Restore arguments descriptor array and IC data array. 1514 // Restore arguments descriptor array and IC data array.
1535 __ Pop(R0); // Pop returned function object into R0. 1515 __ Pop(R0); // Pop returned function object into R0.
1536 __ Pop(R5); // Restore IC Data. 1516 __ Pop(R5); // Restore IC Data.
1537 __ Pop(R4); // Restore arguments descriptor array. 1517 __ Pop(R4); // Restore arguments descriptor array.
1538 if (range_collection_mode == kCollectRanges) {
1539 __ RestoreCodePointer();
1540 }
1541 __ LeaveStubFrame(); 1518 __ LeaveStubFrame();
1542 Label call_target_function; 1519 Label call_target_function;
1543 if (!FLAG_lazy_dispatchers) { 1520 if (!FLAG_lazy_dispatchers) {
1544 GenerateDispatcherCode(assembler, &call_target_function); 1521 GenerateDispatcherCode(assembler, &call_target_function);
1545 } else { 1522 } else {
1546 __ b(&call_target_function); 1523 __ b(&call_target_function);
1547 } 1524 }
1548 1525
1549 __ Bind(&found); 1526 __ Bind(&found);
1550 __ Comment("Update caller's counter"); 1527 __ Comment("Update caller's counter");
1551 // R6: pointer to an IC data check group. 1528 // R6: pointer to an IC data check group.
1552 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1529 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1553 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1530 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1554 __ LoadFromOffset(R0, R6, target_offset); 1531 __ LoadFromOffset(R0, R6, target_offset);
1555 1532
1556 if (FLAG_optimization_counter_threshold >= 0) { 1533 if (FLAG_optimization_counter_threshold >= 0) {
1557 // Update counter. 1534 // Update counter.
1558 __ LoadFromOffset(R1, R6, count_offset); 1535 __ LoadFromOffset(R1, R6, count_offset);
1559 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1536 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1560 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue)); 1537 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue));
1561 __ csel(R1, R2, R1, VS); // Overflow. 1538 __ csel(R1, R2, R1, VS); // Overflow.
1562 __ StoreToOffset(R1, R6, count_offset); 1539 __ StoreToOffset(R1, R6, count_offset);
1563 } 1540 }
1564 1541
1565 __ Comment("Call target"); 1542 __ Comment("Call target");
1566 __ Bind(&call_target_function); 1543 __ Bind(&call_target_function);
1567 // R0: target function. 1544 // R0: target function.
1545 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
1568 if (range_collection_mode == kCollectRanges) { 1546 if (range_collection_mode == kCollectRanges) {
1569 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
1570 __ ldr(R1, Address(SP, 0 * kWordSize)); 1547 __ ldr(R1, Address(SP, 0 * kWordSize));
1571 if (num_args == 2) { 1548 if (num_args == 2) {
1572 __ ldr(R3, Address(SP, 1 * kWordSize)); 1549 __ ldr(R3, Address(SP, 1 * kWordSize));
1573 } 1550 }
1574 __ EnterStubFrame(); 1551 __ EnterStubFrame();
1575 __ Push(R5); 1552 __ Push(R5);
1576 if (num_args == 2) { 1553 if (num_args == 2) {
1577 __ Push(R3); 1554 __ Push(R3);
1578 } 1555 }
1579 __ Push(R1); 1556 __ Push(R1);
1580 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
1581 __ blr(R2); 1557 __ blr(R2);
1582 1558
1583 Label done; 1559 Label done;
1584 __ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize)); 1560 __ ldr(R5, Address(FP, kFirstLocalSlotFromFp * kWordSize));
1585 __ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done); 1561 __ UpdateRangeFeedback(R0, 2, R5, R1, R4, &done);
1586 __ Bind(&done); 1562 __ Bind(&done);
1587 __ LeaveStubFrame(); 1563 __ LeaveStubFrame();
1588 __ ret(); 1564 __ ret();
1589 } else { 1565 } else {
1590 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
1591 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
1592 __ br(R2); 1566 __ br(R2);
1593 } 1567 }
1594 1568
1595 if (FLAG_support_debugger && !optimized) { 1569 if (FLAG_support_debugger && !optimized) {
1596 __ Bind(&stepping); 1570 __ Bind(&stepping);
1597 __ EnterStubFrame(); 1571 __ EnterStubFrame();
1598 __ Push(R5); // Preserve IC data. 1572 __ Push(R5); // Preserve IC data.
1599 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1573 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1600 __ Pop(R5); 1574 __ Pop(R5);
1601 __ RestoreCodePointer();
1602 __ LeaveStubFrame(); 1575 __ LeaveStubFrame();
1603 __ b(&done_stepping); 1576 __ b(&done_stepping);
1604 } 1577 }
1605 } 1578 }
1606 1579
1607 1580
1608 // Use inline cache data array to invoke the target or continue in inline 1581 // Use inline cache data array to invoke the target or continue in inline
1609 // cache miss handler. Stub for 1-argument check (receiver class). 1582 // cache miss handler. Stub for 1-argument check (receiver class).
1610 // LR: return address. 1583 // LR: return address.
1611 // R5: inline cache data object. 1584 // R5: inline cache data object.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1736 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue)); 1709 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue));
1737 __ csel(R1, R2, R1, VS); // Overflow. 1710 __ csel(R1, R2, R1, VS); // Overflow.
1738 __ StoreToOffset(R1, R6, count_offset); 1711 __ StoreToOffset(R1, R6, count_offset);
1739 } 1712 }
1740 1713
1741 // Load arguments descriptor into R4. 1714 // Load arguments descriptor into R4.
1742 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); 1715 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
1743 1716
1744 // Get function and call it, if possible. 1717 // Get function and call it, if possible.
1745 __ LoadFromOffset(R0, R6, target_offset); 1718 __ LoadFromOffset(R0, R6, target_offset);
1746 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
1747 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); 1719 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
1748 __ br(R2); 1720 __ br(R2);
1749 1721
1750 if (FLAG_support_debugger) { 1722 if (FLAG_support_debugger) {
1751 __ Bind(&stepping); 1723 __ Bind(&stepping);
1752 __ EnterStubFrame(); 1724 __ EnterStubFrame();
1753 __ Push(R5); // Preserve IC data. 1725 __ Push(R5); // Preserve IC data.
1754 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1726 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1755 __ Pop(R5); 1727 __ Pop(R5);
1756 __ RestoreCodePointer();
1757 __ LeaveStubFrame(); 1728 __ LeaveStubFrame();
1758 __ b(&done_stepping); 1729 __ b(&done_stepping);
1759 } 1730 }
1760 } 1731 }
1761 1732
1762 1733
1763 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1734 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1764 GenerateUsageCounterIncrement(assembler, R6); 1735 GenerateUsageCounterIncrement(assembler, R6);
1765 GenerateNArgsCheckInlineCacheStub( 1736 GenerateNArgsCheckInlineCacheStub(
1766 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL, 1737 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL,
(...skipping 18 matching lines...) Expand all
1785 __ EnterStubFrame(); 1756 __ EnterStubFrame();
1786 __ Push(R5); // Save IC Data. 1757 __ Push(R5); // Save IC Data.
1787 __ Push(R4); // Save arg. desc. 1758 __ Push(R4); // Save arg. desc.
1788 __ Push(R0); // Pass function. 1759 __ Push(R0); // Pass function.
1789 __ CallRuntime(kCompileFunctionRuntimeEntry, 1); 1760 __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
1790 __ Pop(R0); // Restore argument. 1761 __ Pop(R0); // Restore argument.
1791 __ Pop(R4); // Restore arg desc. 1762 __ Pop(R4); // Restore arg desc.
1792 __ Pop(R5); // Restore IC Data. 1763 __ Pop(R5); // Restore IC Data.
1793 __ LeaveStubFrame(); 1764 __ LeaveStubFrame();
1794 1765
1795 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
1796 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); 1766 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
1797 __ br(R2); 1767 __ br(R2);
1798 } 1768 }
1799 1769
1800 1770
1801 // R5: Contains an ICData. 1771 // R5: Contains an ICData.
1802 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) { 1772 void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
1803 __ EnterStubFrame(); 1773 __ EnterStubFrame();
1804 __ Push(R5); 1774 __ Push(R5);
1805 __ PushObject(Object::null_object()); // Space for result. 1775 __ PushObject(Object::null_object()); // Space for result.
1806 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1776 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1807 __ Pop(CODE_REG); 1777 __ Pop(R0);
1808 __ Pop(R5); 1778 __ Pop(R5);
1809 __ LeaveStubFrame(); 1779 __ LeaveStubFrame();
1810 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
1811 __ br(R0); 1780 __ br(R0);
1812 } 1781 }
1813 1782
1814 1783
1815 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) { 1784 void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
1816 __ EnterStubFrame(); 1785 __ EnterStubFrame();
1817 __ PushObject(Object::null_object()); // Space for result. 1786 __ PushObject(Object::null_object()); // Space for result.
1818 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); 1787 __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
1819 __ Pop(CODE_REG); 1788 __ Pop(R0);
1820 __ LeaveStubFrame(); 1789 __ LeaveStubFrame();
1821 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
1822 __ br(R0); 1790 __ br(R0);
1823 } 1791 }
1824 1792
1825 // Called only from unoptimized code. All relevant registers have been saved. 1793 // Called only from unoptimized code. All relevant registers have been saved.
1826 void StubCode::GenerateDebugStepCheckStub( 1794 void StubCode::GenerateDebugStepCheckStub(
1827 Assembler* assembler) { 1795 Assembler* assembler) {
1828 // Check single stepping. 1796 // Check single stepping.
1829 Label stepping, done_stepping; 1797 Label stepping, done_stepping;
1830 __ LoadIsolate(R1); 1798 __ LoadIsolate(R1);
1831 __ LoadFromOffset( 1799 __ LoadFromOffset(
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 // R6: function to be re-optimized. 1957 // R6: function to be re-optimized.
1990 // R4: argument descriptor (preserved). 1958 // R4: argument descriptor (preserved).
1991 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1959 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
1992 __ EnterStubFrame(); 1960 __ EnterStubFrame();
1993 __ Push(R4); 1961 __ Push(R4);
1994 // Setup space on stack for the return value. 1962 // Setup space on stack for the return value.
1995 __ PushObject(Object::null_object()); 1963 __ PushObject(Object::null_object());
1996 __ Push(R6); 1964 __ Push(R6);
1997 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1); 1965 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
1998 __ Pop(R0); // Discard argument. 1966 __ Pop(R0); // Discard argument.
1999 __ Pop(CODE_REG); // Get Code object 1967 __ Pop(R0); // Get Code object
2000 __ Pop(R4); // Restore argument descriptor. 1968 __ Pop(R4); // Restore argument descriptor.
2001 __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset()); 1969 __ LoadFieldFromOffset(R0, R0, Code::entry_point_offset());
2002 __ LeaveStubFrame(); 1970 __ LeaveStubFrame();
2003 __ br(R0); 1971 __ br(R0);
2004 __ brk(0); 1972 __ brk(0);
2005 } 1973 }
2006 1974
2007 1975
2008 // Does identical check (object references are equal or not equal) with special 1976 // Does identical check (object references are equal or not equal) with special
2009 // checks for boxed numbers. 1977 // checks for boxed numbers.
2010 // Left and right are pushed on stack. 1978 // Left and right are pushed on stack.
2011 // Return Zero condition flag set if equal. 1979 // Return Zero condition flag set if equal.
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 const Register right = R0; 2052 const Register right = R0;
2085 __ LoadFromOffset(left, SP, 1 * kWordSize); 2053 __ LoadFromOffset(left, SP, 1 * kWordSize);
2086 __ LoadFromOffset(right, SP, 0 * kWordSize); 2054 __ LoadFromOffset(right, SP, 0 * kWordSize);
2087 GenerateIdenticalWithNumberCheckStub(assembler, left, right); 2055 GenerateIdenticalWithNumberCheckStub(assembler, left, right);
2088 __ ret(); 2056 __ ret();
2089 2057
2090 if (FLAG_support_debugger) { 2058 if (FLAG_support_debugger) {
2091 __ Bind(&stepping); 2059 __ Bind(&stepping);
2092 __ EnterStubFrame(); 2060 __ EnterStubFrame();
2093 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 2061 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
2094 __ RestoreCodePointer();
2095 __ LeaveStubFrame(); 2062 __ LeaveStubFrame();
2096 __ b(&done_stepping); 2063 __ b(&done_stepping);
2097 } 2064 }
2098 } 2065 }
2099 2066
2100 2067
2101 // Called from optimized code only. 2068 // Called from optimized code only.
2102 // LR: return address. 2069 // LR: return address.
2103 // SP + 4: left operand. 2070 // SP + 4: left operand.
2104 // SP + 0: right operand. 2071 // SP + 0: right operand.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 __ CompareRegisters(R4, R0); 2110 __ CompareRegisters(R4, R0);
2144 __ b(&update, NE); 2111 __ b(&update, NE);
2145 2112
2146 __ Bind(&call_target_function); 2113 __ Bind(&call_target_function);
2147 // Call the target found in the cache. For a class id match, this is a 2114 // Call the target found in the cache. For a class id match, this is a
2148 // proper target for the given name and arguments descriptor. If the 2115 // proper target for the given name and arguments descriptor. If the
2149 // illegal class id was found, the target is a cache miss handler that can 2116 // illegal class id was found, the target is a cache miss handler that can
2150 // be invoked as a normal Dart function. 2117 // be invoked as a normal Dart function.
2151 __ add(TMP, R2, Operand(R3, LSL, 3)); 2118 __ add(TMP, R2, Operand(R3, LSL, 3));
2152 __ LoadFieldFromOffset(R0, TMP, base + kWordSize); 2119 __ LoadFieldFromOffset(R0, TMP, base + kWordSize);
2153 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
2154 __ LoadFieldFromOffset(R1, R0, Function::entry_point_offset()); 2120 __ LoadFieldFromOffset(R1, R0, Function::entry_point_offset());
2155 } 2121 }
2156 2122
2157 2123
2158 // Called from megamorphic calls. 2124 // Called from megamorphic calls.
2159 // R0: receiver. 2125 // R0: receiver.
2160 // R1: lookup cache. 2126 // R1: lookup cache.
2161 // Result: 2127 // Result:
2162 // R1: entry point. 2128 // R1: entry point.
2163 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { 2129 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
2164 EmitMegamorphicLookup(assembler, R0, R1, R1); 2130 EmitMegamorphicLookup(assembler, R0, R1, R1);
2165 __ ret(); 2131 __ ret();
2166 } 2132 }
2167 2133
2168 } // namespace dart 2134 } // namespace dart
2169 2135
2170 #endif // defined TARGET_ARCH_ARM64 2136 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_arm.cc ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698