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 #include "src/torque/instructions.h"
6 #include "src/torque/cfg.h"
7 #include "src/torque/type-oracle.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace torque {
12
13 #define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name) \
14 const InstructionKind Name::kKind = InstructionKind::k##Name; \
15 std::unique_ptr<InstructionBase> Name::Clone() const { \
16 return std::unique_ptr<InstructionBase>(new Name(*this)); \
17 } \
18 void Name::Assign(const InstructionBase& other) { \
19 *this = static_cast<const Name&>(other); \
20 }
21 TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS)
22 #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS
23
24 namespace {
ExpectType(const Type * expected,const Type * actual)25 void ExpectType(const Type* expected, const Type* actual) {
26 if (expected != actual) {
27 ReportError("expected type ", *expected, " but found ", *actual);
28 }
29 }
ExpectSubtype(const Type * subtype,const Type * supertype)30 void ExpectSubtype(const Type* subtype, const Type* supertype) {
31 if (!subtype->IsSubtypeOf(supertype)) {
32 ReportError("type ", *subtype, " is not a subtype of ", *supertype);
33 }
34 }
35 } // namespace
36
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const37 void PeekInstruction::TypeInstruction(Stack<const Type*>* stack,
38 ControlFlowGraph* cfg) const {
39 const Type* type = stack->Peek(slot);
40 if (widened_type) {
41 if (type->IsTopType()) {
42 const TopType* top_type = TopType::cast(type);
43 ReportError("use of " + top_type->reason());
44 }
45 ExpectSubtype(type, *widened_type);
46 type = *widened_type;
47 }
48 stack->Push(type);
49 }
50
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const51 void PeekInstruction::RecomputeDefinitionLocations(
52 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
53 locations->Push(locations->Peek(slot));
54 }
55
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const56 void PokeInstruction::TypeInstruction(Stack<const Type*>* stack,
57 ControlFlowGraph* cfg) const {
58 const Type* type = stack->Top();
59 if (widened_type) {
60 ExpectSubtype(type, *widened_type);
61 type = *widened_type;
62 }
63 stack->Poke(slot, type);
64 stack->Pop();
65 }
66
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const67 void PokeInstruction::RecomputeDefinitionLocations(
68 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
69 locations->Poke(slot, locations->Pop());
70 }
71
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const72 void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack,
73 ControlFlowGraph* cfg) const {
74 stack->DeleteRange(range);
75 }
76
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const77 void DeleteRangeInstruction::RecomputeDefinitionLocations(
78 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
79 locations->DeleteRange(range);
80 }
81
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const82 void PushUninitializedInstruction::TypeInstruction(
83 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
84 stack->Push(type);
85 }
86
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const87 void PushUninitializedInstruction::RecomputeDefinitionLocations(
88 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
89 locations->Push(GetValueDefinition());
90 }
91
GetValueDefinition() const92 DefinitionLocation PushUninitializedInstruction::GetValueDefinition() const {
93 return DefinitionLocation::Instruction(this, 0);
94 }
95
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const96 void PushBuiltinPointerInstruction::TypeInstruction(
97 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
98 stack->Push(type);
99 }
100
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const101 void PushBuiltinPointerInstruction::RecomputeDefinitionLocations(
102 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
103 locations->Push(GetValueDefinition());
104 }
105
GetValueDefinition() const106 DefinitionLocation PushBuiltinPointerInstruction::GetValueDefinition() const {
107 return DefinitionLocation::Instruction(this, 0);
108 }
109
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const110 void NamespaceConstantInstruction::TypeInstruction(
111 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
112 stack->PushMany(LowerType(constant->type()));
113 }
114
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const115 void NamespaceConstantInstruction::RecomputeDefinitionLocations(
116 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
117 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) {
118 locations->Push(GetValueDefinition(i));
119 }
120 }
121
GetValueDefinitionCount() const122 std::size_t NamespaceConstantInstruction::GetValueDefinitionCount() const {
123 return LowerType(constant->type()).size();
124 }
125
GetValueDefinition(std::size_t index) const126 DefinitionLocation NamespaceConstantInstruction::GetValueDefinition(
127 std::size_t index) const {
128 DCHECK_LT(index, GetValueDefinitionCount());
129 return DefinitionLocation::Instruction(this, index);
130 }
131
InvalidateTransientTypes(Stack<const Type * > * stack) const132 void InstructionBase::InvalidateTransientTypes(
133 Stack<const Type*>* stack) const {
134 auto current = stack->begin();
135 while (current != stack->end()) {
136 if ((*current)->IsTransient()) {
137 std::stringstream stream;
138 stream << "type " << **current
139 << " is made invalid by transitioning callable invocation at "
140 << PositionAsString(pos);
141 *current = TypeOracle::GetTopType(stream.str(), *current);
142 }
143 ++current;
144 }
145 }
146
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const147 void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack,
148 ControlFlowGraph* cfg) const {
149 std::vector<const Type*> parameter_types =
150 LowerParameterTypes(intrinsic->signature().parameter_types);
151 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
152 const Type* arg_type = stack->Pop();
153 const Type* parameter_type = parameter_types.back();
154 parameter_types.pop_back();
155 if (arg_type != parameter_type) {
156 ReportError("parameter ", i, ": expected type ", *parameter_type,
157 " but found type ", *arg_type);
158 }
159 }
160 if (intrinsic->IsTransitioning()) {
161 InvalidateTransientTypes(stack);
162 }
163 stack->PushMany(LowerType(intrinsic->signature().return_type));
164 }
165
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const166 void CallIntrinsicInstruction::RecomputeDefinitionLocations(
167 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
168 auto parameter_types =
169 LowerParameterTypes(intrinsic->signature().parameter_types);
170 locations->PopMany(parameter_types.size());
171 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) {
172 locations->Push(DefinitionLocation::Instruction(this, i));
173 }
174 }
175
GetValueDefinitionCount() const176 std::size_t CallIntrinsicInstruction::GetValueDefinitionCount() const {
177 return LowerType(intrinsic->signature().return_type).size();
178 }
179
GetValueDefinition(std::size_t index) const180 DefinitionLocation CallIntrinsicInstruction::GetValueDefinition(
181 std::size_t index) const {
182 DCHECK_LT(index, GetValueDefinitionCount());
183 return DefinitionLocation::Instruction(this, index);
184 }
185
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const186 void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack,
187 ControlFlowGraph* cfg) const {
188 std::vector<const Type*> parameter_types =
189 LowerParameterTypes(macro->signature().parameter_types);
190 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
191 const Type* arg_type = stack->Pop();
192 const Type* parameter_type = parameter_types.back();
193 parameter_types.pop_back();
194 if (arg_type != parameter_type) {
195 ReportError("parameter ", i, ": expected type ", *parameter_type,
196 " but found type ", *arg_type);
197 }
198 }
199
200 if (macro->IsTransitioning()) {
201 InvalidateTransientTypes(stack);
202 }
203
204 if (catch_block) {
205 Stack<const Type*> catch_stack = *stack;
206 catch_stack.Push(TypeOracle::GetJSAnyType());
207 (*catch_block)->SetInputTypes(catch_stack);
208 }
209
210 stack->PushMany(LowerType(macro->signature().return_type));
211 }
212
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const213 void CallCsaMacroInstruction::RecomputeDefinitionLocations(
214 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
215 auto parameter_types =
216 LowerParameterTypes(macro->signature().parameter_types);
217 locations->PopMany(parameter_types.size());
218
219 if (catch_block) {
220 locations->Push(*GetExceptionObjectDefinition());
221 (*catch_block)->MergeInputDefinitions(*locations, worklist);
222 locations->Pop();
223 }
224
225 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) {
226 locations->Push(GetValueDefinition(i));
227 }
228 }
229
230 base::Optional<DefinitionLocation>
GetExceptionObjectDefinition() const231 CallCsaMacroInstruction::GetExceptionObjectDefinition() const {
232 if (!catch_block) return base::nullopt;
233 return DefinitionLocation::Instruction(this, GetValueDefinitionCount());
234 }
235
GetValueDefinitionCount() const236 std::size_t CallCsaMacroInstruction::GetValueDefinitionCount() const {
237 return LowerType(macro->signature().return_type).size();
238 }
239
GetValueDefinition(std::size_t index) const240 DefinitionLocation CallCsaMacroInstruction::GetValueDefinition(
241 std::size_t index) const {
242 DCHECK_LT(index, GetValueDefinitionCount());
243 return DefinitionLocation::Instruction(this, index);
244 }
245
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const246 void CallCsaMacroAndBranchInstruction::TypeInstruction(
247 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
248 std::vector<const Type*> parameter_types =
249 LowerParameterTypes(macro->signature().parameter_types);
250 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) {
251 const Type* arg_type = stack->Pop();
252 const Type* parameter_type = parameter_types.back();
253 parameter_types.pop_back();
254 if (arg_type != parameter_type) {
255 ReportError("parameter ", i, ": expected type ", *parameter_type,
256 " but found type ", *arg_type);
257 }
258 }
259
260 if (label_blocks.size() != macro->signature().labels.size()) {
261 ReportError("wrong number of labels");
262 }
263 for (size_t i = 0; i < label_blocks.size(); ++i) {
264 Stack<const Type*> continuation_stack = *stack;
265 continuation_stack.PushMany(
266 LowerParameterTypes(macro->signature().labels[i].types));
267 label_blocks[i]->SetInputTypes(std::move(continuation_stack));
268 }
269
270 if (macro->IsTransitioning()) {
271 InvalidateTransientTypes(stack);
272 }
273
274 if (catch_block) {
275 Stack<const Type*> catch_stack = *stack;
276 catch_stack.Push(TypeOracle::GetJSAnyType());
277 (*catch_block)->SetInputTypes(catch_stack);
278 }
279
280 if (macro->signature().return_type != TypeOracle::GetNeverType()) {
281 Stack<const Type*> return_stack = *stack;
282 return_stack.PushMany(LowerType(macro->signature().return_type));
283 if (return_continuation == base::nullopt) {
284 ReportError("missing return continuation.");
285 }
286 (*return_continuation)->SetInputTypes(return_stack);
287 } else {
288 if (return_continuation != base::nullopt) {
289 ReportError("unreachable return continuation.");
290 }
291 }
292 }
293
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const294 void CallCsaMacroAndBranchInstruction::RecomputeDefinitionLocations(
295 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
296 auto parameter_types =
297 LowerParameterTypes(macro->signature().parameter_types);
298 locations->PopMany(parameter_types.size());
299
300 for (std::size_t label_index = 0; label_index < label_blocks.size();
301 ++label_index) {
302 const std::size_t count = GetLabelValueDefinitionCount(label_index);
303 for (std::size_t i = 0; i < count; ++i) {
304 locations->Push(GetLabelValueDefinition(label_index, i));
305 }
306 label_blocks[label_index]->MergeInputDefinitions(*locations, worklist);
307 locations->PopMany(count);
308 }
309
310 if (catch_block) {
311 locations->Push(*GetExceptionObjectDefinition());
312 (*catch_block)->MergeInputDefinitions(*locations, worklist);
313 locations->Pop();
314 }
315
316 if (macro->signature().return_type != TypeOracle::GetNeverType()) {
317 if (return_continuation) {
318 const std::size_t count = GetValueDefinitionCount();
319 for (std::size_t i = 0; i < count; ++i) {
320 locations->Push(GetValueDefinition(i));
321 }
322 (*return_continuation)->MergeInputDefinitions(*locations, worklist);
323 locations->PopMany(count);
324 }
325 }
326 }
327
GetLabelCount() const328 std::size_t CallCsaMacroAndBranchInstruction::GetLabelCount() const {
329 return label_blocks.size();
330 }
331
GetLabelValueDefinitionCount(std::size_t label) const332 std::size_t CallCsaMacroAndBranchInstruction::GetLabelValueDefinitionCount(
333 std::size_t label) const {
334 DCHECK_LT(label, GetLabelCount());
335 return LowerParameterTypes(macro->signature().labels[label].types).size();
336 }
337
GetLabelValueDefinition(std::size_t label,std::size_t index) const338 DefinitionLocation CallCsaMacroAndBranchInstruction::GetLabelValueDefinition(
339 std::size_t label, std::size_t index) const {
340 DCHECK_LT(index, GetLabelValueDefinitionCount(label));
341 std::size_t offset = GetValueDefinitionCount() + (catch_block ? 1 : 0);
342 for (std::size_t label_index = 0; label_index < label; ++label_index) {
343 offset += GetLabelValueDefinitionCount(label_index);
344 }
345 return DefinitionLocation::Instruction(this, offset + index);
346 }
347
GetValueDefinitionCount() const348 std::size_t CallCsaMacroAndBranchInstruction::GetValueDefinitionCount() const {
349 if (macro->signature().return_type == TypeOracle::GetNeverType()) return 0;
350 if (!return_continuation) return 0;
351 return LowerType(macro->signature().return_type).size();
352 }
353
GetValueDefinition(std::size_t index) const354 DefinitionLocation CallCsaMacroAndBranchInstruction::GetValueDefinition(
355 std::size_t index) const {
356 DCHECK_LT(index, GetValueDefinitionCount());
357 return DefinitionLocation::Instruction(this, index);
358 }
359
360 base::Optional<DefinitionLocation>
GetExceptionObjectDefinition() const361 CallCsaMacroAndBranchInstruction::GetExceptionObjectDefinition() const {
362 if (!catch_block) return base::nullopt;
363 return DefinitionLocation::Instruction(this, GetValueDefinitionCount());
364 }
365
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const366 void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack,
367 ControlFlowGraph* cfg) const {
368 std::vector<const Type*> argument_types = stack->PopMany(argc);
369 if (argument_types !=
370 LowerParameterTypes(builtin->signature().parameter_types)) {
371 ReportError("wrong argument types");
372 }
373 if (builtin->IsTransitioning()) {
374 InvalidateTransientTypes(stack);
375 }
376
377 if (catch_block) {
378 Stack<const Type*> catch_stack = *stack;
379 catch_stack.Push(TypeOracle::GetJSAnyType());
380 (*catch_block)->SetInputTypes(catch_stack);
381 }
382
383 stack->PushMany(LowerType(builtin->signature().return_type));
384 }
385
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const386 void CallBuiltinInstruction::RecomputeDefinitionLocations(
387 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
388 locations->PopMany(argc);
389
390 if (catch_block) {
391 locations->Push(*GetExceptionObjectDefinition());
392 (*catch_block)->MergeInputDefinitions(*locations, worklist);
393 locations->Pop();
394 }
395
396 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) {
397 locations->Push(GetValueDefinition(i));
398 }
399 }
400
GetValueDefinitionCount() const401 std::size_t CallBuiltinInstruction::GetValueDefinitionCount() const {
402 return LowerType(builtin->signature().return_type).size();
403 }
404
GetValueDefinition(std::size_t index) const405 DefinitionLocation CallBuiltinInstruction::GetValueDefinition(
406 std::size_t index) const {
407 DCHECK_LT(index, GetValueDefinitionCount());
408 return DefinitionLocation::Instruction(this, index);
409 }
410
411 base::Optional<DefinitionLocation>
GetExceptionObjectDefinition() const412 CallBuiltinInstruction::GetExceptionObjectDefinition() const {
413 if (!catch_block) return base::nullopt;
414 return DefinitionLocation::Instruction(this, GetValueDefinitionCount());
415 }
416
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const417 void CallBuiltinPointerInstruction::TypeInstruction(
418 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
419 std::vector<const Type*> argument_types = stack->PopMany(argc);
420 const BuiltinPointerType* f = BuiltinPointerType::DynamicCast(stack->Pop());
421 if (!f) ReportError("expected function pointer type");
422 if (argument_types != LowerParameterTypes(f->parameter_types())) {
423 ReportError("wrong argument types");
424 }
425 DCHECK_EQ(type, f);
426 // TODO(tebbi): Only invalidate transient types if the function pointer type
427 // is transitioning.
428 InvalidateTransientTypes(stack);
429 stack->PushMany(LowerType(f->return_type()));
430 }
431
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const432 void CallBuiltinPointerInstruction::RecomputeDefinitionLocations(
433 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
434 locations->PopMany(argc + 1);
435 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) {
436 locations->Push(GetValueDefinition(i));
437 }
438 }
439
GetValueDefinitionCount() const440 std::size_t CallBuiltinPointerInstruction::GetValueDefinitionCount() const {
441 return LowerType(type->return_type()).size();
442 }
443
GetValueDefinition(std::size_t index) const444 DefinitionLocation CallBuiltinPointerInstruction::GetValueDefinition(
445 std::size_t index) const {
446 DCHECK_LT(index, GetValueDefinitionCount());
447 return DefinitionLocation::Instruction(this, index);
448 }
449
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const450 void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack,
451 ControlFlowGraph* cfg) const {
452 std::vector<const Type*> argument_types = stack->PopMany(argc);
453 if (argument_types !=
454 LowerParameterTypes(runtime_function->signature().parameter_types,
455 argc)) {
456 ReportError("wrong argument types");
457 }
458 if (runtime_function->IsTransitioning()) {
459 InvalidateTransientTypes(stack);
460 }
461
462 if (catch_block) {
463 Stack<const Type*> catch_stack = *stack;
464 catch_stack.Push(TypeOracle::GetJSAnyType());
465 (*catch_block)->SetInputTypes(catch_stack);
466 }
467
468 const Type* return_type = runtime_function->signature().return_type;
469 if (return_type != TypeOracle::GetNeverType()) {
470 stack->PushMany(LowerType(return_type));
471 }
472 }
473
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const474 void CallRuntimeInstruction::RecomputeDefinitionLocations(
475 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
476 locations->PopMany(argc);
477
478 if (catch_block) {
479 locations->Push(*GetExceptionObjectDefinition());
480 (*catch_block)->MergeInputDefinitions(*locations, worklist);
481 locations->Pop();
482 }
483
484 const Type* return_type = runtime_function->signature().return_type;
485 if (return_type != TypeOracle::GetNeverType()) {
486 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) {
487 locations->Push(GetValueDefinition(i));
488 }
489 }
490 }
491
GetValueDefinitionCount() const492 std::size_t CallRuntimeInstruction::GetValueDefinitionCount() const {
493 const Type* return_type = runtime_function->signature().return_type;
494 if (return_type == TypeOracle::GetNeverType()) return 0;
495 return LowerType(return_type).size();
496 }
497
GetValueDefinition(std::size_t index) const498 DefinitionLocation CallRuntimeInstruction::GetValueDefinition(
499 std::size_t index) const {
500 DCHECK_LT(index, GetValueDefinitionCount());
501 return DefinitionLocation::Instruction(this, index);
502 }
503
504 base::Optional<DefinitionLocation>
GetExceptionObjectDefinition() const505 CallRuntimeInstruction::GetExceptionObjectDefinition() const {
506 if (!catch_block) return base::nullopt;
507 return DefinitionLocation::Instruction(this, GetValueDefinitionCount());
508 }
509
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const510 void BranchInstruction::TypeInstruction(Stack<const Type*>* stack,
511 ControlFlowGraph* cfg) const {
512 const Type* condition_type = stack->Pop();
513 if (condition_type != TypeOracle::GetBoolType()) {
514 ReportError("condition has to have type bool");
515 }
516 if_true->SetInputTypes(*stack);
517 if_false->SetInputTypes(*stack);
518 }
519
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const520 void BranchInstruction::RecomputeDefinitionLocations(
521 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
522 locations->Pop();
523 if_true->MergeInputDefinitions(*locations, worklist);
524 if_false->MergeInputDefinitions(*locations, worklist);
525 }
526
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const527 void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack,
528 ControlFlowGraph* cfg) const {
529 if_true->SetInputTypes(*stack);
530 if_false->SetInputTypes(*stack);
531 }
532
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const533 void ConstexprBranchInstruction::RecomputeDefinitionLocations(
534 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
535 if_true->MergeInputDefinitions(*locations, worklist);
536 if_false->MergeInputDefinitions(*locations, worklist);
537 }
538
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const539 void GotoInstruction::TypeInstruction(Stack<const Type*>* stack,
540 ControlFlowGraph* cfg) const {
541 destination->SetInputTypes(*stack);
542 }
543
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const544 void GotoInstruction::RecomputeDefinitionLocations(
545 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
546 destination->MergeInputDefinitions(*locations, worklist);
547 }
548
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const549 void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack,
550 ControlFlowGraph* cfg) const {
551 if (variable_names.size() != stack->Size()) {
552 ReportError("goto external label with wrong parameter count.");
553 }
554 }
555
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const556 void GotoExternalInstruction::RecomputeDefinitionLocations(
557 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {}
558
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const559 void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack,
560 ControlFlowGraph* cfg) const {
561 cfg->SetReturnType(stack->Pop());
562 }
563
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const564 void ReturnInstruction::RecomputeDefinitionLocations(
565 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
566 locations->Pop();
567 }
568
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const569 void PrintConstantStringInstruction::TypeInstruction(
570 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {}
571
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const572 void PrintConstantStringInstruction::RecomputeDefinitionLocations(
573 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {}
574
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const575 void AbortInstruction::TypeInstruction(Stack<const Type*>* stack,
576 ControlFlowGraph* cfg) const {}
577
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const578 void AbortInstruction::RecomputeDefinitionLocations(
579 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {}
580
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const581 void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
582 ControlFlowGraph* cfg) const {
583 stack->Poke(stack->AboveTop() - 1, destination_type);
584 }
585
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const586 void UnsafeCastInstruction::RecomputeDefinitionLocations(
587 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
588 locations->Poke(locations->AboveTop() - 1, GetValueDefinition());
589 }
590
GetValueDefinition() const591 DefinitionLocation UnsafeCastInstruction::GetValueDefinition() const {
592 return DefinitionLocation::Instruction(this, 0);
593 }
594
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const595 void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
596 ControlFlowGraph* cfg) const {
597 ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
598 ExpectSubtype(stack->Pop(), TypeOracle::GetHeapObjectType());
599 DCHECK_EQ(std::vector<const Type*>{type}, LowerType(type));
600 stack->Push(type);
601 }
602
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const603 void LoadReferenceInstruction::RecomputeDefinitionLocations(
604 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
605 locations->Pop();
606 locations->Pop();
607 locations->Push(GetValueDefinition());
608 }
609
GetValueDefinition() const610 DefinitionLocation LoadReferenceInstruction::GetValueDefinition() const {
611 return DefinitionLocation::Instruction(this, 0);
612 }
613
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const614 void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
615 ControlFlowGraph* cfg) const {
616 ExpectSubtype(stack->Pop(), type);
617 ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
618 ExpectSubtype(stack->Pop(), TypeOracle::GetHeapObjectType());
619 }
620
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const621 void StoreReferenceInstruction::RecomputeDefinitionLocations(
622 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
623 locations->Pop();
624 locations->Pop();
625 locations->Pop();
626 }
627
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const628 void LoadBitFieldInstruction::TypeInstruction(Stack<const Type*>* stack,
629 ControlFlowGraph* cfg) const {
630 ExpectType(bit_field_struct_type, stack->Pop());
631 stack->Push(bit_field.name_and_type.type);
632 }
633
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const634 void LoadBitFieldInstruction::RecomputeDefinitionLocations(
635 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
636 locations->Pop();
637 locations->Push(GetValueDefinition());
638 }
639
GetValueDefinition() const640 DefinitionLocation LoadBitFieldInstruction::GetValueDefinition() const {
641 return DefinitionLocation::Instruction(this, 0);
642 }
643
TypeInstruction(Stack<const Type * > * stack,ControlFlowGraph * cfg) const644 void StoreBitFieldInstruction::TypeInstruction(Stack<const Type*>* stack,
645 ControlFlowGraph* cfg) const {
646 ExpectSubtype(bit_field.name_and_type.type, stack->Pop());
647 ExpectType(bit_field_struct_type, stack->Pop());
648 stack->Push(bit_field_struct_type);
649 }
650
RecomputeDefinitionLocations(Stack<DefinitionLocation> * locations,Worklist<Block * > * worklist) const651 void StoreBitFieldInstruction::RecomputeDefinitionLocations(
652 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {
653 locations->Pop();
654 locations->Pop();
655 locations->Push(GetValueDefinition());
656 }
657
GetValueDefinition() const658 DefinitionLocation StoreBitFieldInstruction::GetValueDefinition() const {
659 return DefinitionLocation::Instruction(this, 0);
660 }
661
IsBlockTerminator() const662 bool CallRuntimeInstruction::IsBlockTerminator() const {
663 return is_tailcall || runtime_function->signature().return_type ==
664 TypeOracle::GetNeverType();
665 }
666
667 } // namespace torque
668 } // namespace internal
669 } // namespace v8
670