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 9namespace v8 { 10namespace internal { 11namespace 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 } 21TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS) 22#undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS 23 24namespace { 25void ExpectType(const Type* expected, const Type* actual) { 26 if (expected != actual) { 27 ReportError("expected type ", *expected, " but found ", *actual); 28 } 29} 30void 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 37void 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 51void PeekInstruction::RecomputeDefinitionLocations( 52 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 53 locations->Push(locations->Peek(slot)); 54} 55 56void 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 67void PokeInstruction::RecomputeDefinitionLocations( 68 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 69 locations->Poke(slot, locations->Pop()); 70} 71 72void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack, 73 ControlFlowGraph* cfg) const { 74 stack->DeleteRange(range); 75} 76 77void DeleteRangeInstruction::RecomputeDefinitionLocations( 78 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 79 locations->DeleteRange(range); 80} 81 82void PushUninitializedInstruction::TypeInstruction( 83 Stack<const Type*>* stack, ControlFlowGraph* cfg) const { 84 stack->Push(type); 85} 86 87void PushUninitializedInstruction::RecomputeDefinitionLocations( 88 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 89 locations->Push(GetValueDefinition()); 90} 91 92DefinitionLocation PushUninitializedInstruction::GetValueDefinition() const { 93 return DefinitionLocation::Instruction(this, 0); 94} 95 96void PushBuiltinPointerInstruction::TypeInstruction( 97 Stack<const Type*>* stack, ControlFlowGraph* cfg) const { 98 stack->Push(type); 99} 100 101void PushBuiltinPointerInstruction::RecomputeDefinitionLocations( 102 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 103 locations->Push(GetValueDefinition()); 104} 105 106DefinitionLocation PushBuiltinPointerInstruction::GetValueDefinition() const { 107 return DefinitionLocation::Instruction(this, 0); 108} 109 110void NamespaceConstantInstruction::TypeInstruction( 111 Stack<const Type*>* stack, ControlFlowGraph* cfg) const { 112 stack->PushMany(LowerType(constant->type())); 113} 114 115void 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 122std::size_t NamespaceConstantInstruction::GetValueDefinitionCount() const { 123 return LowerType(constant->type()).size(); 124} 125 126DefinitionLocation NamespaceConstantInstruction::GetValueDefinition( 127 std::size_t index) const { 128 DCHECK_LT(index, GetValueDefinitionCount()); 129 return DefinitionLocation::Instruction(this, index); 130} 131 132std::ostream& operator<<(std::ostream& os, 133 const NamespaceConstantInstruction& instruction) { 134 return os << "NamespaceConstant " << instruction.constant->external_name(); 135} 136 137void InstructionBase::InvalidateTransientTypes( 138 Stack<const Type*>* stack) const { 139 auto current = stack->begin(); 140 while (current != stack->end()) { 141 if ((*current)->IsTransient()) { 142 std::stringstream stream; 143 stream << "type " << **current 144 << " is made invalid by transitioning callable invocation at " 145 << PositionAsString(pos); 146 *current = TypeOracle::GetTopType(stream.str(), *current); 147 } 148 ++current; 149 } 150} 151 152void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack, 153 ControlFlowGraph* cfg) const { 154 std::vector<const Type*> parameter_types = 155 LowerParameterTypes(intrinsic->signature().parameter_types); 156 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { 157 const Type* arg_type = stack->Pop(); 158 const Type* parameter_type = parameter_types.back(); 159 parameter_types.pop_back(); 160 if (arg_type != parameter_type) { 161 ReportError("parameter ", i, ": expected type ", *parameter_type, 162 " but found type ", *arg_type); 163 } 164 } 165 if (intrinsic->IsTransitioning()) { 166 InvalidateTransientTypes(stack); 167 } 168 stack->PushMany(LowerType(intrinsic->signature().return_type)); 169} 170 171void CallIntrinsicInstruction::RecomputeDefinitionLocations( 172 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 173 auto parameter_types = 174 LowerParameterTypes(intrinsic->signature().parameter_types); 175 locations->PopMany(parameter_types.size()); 176 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { 177 locations->Push(DefinitionLocation::Instruction(this, i)); 178 } 179} 180 181std::size_t CallIntrinsicInstruction::GetValueDefinitionCount() const { 182 return LowerType(intrinsic->signature().return_type).size(); 183} 184 185DefinitionLocation CallIntrinsicInstruction::GetValueDefinition( 186 std::size_t index) const { 187 DCHECK_LT(index, GetValueDefinitionCount()); 188 return DefinitionLocation::Instruction(this, index); 189} 190 191std::ostream& operator<<(std::ostream& os, 192 const CallIntrinsicInstruction& instruction) { 193 os << "CallIntrinsic " << instruction.intrinsic->ReadableName(); 194 if (!instruction.specialization_types.empty()) { 195 os << "<"; 196 PrintCommaSeparatedList( 197 os, instruction.specialization_types, 198 [](const Type* type) -> const Type& { return *type; }); 199 os << ">"; 200 } 201 os << "("; 202 PrintCommaSeparatedList(os, instruction.constexpr_arguments); 203 os << ")"; 204 return os; 205} 206 207void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack, 208 ControlFlowGraph* cfg) const { 209 std::vector<const Type*> parameter_types = 210 LowerParameterTypes(macro->signature().parameter_types); 211 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { 212 const Type* arg_type = stack->Pop(); 213 const Type* parameter_type = parameter_types.back(); 214 parameter_types.pop_back(); 215 if (arg_type != parameter_type) { 216 ReportError("parameter ", i, ": expected type ", *parameter_type, 217 " but found type ", *arg_type); 218 } 219 } 220 221 if (macro->IsTransitioning()) { 222 InvalidateTransientTypes(stack); 223 } 224 225 if (catch_block) { 226 Stack<const Type*> catch_stack = *stack; 227 catch_stack.Push(TypeOracle::GetJSAnyType()); 228 (*catch_block)->SetInputTypes(catch_stack); 229 } 230 231 stack->PushMany(LowerType(macro->signature().return_type)); 232} 233 234void CallCsaMacroInstruction::RecomputeDefinitionLocations( 235 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 236 auto parameter_types = 237 LowerParameterTypes(macro->signature().parameter_types); 238 locations->PopMany(parameter_types.size()); 239 240 if (catch_block) { 241 locations->Push(*GetExceptionObjectDefinition()); 242 (*catch_block)->MergeInputDefinitions(*locations, worklist); 243 locations->Pop(); 244 } 245 246 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { 247 locations->Push(GetValueDefinition(i)); 248 } 249} 250 251base::Optional<DefinitionLocation> 252CallCsaMacroInstruction::GetExceptionObjectDefinition() const { 253 if (!catch_block) return base::nullopt; 254 return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); 255} 256 257std::size_t CallCsaMacroInstruction::GetValueDefinitionCount() const { 258 return LowerType(macro->signature().return_type).size(); 259} 260 261DefinitionLocation CallCsaMacroInstruction::GetValueDefinition( 262 std::size_t index) const { 263 DCHECK_LT(index, GetValueDefinitionCount()); 264 return DefinitionLocation::Instruction(this, index); 265} 266 267std::ostream& operator<<(std::ostream& os, 268 const CallCsaMacroInstruction& instruction) { 269 os << "CallCsaMacro " << instruction.macro->ReadableName(); 270 os << "("; 271 PrintCommaSeparatedList(os, instruction.constexpr_arguments); 272 os << ")"; 273 if (instruction.catch_block) { 274 os << ", catch block " << (*instruction.catch_block)->id(); 275 } 276 return os; 277} 278 279void CallCsaMacroAndBranchInstruction::TypeInstruction( 280 Stack<const Type*>* stack, ControlFlowGraph* cfg) const { 281 std::vector<const Type*> parameter_types = 282 LowerParameterTypes(macro->signature().parameter_types); 283 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { 284 const Type* arg_type = stack->Pop(); 285 const Type* parameter_type = parameter_types.back(); 286 parameter_types.pop_back(); 287 if (arg_type != parameter_type) { 288 ReportError("parameter ", i, ": expected type ", *parameter_type, 289 " but found type ", *arg_type); 290 } 291 } 292 293 if (label_blocks.size() != macro->signature().labels.size()) { 294 ReportError("wrong number of labels"); 295 } 296 for (size_t i = 0; i < label_blocks.size(); ++i) { 297 Stack<const Type*> continuation_stack = *stack; 298 continuation_stack.PushMany( 299 LowerParameterTypes(macro->signature().labels[i].types)); 300 label_blocks[i]->SetInputTypes(std::move(continuation_stack)); 301 } 302 303 if (macro->IsTransitioning()) { 304 InvalidateTransientTypes(stack); 305 } 306 307 if (catch_block) { 308 Stack<const Type*> catch_stack = *stack; 309 catch_stack.Push(TypeOracle::GetJSAnyType()); 310 (*catch_block)->SetInputTypes(catch_stack); 311 } 312 313 if (macro->signature().return_type != TypeOracle::GetNeverType()) { 314 Stack<const Type*> return_stack = *stack; 315 return_stack.PushMany(LowerType(macro->signature().return_type)); 316 if (return_continuation == base::nullopt) { 317 ReportError("missing return continuation."); 318 } 319 (*return_continuation)->SetInputTypes(return_stack); 320 } else { 321 if (return_continuation != base::nullopt) { 322 ReportError("unreachable return continuation."); 323 } 324 } 325} 326 327void CallCsaMacroAndBranchInstruction::RecomputeDefinitionLocations( 328 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 329 auto parameter_types = 330 LowerParameterTypes(macro->signature().parameter_types); 331 locations->PopMany(parameter_types.size()); 332 333 for (std::size_t label_index = 0; label_index < label_blocks.size(); 334 ++label_index) { 335 const std::size_t count = GetLabelValueDefinitionCount(label_index); 336 for (std::size_t i = 0; i < count; ++i) { 337 locations->Push(GetLabelValueDefinition(label_index, i)); 338 } 339 label_blocks[label_index]->MergeInputDefinitions(*locations, worklist); 340 locations->PopMany(count); 341 } 342 343 if (catch_block) { 344 locations->Push(*GetExceptionObjectDefinition()); 345 (*catch_block)->MergeInputDefinitions(*locations, worklist); 346 locations->Pop(); 347 } 348 349 if (macro->signature().return_type != TypeOracle::GetNeverType()) { 350 if (return_continuation) { 351 const std::size_t count = GetValueDefinitionCount(); 352 for (std::size_t i = 0; i < count; ++i) { 353 locations->Push(GetValueDefinition(i)); 354 } 355 (*return_continuation)->MergeInputDefinitions(*locations, worklist); 356 locations->PopMany(count); 357 } 358 } 359} 360 361std::size_t CallCsaMacroAndBranchInstruction::GetLabelCount() const { 362 return label_blocks.size(); 363} 364 365std::size_t CallCsaMacroAndBranchInstruction::GetLabelValueDefinitionCount( 366 std::size_t label) const { 367 DCHECK_LT(label, GetLabelCount()); 368 return LowerParameterTypes(macro->signature().labels[label].types).size(); 369} 370 371DefinitionLocation CallCsaMacroAndBranchInstruction::GetLabelValueDefinition( 372 std::size_t label, std::size_t index) const { 373 DCHECK_LT(index, GetLabelValueDefinitionCount(label)); 374 std::size_t offset = GetValueDefinitionCount() + (catch_block ? 1 : 0); 375 for (std::size_t label_index = 0; label_index < label; ++label_index) { 376 offset += GetLabelValueDefinitionCount(label_index); 377 } 378 return DefinitionLocation::Instruction(this, offset + index); 379} 380 381std::size_t CallCsaMacroAndBranchInstruction::GetValueDefinitionCount() const { 382 if (macro->signature().return_type == TypeOracle::GetNeverType()) return 0; 383 if (!return_continuation) return 0; 384 return LowerType(macro->signature().return_type).size(); 385} 386 387DefinitionLocation CallCsaMacroAndBranchInstruction::GetValueDefinition( 388 std::size_t index) const { 389 DCHECK_LT(index, GetValueDefinitionCount()); 390 return DefinitionLocation::Instruction(this, index); 391} 392 393base::Optional<DefinitionLocation> 394CallCsaMacroAndBranchInstruction::GetExceptionObjectDefinition() const { 395 if (!catch_block) return base::nullopt; 396 return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); 397} 398 399std::ostream& operator<<(std::ostream& os, 400 const CallCsaMacroAndBranchInstruction& instruction) { 401 os << "CallCsaMacroAndBranch " << instruction.macro->ReadableName(); 402 os << "("; 403 PrintCommaSeparatedList(os, instruction.constexpr_arguments); 404 os << ")"; 405 if (instruction.return_continuation) { 406 os << ", return continuation " << (*instruction.return_continuation)->id(); 407 } 408 if (!instruction.label_blocks.empty()) { 409 os << ", label blocks "; 410 PrintCommaSeparatedList(os, instruction.label_blocks, 411 [](Block* block) { return block->id(); }); 412 } 413 if (instruction.catch_block) { 414 os << ", catch block " << (*instruction.catch_block)->id(); 415 } 416 return os; 417} 418 419void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack, 420 ControlFlowGraph* cfg) const { 421 std::vector<const Type*> argument_types = stack->PopMany(argc); 422 if (argument_types != 423 LowerParameterTypes(builtin->signature().parameter_types)) { 424 ReportError("wrong argument types"); 425 } 426 if (builtin->IsTransitioning()) { 427 InvalidateTransientTypes(stack); 428 } 429 430 if (catch_block) { 431 Stack<const Type*> catch_stack = *stack; 432 catch_stack.Push(TypeOracle::GetJSAnyType()); 433 (*catch_block)->SetInputTypes(catch_stack); 434 } 435 436 stack->PushMany(LowerType(builtin->signature().return_type)); 437} 438 439void CallBuiltinInstruction::RecomputeDefinitionLocations( 440 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 441 locations->PopMany(argc); 442 443 if (catch_block) { 444 locations->Push(*GetExceptionObjectDefinition()); 445 (*catch_block)->MergeInputDefinitions(*locations, worklist); 446 locations->Pop(); 447 } 448 449 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { 450 locations->Push(GetValueDefinition(i)); 451 } 452} 453 454std::size_t CallBuiltinInstruction::GetValueDefinitionCount() const { 455 return LowerType(builtin->signature().return_type).size(); 456} 457 458DefinitionLocation CallBuiltinInstruction::GetValueDefinition( 459 std::size_t index) const { 460 DCHECK_LT(index, GetValueDefinitionCount()); 461 return DefinitionLocation::Instruction(this, index); 462} 463 464base::Optional<DefinitionLocation> 465CallBuiltinInstruction::GetExceptionObjectDefinition() const { 466 if (!catch_block) return base::nullopt; 467 return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); 468} 469 470void CallBuiltinPointerInstruction::TypeInstruction( 471 Stack<const Type*>* stack, ControlFlowGraph* cfg) const { 472 std::vector<const Type*> argument_types = stack->PopMany(argc); 473 const BuiltinPointerType* f = BuiltinPointerType::DynamicCast(stack->Pop()); 474 if (!f) ReportError("expected function pointer type"); 475 if (argument_types != LowerParameterTypes(f->parameter_types())) { 476 ReportError("wrong argument types"); 477 } 478 DCHECK_EQ(type, f); 479 // TODO(turbofan): Only invalidate transient types if the function pointer 480 // type is transitioning. 481 InvalidateTransientTypes(stack); 482 stack->PushMany(LowerType(f->return_type())); 483} 484 485void CallBuiltinPointerInstruction::RecomputeDefinitionLocations( 486 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 487 locations->PopMany(argc + 1); 488 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { 489 locations->Push(GetValueDefinition(i)); 490 } 491} 492 493std::size_t CallBuiltinPointerInstruction::GetValueDefinitionCount() const { 494 return LowerType(type->return_type()).size(); 495} 496 497DefinitionLocation CallBuiltinPointerInstruction::GetValueDefinition( 498 std::size_t index) const { 499 DCHECK_LT(index, GetValueDefinitionCount()); 500 return DefinitionLocation::Instruction(this, index); 501} 502 503std::ostream& operator<<(std::ostream& os, 504 const CallBuiltinInstruction& instruction) { 505 os << "CallBuiltin " << instruction.builtin->ReadableName() 506 << ", argc: " << instruction.argc; 507 if (instruction.is_tailcall) { 508 os << ", is_tailcall"; 509 } 510 if (instruction.catch_block) { 511 os << ", catch block " << (*instruction.catch_block)->id(); 512 } 513 return os; 514} 515 516void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack, 517 ControlFlowGraph* cfg) const { 518 std::vector<const Type*> argument_types = stack->PopMany(argc); 519 if (argument_types != 520 LowerParameterTypes(runtime_function->signature().parameter_types, 521 argc)) { 522 ReportError("wrong argument types"); 523 } 524 if (runtime_function->IsTransitioning()) { 525 InvalidateTransientTypes(stack); 526 } 527 528 if (catch_block) { 529 Stack<const Type*> catch_stack = *stack; 530 catch_stack.Push(TypeOracle::GetJSAnyType()); 531 (*catch_block)->SetInputTypes(catch_stack); 532 } 533 534 const Type* return_type = runtime_function->signature().return_type; 535 if (return_type != TypeOracle::GetNeverType()) { 536 stack->PushMany(LowerType(return_type)); 537 } 538} 539 540void CallRuntimeInstruction::RecomputeDefinitionLocations( 541 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 542 locations->PopMany(argc); 543 544 if (catch_block) { 545 locations->Push(*GetExceptionObjectDefinition()); 546 (*catch_block)->MergeInputDefinitions(*locations, worklist); 547 locations->Pop(); 548 } 549 550 const Type* return_type = runtime_function->signature().return_type; 551 if (return_type != TypeOracle::GetNeverType()) { 552 for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { 553 locations->Push(GetValueDefinition(i)); 554 } 555 } 556} 557 558std::size_t CallRuntimeInstruction::GetValueDefinitionCount() const { 559 const Type* return_type = runtime_function->signature().return_type; 560 if (return_type == TypeOracle::GetNeverType()) return 0; 561 return LowerType(return_type).size(); 562} 563 564DefinitionLocation CallRuntimeInstruction::GetValueDefinition( 565 std::size_t index) const { 566 DCHECK_LT(index, GetValueDefinitionCount()); 567 return DefinitionLocation::Instruction(this, index); 568} 569 570base::Optional<DefinitionLocation> 571CallRuntimeInstruction::GetExceptionObjectDefinition() const { 572 if (!catch_block) return base::nullopt; 573 return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); 574} 575 576std::ostream& operator<<(std::ostream& os, 577 const CallRuntimeInstruction& instruction) { 578 os << "CallRuntime " << instruction.runtime_function->ReadableName() 579 << ", argc: " << instruction.argc; 580 if (instruction.is_tailcall) { 581 os << ", is_tailcall"; 582 } 583 if (instruction.catch_block) { 584 os << ", catch block " << (*instruction.catch_block)->id(); 585 } 586 return os; 587} 588 589void BranchInstruction::TypeInstruction(Stack<const Type*>* stack, 590 ControlFlowGraph* cfg) const { 591 const Type* condition_type = stack->Pop(); 592 if (condition_type != TypeOracle::GetBoolType()) { 593 ReportError("condition has to have type bool"); 594 } 595 if_true->SetInputTypes(*stack); 596 if_false->SetInputTypes(*stack); 597} 598 599void BranchInstruction::RecomputeDefinitionLocations( 600 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 601 locations->Pop(); 602 if_true->MergeInputDefinitions(*locations, worklist); 603 if_false->MergeInputDefinitions(*locations, worklist); 604} 605 606std::ostream& operator<<(std::ostream& os, 607 const BranchInstruction& instruction) { 608 return os << "Branch true: " << instruction.if_true->id() 609 << ", false: " << instruction.if_false->id(); 610} 611 612void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack, 613 ControlFlowGraph* cfg) const { 614 if_true->SetInputTypes(*stack); 615 if_false->SetInputTypes(*stack); 616} 617 618void ConstexprBranchInstruction::RecomputeDefinitionLocations( 619 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 620 if_true->MergeInputDefinitions(*locations, worklist); 621 if_false->MergeInputDefinitions(*locations, worklist); 622} 623 624std::ostream& operator<<(std::ostream& os, 625 const ConstexprBranchInstruction& instruction) { 626 return os << "ConstexprBranch " << instruction.condition 627 << ", true: " << instruction.if_true->id() 628 << ", false: " << instruction.if_false->id(); 629} 630 631void GotoInstruction::TypeInstruction(Stack<const Type*>* stack, 632 ControlFlowGraph* cfg) const { 633 destination->SetInputTypes(*stack); 634} 635 636void GotoInstruction::RecomputeDefinitionLocations( 637 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 638 destination->MergeInputDefinitions(*locations, worklist); 639} 640 641std::ostream& operator<<(std::ostream& os, const GotoInstruction& instruction) { 642 return os << "Goto " << instruction.destination->id(); 643} 644 645void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack, 646 ControlFlowGraph* cfg) const { 647 if (variable_names.size() != stack->Size()) { 648 ReportError("goto external label with wrong parameter count."); 649 } 650} 651 652void GotoExternalInstruction::RecomputeDefinitionLocations( 653 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {} 654 655void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack, 656 ControlFlowGraph* cfg) const { 657 cfg->SetReturnType(stack->PopMany(count)); 658} 659 660void ReturnInstruction::RecomputeDefinitionLocations( 661 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 662 locations->PopMany(count); 663} 664 665void PrintConstantStringInstruction::TypeInstruction( 666 Stack<const Type*>* stack, ControlFlowGraph* cfg) const {} 667 668void PrintConstantStringInstruction::RecomputeDefinitionLocations( 669 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {} 670 671void AbortInstruction::TypeInstruction(Stack<const Type*>* stack, 672 ControlFlowGraph* cfg) const {} 673 674void AbortInstruction::RecomputeDefinitionLocations( 675 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {} 676 677void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack, 678 ControlFlowGraph* cfg) const { 679 stack->Poke(stack->AboveTop() - 1, destination_type); 680} 681 682void UnsafeCastInstruction::RecomputeDefinitionLocations( 683 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 684 locations->Poke(locations->AboveTop() - 1, GetValueDefinition()); 685} 686 687DefinitionLocation UnsafeCastInstruction::GetValueDefinition() const { 688 return DefinitionLocation::Instruction(this, 0); 689} 690 691void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, 692 ControlFlowGraph* cfg) const { 693 ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); 694 ExpectSubtype(stack->Pop(), TypeOracle::GetUnionType( 695 TypeOracle::GetHeapObjectType(), 696 TypeOracle::GetTaggedZeroPatternType())); 697 DCHECK_EQ(std::vector<const Type*>{type}, LowerType(type)); 698 stack->Push(type); 699} 700 701void LoadReferenceInstruction::RecomputeDefinitionLocations( 702 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 703 locations->Pop(); 704 locations->Pop(); 705 locations->Push(GetValueDefinition()); 706} 707 708DefinitionLocation LoadReferenceInstruction::GetValueDefinition() const { 709 return DefinitionLocation::Instruction(this, 0); 710} 711 712void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, 713 ControlFlowGraph* cfg) const { 714 ExpectSubtype(stack->Pop(), type); 715 ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); 716 ExpectSubtype(stack->Pop(), TypeOracle::GetUnionType( 717 TypeOracle::GetHeapObjectType(), 718 TypeOracle::GetTaggedZeroPatternType())); 719} 720 721void StoreReferenceInstruction::RecomputeDefinitionLocations( 722 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 723 locations->Pop(); 724 locations->Pop(); 725 locations->Pop(); 726} 727 728void LoadBitFieldInstruction::TypeInstruction(Stack<const Type*>* stack, 729 ControlFlowGraph* cfg) const { 730 ExpectType(bit_field_struct_type, stack->Pop()); 731 stack->Push(bit_field.name_and_type.type); 732} 733 734void LoadBitFieldInstruction::RecomputeDefinitionLocations( 735 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 736 locations->Pop(); 737 locations->Push(GetValueDefinition()); 738} 739 740DefinitionLocation LoadBitFieldInstruction::GetValueDefinition() const { 741 return DefinitionLocation::Instruction(this, 0); 742} 743 744void StoreBitFieldInstruction::TypeInstruction(Stack<const Type*>* stack, 745 ControlFlowGraph* cfg) const { 746 ExpectSubtype(bit_field.name_and_type.type, stack->Pop()); 747 ExpectType(bit_field_struct_type, stack->Pop()); 748 stack->Push(bit_field_struct_type); 749} 750 751void StoreBitFieldInstruction::RecomputeDefinitionLocations( 752 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 753 locations->Pop(); 754 locations->Pop(); 755 locations->Push(GetValueDefinition()); 756} 757 758DefinitionLocation StoreBitFieldInstruction::GetValueDefinition() const { 759 return DefinitionLocation::Instruction(this, 0); 760} 761 762void MakeLazyNodeInstruction::TypeInstruction(Stack<const Type*>* stack, 763 ControlFlowGraph* cfg) const { 764 std::vector<const Type*> parameter_types = 765 LowerParameterTypes(macro->signature().parameter_types); 766 for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { 767 const Type* arg_type = stack->Pop(); 768 const Type* parameter_type = parameter_types.back(); 769 parameter_types.pop_back(); 770 if (arg_type != parameter_type) { 771 ReportError("parameter ", i, ": expected type ", *parameter_type, 772 " but found type ", *arg_type); 773 } 774 } 775 776 stack->Push(result_type); 777} 778 779void MakeLazyNodeInstruction::RecomputeDefinitionLocations( 780 Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { 781 auto parameter_types = 782 LowerParameterTypes(macro->signature().parameter_types); 783 locations->PopMany(parameter_types.size()); 784 785 locations->Push(GetValueDefinition()); 786} 787 788DefinitionLocation MakeLazyNodeInstruction::GetValueDefinition() const { 789 return DefinitionLocation::Instruction(this, 0); 790} 791 792std::ostream& operator<<(std::ostream& os, 793 const MakeLazyNodeInstruction& instruction) { 794 os << "MakeLazyNode " << instruction.macro->ReadableName() << ", " 795 << *instruction.result_type; 796 for (const std::string& arg : instruction.constexpr_arguments) { 797 os << ", " << arg; 798 } 799 return os; 800} 801 802bool CallRuntimeInstruction::IsBlockTerminator() const { 803 return is_tailcall || runtime_function->signature().return_type == 804 TypeOracle::GetNeverType(); 805} 806 807} // namespace torque 808} // namespace internal 809} // namespace v8 810