| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/torque/instructions.h" |
| #include "src/torque/cfg.h" |
| #include "src/torque/type-oracle.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace torque { |
| |
| #define TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS(Name) \ |
| const InstructionKind Name::kKind = InstructionKind::k##Name; \ |
| std::unique_ptr<InstructionBase> Name::Clone() const { \ |
| return std::unique_ptr<InstructionBase>(new Name(*this)); \ |
| } \ |
| void Name::Assign(const InstructionBase& other) { \ |
| *this = static_cast<const Name&>(other); \ |
| } |
| TORQUE_INSTRUCTION_LIST(TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS) |
| #undef TORQUE_INSTRUCTION_BOILERPLATE_DEFINITIONS |
| |
| namespace { |
| void ExpectType(const Type* expected, const Type* actual) { |
| if (expected != actual) { |
| ReportError("expected type ", *expected, " but found ", *actual); |
| } |
| } |
| void ExpectSubtype(const Type* subtype, const Type* supertype) { |
| if (!subtype->IsSubtypeOf(supertype)) { |
| ReportError("type ", *subtype, " is not a subtype of ", *supertype); |
| } |
| } |
| } // namespace |
| |
| void PeekInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| const Type* type = stack->Peek(slot); |
| if (widened_type) { |
| if (type->IsTopType()) { |
| const TopType* top_type = TopType::cast(type); |
| ReportError("use of " + top_type->reason()); |
| } |
| ExpectSubtype(type, *widened_type); |
| type = *widened_type; |
| } |
| stack->Push(type); |
| } |
| |
| void PeekInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Push(locations->Peek(slot)); |
| } |
| |
| void PokeInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| const Type* type = stack->Top(); |
| if (widened_type) { |
| ExpectSubtype(type, *widened_type); |
| type = *widened_type; |
| } |
| stack->Poke(slot, type); |
| stack->Pop(); |
| } |
| |
| void PokeInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Poke(slot, locations->Pop()); |
| } |
| |
| void DeleteRangeInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| stack->DeleteRange(range); |
| } |
| |
| void DeleteRangeInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->DeleteRange(range); |
| } |
| |
| void PushUninitializedInstruction::TypeInstruction( |
| Stack<const Type*>* stack, ControlFlowGraph* cfg) const { |
| stack->Push(type); |
| } |
| |
| void PushUninitializedInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Push(GetValueDefinition()); |
| } |
| |
| DefinitionLocation PushUninitializedInstruction::GetValueDefinition() const { |
| return DefinitionLocation::Instruction(this, 0); |
| } |
| |
| void PushBuiltinPointerInstruction::TypeInstruction( |
| Stack<const Type*>* stack, ControlFlowGraph* cfg) const { |
| stack->Push(type); |
| } |
| |
| void PushBuiltinPointerInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Push(GetValueDefinition()); |
| } |
| |
| DefinitionLocation PushBuiltinPointerInstruction::GetValueDefinition() const { |
| return DefinitionLocation::Instruction(this, 0); |
| } |
| |
| void NamespaceConstantInstruction::TypeInstruction( |
| Stack<const Type*>* stack, ControlFlowGraph* cfg) const { |
| stack->PushMany(LowerType(constant->type())); |
| } |
| |
| void NamespaceConstantInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { |
| locations->Push(GetValueDefinition(i)); |
| } |
| } |
| |
| std::size_t NamespaceConstantInstruction::GetValueDefinitionCount() const { |
| return LowerType(constant->type()).size(); |
| } |
| |
| DefinitionLocation NamespaceConstantInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| void InstructionBase::InvalidateTransientTypes( |
| Stack<const Type*>* stack) const { |
| auto current = stack->begin(); |
| while (current != stack->end()) { |
| if ((*current)->IsTransient()) { |
| std::stringstream stream; |
| stream << "type " << **current |
| << " is made invalid by transitioning callable invocation at " |
| << PositionAsString(pos); |
| *current = TypeOracle::GetTopType(stream.str(), *current); |
| } |
| ++current; |
| } |
| } |
| |
| void CallIntrinsicInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| std::vector<const Type*> parameter_types = |
| LowerParameterTypes(intrinsic->signature().parameter_types); |
| for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { |
| const Type* arg_type = stack->Pop(); |
| const Type* parameter_type = parameter_types.back(); |
| parameter_types.pop_back(); |
| if (arg_type != parameter_type) { |
| ReportError("parameter ", i, ": expected type ", *parameter_type, |
| " but found type ", *arg_type); |
| } |
| } |
| if (intrinsic->IsTransitioning()) { |
| InvalidateTransientTypes(stack); |
| } |
| stack->PushMany(LowerType(intrinsic->signature().return_type)); |
| } |
| |
| void CallIntrinsicInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| auto parameter_types = |
| LowerParameterTypes(intrinsic->signature().parameter_types); |
| locations->PopMany(parameter_types.size()); |
| for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { |
| locations->Push(DefinitionLocation::Instruction(this, i)); |
| } |
| } |
| |
| std::size_t CallIntrinsicInstruction::GetValueDefinitionCount() const { |
| return LowerType(intrinsic->signature().return_type).size(); |
| } |
| |
| DefinitionLocation CallIntrinsicInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| std::vector<const Type*> parameter_types = |
| LowerParameterTypes(macro->signature().parameter_types); |
| for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { |
| const Type* arg_type = stack->Pop(); |
| const Type* parameter_type = parameter_types.back(); |
| parameter_types.pop_back(); |
| if (arg_type != parameter_type) { |
| ReportError("parameter ", i, ": expected type ", *parameter_type, |
| " but found type ", *arg_type); |
| } |
| } |
| |
| if (macro->IsTransitioning()) { |
| InvalidateTransientTypes(stack); |
| } |
| |
| if (catch_block) { |
| Stack<const Type*> catch_stack = *stack; |
| catch_stack.Push(TypeOracle::GetJSAnyType()); |
| (*catch_block)->SetInputTypes(catch_stack); |
| } |
| |
| stack->PushMany(LowerType(macro->signature().return_type)); |
| } |
| |
| void CallCsaMacroInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| auto parameter_types = |
| LowerParameterTypes(macro->signature().parameter_types); |
| locations->PopMany(parameter_types.size()); |
| |
| if (catch_block) { |
| locations->Push(*GetExceptionObjectDefinition()); |
| (*catch_block)->MergeInputDefinitions(*locations, worklist); |
| locations->Pop(); |
| } |
| |
| for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { |
| locations->Push(GetValueDefinition(i)); |
| } |
| } |
| |
| base::Optional<DefinitionLocation> |
| CallCsaMacroInstruction::GetExceptionObjectDefinition() const { |
| if (!catch_block) return base::nullopt; |
| return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); |
| } |
| |
| std::size_t CallCsaMacroInstruction::GetValueDefinitionCount() const { |
| return LowerType(macro->signature().return_type).size(); |
| } |
| |
| DefinitionLocation CallCsaMacroInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| void CallCsaMacroAndBranchInstruction::TypeInstruction( |
| Stack<const Type*>* stack, ControlFlowGraph* cfg) const { |
| std::vector<const Type*> parameter_types = |
| LowerParameterTypes(macro->signature().parameter_types); |
| for (intptr_t i = parameter_types.size() - 1; i >= 0; --i) { |
| const Type* arg_type = stack->Pop(); |
| const Type* parameter_type = parameter_types.back(); |
| parameter_types.pop_back(); |
| if (arg_type != parameter_type) { |
| ReportError("parameter ", i, ": expected type ", *parameter_type, |
| " but found type ", *arg_type); |
| } |
| } |
| |
| if (label_blocks.size() != macro->signature().labels.size()) { |
| ReportError("wrong number of labels"); |
| } |
| for (size_t i = 0; i < label_blocks.size(); ++i) { |
| Stack<const Type*> continuation_stack = *stack; |
| continuation_stack.PushMany( |
| LowerParameterTypes(macro->signature().labels[i].types)); |
| label_blocks[i]->SetInputTypes(std::move(continuation_stack)); |
| } |
| |
| if (macro->IsTransitioning()) { |
| InvalidateTransientTypes(stack); |
| } |
| |
| if (catch_block) { |
| Stack<const Type*> catch_stack = *stack; |
| catch_stack.Push(TypeOracle::GetJSAnyType()); |
| (*catch_block)->SetInputTypes(catch_stack); |
| } |
| |
| if (macro->signature().return_type != TypeOracle::GetNeverType()) { |
| Stack<const Type*> return_stack = *stack; |
| return_stack.PushMany(LowerType(macro->signature().return_type)); |
| if (return_continuation == base::nullopt) { |
| ReportError("missing return continuation."); |
| } |
| (*return_continuation)->SetInputTypes(return_stack); |
| } else { |
| if (return_continuation != base::nullopt) { |
| ReportError("unreachable return continuation."); |
| } |
| } |
| } |
| |
| void CallCsaMacroAndBranchInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| auto parameter_types = |
| LowerParameterTypes(macro->signature().parameter_types); |
| locations->PopMany(parameter_types.size()); |
| |
| for (std::size_t label_index = 0; label_index < label_blocks.size(); |
| ++label_index) { |
| const std::size_t count = GetLabelValueDefinitionCount(label_index); |
| for (std::size_t i = 0; i < count; ++i) { |
| locations->Push(GetLabelValueDefinition(label_index, i)); |
| } |
| label_blocks[label_index]->MergeInputDefinitions(*locations, worklist); |
| locations->PopMany(count); |
| } |
| |
| if (catch_block) { |
| locations->Push(*GetExceptionObjectDefinition()); |
| (*catch_block)->MergeInputDefinitions(*locations, worklist); |
| locations->Pop(); |
| } |
| |
| if (macro->signature().return_type != TypeOracle::GetNeverType()) { |
| if (return_continuation) { |
| const std::size_t count = GetValueDefinitionCount(); |
| for (std::size_t i = 0; i < count; ++i) { |
| locations->Push(GetValueDefinition(i)); |
| } |
| (*return_continuation)->MergeInputDefinitions(*locations, worklist); |
| locations->PopMany(count); |
| } |
| } |
| } |
| |
| std::size_t CallCsaMacroAndBranchInstruction::GetLabelCount() const { |
| return label_blocks.size(); |
| } |
| |
| std::size_t CallCsaMacroAndBranchInstruction::GetLabelValueDefinitionCount( |
| std::size_t label) const { |
| DCHECK_LT(label, GetLabelCount()); |
| return LowerParameterTypes(macro->signature().labels[label].types).size(); |
| } |
| |
| DefinitionLocation CallCsaMacroAndBranchInstruction::GetLabelValueDefinition( |
| std::size_t label, std::size_t index) const { |
| DCHECK_LT(index, GetLabelValueDefinitionCount(label)); |
| std::size_t offset = GetValueDefinitionCount() + (catch_block ? 1 : 0); |
| for (std::size_t label_index = 0; label_index < label; ++label_index) { |
| offset += GetLabelValueDefinitionCount(label_index); |
| } |
| return DefinitionLocation::Instruction(this, offset + index); |
| } |
| |
| std::size_t CallCsaMacroAndBranchInstruction::GetValueDefinitionCount() const { |
| if (macro->signature().return_type == TypeOracle::GetNeverType()) return 0; |
| if (!return_continuation) return 0; |
| return LowerType(macro->signature().return_type).size(); |
| } |
| |
| DefinitionLocation CallCsaMacroAndBranchInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| base::Optional<DefinitionLocation> |
| CallCsaMacroAndBranchInstruction::GetExceptionObjectDefinition() const { |
| if (!catch_block) return base::nullopt; |
| return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); |
| } |
| |
| void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| std::vector<const Type*> argument_types = stack->PopMany(argc); |
| if (argument_types != |
| LowerParameterTypes(builtin->signature().parameter_types)) { |
| ReportError("wrong argument types"); |
| } |
| if (builtin->IsTransitioning()) { |
| InvalidateTransientTypes(stack); |
| } |
| |
| if (catch_block) { |
| Stack<const Type*> catch_stack = *stack; |
| catch_stack.Push(TypeOracle::GetJSAnyType()); |
| (*catch_block)->SetInputTypes(catch_stack); |
| } |
| |
| stack->PushMany(LowerType(builtin->signature().return_type)); |
| } |
| |
| void CallBuiltinInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->PopMany(argc); |
| |
| if (catch_block) { |
| locations->Push(*GetExceptionObjectDefinition()); |
| (*catch_block)->MergeInputDefinitions(*locations, worklist); |
| locations->Pop(); |
| } |
| |
| for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { |
| locations->Push(GetValueDefinition(i)); |
| } |
| } |
| |
| std::size_t CallBuiltinInstruction::GetValueDefinitionCount() const { |
| return LowerType(builtin->signature().return_type).size(); |
| } |
| |
| DefinitionLocation CallBuiltinInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| base::Optional<DefinitionLocation> |
| CallBuiltinInstruction::GetExceptionObjectDefinition() const { |
| if (!catch_block) return base::nullopt; |
| return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); |
| } |
| |
| void CallBuiltinPointerInstruction::TypeInstruction( |
| Stack<const Type*>* stack, ControlFlowGraph* cfg) const { |
| std::vector<const Type*> argument_types = stack->PopMany(argc); |
| const BuiltinPointerType* f = BuiltinPointerType::DynamicCast(stack->Pop()); |
| if (!f) ReportError("expected function pointer type"); |
| if (argument_types != LowerParameterTypes(f->parameter_types())) { |
| ReportError("wrong argument types"); |
| } |
| DCHECK_EQ(type, f); |
| // TODO(tebbi): Only invalidate transient types if the function pointer type |
| // is transitioning. |
| InvalidateTransientTypes(stack); |
| stack->PushMany(LowerType(f->return_type())); |
| } |
| |
| void CallBuiltinPointerInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->PopMany(argc + 1); |
| for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { |
| locations->Push(GetValueDefinition(i)); |
| } |
| } |
| |
| std::size_t CallBuiltinPointerInstruction::GetValueDefinitionCount() const { |
| return LowerType(type->return_type()).size(); |
| } |
| |
| DefinitionLocation CallBuiltinPointerInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| std::vector<const Type*> argument_types = stack->PopMany(argc); |
| if (argument_types != |
| LowerParameterTypes(runtime_function->signature().parameter_types, |
| argc)) { |
| ReportError("wrong argument types"); |
| } |
| if (runtime_function->IsTransitioning()) { |
| InvalidateTransientTypes(stack); |
| } |
| |
| if (catch_block) { |
| Stack<const Type*> catch_stack = *stack; |
| catch_stack.Push(TypeOracle::GetJSAnyType()); |
| (*catch_block)->SetInputTypes(catch_stack); |
| } |
| |
| const Type* return_type = runtime_function->signature().return_type; |
| if (return_type != TypeOracle::GetNeverType()) { |
| stack->PushMany(LowerType(return_type)); |
| } |
| } |
| |
| void CallRuntimeInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->PopMany(argc); |
| |
| if (catch_block) { |
| locations->Push(*GetExceptionObjectDefinition()); |
| (*catch_block)->MergeInputDefinitions(*locations, worklist); |
| locations->Pop(); |
| } |
| |
| const Type* return_type = runtime_function->signature().return_type; |
| if (return_type != TypeOracle::GetNeverType()) { |
| for (std::size_t i = 0; i < GetValueDefinitionCount(); ++i) { |
| locations->Push(GetValueDefinition(i)); |
| } |
| } |
| } |
| |
| std::size_t CallRuntimeInstruction::GetValueDefinitionCount() const { |
| const Type* return_type = runtime_function->signature().return_type; |
| if (return_type == TypeOracle::GetNeverType()) return 0; |
| return LowerType(return_type).size(); |
| } |
| |
| DefinitionLocation CallRuntimeInstruction::GetValueDefinition( |
| std::size_t index) const { |
| DCHECK_LT(index, GetValueDefinitionCount()); |
| return DefinitionLocation::Instruction(this, index); |
| } |
| |
| base::Optional<DefinitionLocation> |
| CallRuntimeInstruction::GetExceptionObjectDefinition() const { |
| if (!catch_block) return base::nullopt; |
| return DefinitionLocation::Instruction(this, GetValueDefinitionCount()); |
| } |
| |
| void BranchInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| const Type* condition_type = stack->Pop(); |
| if (condition_type != TypeOracle::GetBoolType()) { |
| ReportError("condition has to have type bool"); |
| } |
| if_true->SetInputTypes(*stack); |
| if_false->SetInputTypes(*stack); |
| } |
| |
| void BranchInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Pop(); |
| if_true->MergeInputDefinitions(*locations, worklist); |
| if_false->MergeInputDefinitions(*locations, worklist); |
| } |
| |
| void ConstexprBranchInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| if_true->SetInputTypes(*stack); |
| if_false->SetInputTypes(*stack); |
| } |
| |
| void ConstexprBranchInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| if_true->MergeInputDefinitions(*locations, worklist); |
| if_false->MergeInputDefinitions(*locations, worklist); |
| } |
| |
| void GotoInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| destination->SetInputTypes(*stack); |
| } |
| |
| void GotoInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| destination->MergeInputDefinitions(*locations, worklist); |
| } |
| |
| void GotoExternalInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| if (variable_names.size() != stack->Size()) { |
| ReportError("goto external label with wrong parameter count."); |
| } |
| } |
| |
| void GotoExternalInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {} |
| |
| void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| cfg->SetReturnType(stack->Pop()); |
| } |
| |
| void ReturnInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Pop(); |
| } |
| |
| void PrintConstantStringInstruction::TypeInstruction( |
| Stack<const Type*>* stack, ControlFlowGraph* cfg) const {} |
| |
| void PrintConstantStringInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {} |
| |
| void AbortInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const {} |
| |
| void AbortInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const {} |
| |
| void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| stack->Poke(stack->AboveTop() - 1, destination_type); |
| } |
| |
| void UnsafeCastInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Poke(locations->AboveTop() - 1, GetValueDefinition()); |
| } |
| |
| DefinitionLocation UnsafeCastInstruction::GetValueDefinition() const { |
| return DefinitionLocation::Instruction(this, 0); |
| } |
| |
| void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); |
| ExpectSubtype(stack->Pop(), TypeOracle::GetHeapObjectType()); |
| DCHECK_EQ(std::vector<const Type*>{type}, LowerType(type)); |
| stack->Push(type); |
| } |
| |
| void LoadReferenceInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Pop(); |
| locations->Pop(); |
| locations->Push(GetValueDefinition()); |
| } |
| |
| DefinitionLocation LoadReferenceInstruction::GetValueDefinition() const { |
| return DefinitionLocation::Instruction(this, 0); |
| } |
| |
| void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| ExpectSubtype(stack->Pop(), type); |
| ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); |
| ExpectSubtype(stack->Pop(), TypeOracle::GetHeapObjectType()); |
| } |
| |
| void StoreReferenceInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Pop(); |
| locations->Pop(); |
| locations->Pop(); |
| } |
| |
| void LoadBitFieldInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| ExpectType(bit_field_struct_type, stack->Pop()); |
| stack->Push(bit_field.name_and_type.type); |
| } |
| |
| void LoadBitFieldInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Pop(); |
| locations->Push(GetValueDefinition()); |
| } |
| |
| DefinitionLocation LoadBitFieldInstruction::GetValueDefinition() const { |
| return DefinitionLocation::Instruction(this, 0); |
| } |
| |
| void StoreBitFieldInstruction::TypeInstruction(Stack<const Type*>* stack, |
| ControlFlowGraph* cfg) const { |
| ExpectSubtype(bit_field.name_and_type.type, stack->Pop()); |
| ExpectType(bit_field_struct_type, stack->Pop()); |
| stack->Push(bit_field_struct_type); |
| } |
| |
| void StoreBitFieldInstruction::RecomputeDefinitionLocations( |
| Stack<DefinitionLocation>* locations, Worklist<Block*>* worklist) const { |
| locations->Pop(); |
| locations->Pop(); |
| locations->Push(GetValueDefinition()); |
| } |
| |
| DefinitionLocation StoreBitFieldInstruction::GetValueDefinition() const { |
| return DefinitionLocation::Instruction(this, 0); |
| } |
| |
| bool CallRuntimeInstruction::IsBlockTerminator() const { |
| return is_tailcall || runtime_function->signature().return_type == |
| TypeOracle::GetNeverType(); |
| } |
| |
| } // namespace torque |
| } // namespace internal |
| } // namespace v8 |