OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 #ifndef VM_ASSEMBLER_X64_H_ | 5 #ifndef VM_ASSEMBLER_X64_H_ |
6 #define VM_ASSEMBLER_X64_H_ | 6 #define VM_ASSEMBLER_X64_H_ |
7 | 7 |
8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
9 #error Do not include assembler_x64.h directly; use assembler.h instead. | 9 #error Do not include assembler_x64.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 SetDisp32(disp); | 205 SetDisp32(disp); |
206 } | 206 } |
207 } | 207 } |
208 | 208 |
209 Address(const Address& other) : Operand(other) { } | 209 Address(const Address& other) : Operand(other) { } |
210 | 210 |
211 Address& operator=(const Address& other) { | 211 Address& operator=(const Address& other) { |
212 Operand::operator=(other); | 212 Operand::operator=(other); |
213 return *this; | 213 return *this; |
214 } | 214 } |
215 | |
216 private: | |
217 Address(Register base, int32_t disp, bool fixed) { | |
218 ASSERT(fixed); | |
219 SetModRM(2, base); | |
220 if ((base & 7) == RSP) { | |
221 SetSIB(TIMES_1, RSP, base); | |
222 } | |
223 SetDisp32(disp); | |
224 } | |
225 | |
226 friend class Assembler; | |
215 }; | 227 }; |
216 | 228 |
217 | 229 |
218 class FieldAddress : public Address { | 230 class FieldAddress : public Address { |
219 public: | 231 public: |
220 FieldAddress(Register base, int32_t disp) | 232 FieldAddress(Register base, int32_t disp) |
221 : Address(base, disp - kHeapObjectTag) { } | 233 : Address(base, disp - kHeapObjectTag) { } |
222 | 234 |
223 FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp) | 235 FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp) |
224 : Address(base, index, scale, disp - kHeapObjectTag) { } | 236 : Address(base, index, scale, disp - kHeapObjectTag) { } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 | 326 |
315 static bool sse4_1_supported_; | 327 static bool sse4_1_supported_; |
316 #ifdef DEBUG | 328 #ifdef DEBUG |
317 static bool initialized_; | 329 static bool initialized_; |
318 #endif | 330 #endif |
319 }; | 331 }; |
320 | 332 |
321 | 333 |
322 class Assembler : public ValueObject { | 334 class Assembler : public ValueObject { |
323 public: | 335 public: |
324 explicit Assembler(bool use_far_branches = false) | 336 explicit Assembler(bool use_far_branches = false); |
325 : buffer_(), | 337 |
326 object_pool_(GrowableObjectArray::Handle()), | |
327 prologue_offset_(-1), | |
328 comments_() { | |
329 // This mode is only needed and implemented for MIPS and ARM. | |
330 ASSERT(!use_far_branches); | |
331 } | |
332 ~Assembler() { } | 338 ~Assembler() { } |
333 | 339 |
334 static const bool kNearJump = true; | 340 static const bool kNearJump = true; |
335 static const bool kFarJump = false; | 341 static const bool kFarJump = false; |
336 | 342 |
337 /* | 343 /* |
338 * Emit Machine Instructions. | 344 * Emit Machine Instructions. |
339 */ | 345 */ |
340 void call(Register reg); | 346 void call(Register reg); |
341 void call(const Address& address); | 347 void call(const Address& address); |
342 void call(Label* label); | 348 void call(Label* label); |
343 void call(const ExternalLabel* label); | 349 void call(const ExternalLabel* label); |
344 | 350 |
345 static const intptr_t kCallExternalLabelSize = 13; | 351 static const intptr_t kCallExternalLabelSize = 10; |
346 | 352 |
347 void pushq(Register reg); | 353 void pushq(Register reg); |
348 void pushq(const Address& address); | 354 void pushq(const Address& address); |
349 void pushq(const Immediate& imm); | 355 void pushq(const Immediate& imm); |
350 | 356 |
351 void popq(Register reg); | 357 void popq(Register reg); |
352 void popq(const Address& address); | 358 void popq(const Address& address); |
353 | 359 |
354 void setcc(Condition condition, ByteRegister dst); | 360 void setcc(Condition condition, ByteRegister dst); |
355 | 361 |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
645 void CompareRegisters(Register a, Register b); | 651 void CompareRegisters(Register a, Register b); |
646 | 652 |
647 // Issues a move instruction if 'to' is not the same as 'from'. | 653 // Issues a move instruction if 'to' is not the same as 'from'. |
648 void MoveRegister(Register to, Register from); | 654 void MoveRegister(Register to, Register from); |
649 void PopRegister(Register r); | 655 void PopRegister(Register r); |
650 | 656 |
651 void AddImmediate(Register reg, const Immediate& imm); | 657 void AddImmediate(Register reg, const Immediate& imm); |
652 | 658 |
653 void Drop(intptr_t stack_elements); | 659 void Drop(intptr_t stack_elements); |
654 | 660 |
655 void LoadObject(Register dst, const Object& object); | 661 enum Patchability { |
662 kPatchable, | |
663 kNotPatchable, | |
664 }; | |
665 | |
666 void LoadObjectFromPool(Register dst, const Object& obj, Register pp); | |
667 void LoadObject(Register dst, const Object& object) { | |
668 LoadObjectFromPool(dst, object, PP); | |
669 } | |
670 void JmpPatchable(const ExternalLabel* label, Register pp); | |
671 void Jmp(const ExternalLabel* label, Register pp); | |
672 void J(Condition condition, const ExternalLabel* label, Register pp); | |
673 void CallPatchable(const ExternalLabel* label); | |
674 void Call(const ExternalLabel* label, Register pp); | |
656 void StoreObject(const Address& dst, const Object& obj); | 675 void StoreObject(const Address& dst, const Object& obj); |
657 void PushObject(const Object& object); | 676 void PushObject(const Object& object); |
658 void CompareObject(Register reg, const Object& object); | 677 void CompareObject(Register reg, const Object& object); |
659 void LoadDoubleConstant(XmmRegister dst, double value); | 678 void LoadDoubleConstant(XmmRegister dst, double value); |
660 | 679 |
661 // Destroys value. | 680 // Destroys value. |
662 void StoreIntoObject(Register object, // Object we are storing into. | 681 void StoreIntoObject(Register object, // Object we are storing into. |
663 const Address& dest, // Where we are storing into. | 682 const Address& dest, // Where we are storing into. |
664 Register value, // Value we are storing. | 683 Register value, // Value we are storing. |
665 bool can_value_be_smi = true); | 684 bool can_value_be_smi = true); |
666 | 685 |
667 void StoreIntoObjectNoBarrier(Register object, | 686 void StoreIntoObjectNoBarrier(Register object, |
668 const Address& dest, | 687 const Address& dest, |
669 Register value); | 688 Register value); |
670 | 689 |
671 void DoubleNegate(XmmRegister d); | 690 void DoubleNegate(XmmRegister d); |
672 void FloatNegate(XmmRegister f); | 691 void FloatNegate(XmmRegister f); |
673 | 692 |
674 void DoubleAbs(XmmRegister reg); | 693 void DoubleAbs(XmmRegister reg); |
675 | 694 |
676 void LockCmpxchgl(const Address& address, Register reg) { | 695 void LockCmpxchgl(const Address& address, Register reg) { |
677 lock(); | 696 lock(); |
678 cmpxchgl(address, reg); | 697 cmpxchgl(address, reg); |
679 } | 698 } |
680 | 699 |
681 void EnterFrame(intptr_t frame_space); | 700 void EnterFrame(intptr_t frame_space); |
682 void LeaveFrame(); | 701 void LeaveFrame(); |
702 void LeaveFrameWithPP(); | |
703 void ReturnPatchable(); | |
683 void ReserveAlignedFrameSpace(intptr_t frame_space); | 704 void ReserveAlignedFrameSpace(intptr_t frame_space); |
684 | 705 |
685 // Create a frame for calling into runtime that preserves all volatile | 706 // Create a frame for calling into runtime that preserves all volatile |
686 // registers. Frame's RSP is guaranteed to be correctly aligned and | 707 // registers. Frame's RSP is guaranteed to be correctly aligned and |
687 // frame_space bytes are reserved under it. | 708 // frame_space bytes are reserved under it. |
688 void EnterCallRuntimeFrame(intptr_t frame_space); | 709 void EnterCallRuntimeFrame(intptr_t frame_space); |
689 void LeaveCallRuntimeFrame(); | 710 void LeaveCallRuntimeFrame(); |
690 | 711 |
691 | 712 |
692 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count); | 713 void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
724 int prologue_offset() const { return prologue_offset_; } | 745 int prologue_offset() const { return prologue_offset_; } |
725 const ZoneGrowableArray<int>& GetPointerOffsets() const { | 746 const ZoneGrowableArray<int>& GetPointerOffsets() const { |
726 return buffer_.pointer_offsets(); | 747 return buffer_.pointer_offsets(); |
727 } | 748 } |
728 const GrowableObjectArray& object_pool() const { return object_pool_; } | 749 const GrowableObjectArray& object_pool() const { return object_pool_; } |
729 | 750 |
730 void FinalizeInstructions(const MemoryRegion& region) { | 751 void FinalizeInstructions(const MemoryRegion& region) { |
731 buffer_.FinalizeInstructions(region); | 752 buffer_.FinalizeInstructions(region); |
732 } | 753 } |
733 | 754 |
755 void LoadPoolPointer(Register pp); | |
756 | |
734 // Set up a Dart frame on entry with a frame pointer and PC information to | 757 // Set up a Dart frame on entry with a frame pointer and PC information to |
735 // enable easy access to the RawInstruction object of code corresponding | 758 // enable easy access to the RawInstruction object of code corresponding |
736 // to this frame. | 759 // to this frame. |
737 // The dart frame layout is as follows: | 760 // The dart frame layout is as follows: |
738 // .... | 761 // .... |
739 // ret PC | 762 // ret PC |
740 // saved RBP <=== RBP | 763 // saved RBP <=== RBP |
741 // pc (used to derive the RawInstruction Object of the dart code) | 764 // pc (used to derive the RawInstruction Object of the dart code) |
765 // saved PP | |
742 // locals space <=== RSP | 766 // locals space <=== RSP |
743 // ..... | 767 // ..... |
744 // This code sets this up with the sequence: | 768 // This code sets this up with the sequence: |
745 // pushq rbp | 769 // pushq rbp |
746 // movq rbp, rsp | 770 // movq rbp, rsp |
747 // call L | 771 // call L |
748 // L: <code to adjust saved pc if there is any intrinsification code> | 772 // L: <code to adjust saved pc if there is any intrinsification code> |
773 // ... | |
774 // pushq r15 | |
749 // ..... | 775 // ..... |
750 void EnterDartFrame(intptr_t frame_size); | 776 void EnterDartFrame(intptr_t frame_size); |
777 void EnterDartFrameWithInfo(intptr_t frame_size, | |
778 Register new_pp, Register new_pc); | |
751 | 779 |
752 // Set up a Dart frame for a function compiled for on-stack replacement. | 780 // Set up a Dart frame for a function compiled for on-stack replacement. |
753 // The frame layout is a normal Dart frame, but the frame is partially set | 781 // The frame layout is a normal Dart frame, but the frame is partially set |
754 // up on entry (it is the frame of the unoptimized code). | 782 // up on entry (it is the frame of the unoptimized code). |
755 void EnterOsrFrame(intptr_t extra_size); | 783 void EnterOsrFrame(intptr_t extra_size, Register new_pp, Register new_pc); |
756 | 784 |
757 // Set up a stub frame so that the stack traversal code can easily identify | 785 // Set up a stub frame so that the stack traversal code can easily identify |
758 // a stub frame. | 786 // a stub frame. |
759 // The stub frame layout is as follows: | 787 // The stub frame layout is as follows: |
760 // .... | 788 // .... |
761 // ret PC | 789 // ret PC |
762 // saved RBP | 790 // saved RBP |
763 // pc (used to derive the RawInstruction Object of the stub) | 791 // pc (used to derive the RawInstruction Object of the stub) |
764 // ..... | 792 // ..... |
765 // This code sets this up with the sequence: | 793 // This code sets this up with the sequence: |
766 // pushq rbp | 794 // pushq rbp |
767 // movq rbp, rsp | 795 // movq rbp, rsp |
768 // pushq immediate(0) | 796 // pushq immediate(0) |
769 // ..... | 797 // ..... |
770 void EnterStubFrame(); | 798 void EnterStubFrame(); |
799 void EnterStubFrameWithPP(); | |
771 | 800 |
772 // Instruction pattern from entrypoint is used in dart frame prologs | 801 // Instruction pattern from entrypoint is used in dart frame prologues |
773 // to set up the frame and save a PC which can be used to figure out the | 802 // to set up the frame and save a PC which can be used to figure out the |
774 // RawInstruction object corresponding to the code running in the frame. | 803 // RawInstruction object corresponding to the code running in the frame. |
775 // entrypoint: | 804 // entrypoint: |
776 // pushq rbp (size is 1 byte) | 805 // pushq rbp (size is 1 byte) |
777 // movq rbp, rsp (size is 3 bytes) | 806 // movq rbp, rsp (size is 3 bytes) |
778 // call L (size is 5 bytes) | 807 // call L (size is 5 bytes) |
779 // L: | 808 // L: |
780 static const intptr_t kEntryPointToPcMarkerOffset = 9; | 809 static const intptr_t kEntryPointToPcMarkerOffset = 9; |
781 | 810 |
782 // Inlined allocation of an instance of class 'cls', code has no runtime | 811 // Inlined allocation of an instance of class 'cls', code has no runtime |
(...skipping 10 matching lines...) Expand all Loading... | |
793 void Unimplemented(const char* message); | 822 void Unimplemented(const char* message); |
794 void Untested(const char* message); | 823 void Untested(const char* message); |
795 void Unreachable(const char* message); | 824 void Unreachable(const char* message); |
796 | 825 |
797 static void InitializeMemoryWithBreakpoints(uword data, int length); | 826 static void InitializeMemoryWithBreakpoints(uword data, int length); |
798 | 827 |
799 static const char* RegisterName(Register reg); | 828 static const char* RegisterName(Register reg); |
800 | 829 |
801 static const char* FpuRegisterName(FpuRegister reg); | 830 static const char* FpuRegisterName(FpuRegister reg); |
802 | 831 |
832 void FixedSizeAddressOffsetTest(); | |
Florian Schneider
2013/09/06 09:58:15
I see - Let me suggest to add a static factory met
zra
2013/09/06 17:53:26
Done.
| |
833 | |
803 private: | 834 private: |
804 AssemblerBuffer buffer_; | 835 AssemblerBuffer buffer_; |
805 GrowableObjectArray& object_pool_; // Object pool is not used on x64. | 836 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
806 int prologue_offset_; | 837 int prologue_offset_; |
807 | 838 |
808 class CodeComment : public ZoneAllocated { | 839 class CodeComment : public ZoneAllocated { |
809 public: | 840 public: |
810 CodeComment(intptr_t pc_offset, const String& comment) | 841 CodeComment(intptr_t pc_offset, const String& comment) |
811 : pc_offset_(pc_offset), comment_(comment) { } | 842 : pc_offset_(pc_offset), comment_(comment) { } |
812 | 843 |
813 intptr_t pc_offset() const { return pc_offset_; } | 844 intptr_t pc_offset() const { return pc_offset_; } |
814 const String& comment() const { return comment_; } | 845 const String& comment() const { return comment_; } |
815 | 846 |
816 private: | 847 private: |
817 intptr_t pc_offset_; | 848 intptr_t pc_offset_; |
818 const String& comment_; | 849 const String& comment_; |
819 | 850 |
820 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 851 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
821 }; | 852 }; |
822 | 853 |
823 GrowableArray<CodeComment*> comments_; | 854 GrowableArray<CodeComment*> comments_; |
824 | 855 |
856 intptr_t FindObject(const Object& obj); | |
857 intptr_t FindExternalLabel(const ExternalLabel* label, | |
858 Patchability patchable); | |
859 void LoadExternalLabel(Register dst, | |
860 const ExternalLabel* label, | |
861 Patchability patchable, | |
862 Register pp); | |
863 bool CanLoadFromObjectPool(const Object& object); | |
864 void LoadWordFromPoolOffset(Register dst, Register pp, int32_t offset); | |
865 | |
825 inline void EmitUint8(uint8_t value); | 866 inline void EmitUint8(uint8_t value); |
826 inline void EmitInt32(int32_t value); | 867 inline void EmitInt32(int32_t value); |
827 inline void EmitInt64(int64_t value); | 868 inline void EmitInt64(int64_t value); |
828 | 869 |
829 inline void EmitRegisterREX(Register reg, uint8_t rex); | 870 inline void EmitRegisterREX(Register reg, uint8_t rex); |
830 inline void EmitRegisterOperand(int rm, int reg); | 871 inline void EmitRegisterOperand(int rm, int reg); |
831 inline void EmitOperandREX(int rm, const Operand& operand, uint8_t rex); | 872 inline void EmitOperandREX(int rm, const Operand& operand, uint8_t rex); |
832 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); | 873 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); |
833 inline void EmitFixup(AssemblerFixup* fixup); | 874 inline void EmitFixup(AssemblerFixup* fixup); |
834 inline void EmitOperandSizeOverride(); | 875 inline void EmitOperandSizeOverride(); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
937 } | 978 } |
938 | 979 |
939 | 980 |
940 inline void Assembler::EmitOperandSizeOverride() { | 981 inline void Assembler::EmitOperandSizeOverride() { |
941 EmitUint8(0x66); | 982 EmitUint8(0x66); |
942 } | 983 } |
943 | 984 |
944 } // namespace dart | 985 } // namespace dart |
945 | 986 |
946 #endif // VM_ASSEMBLER_X64_H_ | 987 #endif // VM_ASSEMBLER_X64_H_ |
OLD | NEW |