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