V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
instructions.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_INSTRUCTIONS_H_
6 #define V8_TORQUE_INSTRUCTIONS_H_
7 
8 #include <memory>
9 
10 #include "src/torque/ast.h"
11 #include "src/torque/source-positions.h"
12 #include "src/torque/types.h"
13 #include "src/torque/utils.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace torque {
18 
19 class Block;
20 class Builtin;
21 class ControlFlowGraph;
22 class Intrinsic;
23 class Macro;
24 class NamespaceConstant;
25 class RuntimeFunction;
26 
27 #define TORQUE_INSTRUCTION_LIST(V) \
28  V(PeekInstruction) \
29  V(PokeInstruction) \
30  V(DeleteRangeInstruction) \
31  V(PushUninitializedInstruction) \
32  V(PushCodePointerInstruction) \
33  V(CallCsaMacroInstruction) \
34  V(CallIntrinsicInstruction) \
35  V(NamespaceConstantInstruction) \
36  V(CallCsaMacroAndBranchInstruction) \
37  V(CallBuiltinInstruction) \
38  V(CallRuntimeInstruction) \
39  V(CallBuiltinPointerInstruction) \
40  V(BranchInstruction) \
41  V(ConstexprBranchInstruction) \
42  V(GotoInstruction) \
43  V(GotoExternalInstruction) \
44  V(ReturnInstruction) \
45  V(PrintConstantStringInstruction) \
46  V(AbortInstruction) \
47  V(UnsafeCastInstruction)
48 
49 #define TORQUE_INSTRUCTION_BOILERPLATE() \
50  static const InstructionKind kKind; \
51  std::unique_ptr<InstructionBase> Clone() const override; \
52  void Assign(const InstructionBase& other) override; \
53  void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) \
54  const override;
55 
56 enum class InstructionKind {
57 #define ENUM_ITEM(name) k##name,
58  TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
59 #undef ENUM_ITEM
60 };
61 
63  InstructionBase() : pos(CurrentSourcePosition::Get()) {}
64  virtual std::unique_ptr<InstructionBase> Clone() const = 0;
65  virtual void Assign(const InstructionBase& other) = 0;
66  virtual ~InstructionBase() = default;
67 
68  virtual void TypeInstruction(Stack<const Type*>* stack,
69  ControlFlowGraph* cfg) const = 0;
70  void InvalidateTransientTypes(Stack<const Type*>* stack) const;
71  virtual bool IsBlockTerminator() const { return false; }
72  virtual void AppendSuccessorBlocks(std::vector<Block*>* block_list) const {}
73 
74  SourcePosition pos;
75 };
76 
77 class Instruction {
78  public:
79  template <class T>
80  Instruction(T instr) // NOLINT(runtime/explicit)
81  : kind_(T::kKind), instruction_(new T(std::move(instr))) {}
82 
83  template <class T>
84  T& Cast() {
85  DCHECK(Is<T>());
86  return static_cast<T&>(*instruction_);
87  }
88 
89  template <class T>
90  const T& Cast() const {
91  DCHECK(Is<T>());
92  return static_cast<const T&>(*instruction_);
93  }
94 
95  template <class T>
96  bool Is() const {
97  return kind_ == T::kKind;
98  }
99 
100  template <class T>
101  T* DynamicCast() {
102  if (Is<T>()) return &Cast<T>();
103  return nullptr;
104  }
105 
106  template <class T>
107  const T* DynamicCast() const {
108  if (Is<T>()) return &Cast<T>();
109  return nullptr;
110  }
111 
112  Instruction(const Instruction& other)
113  : kind_(other.kind_), instruction_(other.instruction_->Clone()) {}
114  Instruction& operator=(const Instruction& other) {
115  if (kind_ == other.kind_) {
116  instruction_->Assign(*other.instruction_);
117  } else {
118  kind_ = other.kind_;
119  instruction_ = other.instruction_->Clone();
120  }
121  return *this;
122  }
123 
124  InstructionKind kind() const { return kind_; }
125  void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
126  return instruction_->TypeInstruction(stack, cfg);
127  }
128 
129  InstructionBase* operator->() { return instruction_.get(); }
130  const InstructionBase* operator->() const { return instruction_.get(); }
131 
132  private:
133  InstructionKind kind_;
134  std::unique_ptr<InstructionBase> instruction_;
135 };
136 
138  TORQUE_INSTRUCTION_BOILERPLATE()
139 
141  : slot(slot), widened_type(widened_type) {}
142 
143  BottomOffset slot;
144  base::Optional<const Type*> widened_type;
145 };
146 
148  TORQUE_INSTRUCTION_BOILERPLATE()
149 
151  : slot(slot), widened_type(widened_type) {}
152 
153  BottomOffset slot;
154  base::Optional<const Type*> widened_type;
155 };
156 
157 // Preserve the top {preserved_slots} number of slots, and delete
158 // {deleted_slots} number or slots below.
160  TORQUE_INSTRUCTION_BOILERPLATE()
161  explicit DeleteRangeInstruction(StackRange range) : range(range) {}
162 
163  StackRange range;
164 };
165 
167  TORQUE_INSTRUCTION_BOILERPLATE()
168  explicit PushUninitializedInstruction(const Type* type) : type(type) {}
169 
170  const Type* type;
171 };
172 
174  TORQUE_INSTRUCTION_BOILERPLATE()
175  PushCodePointerInstruction(std::string external_name, const Type* type)
176  : external_name(std::move(external_name)), type(type) {
177  DCHECK(type->IsFunctionPointerType());
178  }
179 
180  std::string external_name;
181  const Type* type;
182 };
183 
185  TORQUE_INSTRUCTION_BOILERPLATE()
187  : constant(constant) {}
188 
189  NamespaceConstant* constant;
190 };
191 
193  TORQUE_INSTRUCTION_BOILERPLATE()
195  std::vector<std::string> constexpr_arguments)
196  : intrinsic(intrinsic), constexpr_arguments(constexpr_arguments) {}
197 
198  Intrinsic* intrinsic;
199  std::vector<std::string> constexpr_arguments;
200 };
201 
203  TORQUE_INSTRUCTION_BOILERPLATE()
205  std::vector<std::string> constexpr_arguments,
206  base::Optional<Block*> catch_block)
207  : macro(macro),
208  constexpr_arguments(constexpr_arguments),
209  catch_block(catch_block) {}
210  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
211  if (catch_block) block_list->push_back(*catch_block);
212  }
213 
214  Macro* macro;
215  std::vector<std::string> constexpr_arguments;
216  base::Optional<Block*> catch_block;
217 };
218 
220  TORQUE_INSTRUCTION_BOILERPLATE()
222  std::vector<std::string> constexpr_arguments,
223  base::Optional<Block*> return_continuation,
224  std::vector<Block*> label_blocks,
225  base::Optional<Block*> catch_block)
226  : macro(macro),
227  constexpr_arguments(constexpr_arguments),
228  return_continuation(return_continuation),
229  label_blocks(label_blocks),
230  catch_block(catch_block) {}
231  bool IsBlockTerminator() const override { return true; }
232  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
233  if (catch_block) block_list->push_back(*catch_block);
234  if (return_continuation) block_list->push_back(*return_continuation);
235  for (Block* block : label_blocks) block_list->push_back(block);
236  }
237 
238  Macro* macro;
239  std::vector<std::string> constexpr_arguments;
240  base::Optional<Block*> return_continuation;
241  std::vector<Block*> label_blocks;
242  base::Optional<Block*> catch_block;
243 };
244 
246  TORQUE_INSTRUCTION_BOILERPLATE()
247  bool IsBlockTerminator() const override { return is_tailcall; }
248  CallBuiltinInstruction(bool is_tailcall, Builtin* builtin, size_t argc,
249  base::Optional<Block*> catch_block)
250  : is_tailcall(is_tailcall),
251  builtin(builtin),
252  argc(argc),
253  catch_block(catch_block) {}
254  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
255  if (catch_block) block_list->push_back(*catch_block);
256  }
257 
258  bool is_tailcall;
259  Builtin* builtin;
260  size_t argc;
261  base::Optional<Block*> catch_block;
262 };
263 
265  TORQUE_INSTRUCTION_BOILERPLATE()
266  bool IsBlockTerminator() const override { return is_tailcall; }
267  CallBuiltinPointerInstruction(bool is_tailcall,
268  const FunctionPointerType* type, size_t argc)
269  : is_tailcall(is_tailcall), type(type), argc(argc) {}
270 
271  bool is_tailcall;
272  const FunctionPointerType* type;
273  size_t argc;
274 };
275 
277  TORQUE_INSTRUCTION_BOILERPLATE()
278  bool IsBlockTerminator() const override;
279 
280  CallRuntimeInstruction(bool is_tailcall, RuntimeFunction* runtime_function,
281  size_t argc, base::Optional<Block*> catch_block)
282  : is_tailcall(is_tailcall),
283  runtime_function(runtime_function),
284  argc(argc),
285  catch_block(catch_block) {}
286  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
287  if (catch_block) block_list->push_back(*catch_block);
288  }
289 
290  bool is_tailcall;
291  RuntimeFunction* runtime_function;
292  size_t argc;
293  base::Optional<Block*> catch_block;
294 };
295 
297  TORQUE_INSTRUCTION_BOILERPLATE()
298  bool IsBlockTerminator() const override { return true; }
299  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
300  block_list->push_back(if_true);
301  block_list->push_back(if_false);
302  }
303 
304  BranchInstruction(Block* if_true, Block* if_false)
305  : if_true(if_true), if_false(if_false) {}
306 
307  Block* if_true;
308  Block* if_false;
309 };
310 
312  TORQUE_INSTRUCTION_BOILERPLATE()
313  bool IsBlockTerminator() const override { return true; }
314  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
315  block_list->push_back(if_true);
316  block_list->push_back(if_false);
317  }
318 
319  ConstexprBranchInstruction(std::string condition, Block* if_true,
320  Block* if_false)
321  : condition(condition), if_true(if_true), if_false(if_false) {}
322 
323  std::string condition;
324  Block* if_true;
325  Block* if_false;
326 };
327 
329  TORQUE_INSTRUCTION_BOILERPLATE()
330  bool IsBlockTerminator() const override { return true; }
331  void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
332  block_list->push_back(destination);
333  }
334 
335  explicit GotoInstruction(Block* destination) : destination(destination) {}
336 
337  Block* destination;
338 };
339 
341  TORQUE_INSTRUCTION_BOILERPLATE()
342  bool IsBlockTerminator() const override { return true; }
343 
344  GotoExternalInstruction(std::string destination,
345  std::vector<std::string> variable_names)
346  : destination(std::move(destination)),
347  variable_names(std::move(variable_names)) {}
348 
349  std::string destination;
350  std::vector<std::string> variable_names;
351 };
352 
354  TORQUE_INSTRUCTION_BOILERPLATE()
355  bool IsBlockTerminator() const override { return true; }
356 };
357 
359  TORQUE_INSTRUCTION_BOILERPLATE()
360  explicit PrintConstantStringInstruction(std::string message) {
361  // The normal way to write this triggers a bug in Clang on Windows.
362  this->message = std::move(message);
363  }
364 
365  std::string message;
366 };
367 
369  TORQUE_INSTRUCTION_BOILERPLATE()
370  enum class Kind { kDebugBreak, kUnreachable, kAssertionFailure };
371  bool IsBlockTerminator() const override { return kind != Kind::kDebugBreak; }
372  explicit AbortInstruction(Kind kind, std::string message = "") : kind(kind) {
373  // The normal way to write this triggers a bug in Clang on Windows.
374  this->message = std::move(message);
375  }
376 
377  Kind kind;
378  std::string message;
379 };
380 
382  TORQUE_INSTRUCTION_BOILERPLATE()
383  explicit UnsafeCastInstruction(const Type* destination_type)
384  : destination_type(destination_type) {}
385 
386  const Type* destination_type;
387 };
388 
389 } // namespace torque
390 } // namespace internal
391 } // namespace v8
392 
393 #endif // V8_TORQUE_INSTRUCTIONS_H_
Definition: libplatform.h:13