| 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 |