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 branch target in a bytecode array. When a 19 // label is bound, it represents a known position in the bytecode 20 // array. For labels that are forward references there can be at most 21 // one reference whilst it is unbound. 22 class V8_EXPORT_PRIVATE BytecodeLabel final { 23 public: BytecodeLabel()24 BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {} 25 is_bound()26 bool is_bound() const { return bound_; } offset()27 size_t offset() const { return offset_; } 28 29 private: 30 static const size_t kInvalidOffset = static_cast<size_t>(-1); 31 bind_to(size_t offset)32 void bind_to(size_t offset) { 33 DCHECK(!bound_ && offset != kInvalidOffset); 34 offset_ = offset; 35 bound_ = true; 36 } 37 set_referrer(size_t offset)38 void set_referrer(size_t offset) { 39 DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset); 40 offset_ = offset; 41 } 42 is_forward_target()43 bool is_forward_target() const { 44 return offset() != kInvalidOffset && !is_bound(); 45 } 46 47 // There are three states for a label: 48 // bound_ offset_ 49 // UNSET false kInvalidOffset 50 // FORWARD_TARGET false Offset of referring jump 51 // BACKWARD_TARGET true Offset of label in bytecode array when bound 52 bool bound_; 53 size_t offset_; 54 55 friend class BytecodeArrayWriter; 56 }; 57 58 // Class representing a branch target of multiple jumps. 59 class V8_EXPORT_PRIVATE BytecodeLabels { 60 public: BytecodeLabels(Zone * zone)61 explicit BytecodeLabels(Zone* zone) : labels_(zone) {} 62 63 BytecodeLabel* New(); 64 65 void Bind(BytecodeArrayBuilder* builder); 66 67 void BindToLabel(BytecodeArrayBuilder* builder, const BytecodeLabel& target); 68 is_bound()69 bool is_bound() const { 70 bool is_bound = !labels_.empty() && labels_.front().is_bound(); 71 DCHECK(!is_bound || 72 std::all_of(labels_.begin(), labels_.end(), 73 [](const BytecodeLabel& l) { return l.is_bound(); })); 74 return is_bound; 75 } 76 empty()77 bool empty() const { return labels_.empty(); } 78 79 private: 80 ZoneLinkedList<BytecodeLabel> labels_; 81 82 DISALLOW_COPY_AND_ASSIGN(BytecodeLabels); 83 }; 84 85 } // namespace interpreter 86 } // namespace internal 87 } // namespace v8 88 89 #endif // V8_INTERPRETER_BYTECODE_LABEL_H_ 90