V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
cfg.h
1 // Copyright 2018 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_TORQUE_CFG_H_
6 #define V8_TORQUE_CFG_H_
7 
8 #include <list>
9 #include <memory>
10 #include <unordered_map>
11 #include <vector>
12 
13 #include "src/torque/ast.h"
14 #include "src/torque/instructions.h"
15 #include "src/torque/source-positions.h"
16 #include "src/torque/types.h"
17 
18 namespace v8 {
19 namespace internal {
20 namespace torque {
21 
22 class ControlFlowGraph;
23 
24 class Block {
25  public:
26  explicit Block(ControlFlowGraph* cfg, size_t id,
28  bool is_deferred)
29  : cfg_(cfg),
30  input_types_(std::move(input_types)),
31  id_(id),
32  is_deferred_(is_deferred) {}
33  void Add(Instruction instruction) {
34  DCHECK(!IsComplete());
35  instructions_.push_back(std::move(instruction));
36  }
37 
38  bool HasInputTypes() const { return input_types_ != base::nullopt; }
39  const Stack<const Type*>& InputTypes() const { return *input_types_; }
40  void SetInputTypes(const Stack<const Type*>& input_types);
41  void Retype() {
42  Stack<const Type*> current_stack = InputTypes();
43  for (const Instruction& instruction : instructions()) {
44  instruction.TypeInstruction(&current_stack, cfg_);
45  }
46  }
47 
48  const std::vector<Instruction>& instructions() const { return instructions_; }
49  bool IsComplete() const {
50  return !instructions_.empty() && instructions_.back()->IsBlockTerminator();
51  }
52  size_t id() const { return id_; }
53  bool IsDeferred() const { return is_deferred_; }
54 
55  private:
56  ControlFlowGraph* cfg_;
57  std::vector<Instruction> instructions_;
59  const size_t id_;
60  bool is_deferred_;
61 };
62 
64  public:
65  explicit ControlFlowGraph(Stack<const Type*> input_types) {
66  start_ = NewBlock(std::move(input_types), false);
67  PlaceBlock(start_);
68  }
69 
70  Block* NewBlock(base::Optional<Stack<const Type*>> input_types,
71  bool is_deferred) {
72  blocks_.emplace_back(this, next_block_id_++, std::move(input_types),
73  is_deferred);
74  return &blocks_.back();
75  }
76  void PlaceBlock(Block* block) { placed_blocks_.push_back(block); }
77  Block* start() const { return start_; }
78  base::Optional<Block*> end() const { return end_; }
79  void set_end(Block* end) { end_ = end; }
80  void SetReturnType(const Type* t) {
81  if (!return_type_) {
82  return_type_ = t;
83  return;
84  }
85  if (t != *return_type_) {
86  ReportError("expected return type ", **return_type_, " instead of ", *t);
87  }
88  }
89  const std::vector<Block*>& blocks() const { return placed_blocks_; }
90 
91  private:
92  std::list<Block> blocks_;
93  Block* start_;
94  std::vector<Block*> placed_blocks_;
96  base::Optional<const Type*> return_type_;
97  size_t next_block_id_ = 0;
98 };
99 
101  public:
102  explicit CfgAssembler(Stack<const Type*> input_types)
103  : current_stack_(std::move(input_types)), cfg_(current_stack_) {}
104 
105  const ControlFlowGraph& Result() {
106  if (!CurrentBlockIsComplete()) {
107  cfg_.set_end(current_block_);
108  }
109  return cfg_;
110  }
111 
112  Block* NewBlock(
113  base::Optional<Stack<const Type*>> input_types = base::nullopt,
114  bool is_deferred = false) {
115  return cfg_.NewBlock(std::move(input_types), is_deferred);
116  }
117 
118  bool CurrentBlockIsComplete() const { return current_block_->IsComplete(); }
119 
120  void Emit(Instruction instruction) {
121  instruction.TypeInstruction(&current_stack_, &cfg_);
122  current_block_->Add(std::move(instruction));
123  }
124 
125  const Stack<const Type*>& CurrentStack() const { return current_stack_; }
126 
127  StackRange TopRange(size_t slot_count) const {
128  return CurrentStack().TopRange(slot_count);
129  }
130 
131  void Bind(Block* block);
132  void Goto(Block* block);
133  // Goto block while keeping {preserved_slots} many slots on the top and
134  // deleting additional the slots below these to match the input type of the
135  // target block.
136  // Returns the StackRange of the preserved slots in the target block.
137  StackRange Goto(Block* block, size_t preserved_slots);
138  // The condition must be of type bool and on the top of stack. It is removed
139  // from the stack before branching.
140  void Branch(Block* if_true, Block* if_false);
141  // Delete the specified range of slots, moving upper slots to fill the gap.
142  void DeleteRange(StackRange range);
143  void DropTo(BottomOffset new_level);
145  void Poke(StackRange destination, StackRange origin,
147  void Print(std::string s);
148  void AssertionFailure(std::string message);
149  void Unreachable();
150  void DebugBreak();
151 
152  void PrintCurrentStack(std::ostream& s) { s << "stack: " << current_stack_; }
153 
154  private:
156  Stack<const Type*> current_stack_;
157  ControlFlowGraph cfg_;
158  Block* current_block_ = cfg_.start();
159 };
160 
162  public:
164  : assembler_(assembler), saved_block_(block) {
165  saved_stack_ = block->InputTypes();
166  DCHECK(!assembler->CurrentBlockIsComplete());
167  std::swap(saved_block_, assembler->current_block_);
168  std::swap(saved_stack_, assembler->current_stack_);
169  assembler->cfg_.PlaceBlock(block);
170  }
171 
173  DCHECK(assembler_->CurrentBlockIsComplete());
174  std::swap(saved_block_, assembler_->current_block_);
175  std::swap(saved_stack_, assembler_->current_stack_);
176  }
177 
178  private:
179  CfgAssembler* assembler_;
180  Stack<const Type*> saved_stack_;
181  Block* saved_block_;
182 };
183 
184 } // namespace torque
185 } // namespace internal
186 } // namespace v8
187 
188 #endif // V8_TORQUE_CFG_H_
Definition: libplatform.h:13