OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
12 #include "vm/instructions.h" | |
12 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
13 #include "vm/pages.h" | 14 #include "vm/pages.h" |
14 #include "vm/resolver.h" | 15 #include "vm/resolver.h" |
15 #include "vm/scavenger.h" | 16 #include "vm/scavenger.h" |
16 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
17 | 18 |
18 | 19 |
19 #define __ assembler-> | 20 #define __ assembler-> |
20 | 21 |
21 namespace dart { | 22 namespace dart { |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 __ ret(); | 468 __ ret(); |
468 } | 469 } |
469 | 470 |
470 | 471 |
471 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 472 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
472 intptr_t deopt_reason, | 473 intptr_t deopt_reason, |
473 uword saved_registers_address); | 474 uword saved_registers_address); |
474 | 475 |
475 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); | 476 DECLARE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp); |
476 | 477 |
478 | |
477 // This stub translates optimized frame into unoptimized frame. The optimized | 479 // This stub translates optimized frame into unoptimized frame. The optimized |
478 // frame can contain values in registers and on stack, the unoptimized | 480 // frame can contain values in registers and on stack, the unoptimized |
479 // frame contains all values on stack. | 481 // frame contains all values on stack. |
480 // Deoptimization occurs in following steps: | 482 // Deoptimization occurs in following steps: |
481 // - Push all registers that can contain values. | 483 // - Push all registers that can contain values. |
482 // - Call C routine to copy the stack and saved registers into temporary buffer. | 484 // - Call C routine to copy the stack and saved registers into temporary buffer. |
483 // - Adjust caller's frame to correct unoptimized frame size. | 485 // - Adjust caller's frame to correct unoptimized frame size. |
484 // - Fill the unoptimized frame. | 486 // - Fill the unoptimized frame. |
485 // - Materialize objects that require allocation (e.g. Double instances). | 487 // - Materialize objects that require allocation (e.g. Double instances). |
486 // GC can occur only after frame is fully rewritten. | 488 // GC can occur only after frame is fully rewritten. |
487 // Stack: | 489 // Stack: |
488 // +------------------+ | 490 // +------------------+ |
489 // | 0 as PC marker | <- TOS | |
490 // +------------------+ | |
491 // | Saved FP | | 491 // | Saved FP | |
492 // +------------------+ | 492 // +------------------+ |
493 // | return-address | (deoptimization point) | 493 // | return-address | (deoptimization point) |
494 // +------------------+ | 494 // +------------------+ |
495 // | optimized frame | | 495 // | optimized frame | |
496 // | ... | | 496 // | ... | |
497 // | 497 // |
498 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | 498 // Parts of the code cannot GC, part of the code can GC. |
499 static void GenerateDeoptimizationSequence(Assembler* assembler, | |
500 bool preserve_rax) { | |
499 __ EnterFrame(0); | 501 __ EnterFrame(0); |
502 const intptr_t saved_rax_offset_from_ebp = -(kNumberOfCpuRegisters - RAX); | |
503 // Result in EAX is preserved as part of pushing all registers below. | |
504 | |
500 // Push registers in their enumeration order: lowest register number at | 505 // Push registers in their enumeration order: lowest register number at |
501 // lowest address. | 506 // lowest address. |
502 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { | 507 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
503 __ pushq(static_cast<Register>(i)); | 508 __ pushq(static_cast<Register>(i)); |
504 } | 509 } |
505 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kDoubleSize)); | 510 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kDoubleSize)); |
506 intptr_t offset = 0; | 511 intptr_t offset = 0; |
507 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 512 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
508 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 513 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
509 __ movsd(Address(RSP, offset), xmm_reg); | 514 __ movsd(Address(RSP, offset), xmm_reg); |
510 offset += kDoubleSize; | 515 offset += kDoubleSize; |
511 } | 516 } |
512 | 517 |
513 __ movq(RCX, RSP); // Saved saved registers block. | 518 __ movq(RCX, RSP); // Saved saved registers block. |
514 __ ReserveAlignedFrameSpace(0); | 519 __ ReserveAlignedFrameSpace(0); |
515 __ SmiUntag(RAX); | 520 __ SmiUntag(RAX); |
516 __ movq(RDI, RCX); // Set up argument 1 saved_registers_address. | 521 __ movq(RDI, RCX); // Set up argument 1 saved_registers_address. |
517 | 522 |
518 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 523 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
519 // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address. | 524 // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address. |
525 | |
526 if (preserve_rax) { | |
527 // Restore result into RBX temporarily. | |
528 __ movq(RBX, Address(RBP, saved_rax_offset_from_ebp * kWordSize)); | |
529 } | |
530 | |
520 __ LeaveFrame(); | 531 __ LeaveFrame(); |
521 __ popq(RCX); // Preserve return address. | 532 __ popq(RCX); // Preserve return address. |
522 __ movq(RSP, RBP); | 533 __ movq(RSP, RBP); |
523 __ subq(RSP, RAX); | 534 __ subq(RSP, RAX); |
524 __ movq(Address(RSP, 0), RCX); | 535 __ movq(Address(RSP, 0), RCX); |
525 | 536 |
526 __ EnterFrame(0); | 537 __ EnterFrame(0); |
527 __ movq(RCX, RSP); // Get last FP address. | 538 __ movq(RCX, RSP); // Get last FP address. |
539 if (preserve_rax) { | |
540 __ pushq(RBX); // Preserve result. | |
541 } | |
528 __ ReserveAlignedFrameSpace(0); | 542 __ ReserveAlignedFrameSpace(0); |
529 __ movq(RDI, RCX); // Set up argument 1 last_fp. | 543 __ movq(RDI, RCX); // Set up argument 1 last_fp. |
530 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); | 544 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); |
545 if (preserve_rax) { | |
546 // Restore result into RAX. | |
547 __ movq(RAX, Address(RBP, -1 * kWordSize)); | |
548 } | |
531 __ LeaveFrame(); | 549 __ LeaveFrame(); |
siva
2012/09/07 23:16:17
Ditto comment regarding GC:
Could you add a comme
srdjan
2012/09/12 06:15:26
Done.
| |
532 | 550 |
533 // Frame is fully rewritten at this point and it is safe to perform a GC. | 551 // Frame is fully rewritten at this point and it is safe to perform a GC. |
534 // Materialize any objects that were deferred by FillFrame because they | 552 // Materialize any objects that were deferred by FillFrame because they |
535 // require allocation. | 553 // require allocation. |
536 __ EnterFrame(0); | 554 __ EnterFrame(0); |
555 if (preserve_rax) { | |
556 __ pushq(RAX); // Preserve result, it will be GC-d here. | |
557 } | |
537 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); | 558 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); |
559 if (preserve_rax) { | |
560 __ popq(RAX); // Restore result. | |
561 } | |
538 __ LeaveFrame(); | 562 __ LeaveFrame(); |
539 | 563 |
540 __ ret(); | 564 __ ret(); |
541 } | 565 } |
542 | 566 |
543 | 567 |
568 // TOS: return address + call-instruction-size (5 bytes). | |
569 // RAX: result, must be preserved | |
570 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { | |
571 // Correct return address to point just after the call that is being | |
572 // deoptimized. | |
573 __ popq(RBX); | |
574 __ subq(RBX, Immediate(ShortCallPattern::InstructionLength())); | |
575 __ pushq(RBX); | |
576 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. | |
577 } | |
578 | |
579 | |
580 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { | |
581 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. | |
582 } | |
583 | |
584 | |
544 // Called for inline allocation of arrays. | 585 // Called for inline allocation of arrays. |
545 // Input parameters: | 586 // Input parameters: |
546 // R10 : Array length as Smi. | 587 // R10 : Array length as Smi. |
547 // RBX : array element type (either NULL or an instantiated type). | 588 // RBX : array element type (either NULL or an instantiated type). |
548 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 589 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
549 // The newly allocated object is returned in RAX. | 590 // The newly allocated object is returned in RAX. |
550 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 591 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
551 Label slow_case; | 592 Label slow_case; |
552 const Immediate raw_null = | 593 const Immediate raw_null = |
553 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 594 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1865 void StubCode::GenerateJumpToErrorHandlerStub(Assembler* assembler) { | 1906 void StubCode::GenerateJumpToErrorHandlerStub(Assembler* assembler) { |
1866 __ movq(RAX, RCX); // error object. | 1907 __ movq(RAX, RCX); // error object. |
1867 __ movq(RBP, RDX); // target frame_pointer. | 1908 __ movq(RBP, RDX); // target frame_pointer. |
1868 __ movq(RSP, RSI); // target stack_pointer. | 1909 __ movq(RSP, RSI); // target stack_pointer. |
1869 __ jmp(RDI); // Jump to the exception handler code. | 1910 __ jmp(RDI); // Jump to the exception handler code. |
1870 } | 1911 } |
1871 | 1912 |
1872 } // namespace dart | 1913 } // namespace dart |
1873 | 1914 |
1874 #endif // defined TARGET_ARCH_X64 | 1915 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |