#ifndef V8_COMPILER_SCHEDULE_H_
#define V8_COMPILER_SCHEDULE_H_
#include <iosfwd>
#include "src/base/compiler-specific.h"
#include "src/common/globals.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
class BasicBlock;
class Node;
using BasicBlockVector = ZoneVector<BasicBlock*>;
using NodeVector = ZoneVector<Node*>;
class V8_EXPORT_PRIVATE BasicBlock final
: public NON_EXPORTED_BASE(ZoneObject) {
public:
enum Control {
kNone,
kGoto,
kCall,
kBranch,
kSwitch,
kDeoptimize,
kTailCall,
kReturn,
kThrow
};
class Id {
public:
int ToInt() const { return static_cast<int>(index_); }
size_t ToSize() const { return index_; }
static Id FromSize(size_t index) { return Id(index); }
static Id FromInt(int index) { return Id(static_cast<size_t>(index)); }
private:
explicit Id(size_t index) : index_(index) {}
size_t index_;
};
BasicBlock(Zone* zone, Id id);
BasicBlock(const BasicBlock&) = delete;
BasicBlock& operator=(const BasicBlock&) = delete;
Id id() const { return id_; }
#if DEBUG
void set_debug_info(AssemblerDebugInfo debug_info) {
debug_info_ = debug_info;
}
AssemblerDebugInfo debug_info() const { return debug_info_; }
#endif
void Print();
BasicBlockVector& predecessors() { return predecessors_; }
const BasicBlockVector& predecessors() const { return predecessors_; }
size_t PredecessorCount() const { return predecessors_.size(); }
BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
void ClearPredecessors() { predecessors_.clear(); }
void AddPredecessor(BasicBlock* predecessor);
void RemovePredecessor(size_t index);
BasicBlockVector& successors() { return successors_; }
const BasicBlockVector& successors() const { return successors_; }
size_t SuccessorCount() const { return successors_.size(); }
BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
void ClearSuccessors() { successors_.clear(); }
void AddSuccessor(BasicBlock* successor);
using value_type = Node*;
bool empty() const { return nodes_.empty(); }
size_t size() const { return nodes_.size(); }
Node* NodeAt(size_t index) { return nodes_[index]; }
size_t NodeCount() const { return nodes_.size(); }
value_type& front() { return nodes_.front(); }
value_type const& front() const { return nodes_.front(); }
using iterator = NodeVector::iterator;
iterator begin() { return nodes_.begin(); }
iterator end() { return nodes_.end(); }
void RemoveNode(iterator it) { nodes_.erase(it); }
using const_iterator = NodeVector::const_iterator;
const_iterator begin() const { return nodes_.begin(); }
const_iterator end() const { return nodes_.end(); }
using reverse_iterator = NodeVector::reverse_iterator;
reverse_iterator rbegin() { return nodes_.rbegin(); }
reverse_iterator rend() { return nodes_.rend(); }
void AddNode(Node* node);
template <class InputIterator>
void InsertNodes(iterator insertion_point, InputIterator insertion_start,
InputIterator insertion_end) {
nodes_.insert(insertion_point, insertion_start, insertion_end);
}
void TrimNodes(iterator new_end);
void ResetRPOInfo();
Control control() const { return control_; }
void set_control(Control control);
Node* control_input() const { return control_input_; }
void set_control_input(Node* control_input);
bool deferred() const { return deferred_; }
void set_deferred(bool deferred) { deferred_ = deferred; }
int32_t dominator_depth() const { return dominator_depth_; }
void set_dominator_depth(int32_t depth) { dominator_depth_ = depth; }
BasicBlock* dominator() const { return dominator_; }
void set_dominator(BasicBlock* dominator) { dominator_ = dominator; }
BasicBlock* rpo_next() const { return rpo_next_; }
void set_rpo_next(BasicBlock* rpo_next) { rpo_next_ = rpo_next; }
BasicBlock* loop_header() const { return loop_header_; }
void set_loop_header(BasicBlock* loop_header);
BasicBlock* loop_end() const { return loop_end_; }
void set_loop_end(BasicBlock* loop_end);
int32_t loop_depth() const { return loop_depth_; }
void set_loop_depth(int32_t loop_depth);
int32_t loop_number() const { return loop_number_; }
void set_loop_number(int32_t loop_number) { loop_number_ = loop_number; }
int32_t rpo_number() const { return rpo_number_; }
void set_rpo_number(int32_t rpo_number);
NodeVector* nodes() { return &nodes_; }
#ifdef LOG_BUILTIN_BLOCK_COUNT
uint64_t pgo_execution_count() { return pgo_execution_count_; }
void set_pgo_execution_count(uint64_t count) { pgo_execution_count_ = count; }
#endif
inline bool IsLoopHeader() const { return loop_end_ != nullptr; }
bool LoopContains(BasicBlock* block) const;
static BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);
private:
int32_t loop_number_;
int32_t rpo_number_;
bool deferred_;
int32_t dominator_depth_;
BasicBlock* dominator_;
BasicBlock* rpo_next_;
BasicBlock* loop_header_;
BasicBlock* loop_end_;
int32_t loop_depth_;
Control control_;
Node* control_input_;
NodeVector nodes_;
BasicBlockVector successors_;
BasicBlockVector predecessors_;
#if DEBUG
AssemblerDebugInfo debug_info_;
#endif
#ifdef LOG_BUILTIN_BLOCK_COUNT
uint64_t pgo_execution_count_;
#endif
Id id_;
};
std::ostream& operator<<(std::ostream&, const BasicBlock&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
public:
explicit Schedule(Zone* zone, size_t node_count_hint = 0);
Schedule(const Schedule&) = delete;
Schedule& operator=(const Schedule&) = delete;
BasicBlock* block(Node* node) const;
bool IsScheduled(Node* node);
BasicBlock* GetBlockById(BasicBlock::Id block_id);
void ClearBlockById(BasicBlock::Id block_id);
size_t BasicBlockCount() const { return all_blocks_.size(); }
size_t RpoBlockCount() const { return rpo_order_.size(); }
bool SameBasicBlock(Node* a, Node* b) const;
BasicBlock* NewBasicBlock();
void PlanNode(BasicBlock* block, Node* node);
void AddNode(BasicBlock* block, Node* node);
void AddGoto(BasicBlock* block, BasicBlock* succ);
void AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
BasicBlock* exception_block);
void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
BasicBlock* fblock);
void AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
size_t succ_count);
void AddDeoptimize(BasicBlock* block, Node* input);
void AddTailCall(BasicBlock* block, Node* input);
void AddReturn(BasicBlock* block, Node* input);
void AddThrow(BasicBlock* block, Node* input);
void InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
BasicBlock* tblock, BasicBlock* fblock);
void InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
BasicBlock** succ_blocks, size_t succ_count);
void AddSuccessorForTesting(BasicBlock* block, BasicBlock* succ) {
return AddSuccessor(block, succ);
}
const BasicBlockVector* all_blocks() const { return &all_blocks_; }
BasicBlockVector* rpo_order() { return &rpo_order_; }
const BasicBlockVector* rpo_order() const { return &rpo_order_; }
BasicBlock* start() { return start_; }
BasicBlock* end() { return end_; }
Zone* zone() const { return zone_; }
private:
friend class GraphAssembler;
friend class Scheduler;
friend class RawMachineAssembler;
void EnsureCFGWellFormedness();
void EliminateRedundantPhiNodes();
void EnsureSplitEdgeForm(BasicBlock* block);
void MovePhis(BasicBlock* from, BasicBlock* to);
void PropagateDeferredMark();
void AddSuccessor(BasicBlock* block, BasicBlock* succ);
void MoveSuccessors(BasicBlock* from, BasicBlock* to);
void SetControlInput(BasicBlock* block, Node* node);
void SetBlockForNode(BasicBlock* block, Node* node);
Zone* zone_;
BasicBlockVector all_blocks_;
BasicBlockVector nodeid_to_block_;
BasicBlockVector rpo_order_;
BasicBlock* start_;
BasicBlock* end_;
};
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const Schedule&);
}
}
}
#endif