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