xref: /third_party/node/deps/v8/src/codegen/label.h (revision 1cb0ef41)
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