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

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

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