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 10namespace v8 { 11namespace 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 19class 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 // Disallow copy construction and assignment, but allow move construction and 29 // move assignment on selected platforms (see below). 30 Label(const Label&) = delete; 31 Label& operator=(const Label&) = delete; 32 33// On ARM64, the Assembler keeps track of pointers to Labels to resolve 34// branches to distant targets. Copying labels would confuse the Assembler. 35// On other platforms, allow move construction. 36#if !V8_TARGET_ARCH_ARM64 37// In debug builds, the old Label has to be cleared in order to avoid a DCHECK 38// failure in it's destructor. 39#ifdef DEBUG 40 Label(Label&& other) V8_NOEXCEPT { *this = std::move(other); } 41 Label& operator=(Label&& other) V8_NOEXCEPT { 42 pos_ = other.pos_; 43 near_link_pos_ = other.near_link_pos_; 44 other.Unuse(); 45 other.UnuseNear(); 46 return *this; 47 } 48#else 49 Label(Label&&) V8_NOEXCEPT = default; 50 Label& operator=(Label&&) V8_NOEXCEPT = default; 51#endif 52#endif 53 54#ifdef DEBUG 55 V8_INLINE ~Label() { 56 DCHECK(!is_linked()); 57 DCHECK(!is_near_linked()); 58 } 59#endif 60 61 V8_INLINE void Unuse() { pos_ = 0; } 62 V8_INLINE void UnuseNear() { near_link_pos_ = 0; } 63 64 V8_INLINE bool is_bound() const { return pos_ < 0; } 65 V8_INLINE bool is_unused() const { return pos_ == 0 && near_link_pos_ == 0; } 66 V8_INLINE bool is_linked() const { return pos_ > 0; } 67 V8_INLINE bool is_near_linked() const { return near_link_pos_ > 0; } 68 69 // Returns the position of bound or linked labels. Cannot be used 70 // for unused labels. 71 int pos() const { 72 if (pos_ < 0) return -pos_ - 1; 73 if (pos_ > 0) return pos_ - 1; 74 UNREACHABLE(); 75 } 76 77 int near_link_pos() const { return near_link_pos_ - 1; } 78 79 private: 80 // pos_ encodes both the binding state (via its sign) 81 // and the binding position (via its value) of a label. 82 // 83 // pos_ < 0 bound label, pos() returns the jump target position 84 // pos_ == 0 unused label 85 // pos_ > 0 linked label, pos() returns the last reference position 86 int pos_ = 0; 87 88 // Behaves like |pos_| in the "> 0" case, but for near jumps to this label. 89 int near_link_pos_ = 0; 90 91 void bind_to(int pos) { 92 pos_ = -pos - 1; 93 DCHECK(is_bound()); 94 } 95 void link_to(int pos, Distance distance = kFar) { 96 if (distance == kNear) { 97 near_link_pos_ = pos + 1; 98 DCHECK(is_near_linked()); 99 } else { 100 pos_ = pos + 1; 101 DCHECK(is_linked()); 102 } 103 } 104 105 friend class Assembler; 106 friend class Displacement; 107 friend class RegExpBytecodeGenerator; 108}; 109 110} // namespace internal 111} // namespace v8 112 113#endif // V8_CODEGEN_LABEL_H_ 114