| 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 // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry |
| 503 // and kDeoptimizeFillFrameRuntimeEntry are leaf runtime calls. |
| 504 const intptr_t saved_rax_offset_from_ebp = -(kNumberOfCpuRegisters - RAX); |
| 505 // Result in EAX is preserved as part of pushing all registers below. |
| 506 |
| 500 // Push registers in their enumeration order: lowest register number at | 507 // Push registers in their enumeration order: lowest register number at |
| 501 // lowest address. | 508 // lowest address. |
| 502 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { | 509 for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) { |
| 503 __ pushq(static_cast<Register>(i)); | 510 __ pushq(static_cast<Register>(i)); |
| 504 } | 511 } |
| 505 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kDoubleSize)); | 512 __ subq(RSP, Immediate(kNumberOfXmmRegisters * kDoubleSize)); |
| 506 intptr_t offset = 0; | 513 intptr_t offset = 0; |
| 507 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { | 514 for (intptr_t reg_idx = 0; reg_idx < kNumberOfXmmRegisters; ++reg_idx) { |
| 508 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); | 515 XmmRegister xmm_reg = static_cast<XmmRegister>(reg_idx); |
| 509 __ movsd(Address(RSP, offset), xmm_reg); | 516 __ movsd(Address(RSP, offset), xmm_reg); |
| 510 offset += kDoubleSize; | 517 offset += kDoubleSize; |
| 511 } | 518 } |
| 512 | 519 |
| 513 __ movq(RCX, RSP); // Saved saved registers block. | 520 __ movq(RCX, RSP); // Saved saved registers block. |
| 514 __ ReserveAlignedFrameSpace(0); | 521 __ ReserveAlignedFrameSpace(0); |
| 515 __ SmiUntag(RAX); | 522 __ SmiUntag(RAX); |
| 516 __ movq(RDI, RCX); // Set up argument 1 saved_registers_address. | 523 __ movq(RDI, RCX); // Set up argument 1 saved_registers_address. |
| 517 | 524 |
| 518 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); | 525 __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry); |
| 519 // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address. | 526 // Result (RAX) is stack-size (FP - SP) in bytes, incl. the return address. |
| 527 |
| 528 if (preserve_rax) { |
| 529 // Restore result into RBX temporarily. |
| 530 __ movq(RBX, Address(RBP, saved_rax_offset_from_ebp * kWordSize)); |
| 531 } |
| 532 |
| 520 __ LeaveFrame(); | 533 __ LeaveFrame(); |
| 521 __ popq(RCX); // Preserve return address. | 534 __ popq(RCX); // Preserve return address. |
| 522 __ movq(RSP, RBP); | 535 __ movq(RSP, RBP); |
| 523 __ subq(RSP, RAX); | 536 __ subq(RSP, RAX); |
| 524 __ movq(Address(RSP, 0), RCX); | 537 __ movq(Address(RSP, 0), RCX); |
| 525 | 538 |
| 526 __ EnterFrame(0); | 539 __ EnterFrame(0); |
| 527 __ movq(RCX, RSP); // Get last FP address. | 540 __ movq(RCX, RSP); // Get last FP address. |
| 541 if (preserve_rax) { |
| 542 __ pushq(RBX); // Preserve result. |
| 543 } |
| 528 __ ReserveAlignedFrameSpace(0); | 544 __ ReserveAlignedFrameSpace(0); |
| 529 __ movq(RDI, RCX); // Set up argument 1 last_fp. | 545 __ movq(RDI, RCX); // Set up argument 1 last_fp. |
| 530 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); | 546 __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry); |
| 547 if (preserve_rax) { |
| 548 // Restore result into RAX. |
| 549 __ movq(RAX, Address(RBP, -1 * kWordSize)); |
| 550 } |
| 551 // Code above cannot cause GC. |
| 531 __ LeaveFrame(); | 552 __ LeaveFrame(); |
| 532 | 553 |
| 533 // Frame is fully rewritten at this point and it is safe to perform a GC. | 554 // 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 | 555 // Materialize any objects that were deferred by FillFrame because they |
| 535 // require allocation. | 556 // require allocation. |
| 536 __ EnterFrame(0); | 557 __ EnterFrame(0); |
| 558 if (preserve_rax) { |
| 559 __ pushq(RAX); // Preserve result, it will be GC-d here. |
| 560 } |
| 537 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); | 561 __ CallRuntime(kDeoptimizeMaterializeDoublesRuntimeEntry); |
| 562 if (preserve_rax) { |
| 563 __ popq(RAX); // Restore result. |
| 564 } |
| 538 __ LeaveFrame(); | 565 __ LeaveFrame(); |
| 539 | 566 |
| 540 __ ret(); | 567 __ ret(); |
| 541 } | 568 } |
| 542 | 569 |
| 543 | 570 |
| 571 // TOS: return address + call-instruction-size (5 bytes). |
| 572 // RAX: result, must be preserved |
| 573 void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) { |
| 574 // Correct return address to point just after the call that is being |
| 575 // deoptimized. |
| 576 __ popq(RBX); |
| 577 __ subq(RBX, Immediate(ShortCallPattern::InstructionLength())); |
| 578 __ pushq(RBX); |
| 579 GenerateDeoptimizationSequence(assembler, true); // Preserve RAX. |
| 580 } |
| 581 |
| 582 |
| 583 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { |
| 584 GenerateDeoptimizationSequence(assembler, false); // Don't preserve RAX. |
| 585 } |
| 586 |
| 587 |
| 544 // Called for inline allocation of arrays. | 588 // Called for inline allocation of arrays. |
| 545 // Input parameters: | 589 // Input parameters: |
| 546 // R10 : Array length as Smi. | 590 // R10 : Array length as Smi. |
| 547 // RBX : array element type (either NULL or an instantiated type). | 591 // 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. | 592 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
| 549 // The newly allocated object is returned in RAX. | 593 // The newly allocated object is returned in RAX. |
| 550 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 594 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 551 Label slow_case; | 595 Label slow_case; |
| 552 const Immediate raw_null = | 596 const Immediate raw_null = |
| 553 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 597 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) { | 1909 void StubCode::GenerateJumpToErrorHandlerStub(Assembler* assembler) { |
| 1866 __ movq(RAX, RCX); // error object. | 1910 __ movq(RAX, RCX); // error object. |
| 1867 __ movq(RBP, RDX); // target frame_pointer. | 1911 __ movq(RBP, RDX); // target frame_pointer. |
| 1868 __ movq(RSP, RSI); // target stack_pointer. | 1912 __ movq(RSP, RSI); // target stack_pointer. |
| 1869 __ jmp(RDI); // Jump to the exception handler code. | 1913 __ jmp(RDI); // Jump to the exception handler code. |
| 1870 } | 1914 } |
| 1871 | 1915 |
| 1872 } // namespace dart | 1916 } // namespace dart |
| 1873 | 1917 |
| 1874 #endif // defined TARGET_ARCH_X64 | 1918 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |