• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_INTERPRETER_BYTECODE_LABEL_H_
6 #define V8_INTERPRETER_BYTECODE_LABEL_H_
7 
8 #include <algorithm>
9 
10 #include "src/zone/zone-containers.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace interpreter {
15 
16 class BytecodeArrayBuilder;
17 
18 // A label representing a loop header in a bytecode array. It is bound before
19 // the jump is seen, so its position is always known by the time the jump is
20 // reached.
21 class V8_EXPORT_PRIVATE BytecodeLoopHeader final {
22  public:
BytecodeLoopHeader()23   BytecodeLoopHeader() : offset_(kInvalidOffset) {}
24 
offset()25   size_t offset() const {
26     DCHECK_NE(offset_, kInvalidOffset);
27     return offset_;
28   }
29 
30  private:
31   static const size_t kInvalidOffset = static_cast<size_t>(-1);
32 
bind_to(size_t offset)33   void bind_to(size_t offset) {
34     DCHECK_NE(offset, kInvalidOffset);
35     DCHECK_EQ(offset_, kInvalidOffset);
36     offset_ = offset;
37   }
38 
39   // The bytecode offset of the loop header.
40   size_t offset_;
41 
42   friend class BytecodeArrayWriter;
43 };
44 
45 // A label representing a forward branch target in a bytecode array. When a
46 // label is bound, it represents a known position in the bytecode array. A label
47 // can only have at most one referrer jump.
48 class V8_EXPORT_PRIVATE BytecodeLabel final {
49  public:
BytecodeLabel()50   BytecodeLabel() : bound_(false), jump_offset_(kInvalidOffset) {}
51 
is_bound()52   bool is_bound() const { return bound_; }
jump_offset()53   size_t jump_offset() const {
54     DCHECK_NE(jump_offset_, kInvalidOffset);
55     return jump_offset_;
56   }
57 
has_referrer_jump()58   bool has_referrer_jump() const { return jump_offset_ != kInvalidOffset; }
59 
60  private:
61   static const size_t kInvalidOffset = static_cast<size_t>(-1);
62 
bind()63   void bind() {
64     DCHECK(!bound_);
65     bound_ = true;
66   }
67 
set_referrer(size_t offset)68   void set_referrer(size_t offset) {
69     DCHECK(!bound_);
70     DCHECK_NE(offset, kInvalidOffset);
71     DCHECK_EQ(jump_offset_, kInvalidOffset);
72     jump_offset_ = offset;
73   }
74 
75   // Set when the label is bound (i.e. the start of the target basic block).
76   bool bound_;
77   // Set when the jump referrer is set (i.e. the location of the jump).
78   size_t jump_offset_;
79 
80   friend class BytecodeArrayWriter;
81 };
82 
83 // Class representing a branch target of multiple jumps.
84 class V8_EXPORT_PRIVATE BytecodeLabels {
85  public:
BytecodeLabels(Zone * zone)86   explicit BytecodeLabels(Zone* zone) : labels_(zone), is_bound_(false) {}
87   BytecodeLabels(const BytecodeLabels&) = delete;
88   BytecodeLabels& operator=(const BytecodeLabels&) = delete;
89 
90   BytecodeLabel* New();
91 
92   void Bind(BytecodeArrayBuilder* builder);
93 
is_bound()94   bool is_bound() const {
95     DCHECK_IMPLIES(
96         is_bound_,
97         std::all_of(labels_.begin(), labels_.end(), [](const BytecodeLabel& l) {
98           return !l.has_referrer_jump() || l.is_bound();
99         }));
100     return is_bound_;
101   }
102 
empty()103   bool empty() const { return labels_.empty(); }
104 
105  private:
106   ZoneLinkedList<BytecodeLabel> labels_;
107   bool is_bound_;
108 };
109 
110 }  // namespace interpreter
111 }  // namespace internal
112 }  // namespace v8
113 
114 #endif  // V8_INTERPRETER_BYTECODE_LABEL_H_
115