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_LABEL_H_
6#define V8_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// 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
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
50 V8_INLINE ~Label() {
51 DCHECK(!is_linked());
52 DCHECK(!is_near_linked());
53 }
54#endif
55
56 V8_INLINE void Unuse() { pos_ = 0; }
57 V8_INLINE void UnuseNear() { near_link_pos_ = 0; }
58
59 V8_INLINE bool is_bound() const { return pos_ < 0; }
60 V8_INLINE bool is_unused() const { return pos_ == 0 && near_link_pos_ == 0; }
61 V8_INLINE bool is_linked() const { return pos_ > 0; }
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.
66 int pos() const {
67 if (pos_ < 0) return -pos_ - 1;
68 if (pos_ > 0) return pos_ - 1;
69 UNREACHABLE();
70 }
71
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
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 RegExpMacroAssemblerIrregexp;
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_LABEL_H_
113