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 RUNTIME_VM_ASSEMBLER_X64_H_ | 5 #ifndef RUNTIME_VM_ASSEMBLER_X64_H_ |
6 #define RUNTIME_VM_ASSEMBLER_X64_H_ | 6 #define RUNTIME_VM_ASSEMBLER_X64_H_ |
7 | 7 |
8 #ifndef RUNTIME_VM_ASSEMBLER_H_ | 8 #ifndef RUNTIME_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 |
11 | 11 |
12 #include "platform/assert.h" | 12 #include "platform/assert.h" |
13 #include "platform/utils.h" | 13 #include "platform/utils.h" |
14 #include "vm/constants_x64.h" | 14 #include "vm/constants_x64.h" |
15 #include "vm/hash_map.h" | 15 #include "vm/hash_map.h" |
16 #include "vm/object.h" | 16 #include "vm/object.h" |
17 | 17 |
18 namespace dart { | 18 namespace dart { |
19 | 19 |
20 // Forward declarations. | 20 // Forward declarations. |
21 class RuntimeEntry; | 21 class RuntimeEntry; |
22 class StubEntry; | 22 class StubEntry; |
23 | 23 |
24 class Immediate : public ValueObject { | 24 class Immediate : public ValueObject { |
25 public: | 25 public: |
26 explicit Immediate(int64_t value) : value_(value) { } | 26 explicit Immediate(int64_t value) : value_(value) {} |
27 | 27 |
28 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) { } | 28 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) {} |
29 | 29 |
30 int64_t value() const { return value_; } | 30 int64_t value() const { return value_; } |
31 | 31 |
32 bool is_int8() const { return Utils::IsInt(8, value_); } | 32 bool is_int8() const { return Utils::IsInt(8, value_); } |
33 bool is_uint8() const { return Utils::IsUint(8, value_); } | 33 bool is_uint8() const { return Utils::IsUint(8, value_); } |
34 bool is_uint16() const { return Utils::IsUint(16, value_); } | 34 bool is_uint16() const { return Utils::IsUint(16, value_); } |
35 bool is_int32() const { return Utils::IsInt(32, value_); } | 35 bool is_int32() const { return Utils::IsInt(32, value_); } |
36 | 36 |
37 private: | 37 private: |
38 const int64_t value_; | 38 const int64_t value_; |
39 | 39 |
40 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac | 40 // TODO(5411081): Add DISALLOW_COPY_AND_ASSIGN(Immediate) once the mac |
41 // build issue is resolved. | 41 // build issue is resolved. |
42 // And remove the unnecessary copy constructor. | 42 // And remove the unnecessary copy constructor. |
43 }; | 43 }; |
44 | 44 |
45 | 45 |
46 class Operand : public ValueObject { | 46 class Operand : public ValueObject { |
47 public: | 47 public: |
48 uint8_t rex() const { | 48 uint8_t rex() const { return rex_; } |
49 return rex_; | |
50 } | |
51 | 49 |
52 uint8_t mod() const { | 50 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } |
53 return (encoding_at(0) >> 6) & 3; | |
54 } | |
55 | 51 |
56 Register rm() const { | 52 Register rm() const { |
57 int rm_rex = (rex_ & REX_B) << 3; | 53 int rm_rex = (rex_ & REX_B) << 3; |
58 return static_cast<Register>(rm_rex + (encoding_at(0) & 7)); | 54 return static_cast<Register>(rm_rex + (encoding_at(0) & 7)); |
59 } | 55 } |
60 | 56 |
61 ScaleFactor scale() const { | 57 ScaleFactor scale() const { |
62 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); | 58 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); |
63 } | 59 } |
64 | 60 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 bool Equals(const Operand& other) const { | 93 bool Equals(const Operand& other) const { |
98 if (length_ != other.length_) return false; | 94 if (length_ != other.length_) return false; |
99 if (rex_ != other.rex_) return false; | 95 if (rex_ != other.rex_) return false; |
100 for (uint8_t i = 0; i < length_; i++) { | 96 for (uint8_t i = 0; i < length_; i++) { |
101 if (encoding_[i] != other.encoding_[i]) return false; | 97 if (encoding_[i] != other.encoding_[i]) return false; |
102 } | 98 } |
103 return true; | 99 return true; |
104 } | 100 } |
105 | 101 |
106 protected: | 102 protected: |
107 Operand() : length_(0), rex_(REX_NONE) { } // Needed by subclass Address. | 103 Operand() : length_(0), rex_(REX_NONE) {} // Needed by subclass Address. |
108 | 104 |
109 void SetModRM(int mod, Register rm) { | 105 void SetModRM(int mod, Register rm) { |
110 ASSERT((mod & ~3) == 0); | 106 ASSERT((mod & ~3) == 0); |
111 if ((rm > 7) && !((rm == R12) && (mod != 3))) { | 107 if ((rm > 7) && !((rm == R12) && (mod != 3))) { |
112 rex_ |= REX_B; | 108 rex_ |= REX_B; |
113 } | 109 } |
114 encoding_[0] = (mod << 6) | (rm & 7); | 110 encoding_[0] = (mod << 6) | (rm & 7); |
115 length_ = 1; | 111 length_ = 1; |
116 } | 112 } |
117 | 113 |
(...skipping 30 matching lines...) Expand all Loading... |
148 // Get the operand encoding byte at the given index. | 144 // Get the operand encoding byte at the given index. |
149 uint8_t encoding_at(intptr_t index) const { | 145 uint8_t encoding_at(intptr_t index) const { |
150 ASSERT(index >= 0 && index < length_); | 146 ASSERT(index >= 0 && index < length_); |
151 return encoding_[index]; | 147 return encoding_[index]; |
152 } | 148 } |
153 | 149 |
154 // Returns whether or not this operand is really the given register in | 150 // Returns whether or not this operand is really the given register in |
155 // disguise. Used from the assembler to generate better encodings. | 151 // disguise. Used from the assembler to generate better encodings. |
156 bool IsRegister(Register reg) const { | 152 bool IsRegister(Register reg) const { |
157 return ((reg > 7 ? 1 : 0) == (rex_ & REX_B)) // REX.B match. | 153 return ((reg > 7 ? 1 : 0) == (rex_ & REX_B)) // REX.B match. |
158 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register. | 154 && ((encoding_at(0) & 0xF8) == 0xC0) // Addressing mode is register. |
159 && ((encoding_at(0) & 0x07) == reg); // Register codes match. | 155 && ((encoding_at(0) & 0x07) == reg); // Register codes match. |
160 } | 156 } |
161 | 157 |
162 friend class Assembler; | 158 friend class Assembler; |
163 }; | 159 }; |
164 | 160 |
165 | 161 |
166 class Address : public Operand { | 162 class Address : public Operand { |
167 public: | 163 public: |
168 Address(Register base, int32_t disp) { | 164 Address(Register base, int32_t disp) { |
169 if ((disp == 0) && ((base & 7) != RBP)) { | 165 if ((disp == 0) && ((base & 7) != RBP)) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 } else { | 207 } else { |
212 SetModRM(2, RSP); | 208 SetModRM(2, RSP); |
213 SetSIB(scale, index, base); | 209 SetSIB(scale, index, base); |
214 SetDisp32(disp); | 210 SetDisp32(disp); |
215 } | 211 } |
216 } | 212 } |
217 | 213 |
218 // This addressing mode does not exist. | 214 // This addressing mode does not exist. |
219 Address(Register base, Register index, ScaleFactor scale, Register r); | 215 Address(Register base, Register index, ScaleFactor scale, Register r); |
220 | 216 |
221 Address(const Address& other) : Operand(other) { } | 217 Address(const Address& other) : Operand(other) {} |
222 | 218 |
223 Address& operator=(const Address& other) { | 219 Address& operator=(const Address& other) { |
224 Operand::operator=(other); | 220 Operand::operator=(other); |
225 return *this; | 221 return *this; |
226 } | 222 } |
227 | 223 |
228 static Address AddressRIPRelative(int32_t disp) { | 224 static Address AddressRIPRelative(int32_t disp) { |
229 return Address(RIPRelativeDisp(disp)); | 225 return Address(RIPRelativeDisp(disp)); |
230 } | 226 } |
231 static Address AddressBaseImm32(Register base, int32_t disp) { | 227 static Address AddressBaseImm32(Register base, int32_t disp) { |
232 return Address(base, disp, true); | 228 return Address(base, disp, true); |
233 } | 229 } |
234 | 230 |
235 // This addressing mode does not exist. | 231 // This addressing mode does not exist. |
236 static Address AddressBaseImm32(Register base, Register r); | 232 static Address AddressBaseImm32(Register base, Register r); |
237 | 233 |
238 private: | 234 private: |
239 Address(Register base, int32_t disp, bool fixed) { | 235 Address(Register base, int32_t disp, bool fixed) { |
240 ASSERT(fixed); | 236 ASSERT(fixed); |
241 SetModRM(2, base); | 237 SetModRM(2, base); |
242 if ((base & 7) == RSP) { | 238 if ((base & 7) == RSP) { |
243 SetSIB(TIMES_1, RSP, base); | 239 SetSIB(TIMES_1, RSP, base); |
244 } | 240 } |
245 SetDisp32(disp); | 241 SetDisp32(disp); |
246 } | 242 } |
247 | 243 |
248 struct RIPRelativeDisp { | 244 struct RIPRelativeDisp { |
249 explicit RIPRelativeDisp(int32_t disp) : disp_(disp) { } | 245 explicit RIPRelativeDisp(int32_t disp) : disp_(disp) {} |
250 const int32_t disp_; | 246 const int32_t disp_; |
251 }; | 247 }; |
252 | 248 |
253 explicit Address(const RIPRelativeDisp& disp) { | 249 explicit Address(const RIPRelativeDisp& disp) { |
254 SetModRM(0, static_cast<Register>(0x5)); | 250 SetModRM(0, static_cast<Register>(0x5)); |
255 SetDisp32(disp.disp_); | 251 SetDisp32(disp.disp_); |
256 } | 252 } |
257 }; | 253 }; |
258 | 254 |
259 | 255 |
260 class FieldAddress : public Address { | 256 class FieldAddress : public Address { |
261 public: | 257 public: |
262 FieldAddress(Register base, int32_t disp) | 258 FieldAddress(Register base, int32_t disp) |
263 : Address(base, disp - kHeapObjectTag) { } | 259 : Address(base, disp - kHeapObjectTag) {} |
264 | 260 |
265 // This addressing mode does not exist. | 261 // This addressing mode does not exist. |
266 FieldAddress(Register base, Register r); | 262 FieldAddress(Register base, Register r); |
267 | 263 |
268 FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp) | 264 FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp) |
269 : Address(base, index, scale, disp - kHeapObjectTag) { } | 265 : Address(base, index, scale, disp - kHeapObjectTag) {} |
270 | 266 |
271 // This addressing mode does not exist. | 267 // This addressing mode does not exist. |
272 FieldAddress(Register base, Register index, ScaleFactor scale, Register r); | 268 FieldAddress(Register base, Register index, ScaleFactor scale, Register r); |
273 | 269 |
274 FieldAddress(const FieldAddress& other) : Address(other) { } | 270 FieldAddress(const FieldAddress& other) : Address(other) {} |
275 | 271 |
276 FieldAddress& operator=(const FieldAddress& other) { | 272 FieldAddress& operator=(const FieldAddress& other) { |
277 Address::operator=(other); | 273 Address::operator=(other); |
278 return *this; | 274 return *this; |
279 } | 275 } |
280 }; | 276 }; |
281 | 277 |
282 | 278 |
283 class Label : public ValueObject { | 279 class Label : public ValueObject { |
284 public: | 280 public: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 | 342 |
347 friend class Assembler; | 343 friend class Assembler; |
348 DISALLOW_COPY_AND_ASSIGN(Label); | 344 DISALLOW_COPY_AND_ASSIGN(Label); |
349 }; | 345 }; |
350 | 346 |
351 | 347 |
352 class Assembler : public ValueObject { | 348 class Assembler : public ValueObject { |
353 public: | 349 public: |
354 explicit Assembler(bool use_far_branches = false); | 350 explicit Assembler(bool use_far_branches = false); |
355 | 351 |
356 ~Assembler() { } | 352 ~Assembler() {} |
357 | 353 |
358 static const bool kNearJump = true; | 354 static const bool kNearJump = true; |
359 static const bool kFarJump = false; | 355 static const bool kFarJump = false; |
360 | 356 |
361 /* | 357 /* |
362 * Emit Machine Instructions. | 358 * Emit Machine Instructions. |
363 */ | 359 */ |
364 void call(Register reg); | 360 void call(Register reg); |
365 void call(const Address& address); | 361 void call(const Address& address); |
366 void call(Label* label); | 362 void call(Label* label); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 void cvtsi2sdl(XmmRegister a, Register b); | 492 void cvtsi2sdl(XmmRegister a, Register b); |
497 void cvttsd2siq(Register dst, XmmRegister src); | 493 void cvttsd2siq(Register dst, XmmRegister src); |
498 | 494 |
499 void cvtss2sd(XmmRegister dst, XmmRegister src); | 495 void cvtss2sd(XmmRegister dst, XmmRegister src); |
500 void cvtsd2ss(XmmRegister dst, XmmRegister src); | 496 void cvtsd2ss(XmmRegister dst, XmmRegister src); |
501 | 497 |
502 void pxor(XmmRegister dst, XmmRegister src); | 498 void pxor(XmmRegister dst, XmmRegister src); |
503 | 499 |
504 enum RoundingMode { | 500 enum RoundingMode { |
505 kRoundToNearest = 0x0, | 501 kRoundToNearest = 0x0, |
506 kRoundDown = 0x1, | 502 kRoundDown = 0x1, |
507 kRoundUp = 0x2, | 503 kRoundUp = 0x2, |
508 kRoundToZero = 0x3 | 504 kRoundToZero = 0x3 |
509 }; | 505 }; |
510 void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode); | 506 void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode); |
511 | 507 |
512 void xchgl(Register dst, Register src); | 508 void xchgl(Register dst, Register src); |
513 void xchgq(Register dst, Register src); | 509 void xchgq(Register dst, Register src); |
514 | 510 |
515 void cmpb(const Address& address, const Immediate& imm); | 511 void cmpb(const Address& address, const Immediate& imm); |
516 | 512 |
517 void cmpw(Register reg, const Address& address); | 513 void cmpw(Register reg, const Address& address); |
518 void cmpw(const Address& address, const Immediate& imm); | 514 void cmpw(const Address& address, const Immediate& imm); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 void ffree(intptr_t value); | 671 void ffree(intptr_t value); |
676 | 672 |
677 void fsin(); | 673 void fsin(); |
678 void fcos(); | 674 void fcos(); |
679 | 675 |
680 // 'size' indicates size in bytes and must be in the range 1..8. | 676 // 'size' indicates size in bytes and must be in the range 1..8. |
681 void nop(int size = 1); | 677 void nop(int size = 1); |
682 void int3(); | 678 void int3(); |
683 void hlt(); | 679 void hlt(); |
684 | 680 |
685 static uword GetBreakInstructionFiller() { | 681 static uword GetBreakInstructionFiller() { return 0xCCCCCCCCCCCCCCCC; } |
686 return 0xCCCCCCCCCCCCCCCC; | |
687 } | |
688 | 682 |
689 void j(Condition condition, Label* label, bool near = kFarJump); | 683 void j(Condition condition, Label* label, bool near = kFarJump); |
690 | 684 |
691 void jmp(Register reg); | 685 void jmp(Register reg); |
692 void jmp(const Address& address); | 686 void jmp(const Address& address); |
693 void jmp(Label* label, bool near = kFarJump); | 687 void jmp(Label* label, bool near = kFarJump); |
694 void jmp(const ExternalLabel* label); | 688 void jmp(const ExternalLabel* label); |
695 void jmp(const StubEntry& stub_entry); | 689 void jmp(const StubEntry& stub_entry); |
696 | 690 |
697 void lock(); | 691 void lock(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 // Macros for adding/subtracting an immediate value that may be loaded from | 736 // Macros for adding/subtracting an immediate value that may be loaded from |
743 // the constant pool. | 737 // the constant pool. |
744 // TODO(koda): Assert that these are not used for heap objects. | 738 // TODO(koda): Assert that these are not used for heap objects. |
745 void AddImmediate(Register reg, const Immediate& imm); | 739 void AddImmediate(Register reg, const Immediate& imm); |
746 void AddImmediate(const Address& address, const Immediate& imm); | 740 void AddImmediate(const Address& address, const Immediate& imm); |
747 void SubImmediate(Register reg, const Immediate& imm); | 741 void SubImmediate(Register reg, const Immediate& imm); |
748 void SubImmediate(const Address& address, const Immediate& imm); | 742 void SubImmediate(const Address& address, const Immediate& imm); |
749 | 743 |
750 void Drop(intptr_t stack_elements, Register tmp = TMP); | 744 void Drop(intptr_t stack_elements, Register tmp = TMP); |
751 | 745 |
752 bool constant_pool_allowed() const { | 746 bool constant_pool_allowed() const { return constant_pool_allowed_; } |
753 return constant_pool_allowed_; | 747 void set_constant_pool_allowed(bool b) { constant_pool_allowed_ = b; } |
754 } | |
755 void set_constant_pool_allowed(bool b) { | |
756 constant_pool_allowed_ = b; | |
757 } | |
758 | 748 |
759 void LoadImmediate(Register reg, const Immediate& imm); | 749 void LoadImmediate(Register reg, const Immediate& imm); |
760 void LoadIsolate(Register dst); | 750 void LoadIsolate(Register dst); |
761 void LoadObject(Register dst, const Object& obj); | 751 void LoadObject(Register dst, const Object& obj); |
762 void LoadUniqueObject(Register dst, const Object& obj); | 752 void LoadUniqueObject(Register dst, const Object& obj); |
763 void LoadNativeEntry(Register dst, | 753 void LoadNativeEntry(Register dst, |
764 const ExternalLabel* label, | 754 const ExternalLabel* label, |
765 Patchability patchable); | 755 Patchability patchable); |
766 void LoadFunctionFromCalleePool(Register dst, | 756 void LoadFunctionFromCalleePool(Register dst, |
767 const Function& function, | 757 const Function& function, |
768 Register new_pp); | 758 Register new_pp); |
769 void JmpPatchable(const StubEntry& stub_entry, Register pp); | 759 void JmpPatchable(const StubEntry& stub_entry, Register pp); |
770 void Jmp(const StubEntry& stub_entry, Register pp = PP); | 760 void Jmp(const StubEntry& stub_entry, Register pp = PP); |
771 void J(Condition condition, const StubEntry& stub_entry, Register pp); | 761 void J(Condition condition, const StubEntry& stub_entry, Register pp); |
772 void CallPatchable(const StubEntry& stub_entry); | 762 void CallPatchable(const StubEntry& stub_entry); |
773 void Call(const StubEntry& stub_entry); | 763 void Call(const StubEntry& stub_entry); |
774 void CallToRuntime(); | 764 void CallToRuntime(); |
775 // Emit a call that shares its object pool entries with other calls | 765 // Emit a call that shares its object pool entries with other calls |
776 // that have the same equivalence marker. | 766 // that have the same equivalence marker. |
777 void CallWithEquivalence(const StubEntry& stub_entry, | 767 void CallWithEquivalence(const StubEntry& stub_entry, |
778 const Object& equivalence); | 768 const Object& equivalence); |
779 // Unaware of write barrier (use StoreInto* methods for storing to objects). | 769 // Unaware of write barrier (use StoreInto* methods for storing to objects). |
780 // TODO(koda): Add StackAddress/HeapAddress types to prevent misuse. | 770 // TODO(koda): Add StackAddress/HeapAddress types to prevent misuse. |
781 void StoreObject(const Address& dst, const Object& obj); | 771 void StoreObject(const Address& dst, const Object& obj); |
782 void PushObject(const Object& object); | 772 void PushObject(const Object& object); |
783 void CompareObject(Register reg, const Object& object); | 773 void CompareObject(Register reg, const Object& object); |
784 | 774 |
785 // Destroys value. | 775 // Destroys value. |
786 void StoreIntoObject(Register object, // Object we are storing into. | 776 void StoreIntoObject(Register object, // Object we are storing into. |
787 const Address& dest, // Where we are storing into. | 777 const Address& dest, // Where we are storing into. |
788 Register value, // Value we are storing. | 778 Register value, // Value we are storing. |
789 bool can_value_be_smi = true); | 779 bool can_value_be_smi = true); |
790 | 780 |
791 void StoreIntoObjectNoBarrier(Register object, | 781 void StoreIntoObjectNoBarrier(Register object, |
792 const Address& dest, | 782 const Address& dest, |
793 Register value); | 783 Register value); |
794 void StoreIntoObjectNoBarrier(Register object, | 784 void StoreIntoObjectNoBarrier(Register object, |
795 const Address& dest, | 785 const Address& dest, |
796 const Object& value); | 786 const Object& value); |
797 | 787 |
798 // Stores a Smi value into a heap object field that always contains a Smi. | 788 // Stores a Smi value into a heap object field that always contains a Smi. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 void LoadClassIdMayBeSmi(Register result, Register object); | 836 void LoadClassIdMayBeSmi(Register result, Register object); |
847 void LoadTaggedClassIdMayBeSmi(Register result, Register object); | 837 void LoadTaggedClassIdMayBeSmi(Register result, Register object); |
848 | 838 |
849 // CheckClassIs fused with optimistic SmiUntag. | 839 // CheckClassIs fused with optimistic SmiUntag. |
850 // Value in the register object is untagged optimistically. | 840 // Value in the register object is untagged optimistically. |
851 void SmiUntagOrCheckClass(Register object, intptr_t class_id, Label* smi); | 841 void SmiUntagOrCheckClass(Register object, intptr_t class_id, Label* smi); |
852 | 842 |
853 /* | 843 /* |
854 * Misc. functionality. | 844 * Misc. functionality. |
855 */ | 845 */ |
856 void SmiTag(Register reg) { | 846 void SmiTag(Register reg) { addq(reg, reg); } |
857 addq(reg, reg); | |
858 } | |
859 | 847 |
860 void SmiUntag(Register reg) { | 848 void SmiUntag(Register reg) { sarq(reg, Immediate(kSmiTagSize)); } |
861 sarq(reg, Immediate(kSmiTagSize)); | |
862 } | |
863 | 849 |
864 void BranchIfNotSmi(Register reg, Label* label) { | 850 void BranchIfNotSmi(Register reg, Label* label) { |
865 testq(reg, Immediate(kSmiTagMask)); | 851 testq(reg, Immediate(kSmiTagMask)); |
866 j(NOT_ZERO, label); | 852 j(NOT_ZERO, label); |
867 } | 853 } |
868 | 854 |
869 void Align(int alignment, intptr_t offset); | 855 void Align(int alignment, intptr_t offset); |
870 void Bind(Label* label); | 856 void Bind(Label* label); |
871 void Jump(Label* label) { jmp(label); } | 857 void Jump(Label* label) { jmp(label); } |
872 | 858 |
873 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); | 859 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); |
874 static bool EmittingComments(); | 860 static bool EmittingComments(); |
875 | 861 |
876 const Code::Comments& GetCodeComments() const; | 862 const Code::Comments& GetCodeComments() const; |
877 | 863 |
878 // Address of code at offset. | 864 // Address of code at offset. |
879 uword CodeAddress(intptr_t offset) { | 865 uword CodeAddress(intptr_t offset) { return buffer_.Address(offset); } |
880 return buffer_.Address(offset); | |
881 } | |
882 | 866 |
883 intptr_t CodeSize() const { return buffer_.Size(); } | 867 intptr_t CodeSize() const { return buffer_.Size(); } |
884 intptr_t prologue_offset() const { return prologue_offset_; } | 868 intptr_t prologue_offset() const { return prologue_offset_; } |
885 bool has_single_entry_point() const { return has_single_entry_point_; } | 869 bool has_single_entry_point() const { return has_single_entry_point_; } |
886 | 870 |
887 // Count the fixups that produce a pointer offset, without processing | 871 // Count the fixups that produce a pointer offset, without processing |
888 // the fixups. | 872 // the fixups. |
889 intptr_t CountPointerOffsets() const { | 873 intptr_t CountPointerOffsets() const { return buffer_.CountPointerOffsets(); } |
890 return buffer_.CountPointerOffsets(); | |
891 } | |
892 | 874 |
893 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const { | 875 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const { |
894 return buffer_.pointer_offsets(); | 876 return buffer_.pointer_offsets(); |
895 } | 877 } |
896 | 878 |
897 ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; } | 879 ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; } |
898 | 880 |
899 RawObjectPool* MakeObjectPool() { | 881 RawObjectPool* MakeObjectPool() { |
900 return object_pool_wrapper_.MakeObjectPool(); | 882 return object_pool_wrapper_.MakeObjectPool(); |
901 } | 883 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
945 // This code sets this up with the sequence: | 927 // This code sets this up with the sequence: |
946 // pushq rbp | 928 // pushq rbp |
947 // movq rbp, rsp | 929 // movq rbp, rsp |
948 // pushq immediate(0) | 930 // pushq immediate(0) |
949 // ..... | 931 // ..... |
950 void EnterStubFrame(); | 932 void EnterStubFrame(); |
951 void LeaveStubFrame(); | 933 void LeaveStubFrame(); |
952 | 934 |
953 void MonomorphicCheckedEntry(); | 935 void MonomorphicCheckedEntry(); |
954 | 936 |
955 void UpdateAllocationStats(intptr_t cid, | 937 void UpdateAllocationStats(intptr_t cid, Heap::Space space); |
956 Heap::Space space); | |
957 | 938 |
958 void UpdateAllocationStatsWithSize(intptr_t cid, | 939 void UpdateAllocationStatsWithSize(intptr_t cid, |
959 Register size_reg, | 940 Register size_reg, |
960 Heap::Space space); | 941 Heap::Space space); |
961 void UpdateAllocationStatsWithSize(intptr_t cid, | 942 void UpdateAllocationStatsWithSize(intptr_t cid, |
962 intptr_t instance_size, | 943 intptr_t instance_size, |
963 Heap::Space space); | 944 Heap::Space space); |
964 | 945 |
965 // If allocation tracing for |cid| is enabled, will jump to |trace| label, | 946 // If allocation tracing for |cid| is enabled, will jump to |trace| label, |
966 // which will allocate in the runtime where tracing occurs. | 947 // which will allocate in the runtime where tracing occurs. |
967 void MaybeTraceAllocation(intptr_t cid, | 948 void MaybeTraceAllocation(intptr_t cid, Label* trace, bool near_jump); |
968 Label* trace, | |
969 bool near_jump); | |
970 | 949 |
971 // Inlined allocation of an instance of class 'cls', code has no runtime | 950 // Inlined allocation of an instance of class 'cls', code has no runtime |
972 // calls. Jump to 'failure' if the instance cannot be allocated here. | 951 // calls. Jump to 'failure' if the instance cannot be allocated here. |
973 // Allocated instance is returned in 'instance_reg'. | 952 // Allocated instance is returned in 'instance_reg'. |
974 // Only the tags field of the object is initialized. | 953 // Only the tags field of the object is initialized. |
975 void TryAllocate(const Class& cls, | 954 void TryAllocate(const Class& cls, |
976 Label* failure, | 955 Label* failure, |
977 bool near_jump, | 956 bool near_jump, |
978 Register instance_reg, | 957 Register instance_reg, |
979 Register temp); | 958 Register temp); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 AssemblerBuffer buffer_; | 1001 AssemblerBuffer buffer_; |
1023 | 1002 |
1024 ObjectPoolWrapper object_pool_wrapper_; | 1003 ObjectPoolWrapper object_pool_wrapper_; |
1025 | 1004 |
1026 intptr_t prologue_offset_; | 1005 intptr_t prologue_offset_; |
1027 bool has_single_entry_point_; | 1006 bool has_single_entry_point_; |
1028 | 1007 |
1029 class CodeComment : public ZoneAllocated { | 1008 class CodeComment : public ZoneAllocated { |
1030 public: | 1009 public: |
1031 CodeComment(intptr_t pc_offset, const String& comment) | 1010 CodeComment(intptr_t pc_offset, const String& comment) |
1032 : pc_offset_(pc_offset), comment_(comment) { } | 1011 : pc_offset_(pc_offset), comment_(comment) {} |
1033 | 1012 |
1034 intptr_t pc_offset() const { return pc_offset_; } | 1013 intptr_t pc_offset() const { return pc_offset_; } |
1035 const String& comment() const { return comment_; } | 1014 const String& comment() const { return comment_; } |
1036 | 1015 |
1037 private: | 1016 private: |
1038 intptr_t pc_offset_; | 1017 intptr_t pc_offset_; |
1039 const String& comment_; | 1018 const String& comment_; |
1040 | 1019 |
1041 DISALLOW_COPY_AND_ASSIGN(CodeComment); | 1020 DISALLOW_COPY_AND_ASSIGN(CodeComment); |
1042 }; | 1021 }; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 | 1118 |
1140 inline void Assembler::EmitREX_RB(XmmRegister reg, | 1119 inline void Assembler::EmitREX_RB(XmmRegister reg, |
1141 const Operand& operand, | 1120 const Operand& operand, |
1142 uint8_t rex) { | 1121 uint8_t rex) { |
1143 if (reg > 7) rex |= REX_R; | 1122 if (reg > 7) rex |= REX_R; |
1144 rex |= operand.rex(); | 1123 rex |= operand.rex(); |
1145 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex); | 1124 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex); |
1146 } | 1125 } |
1147 | 1126 |
1148 | 1127 |
1149 inline void Assembler::EmitREX_RB(XmmRegister reg, | 1128 inline void Assembler::EmitREX_RB(XmmRegister reg, Register base, uint8_t rex) { |
1150 Register base, | |
1151 uint8_t rex) { | |
1152 if (reg > 7) rex |= REX_R; | 1129 if (reg > 7) rex |= REX_R; |
1153 if (base > 7) rex |= REX_B; | 1130 if (base > 7) rex |= REX_B; |
1154 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex); | 1131 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex); |
1155 } | 1132 } |
1156 | 1133 |
1157 | 1134 |
1158 inline void Assembler::EmitREX_RB(Register reg, | 1135 inline void Assembler::EmitREX_RB(Register reg, XmmRegister base, uint8_t rex) { |
1159 XmmRegister base, | |
1160 uint8_t rex) { | |
1161 if (reg > 7) rex |= REX_R; | 1136 if (reg > 7) rex |= REX_R; |
1162 if (base > 7) rex |= REX_B; | 1137 if (base > 7) rex |= REX_B; |
1163 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex); | 1138 if (rex != REX_NONE) EmitUint8(REX_PREFIX | rex); |
1164 } | 1139 } |
1165 | 1140 |
1166 | 1141 |
1167 inline void Assembler::EmitFixup(AssemblerFixup* fixup) { | 1142 inline void Assembler::EmitFixup(AssemblerFixup* fixup) { |
1168 buffer_.EmitFixup(fixup); | 1143 buffer_.EmitFixup(fixup); |
1169 } | 1144 } |
1170 | 1145 |
1171 | 1146 |
1172 inline void Assembler::EmitOperandSizeOverride() { | 1147 inline void Assembler::EmitOperandSizeOverride() { |
1173 EmitUint8(0x66); | 1148 EmitUint8(0x66); |
1174 } | 1149 } |
1175 | 1150 |
1176 } // namespace dart | 1151 } // namespace dart |
1177 | 1152 |
1178 #endif // RUNTIME_VM_ASSEMBLER_X64_H_ | 1153 #endif // RUNTIME_VM_ASSEMBLER_X64_H_ |
OLD | NEW |