1 // Copyright 2017 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_CODEGEN_LABEL_H_ 6 #define V8_CODEGEN_LABEL_H_ 7 8 #include "src/base/macros.h" 9 10 namespace v8 { 11 namespace internal { 12 13 // ----------------------------------------------------------------------------- 14 // Labels represent pc locations; they are typically jump or call targets. 15 // After declaration, a label can be freely used to denote known or (yet) 16 // unknown pc location. Assembler::bind() is used to bind a label to the 17 // current pc. A label can be bound only once. 18 19 class Label { 20 public: 21 enum Distance { 22 kNear, // near jump: 8 bit displacement (signed) 23 kFar // far jump: 32 bit displacement (signed) 24 }; 25 26 Label() = default; 27 28 // On ARM64, the Assembler keeps track of pointers to Labels to resolve 29 // branches to distant targets. Copying labels would confuse the Assembler. 30 // On other platforms, allow move construction. 31 #if !V8_TARGET_ARCH_ARM64 32 // In debug builds, the old Label has to be cleared in order to avoid a DCHECK 33 // failure in it's destructor. 34 #ifdef DEBUG Label(Label && other)35 Label(Label&& other) V8_NOEXCEPT { *this = std::move(other); } 36 Label& operator=(Label&& other) V8_NOEXCEPT { 37 pos_ = other.pos_; 38 near_link_pos_ = other.near_link_pos_; 39 other.Unuse(); 40 other.UnuseNear(); 41 return *this; 42 } 43 #else 44 Label(Label&&) V8_NOEXCEPT = default; 45 Label& operator=(Label&&) V8_NOEXCEPT = default; 46 #endif 47 #endif 48 49 #ifdef DEBUG ~Label()50 V8_INLINE ~Label() { 51 DCHECK(!is_linked()); 52 DCHECK(!is_near_linked()); 53 } 54 #endif 55 Unuse()56 V8_INLINE void Unuse() { pos_ = 0; } UnuseNear()57 V8_INLINE void UnuseNear() { near_link_pos_ = 0; } 58 is_bound()59 V8_INLINE bool is_bound() const { return pos_ < 0; } is_unused()60 V8_INLINE bool is_unused() const { return pos_ == 0 && near_link_pos_ == 0; } is_linked()61 V8_INLINE bool is_linked() const { return pos_ > 0; } is_near_linked()62 V8_INLINE bool is_near_linked() const { return near_link_pos_ > 0; } 63 64 // Returns the position of bound or linked labels. Cannot be used 65 // for unused labels. pos()66 int pos() const { 67 if (pos_ < 0) return -pos_ - 1; 68 if (pos_ > 0) return pos_ - 1; 69 UNREACHABLE(); 70 } 71 near_link_pos()72 int near_link_pos() const { return near_link_pos_ - 1; } 73 74 private: 75 // pos_ encodes both the binding state (via its sign) 76 // and the binding position (via its value) of a label. 77 // 78 // pos_ < 0 bound label, pos() returns the jump target position 79 // pos_ == 0 unused label 80 // pos_ > 0 linked label, pos() returns the last reference position 81 int pos_ = 0; 82 83 // Behaves like |pos_| in the "> 0" case, but for near jumps to this label. 84 int near_link_pos_ = 0; 85 bind_to(int pos)86 void bind_to(int pos) { 87 pos_ = -pos - 1; 88 DCHECK(is_bound()); 89 } 90 void link_to(int pos, Distance distance = kFar) { 91 if (distance == kNear) { 92 near_link_pos_ = pos + 1; 93 DCHECK(is_near_linked()); 94 } else { 95 pos_ = pos + 1; 96 DCHECK(is_linked()); 97 } 98 } 99 100 friend class Assembler; 101 friend class Displacement; 102 friend class RegExpBytecodeGenerator; 103 104 // Disallow copy construction and assignment, but allow move construction and 105 // move assignment on selected platforms (see above). 106 DISALLOW_COPY_AND_ASSIGN(Label); 107 }; 108 109 } // namespace internal 110 } // namespace v8 111 112 #endif // V8_CODEGEN_LABEL_H_ 113