| // 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 branch target in a bytecode array. When a | |
| // label is bound, it represents a known position in the bytecode | |
| // array. For labels that are forward references there can be at most | |
| // one reference whilst it is unbound. | |
| class V8_EXPORT_PRIVATE BytecodeLabel final { | |
| public: | |
| BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {} | |
| bool is_bound() const { return bound_; } | |
| size_t offset() const { return offset_; } | |
| private: | |
| static const size_t kInvalidOffset = static_cast<size_t>(-1); | |
| void bind_to(size_t offset) { | |
| DCHECK(!bound_ && offset != kInvalidOffset); | |
| offset_ = offset; | |
| bound_ = true; | |
| } | |
| void set_referrer(size_t offset) { | |
| DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset); | |
| offset_ = offset; | |
| } | |
| bool is_forward_target() const { | |
| return offset() != kInvalidOffset && !is_bound(); | |
| } | |
| // There are three states for a label: | |
| // bound_ offset_ | |
| // UNSET false kInvalidOffset | |
| // FORWARD_TARGET false Offset of referring jump | |
| // BACKWARD_TARGET true Offset of label in bytecode array when bound | |
| bool bound_; | |
| size_t offset_; | |
| friend class BytecodeArrayWriter; | |
| }; | |
| // Class representing a branch target of multiple jumps. | |
| class V8_EXPORT_PRIVATE BytecodeLabels { | |
| public: | |
| explicit BytecodeLabels(Zone* zone) : labels_(zone) {} | |
| BytecodeLabel* New(); | |
| void Bind(BytecodeArrayBuilder* builder); | |
| void BindToLabel(BytecodeArrayBuilder* builder, const BytecodeLabel& target); | |
| bool is_bound() const { | |
| bool is_bound = !labels_.empty() && labels_.front().is_bound(); | |
| DCHECK(!is_bound || | |
| std::all_of(labels_.begin(), labels_.end(), | |
| [](const BytecodeLabel& l) { return l.is_bound(); })); | |
| return is_bound; | |
| } | |
| bool empty() const { return labels_.empty(); } | |
| private: | |
| ZoneLinkedList<BytecodeLabel> labels_; | |
| DISALLOW_COPY_AND_ASSIGN(BytecodeLabels); | |
| }; | |
| } // namespace interpreter | |
| } // namespace internal | |
| } // namespace v8 | |
| #endif // V8_INTERPRETER_BYTECODE_LABEL_H_ |