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 12namespace v8 { 13namespace internal { 14namespace interpreter { 15 16class 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. 21class V8_EXPORT_PRIVATE BytecodeLoopHeader final { 22 public: 23 BytecodeLoopHeader() : offset_(kInvalidOffset) {} 24 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 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. 48class V8_EXPORT_PRIVATE BytecodeLabel final { 49 public: 50 BytecodeLabel() : bound_(false), jump_offset_(kInvalidOffset) {} 51 52 bool is_bound() const { return bound_; } 53 size_t jump_offset() const { 54 DCHECK_NE(jump_offset_, kInvalidOffset); 55 return jump_offset_; 56 } 57 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 63 void bind() { 64 DCHECK(!bound_); 65 bound_ = true; 66 } 67 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. 84class V8_EXPORT_PRIVATE BytecodeLabels { 85 public: 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 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 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