| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 : object_(object), | 541 : object_(object), |
| 542 value_(value), | 542 value_(value), |
| 543 address_(address), | 543 address_(address), |
| 544 remembered_set_action_(remembered_set_action), | 544 remembered_set_action_(remembered_set_action), |
| 545 save_fp_regs_mode_(fp_mode), | 545 save_fp_regs_mode_(fp_mode), |
| 546 regs_(object, // An input reg. | 546 regs_(object, // An input reg. |
| 547 address, // An input reg. | 547 address, // An input reg. |
| 548 value) { // One scratch reg. | 548 value) { // One scratch reg. |
| 549 } | 549 } |
| 550 | 550 |
| 551 static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8. | 551 enum Mode { |
| 552 static const byte kSkipNonIncrementalPartInstruction = 0xeb; // Jmp #imm8. | 552 STORE_BUFFER_ONLY, |
| 553 INCREMENTAL, |
| 554 INCREMENTAL_COMPACTION |
| 555 }; |
| 553 | 556 |
| 554 static byte GetInstruction(bool enable) { | 557 static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8. |
| 555 // Can't use ternary operator here, because gcc makes an undefined | 558 static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8. |
| 556 // reference to a static const int. | 559 |
| 557 if (enable) { | 560 static const byte kFiveByteNopInstruction = 0x3d; // Cmpl eax, #imm32. |
| 558 return kSkipNonIncrementalPartInstruction; | 561 static const byte kFiveByteJumpInstruction = 0xe9; // Jmp #imm32. |
| 559 } else { | 562 |
| 560 return kTwoByteNopInstruction; | 563 static Mode GetMode(Code* stub) { |
| 564 byte first_instruction = stub->instruction_start()[0]; |
| 565 byte second_instruction = stub->instruction_start()[2]; |
| 566 |
| 567 if (first_instruction == kTwoByteJumpInstruction) { |
| 568 return INCREMENTAL; |
| 561 } | 569 } |
| 570 |
| 571 ASSERT(first_instruction == kTwoByteNopInstruction); |
| 572 |
| 573 if (second_instruction == kFiveByteJumpInstruction) { |
| 574 return INCREMENTAL_COMPACTION; |
| 575 } |
| 576 |
| 577 ASSERT(second_instruction == kFiveByteNopInstruction); |
| 578 |
| 579 return STORE_BUFFER_ONLY; |
| 562 } | 580 } |
| 563 | 581 |
| 564 static void Patch(Code* stub, bool enable) { | 582 static void Patch(Code* stub, Mode mode) { |
| 565 ASSERT(*stub->instruction_start() == GetInstruction(!enable)); | 583 switch (mode) { |
| 566 *stub->instruction_start() = GetInstruction(enable); | 584 case STORE_BUFFER_ONLY: |
| 585 ASSERT(GetMode(stub) == INCREMENTAL || |
| 586 GetMode(stub) == INCREMENTAL_COMPACTION); |
| 587 stub->instruction_start()[0] = kTwoByteNopInstruction; |
| 588 stub->instruction_start()[2] = kFiveByteNopInstruction; |
| 589 break; |
| 590 case INCREMENTAL: |
| 591 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); |
| 592 stub->instruction_start()[0] = kTwoByteJumpInstruction; |
| 593 break; |
| 594 case INCREMENTAL_COMPACTION: |
| 595 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); |
| 596 stub->instruction_start()[0] = kTwoByteNopInstruction; |
| 597 stub->instruction_start()[2] = kFiveByteJumpInstruction; |
| 598 break; |
| 599 } |
| 600 ASSERT(GetMode(stub) == mode); |
| 567 } | 601 } |
| 568 | 602 |
| 569 private: | 603 private: |
| 570 // This is a helper class for freeing up 3 scratch registers, where the third | 604 // This is a helper class for freeing up 3 scratch registers, where the third |
| 571 // is always rcx (needed for shift operations). The input is two registers | 605 // is always rcx (needed for shift operations). The input is two registers |
| 572 // that must be preserved and one scratch register provided by the caller. | 606 // that must be preserved and one scratch register provided by the caller. |
| 573 class RegisterAllocation { | 607 class RegisterAllocation { |
| 574 public: | 608 public: |
| 575 RegisterAllocation(Register object, | 609 RegisterAllocation(Register object, |
| 576 Register address, | 610 Register address, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 } | 722 } |
| 689 friend class RecordWriteStub; | 723 friend class RecordWriteStub; |
| 690 }; | 724 }; |
| 691 | 725 |
| 692 enum OnNoNeedToInformIncrementalMarker { | 726 enum OnNoNeedToInformIncrementalMarker { |
| 693 kReturnOnNoNeedToInformIncrementalMarker, | 727 kReturnOnNoNeedToInformIncrementalMarker, |
| 694 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker | 728 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker |
| 695 }; | 729 }; |
| 696 | 730 |
| 697 void Generate(MacroAssembler* masm); | 731 void Generate(MacroAssembler* masm); |
| 698 void GenerateIncremental(MacroAssembler* masm); | 732 void GenerateIncremental(MacroAssembler* masm, Mode mode); |
| 699 void CheckNeedsToInformIncrementalMarker( | 733 void CheckNeedsToInformIncrementalMarker( |
| 700 MacroAssembler* masm, | 734 MacroAssembler* masm, |
| 701 OnNoNeedToInformIncrementalMarker on_no_need); | 735 OnNoNeedToInformIncrementalMarker on_no_need, |
| 702 void InformIncrementalMarker(MacroAssembler* masm); | 736 Mode mode); |
| 737 void InformIncrementalMarker(MacroAssembler* masm, Mode mode); |
| 703 | 738 |
| 704 Major MajorKey() { return RecordWrite; } | 739 Major MajorKey() { return RecordWrite; } |
| 705 | 740 |
| 706 int MinorKey() { | 741 int MinorKey() { |
| 707 return ObjectBits::encode(object_.code()) | | 742 return ObjectBits::encode(object_.code()) | |
| 708 ValueBits::encode(value_.code()) | | 743 ValueBits::encode(value_.code()) | |
| 709 AddressBits::encode(address_.code()) | | 744 AddressBits::encode(address_.code()) | |
| 710 RememberedSetActionBits::encode(remembered_set_action_) | | 745 RememberedSetActionBits::encode(remembered_set_action_) | |
| 711 SaveFPRegsModeBits::encode(save_fp_regs_mode_); | 746 SaveFPRegsModeBits::encode(save_fp_regs_mode_); |
| 712 } | 747 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 723 RememberedSetAction remembered_set_action_; | 758 RememberedSetAction remembered_set_action_; |
| 724 SaveFPRegsMode save_fp_regs_mode_; | 759 SaveFPRegsMode save_fp_regs_mode_; |
| 725 Label slow_; | 760 Label slow_; |
| 726 RegisterAllocation regs_; | 761 RegisterAllocation regs_; |
| 727 }; | 762 }; |
| 728 | 763 |
| 729 | 764 |
| 730 } } // namespace v8::internal | 765 } } // namespace v8::internal |
| 731 | 766 |
| 732 #endif // V8_X64_CODE_STUBS_X64_H_ | 767 #endif // V8_X64_CODE_STUBS_X64_H_ |
| OLD | NEW |