| // 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_ |