Line data Source code
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(PushBuiltinPointerInstruction) \
33 : V(LoadObjectFieldInstruction) \
34 : V(StoreObjectFieldInstruction) \
35 : V(CallCsaMacroInstruction) \
36 : V(CallIntrinsicInstruction) \
37 : V(NamespaceConstantInstruction) \
38 : V(CallCsaMacroAndBranchInstruction) \
39 : V(CallBuiltinInstruction) \
40 : V(CallRuntimeInstruction) \
41 : V(CallBuiltinPointerInstruction) \
42 : V(BranchInstruction) \
43 : V(ConstexprBranchInstruction) \
44 : V(GotoInstruction) \
45 : V(GotoExternalInstruction) \
46 : V(ReturnInstruction) \
47 : V(PrintConstantStringInstruction) \
48 : V(AbortInstruction) \
49 : V(UnsafeCastInstruction)
50 :
51 : #define TORQUE_INSTRUCTION_BOILERPLATE() \
52 : static const InstructionKind kKind; \
53 : std::unique_ptr<InstructionBase> Clone() const override; \
54 : void Assign(const InstructionBase& other) override; \
55 : void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) \
56 : const override;
57 :
58 : enum class InstructionKind {
59 : #define ENUM_ITEM(name) k##name,
60 : TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
61 : #undef ENUM_ITEM
62 : };
63 :
64 159505 : struct InstructionBase {
65 78640 : InstructionBase() : pos(CurrentSourcePosition::Get()) {}
66 : virtual std::unique_ptr<InstructionBase> Clone() const = 0;
67 : virtual void Assign(const InstructionBase& other) = 0;
68 198825 : virtual ~InstructionBase() = default;
69 :
70 : virtual void TypeInstruction(Stack<const Type*>* stack,
71 : ControlFlowGraph* cfg) const = 0;
72 : void InvalidateTransientTypes(Stack<const Type*>* stack) const;
73 3626 : virtual bool IsBlockTerminator() const { return false; }
74 0 : virtual void AppendSuccessorBlocks(std::vector<Block*>* block_list) const {}
75 :
76 : SourcePosition pos;
77 : };
78 :
79 159505 : class Instruction {
80 : public:
81 : template <class T>
82 38152 : Instruction(T instr) // NOLINT(runtime/explicit)
83 76304 : : kind_(T::kKind), instruction_(new T(std::move(instr))) {}
84 :
85 : template <class T>
86 : T& Cast() {
87 : DCHECK(Is<T>());
88 : return static_cast<T&>(*instruction_);
89 : }
90 :
91 : template <class T>
92 : const T& Cast() const {
93 : DCHECK(Is<T>());
94 : return static_cast<const T&>(*instruction_);
95 : }
96 :
97 : template <class T>
98 : bool Is() const {
99 : return kind_ == T::kKind;
100 : }
101 :
102 : template <class T>
103 : T* DynamicCast() {
104 : if (Is<T>()) return &Cast<T>();
105 : return nullptr;
106 : }
107 :
108 : template <class T>
109 : const T* DynamicCast() const {
110 : if (Is<T>()) return &Cast<T>();
111 : return nullptr;
112 : }
113 :
114 : Instruction(const Instruction& other) V8_NOEXCEPT
115 121353 : : kind_(other.kind_),
116 242706 : instruction_(other.instruction_->Clone()) {}
117 : Instruction& operator=(const Instruction& other) V8_NOEXCEPT {
118 : if (kind_ == other.kind_) {
119 : instruction_->Assign(*other.instruction_);
120 : } else {
121 : kind_ = other.kind_;
122 : instruction_ = other.instruction_->Clone();
123 : }
124 : return *this;
125 : }
126 :
127 : InstructionKind kind() const { return kind_; }
128 : const char* Mnemonic() const {
129 : switch (kind()) {
130 : #define ENUM_ITEM(name) \
131 : case InstructionKind::k##name: \
132 : return #name;
133 : TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
134 : #undef ENUM_ITEM
135 : default:
136 : UNREACHABLE();
137 : }
138 : }
139 : void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
140 39810 : return instruction_->TypeInstruction(stack, cfg);
141 : }
142 :
143 : InstructionBase* operator->() { return instruction_.get(); }
144 : const InstructionBase* operator->() const { return instruction_.get(); }
145 :
146 : private:
147 : InstructionKind kind_;
148 : std::unique_ptr<InstructionBase> instruction_;
149 : };
150 :
151 268571 : struct PeekInstruction : InstructionBase {
152 : TORQUE_INSTRUCTION_BOILERPLATE()
153 :
154 : PeekInstruction(BottomOffset slot, base::Optional<const Type*> widened_type)
155 16807 : : slot(slot), widened_type(widened_type) {}
156 :
157 : BottomOffset slot;
158 : base::Optional<const Type*> widened_type;
159 : };
160 :
161 7981 : struct PokeInstruction : InstructionBase {
162 : TORQUE_INSTRUCTION_BOILERPLATE()
163 :
164 : PokeInstruction(BottomOffset slot, base::Optional<const Type*> widened_type)
165 584 : : slot(slot), widened_type(widened_type) {}
166 :
167 : BottomOffset slot;
168 : base::Optional<const Type*> widened_type;
169 : };
170 :
171 : // Preserve the top {preserved_slots} number of slots, and delete
172 : // {deleted_slots} number or slots below.
173 111503 : struct DeleteRangeInstruction : InstructionBase {
174 : TORQUE_INSTRUCTION_BOILERPLATE()
175 8556 : explicit DeleteRangeInstruction(StackRange range) : range(range) {}
176 :
177 : StackRange range;
178 : };
179 :
180 1408 : struct PushUninitializedInstruction : InstructionBase {
181 : TORQUE_INSTRUCTION_BOILERPLATE()
182 89 : explicit PushUninitializedInstruction(const Type* type) : type(type) {}
183 :
184 : const Type* type;
185 : };
186 :
187 2199 : struct PushBuiltinPointerInstruction : InstructionBase {
188 : TORQUE_INSTRUCTION_BOILERPLATE()
189 74 : PushBuiltinPointerInstruction(std::string external_name, const Type* type)
190 148 : : external_name(std::move(external_name)), type(type) {
191 : DCHECK(type->IsBuiltinPointerType());
192 74 : }
193 :
194 : std::string external_name;
195 : const Type* type;
196 : };
197 :
198 6230 : struct NamespaceConstantInstruction : InstructionBase {
199 : TORQUE_INSTRUCTION_BOILERPLATE()
200 : explicit NamespaceConstantInstruction(NamespaceConstant* constant)
201 349 : : constant(constant) {}
202 :
203 : NamespaceConstant* constant;
204 : };
205 :
206 6150 : struct LoadObjectFieldInstruction : InstructionBase {
207 : TORQUE_INSTRUCTION_BOILERPLATE()
208 246 : LoadObjectFieldInstruction(const ClassType* class_type,
209 : std::string field_name)
210 492 : : class_type(class_type), field_name(std::move(field_name)) {}
211 : const ClassType* class_type;
212 : std::string field_name;
213 : };
214 :
215 5540 : struct StoreObjectFieldInstruction : InstructionBase {
216 : TORQUE_INSTRUCTION_BOILERPLATE()
217 280 : StoreObjectFieldInstruction(const ClassType* class_type,
218 : std::string field_name)
219 560 : : class_type(class_type), field_name(std::move(field_name)) {}
220 : const ClassType* class_type;
221 : std::string field_name;
222 : };
223 :
224 2201 : struct CallIntrinsicInstruction : InstructionBase {
225 : TORQUE_INSTRUCTION_BOILERPLATE()
226 92 : CallIntrinsicInstruction(Intrinsic* intrinsic,
227 : TypeVector specialization_types,
228 : std::vector<std::string> constexpr_arguments)
229 : : intrinsic(intrinsic),
230 : specialization_types(std::move(specialization_types)),
231 184 : constexpr_arguments(constexpr_arguments) {}
232 :
233 : Intrinsic* intrinsic;
234 : TypeVector specialization_types;
235 : std::vector<std::string> constexpr_arguments;
236 : };
237 :
238 74868 : struct CallCsaMacroInstruction : InstructionBase {
239 : TORQUE_INSTRUCTION_BOILERPLATE()
240 : CallCsaMacroInstruction(Macro* macro,
241 : std::vector<std::string> constexpr_arguments,
242 : base::Optional<Block*> catch_block)
243 : : macro(macro),
244 : constexpr_arguments(constexpr_arguments),
245 4670 : catch_block(catch_block) {}
246 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
247 0 : if (catch_block) block_list->push_back(*catch_block);
248 0 : }
249 :
250 : Macro* macro;
251 : std::vector<std::string> constexpr_arguments;
252 : base::Optional<Block*> catch_block;
253 : };
254 :
255 13386 : struct CallCsaMacroAndBranchInstruction : InstructionBase {
256 : TORQUE_INSTRUCTION_BOILERPLATE()
257 582 : CallCsaMacroAndBranchInstruction(Macro* macro,
258 : std::vector<std::string> constexpr_arguments,
259 : base::Optional<Block*> return_continuation,
260 : std::vector<Block*> label_blocks,
261 : base::Optional<Block*> catch_block)
262 : : macro(macro),
263 : constexpr_arguments(constexpr_arguments),
264 : return_continuation(return_continuation),
265 : label_blocks(label_blocks),
266 582 : catch_block(catch_block) {}
267 389 : bool IsBlockTerminator() const override { return true; }
268 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
269 0 : if (catch_block) block_list->push_back(*catch_block);
270 0 : if (return_continuation) block_list->push_back(*return_continuation);
271 0 : for (Block* block : label_blocks) block_list->push_back(block);
272 0 : }
273 :
274 : Macro* macro;
275 : std::vector<std::string> constexpr_arguments;
276 : base::Optional<Block*> return_continuation;
277 : std::vector<Block*> label_blocks;
278 : base::Optional<Block*> catch_block;
279 : };
280 :
281 1848 : struct CallBuiltinInstruction : InstructionBase {
282 : TORQUE_INSTRUCTION_BOILERPLATE()
283 9 : bool IsBlockTerminator() const override { return is_tailcall; }
284 : CallBuiltinInstruction(bool is_tailcall, Builtin* builtin, size_t argc,
285 : base::Optional<Block*> catch_block)
286 : : is_tailcall(is_tailcall),
287 : builtin(builtin),
288 : argc(argc),
289 138 : catch_block(catch_block) {}
290 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
291 0 : if (catch_block) block_list->push_back(*catch_block);
292 0 : }
293 :
294 : bool is_tailcall;
295 : Builtin* builtin;
296 : size_t argc;
297 : base::Optional<Block*> catch_block;
298 : };
299 :
300 319 : struct CallBuiltinPointerInstruction : InstructionBase {
301 : TORQUE_INSTRUCTION_BOILERPLATE()
302 0 : bool IsBlockTerminator() const override { return is_tailcall; }
303 : CallBuiltinPointerInstruction(bool is_tailcall,
304 : const BuiltinPointerType* type, size_t argc)
305 23 : : is_tailcall(is_tailcall), type(type), argc(argc) {}
306 :
307 : bool is_tailcall;
308 : const BuiltinPointerType* type;
309 : size_t argc;
310 : };
311 :
312 283 : struct CallRuntimeInstruction : InstructionBase {
313 : TORQUE_INSTRUCTION_BOILERPLATE()
314 : bool IsBlockTerminator() const override;
315 :
316 : CallRuntimeInstruction(bool is_tailcall, RuntimeFunction* runtime_function,
317 : size_t argc, base::Optional<Block*> catch_block)
318 : : is_tailcall(is_tailcall),
319 : runtime_function(runtime_function),
320 : argc(argc),
321 23 : catch_block(catch_block) {}
322 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
323 0 : if (catch_block) block_list->push_back(*catch_block);
324 0 : }
325 :
326 : bool is_tailcall;
327 : RuntimeFunction* runtime_function;
328 : size_t argc;
329 : base::Optional<Block*> catch_block;
330 : };
331 :
332 8100 : struct BranchInstruction : InstructionBase {
333 : TORQUE_INSTRUCTION_BOILERPLATE()
334 33 : bool IsBlockTerminator() const override { return true; }
335 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
336 0 : block_list->push_back(if_true);
337 0 : block_list->push_back(if_false);
338 0 : }
339 :
340 : BranchInstruction(Block* if_true, Block* if_false)
341 810 : : if_true(if_true), if_false(if_false) {}
342 :
343 : Block* if_true;
344 : Block* if_false;
345 : };
346 :
347 848 : struct ConstexprBranchInstruction : InstructionBase {
348 : TORQUE_INSTRUCTION_BOILERPLATE()
349 0 : bool IsBlockTerminator() const override { return true; }
350 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
351 0 : block_list->push_back(if_true);
352 0 : block_list->push_back(if_false);
353 0 : }
354 :
355 53 : ConstexprBranchInstruction(std::string condition, Block* if_true,
356 : Block* if_false)
357 106 : : condition(condition), if_true(if_true), if_false(if_false) {}
358 :
359 : std::string condition;
360 : Block* if_true;
361 : Block* if_false;
362 : };
363 :
364 43686 : struct GotoInstruction : InstructionBase {
365 : TORQUE_INSTRUCTION_BOILERPLATE()
366 1998 : bool IsBlockTerminator() const override { return true; }
367 0 : void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
368 0 : block_list->push_back(destination);
369 0 : }
370 :
371 5303 : explicit GotoInstruction(Block* destination) : destination(destination) {}
372 :
373 : Block* destination;
374 : };
375 :
376 2660 : struct GotoExternalInstruction : InstructionBase {
377 : TORQUE_INSTRUCTION_BOILERPLATE()
378 22 : bool IsBlockTerminator() const override { return true; }
379 :
380 133 : GotoExternalInstruction(std::string destination,
381 : std::vector<std::string> variable_names)
382 : : destination(std::move(destination)),
383 266 : variable_names(std::move(variable_names)) {}
384 :
385 : std::string destination;
386 : std::vector<std::string> variable_names;
387 : };
388 :
389 2808 : struct ReturnInstruction : InstructionBase {
390 : TORQUE_INSTRUCTION_BOILERPLATE()
391 686 : bool IsBlockTerminator() const override { return true; }
392 : };
393 :
394 0 : struct PrintConstantStringInstruction : InstructionBase {
395 : TORQUE_INSTRUCTION_BOILERPLATE()
396 0 : explicit PrintConstantStringInstruction(std::string message)
397 0 : : message(std::move(message)) {}
398 :
399 : std::string message;
400 : };
401 :
402 3510 : struct AbortInstruction : InstructionBase {
403 : TORQUE_INSTRUCTION_BOILERPLATE()
404 : enum class Kind { kDebugBreak, kUnreachable, kAssertionFailure };
405 222 : bool IsBlockTerminator() const override { return kind != Kind::kDebugBreak; }
406 234 : explicit AbortInstruction(Kind kind, std::string message = "")
407 468 : : kind(kind), message(std::move(message)) {}
408 :
409 : Kind kind;
410 : std::string message;
411 : };
412 :
413 649 : struct UnsafeCastInstruction : InstructionBase {
414 : TORQUE_INSTRUCTION_BOILERPLATE()
415 : explicit UnsafeCastInstruction(const Type* destination_type)
416 40 : : destination_type(destination_type) {}
417 :
418 : const Type* destination_type;
419 : };
420 :
421 : } // namespace torque
422 : } // namespace internal
423 : } // namespace v8
424 :
425 : #endif // V8_TORQUE_INSTRUCTIONS_H_
|