aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/bytecode-label.h
blob: 4581f4f4e2b03cefb857879f1839643bb8fd4583 (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
114
// Copyright 2015 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_INTERPRETER_BYTECODE_LABEL_H_
#define V8_INTERPRETER_BYTECODE_LABEL_H_

#include <algorithm>

#include "src/zone/zone-containers.h"

namespace v8 {
namespace internal {
namespace interpreter {

class BytecodeArrayBuilder;

// A label representing a loop header in a bytecode array. It is bound before
// the jump is seen, so its position is always known by the time the jump is
// reached.
class V8_EXPORT_PRIVATE BytecodeLoopHeader final {
 public:
  BytecodeLoopHeader() : offset_(kInvalidOffset) {}

  size_t offset() const {
    DCHECK_NE(offset_, kInvalidOffset);
    return offset_;
  }

 private:
  static const size_t kInvalidOffset = static_cast<size_t>(-1);

  void bind_to(size_t offset) {
    DCHECK_NE(offset, kInvalidOffset);
    DCHECK_EQ(offset_, kInvalidOffset);
    offset_ = offset;
  }

  // The bytecode offset of the loop header.
  size_t offset_;

  friend class BytecodeArrayWriter;
};

// A label representing a forward branch target in a bytecode array. When a
// label is bound, it represents a known position in the bytecode array. A label
// can only have at most one referrer jump.
class V8_EXPORT_PRIVATE BytecodeLabel final {
 public:
  BytecodeLabel() : bound_(false), jump_offset_(kInvalidOffset) {}

  bool is_bound() const { return bound_; }
  size_t jump_offset() const {
    DCHECK_NE(jump_offset_, kInvalidOffset);
    return jump_offset_;
  }

  bool has_referrer_jump() const { return jump_offset_ != kInvalidOffset; }

 private:
  static const size_t kInvalidOffset = static_cast<size_t>(-1);

  void bind() {
    DCHECK(!bound_);
    bound_ = true;
  }

  void set_referrer(size_t offset) {
    DCHECK(!bound_);
    DCHECK_NE(offset, kInvalidOffset);
    DCHECK_EQ(jump_offset_, kInvalidOffset);
    jump_offset_ = offset;
  }

  // Set when the label is bound (i.e. the start of the target basic block).
  bool bound_;
  // Set when the jump referrer is set (i.e. the location of the jump).
  size_t jump_offset_;

  friend class BytecodeArrayWriter;
};

// Class representing a branch target of multiple jumps.
class V8_EXPORT_PRIVATE BytecodeLabels {
 public:
  explicit BytecodeLabels(Zone* zone) : labels_(zone), is_bound_(false) {}

  BytecodeLabel* New();

  void Bind(BytecodeArrayBuilder* builder);

  bool is_bound() const {
    DCHECK_IMPLIES(
        is_bound_,
        std::all_of(labels_.begin(), labels_.end(), [](const BytecodeLabel& l) {
          return !l.has_referrer_jump() || l.is_bound();
        }));
    return is_bound_;
  }

  bool empty() const { return labels_.empty(); }

 private:
  ZoneLinkedList<BytecodeLabel> labels_;
  bool is_bound_;

  DISALLOW_COPY_AND_ASSIGN(BytecodeLabels);
};

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODE_LABEL_H_