blob: 1c9d0e9d6b3c2a235dbb8d7d912a427f988a1fa2 [file] [log] [blame]
// 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 loop header in a bytecode array. It is bound before
// the jump is seen, so its position is always known by the time the jump is
// reached.
class V8_EXPORT_PRIVATE BytecodeLoopHeader final {
public:
BytecodeLoopHeader() : offset_(kInvalidOffset) {}
size_t offset() const {
DCHECK_NE(offset_, kInvalidOffset);
return offset_;
}
private:
static const size_t kInvalidOffset = static_cast<size_t>(-1);
void bind_to(size_t offset) {
DCHECK_NE(offset, kInvalidOffset);
DCHECK_EQ(offset_, kInvalidOffset);
offset_ = offset;
}
// The bytecode offset of the loop header.
size_t offset_;
friend class BytecodeArrayWriter;
};
// A label representing a forward branch target in a bytecode array. When a
// label is bound, it represents a known position in the bytecode array. A label
// can only have at most one referrer jump.
class V8_EXPORT_PRIVATE BytecodeLabel final {
public:
BytecodeLabel() : bound_(false), jump_offset_(kInvalidOffset) {}
bool is_bound() const { return bound_; }
size_t jump_offset() const {
DCHECK_NE(jump_offset_, kInvalidOffset);
return jump_offset_;
}
bool has_referrer_jump() const { return jump_offset_ != kInvalidOffset; }
private:
static const size_t kInvalidOffset = static_cast<size_t>(-1);
void bind() {
DCHECK(!bound_);
bound_ = true;
}
void set_referrer(size_t offset) {
DCHECK(!bound_);
DCHECK_NE(offset, kInvalidOffset);
DCHECK_EQ(jump_offset_, kInvalidOffset);
jump_offset_ = offset;
}
// Set when the label is bound (i.e. the start of the target basic block).
bool bound_;
// Set when the jump referrer is set (i.e. the location of the jump).
size_t jump_offset_;
friend class BytecodeArrayWriter;
};
// Class representing a branch target of multiple jumps.
class V8_EXPORT_PRIVATE BytecodeLabels {
public:
explicit BytecodeLabels(Zone* zone) : labels_(zone), is_bound_(false) {}
BytecodeLabels(const BytecodeLabels&) = delete;
BytecodeLabels& operator=(const BytecodeLabels&) = delete;
BytecodeLabel* New();
void Bind(BytecodeArrayBuilder* builder);
bool is_bound() const {
DCHECK_IMPLIES(
is_bound_,
std::all_of(labels_.begin(), labels_.end(), [](const BytecodeLabel& l) {
return !l.has_referrer_jump() || l.is_bound();
}));
return is_bound_;
}
bool empty() const { return labels_.empty(); }
private:
ZoneLinkedList<BytecodeLabel> labels_;
bool is_bound_;
};
} // namespace interpreter
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETER_BYTECODE_LABEL_H_