diff options
Diffstat (limited to 'chromium/v8/src/torque')
-rw-r--r-- | chromium/v8/src/torque/cfg.h | 2 | ||||
-rw-r--r-- | chromium/v8/src/torque/constants.h | 2 | ||||
-rw-r--r-- | chromium/v8/src/torque/csa-generator.cc | 47 | ||||
-rw-r--r-- | chromium/v8/src/torque/declarable.cc | 19 | ||||
-rw-r--r-- | chromium/v8/src/torque/declarable.h | 29 | ||||
-rw-r--r-- | chromium/v8/src/torque/implementation-visitor.cc | 182 | ||||
-rw-r--r-- | chromium/v8/src/torque/implementation-visitor.h | 31 | ||||
-rw-r--r-- | chromium/v8/src/torque/instance-type-generator.cc | 55 | ||||
-rw-r--r-- | chromium/v8/src/torque/instructions.h | 4 | ||||
-rw-r--r-- | chromium/v8/src/torque/ls/message.h | 8 | ||||
-rw-r--r-- | chromium/v8/src/torque/torque-compiler.cc | 1 | ||||
-rw-r--r-- | chromium/v8/src/torque/torque-parser.cc | 85 | ||||
-rw-r--r-- | chromium/v8/src/torque/type-visitor.cc | 10 | ||||
-rw-r--r-- | chromium/v8/src/torque/types.h | 5 | ||||
-rw-r--r-- | chromium/v8/src/torque/utils.h | 22 |
15 files changed, 382 insertions, 120 deletions
diff --git a/chromium/v8/src/torque/cfg.h b/chromium/v8/src/torque/cfg.h index e45cb75073e..4cacb58edb3 100644 --- a/chromium/v8/src/torque/cfg.h +++ b/chromium/v8/src/torque/cfg.h @@ -63,7 +63,7 @@ class Block { DCHECK_EQ(input_definitions_->Size(), input_definitions.Size()); bool changed = false; - for (BottomOffset i = 0; i < input_definitions.AboveTop(); ++i) { + for (BottomOffset i = {0}; i < input_definitions.AboveTop(); ++i) { auto& current = input_definitions_->Peek(i); auto& input = input_definitions.Peek(i); if (current == input) continue; diff --git a/chromium/v8/src/torque/constants.h b/chromium/v8/src/torque/constants.h index 616e7a23acd..8b9300d6cf2 100644 --- a/chromium/v8/src/torque/constants.h +++ b/chromium/v8/src/torque/constants.h @@ -95,6 +95,7 @@ static const char* const ANNOTATION_IFNOT = "@ifnot"; static const char* const ANNOTATION_GENERATE_BODY_DESCRIPTOR = "@generateBodyDescriptor"; static const char* const ANNOTATION_EXPORT_CPP_CLASS = "@export"; +static const char* const ANNOTATION_DO_NOT_GENERATE_CAST = "@doNotGenerateCast"; inline bool IsConstexprName(const std::string& name) { return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) == @@ -133,6 +134,7 @@ enum class ClassFlag { kUndefinedLayout = 1 << 11, kGenerateBodyDescriptor = 1 << 12, kExport = 1 << 13, + kDoNotGenerateCast = 1 << 14 }; using ClassFlags = base::Flags<ClassFlag>; diff --git a/chromium/v8/src/torque/csa-generator.cc b/chromium/v8/src/torque/csa-generator.cc index 45ed7f3af42..a25c5ce25fe 100644 --- a/chromium/v8/src/torque/csa-generator.cc +++ b/chromium/v8/src/torque/csa-generator.cc @@ -16,7 +16,7 @@ namespace torque { base::Optional<Stack<std::string>> CSAGenerator::EmitGraph( Stack<std::string> parameters) { - for (BottomOffset i = 0; i < parameters.AboveTop(); ++i) { + for (BottomOffset i = {0}; i < parameters.AboveTop(); ++i) { SetDefinitionVariable(DefinitionLocation::Parameter(i.offset), parameters.Peek(i)); } @@ -27,7 +27,7 @@ base::Optional<Stack<std::string>> CSAGenerator::EmitGraph( out() << " compiler::CodeAssemblerParameterizedLabel<"; bool first = true; DCHECK_EQ(block->InputTypes().Size(), block->InputDefinitions().Size()); - for (BottomOffset i = 0; i < block->InputTypes().AboveTop(); ++i) { + for (BottomOffset i = {0}; i < block->InputTypes().AboveTop(); ++i) { if (block->InputDefinitions().Peek(i).IsPhiFromBlock(block)) { if (!first) out() << ", "; out() << block->InputTypes().Peek(i)->GetGeneratedTNodeTypeName(); @@ -70,7 +70,7 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) { Stack<std::string> stack; std::stringstream phi_names; - for (BottomOffset i = 0; i < block->InputTypes().AboveTop(); ++i) { + for (BottomOffset i = {0}; i < block->InputTypes().AboveTop(); ++i) { const auto& def = block->InputDefinitions().Peek(i); stack.Push(DefinitionToVariable(def)); if (def.IsPhiFromBlock(block)) { @@ -274,6 +274,31 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, << return_type->GetGeneratedTNodeTypeName() << ">"; } } + } else if (instruction.intrinsic->ExternalName() == "%GetClassMapConstant") { + if (parameter_types.size() != 0) { + ReportError("%GetClassMapConstant must not take parameters"); + } + if (instruction.specialization_types.size() != 1) { + ReportError( + "%GetClassMapConstant must take a single class as specialization " + "parameter"); + } + const ClassType* class_type = + ClassType::DynamicCast(instruction.specialization_types[0]); + if (!class_type) { + ReportError("%GetClassMapConstant must take a class type parameter"); + } + // If the class isn't actually used as the parameter to a TNode, + // then we can't rely on the class existing in C++ or being of the same + // type (e.g. it could be a template), so don't use the template CSA + // machinery for accessing the class' map. + std::string class_name = + class_type->name() != class_type->GetGeneratedTNodeTypeName() + ? std::string("void") + : class_type->name(); + + out() << std::string("CodeStubAssembler(state_).GetClassMapConstant<") + + class_name + ">"; } else if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { if (parameter_types.size() != 1 || !parameter_types[0]->IsConstexpr()) { ReportError( @@ -468,7 +493,7 @@ void CSAGenerator::EmitInstruction( const auto& input_definitions = (*instruction.return_continuation)->InputDefinitions(); - for (BottomOffset i = 0; i < input_definitions.AboveTop(); ++i) { + for (BottomOffset i = {0}; i < input_definitions.AboveTop(); ++i) { if (input_definitions.Peek(i).IsPhiFromBlock( *instruction.return_continuation)) { out() << ", " @@ -487,7 +512,7 @@ void CSAGenerator::EmitInstruction( const auto& label_definitions = instruction.label_blocks[l]->InputDefinitions(); - BottomOffset i = 0; + BottomOffset i = {0}; for (; i < stack->AboveTop(); ++i) { if (label_definitions.Peek(i).IsPhiFromBlock( instruction.label_blocks[l])) { @@ -630,7 +655,7 @@ void CSAGenerator::PostCallableExceptionPreparation( DCHECK_EQ(stack->Size() + 1, (*catch_block)->InputDefinitions().Size()); const auto& input_definitions = (*catch_block)->InputDefinitions(); - for (BottomOffset i = 0; i < input_definitions.AboveTop(); ++i) { + for (BottomOffset i = {0}; i < input_definitions.AboveTop(); ++i) { if (input_definitions.Peek(i).IsPhiFromBlock(*catch_block)) { if (i < stack->AboveTop()) { out() << ", " << stack->Peek(i); @@ -713,7 +738,7 @@ void CSAGenerator::EmitInstruction(const BranchInstruction& instruction, const auto& true_definitions = instruction.if_true->InputDefinitions(); DCHECK_EQ(stack->Size(), true_definitions.Size()); bool first = true; - for (BottomOffset i = 0; i < stack->AboveTop(); ++i) { + for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { if (true_definitions.Peek(i).IsPhiFromBlock(instruction.if_true)) { if (!first) out() << ", "; out() << stack->Peek(i); @@ -726,7 +751,7 @@ void CSAGenerator::EmitInstruction(const BranchInstruction& instruction, const auto& false_definitions = instruction.if_false->InputDefinitions(); DCHECK_EQ(stack->Size(), false_definitions.Size()); first = true; - for (BottomOffset i = 0; i < stack->AboveTop(); ++i) { + for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { if (false_definitions.Peek(i).IsPhiFromBlock(instruction.if_false)) { if (!first) out() << ", "; out() << stack->Peek(i); @@ -744,7 +769,7 @@ void CSAGenerator::EmitInstruction( const auto& true_definitions = instruction.if_true->InputDefinitions(); DCHECK_EQ(stack->Size(), true_definitions.Size()); - for (BottomOffset i = 0; i < stack->AboveTop(); ++i) { + for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { if (true_definitions.Peek(i).IsPhiFromBlock(instruction.if_true)) { out() << ", " << stack->Peek(i); } @@ -756,7 +781,7 @@ void CSAGenerator::EmitInstruction( const auto& false_definitions = instruction.if_false->InputDefinitions(); DCHECK_EQ(stack->Size(), false_definitions.Size()); - for (BottomOffset i = 0; i < stack->AboveTop(); ++i) { + for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { if (false_definitions.Peek(i).IsPhiFromBlock(instruction.if_false)) { out() << ", " << stack->Peek(i); } @@ -772,7 +797,7 @@ void CSAGenerator::EmitInstruction(const GotoInstruction& instruction, const auto& destination_definitions = instruction.destination->InputDefinitions(); DCHECK_EQ(stack->Size(), destination_definitions.Size()); - for (BottomOffset i = 0; i < stack->AboveTop(); ++i) { + for (BottomOffset i = {0}; i < stack->AboveTop(); ++i) { if (destination_definitions.Peek(i).IsPhiFromBlock( instruction.destination)) { out() << ", " << stack->Peek(i); diff --git a/chromium/v8/src/torque/declarable.cc b/chromium/v8/src/torque/declarable.cc index 7c370c97b3c..fb5ed15f850 100644 --- a/chromium/v8/src/torque/declarable.cc +++ b/chromium/v8/src/torque/declarable.cc @@ -77,9 +77,26 @@ SpecializationRequester::SpecializationRequester(SourcePosition position, this->scope = scope; } +std::vector<Declarable*> Scope::Lookup(const QualifiedName& name) { + if (name.namespace_qualification.size() >= 1 && + name.namespace_qualification[0] == "") { + return GlobalContext::GetDefaultNamespace()->Lookup( + name.DropFirstNamespaceQualification()); + } + std::vector<Declarable*> result; + if (ParentScope()) { + result = ParentScope()->Lookup(name); + } + for (Declarable* declarable : LookupShallow(name)) { + result.push_back(declarable); + } + return result; +} + base::Optional<std::string> TypeConstraint::IsViolated(const Type* type) const { if (upper_bound && !type->IsSubtypeOf(*upper_bound)) { - return {ToString("expected ", *type, " to be a subtype of ", *upper_bound)}; + return { + ToString("expected ", *type, " to be a subtype of ", **upper_bound)}; } return base::nullopt; } diff --git a/chromium/v8/src/torque/declarable.h b/chromium/v8/src/torque/declarable.h index b6fdef67b90..6fbf969e86f 100644 --- a/chromium/v8/src/torque/declarable.h +++ b/chromium/v8/src/torque/declarable.h @@ -36,6 +36,17 @@ struct QualifiedName { explicit QualifiedName(std::string name) : QualifiedName({}, std::move(name)) {} + bool HasNamespaceQualification() const { + return !namespace_qualification.empty(); + } + + QualifiedName DropFirstNamespaceQualification() const { + return QualifiedName{ + std::vector<std::string>(namespace_qualification.begin() + 1, + namespace_qualification.end()), + name}; + } + friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name); }; @@ -163,7 +174,7 @@ class Scope : public Declarable { explicit Scope(Declarable::Kind kind) : Declarable(kind) {} std::vector<Declarable*> LookupShallow(const QualifiedName& name) { - if (name.namespace_qualification.empty()) return declarations_[name.name]; + if (!name.HasNamespaceQualification()) return declarations_[name.name]; Scope* child = nullptr; for (Declarable* declarable : declarations_[name.namespace_qualification.front()]) { @@ -176,22 +187,10 @@ class Scope : public Declarable { } } if (child == nullptr) return {}; - return child->LookupShallow( - QualifiedName({name.namespace_qualification.begin() + 1, - name.namespace_qualification.end()}, - name.name)); + return child->LookupShallow(name.DropFirstNamespaceQualification()); } - std::vector<Declarable*> Lookup(const QualifiedName& name) { - std::vector<Declarable*> result; - if (ParentScope()) { - result = ParentScope()->Lookup(name); - } - for (Declarable* declarable : LookupShallow(name)) { - result.push_back(declarable); - } - return result; - } + std::vector<Declarable*> Lookup(const QualifiedName& name); template <class T> T* AddDeclarable(const std::string& name, T* declarable) { declarations_[name].push_back(declarable); diff --git a/chromium/v8/src/torque/implementation-visitor.cc b/chromium/v8/src/torque/implementation-visitor.cc index bee31b4d32a..b0f7013d350 100644 --- a/chromium/v8/src/torque/implementation-visitor.cc +++ b/chromium/v8/src/torque/implementation-visitor.cc @@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "src/torque/implementation-visitor.h" + #include <algorithm> +#include <iomanip> #include <string> #include "src/base/optional.h" @@ -10,7 +13,6 @@ #include "src/torque/csa-generator.h" #include "src/torque/declaration-visitor.h" #include "src/torque/global-context.h" -#include "src/torque/implementation-visitor.h" #include "src/torque/parameter-difference.h" #include "src/torque/server-data.h" #include "src/torque/type-inference.h" @@ -729,8 +731,17 @@ VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) { VisitResult true_result; { StackScope true_block_scope(this); + VisitResult right_result = Visit(expr->right); + if (TryGetSourceForBitfieldExpression(expr->left) != nullptr && + TryGetSourceForBitfieldExpression(expr->right) != nullptr && + TryGetSourceForBitfieldExpression(expr->left)->value == + TryGetSourceForBitfieldExpression(expr->right)->value) { + Lint( + "Please use & rather than && when checking multiple bitfield " + "values, to avoid complexity in generated code."); + } true_result = true_block_scope.Yield( - GenerateImplicitConvert(TypeOracle::GetBoolType(), Visit(expr->right))); + GenerateImplicitConvert(TypeOracle::GetBoolType(), right_result)); } assembler().Goto(done_block); @@ -775,16 +786,22 @@ VisitResult ImplementationVisitor::Visit(AssignmentExpression* expr) { } VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) { - int32_t i = static_cast<int32_t>(expr->number); const Type* result_type = TypeOracle::GetConstFloat64Type(); - if (i == expr->number) { - if ((i >> 30) == (i >> 31)) { - result_type = TypeOracle::GetConstInt31Type(); - } else { - result_type = TypeOracle::GetConstInt32Type(); + if (expr->number >= std::numeric_limits<int32_t>::min() && + expr->number <= std::numeric_limits<int32_t>::max()) { + int32_t i = static_cast<int32_t>(expr->number); + if (i == expr->number) { + if ((i >> 30) == (i >> 31)) { + result_type = TypeOracle::GetConstInt31Type(); + } else { + result_type = TypeOracle::GetConstInt32Type(); + } } } - return VisitResult{result_type, ToString(expr->number)}; + std::stringstream str; + str << std::setprecision(std::numeric_limits<double>::digits10 + 1) + << expr->number; + return VisitResult{result_type, str.str()}; } VisitResult ImplementationVisitor::Visit(AssumeTypeImpossibleExpression* expr) { @@ -825,6 +842,17 @@ VisitResult ImplementationVisitor::Visit(LocationExpression* expr) { return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr))); } +VisitResult ImplementationVisitor::Visit(FieldAccessExpression* expr) { + StackScope scope(this); + LocationReference location = GetLocationReference(expr); + if (location.IsBitFieldAccess()) { + if (auto* identifier = IdentifierExpression::DynamicCast(expr->object)) { + bitfield_expressions_[expr] = identifier->name; + } + } + return scope.Yield(GenerateFetchFromLocation(location)); +} + const Type* ImplementationVisitor::Visit(GotoStatement* stmt) { Binding<LocalLabel>* label = LookupLabel(stmt->label->value); size_t parameter_count = label->parameter_types.size(); @@ -2005,25 +2033,29 @@ LocationReference ImplementationVisitor::GenerateFieldAccess( ProjectStructField(reference.temporary(), fieldname), reference.temporary_description()); } - if (reference.ReferencedType()->IsBitFieldStructType()) { - const BitFieldStructType* bitfield_struct = - BitFieldStructType::cast(reference.ReferencedType()); - const BitField& field = bitfield_struct->LookupField(fieldname); - return LocationReference::BitFieldAccess(reference, field); - } - if (const auto type_wrapped_in_smi = Type::MatchUnaryGeneric( - reference.ReferencedType(), TypeOracle::GetSmiTaggedGeneric())) { - const BitFieldStructType* bitfield_struct = - BitFieldStructType::DynamicCast(*type_wrapped_in_smi); - if (bitfield_struct == nullptr) { - ReportError( - "When a value of type SmiTagged<T> is used in a field access " - "expression, T is expected to be a bitfield struct type. Instead, T " - "is ", - **type_wrapped_in_smi); + if (base::Optional<const Type*> referenced_type = + reference.ReferencedType()) { + if ((*referenced_type)->IsBitFieldStructType()) { + const BitFieldStructType* bitfield_struct = + BitFieldStructType::cast(*referenced_type); + const BitField& field = bitfield_struct->LookupField(fieldname); + return LocationReference::BitFieldAccess(reference, field); + } + if (const auto type_wrapped_in_smi = Type::MatchUnaryGeneric( + (*referenced_type), TypeOracle::GetSmiTaggedGeneric())) { + const BitFieldStructType* bitfield_struct = + BitFieldStructType::DynamicCast(*type_wrapped_in_smi); + if (bitfield_struct == nullptr) { + ReportError( + "When a value of type SmiTagged<T> is used in a field access " + "expression, T is expected to be a bitfield struct type. Instead, " + "T " + "is ", + **type_wrapped_in_smi); + } + const BitField& field = bitfield_struct->LookupField(fieldname); + return LocationReference::BitFieldAccess(reference, field); } - const BitField& field = bitfield_struct->LookupField(fieldname); - return LocationReference::BitFieldAccess(reference, field); } if (reference.IsHeapReference()) { VisitResult ref = reference.heap_reference(); @@ -2188,7 +2220,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( } else if (reference.IsVariableAccess()) { return GenerateCopy(reference.variable()); } else if (reference.IsHeapReference()) { - const Type* referenced_type = reference.ReferencedType(); + const Type* referenced_type = *reference.ReferencedType(); if (referenced_type == TypeOracle::GetFloat64OrHoleType()) { return GenerateCall(QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, "LoadFloat64OrHole"), @@ -2205,9 +2237,9 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( return VisitResult(referenced_type, result_range); } else { GenerateCopy(reference.heap_reference()); - assembler().Emit(LoadReferenceInstruction{reference.ReferencedType()}); - DCHECK_EQ(1, LoweredSlotCount(reference.ReferencedType())); - return VisitResult(reference.ReferencedType(), assembler().TopRange(1)); + assembler().Emit(LoadReferenceInstruction{referenced_type}); + DCHECK_EQ(1, LoweredSlotCount(referenced_type)); + return VisitResult(referenced_type, assembler().TopRange(1)); } } else if (reference.IsBitFieldAccess()) { // First fetch the bitfield struct, then get the bits out of it. @@ -2215,7 +2247,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( GenerateFetchFromLocation(reference.bit_field_struct_location()); assembler().Emit(LoadBitFieldInstruction{bit_field_struct.type(), reference.bit_field()}); - return VisitResult(reference.ReferencedType(), assembler().TopRange(1)); + return VisitResult(*reference.ReferencedType(), assembler().TopRange(1)); } else { if (reference.IsHeapSlice()) { ReportError( @@ -2248,7 +2280,7 @@ void ImplementationVisitor::GenerateAssignToLocation( } else if (reference.IsHeapSlice()) { ReportError("assigning a value directly to an indexed field isn't allowed"); } else if (reference.IsHeapReference()) { - const Type* referenced_type = reference.ReferencedType(); + const Type* referenced_type = *reference.ReferencedType(); if (reference.IsConst()) { Error("cannot assign to const value of type ", *referenced_type).Throw(); } @@ -2290,7 +2322,7 @@ void ImplementationVisitor::GenerateAssignToLocation( VisitResult bit_field_struct = GenerateFetchFromLocation(reference.bit_field_struct_location()); VisitResult converted_value = - GenerateImplicitConvert(reference.ReferencedType(), assignment_value); + GenerateImplicitConvert(*reference.ReferencedType(), assignment_value); VisitResult updated_bit_field_struct = GenerateSetBitField(bit_field_struct.type(), reference.bit_field(), bit_field_struct, converted_value); @@ -2371,6 +2403,29 @@ void ImplementationVisitor::AddCallParameter( } } +namespace { +std::pair<std::string, std::string> GetClassInstanceTypeRange( + const ClassType* class_type) { + std::pair<std::string, std::string> result; + if (class_type->InstanceTypeRange()) { + auto instance_type_range = *class_type->InstanceTypeRange(); + std::string instance_type_string_first = + "static_cast<InstanceType>(" + + std::to_string(instance_type_range.first) + ")"; + std::string instance_type_string_second = + "static_cast<InstanceType>(" + + std::to_string(instance_type_range.second) + ")"; + result = + std::make_pair(instance_type_string_first, instance_type_string_second); + } else { + ReportError( + "%Min/MaxInstanceType must take a class type that is either a string " + "or has a generated instance type range"); + } + return result; +} +} // namespace + VisitResult ImplementationVisitor::GenerateCall( Callable* callable, base::Optional<LocationReference> this_reference, Arguments arguments, const TypeVector& specialization_types, @@ -2601,6 +2656,48 @@ VisitResult ImplementationVisitor::GenerateCall( Error("size of ", *type, " is not known."); } return VisitResult(return_type, size_string); + } else if (intrinsic->ExternalName() == "%ClassHasMapConstant") { + const Type* type = specialization_types[0]; + const ClassType* class_type = ClassType::DynamicCast(type); + if (!class_type) { + ReportError("%ClassHasMapConstant must take a class type parameter"); + } + // If the class isn't actually used as the parameter to a TNode, + // then we can't rely on the class existing in C++ or being of the same + // type (e.g. it could be a template), so don't use the template CSA + // machinery for accessing the class' map. + if (class_type->name() != class_type->GetGeneratedTNodeTypeName()) { + return VisitResult(return_type, std::string("false")); + } else { + return VisitResult( + return_type, + std::string("CodeStubAssembler(state_).ClassHasMapConstant<") + + class_type->name() + ">()"); + } + } else if (intrinsic->ExternalName() == "%MinInstanceType") { + if (specialization_types.size() != 1) { + ReportError("%MinInstanceType must take a single type parameter"); + } + const Type* type = specialization_types[0]; + const ClassType* class_type = ClassType::DynamicCast(type); + if (!class_type) { + ReportError("%MinInstanceType must take a class type parameter"); + } + std::pair<std::string, std::string> instance_types = + GetClassInstanceTypeRange(class_type); + return VisitResult(return_type, instance_types.first); + } else if (intrinsic->ExternalName() == "%MaxInstanceType") { + if (specialization_types.size() != 1) { + ReportError("%MaxInstanceType must take a single type parameter"); + } + const Type* type = specialization_types[0]; + const ClassType* class_type = ClassType::DynamicCast(type); + if (!class_type) { + ReportError("%MaxInstanceType must take a class type parameter"); + } + std::pair<std::string, std::string> instance_types = + GetClassInstanceTypeRange(class_type); + return VisitResult(return_type, instance_types.second); } else if (intrinsic->ExternalName() == "%RawConstexprCast") { if (intrinsic->signature().parameter_types.types.size() != 1 || constexpr_arguments.size() != 1) { @@ -2674,6 +2771,16 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr, LanguageServerData::AddDefinition(expr->callee->name->pos, callable->IdentifierPosition()); } + if (expr->callee->name->value == "!" && arguments.parameters.size() == 1) { + PropagateBitfieldMark(expr->arguments[0], expr); + } + if (expr->callee->name->value == "==" && arguments.parameters.size() == 2) { + if (arguments.parameters[0].type()->IsConstexpr()) { + PropagateBitfieldMark(expr->arguments[1], expr); + } else if (arguments.parameters[1].type()->IsConstexpr()) { + PropagateBitfieldMark(expr->arguments[0], expr); + } + } return scope.Yield( GenerateCall(name, arguments, specialization_types, is_tailcall)); } @@ -2691,7 +2798,7 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) { target = LocationReference::Temporary(result, "this parameter"); } const AggregateType* target_type = - AggregateType::DynamicCast(target.ReferencedType()); + AggregateType::DynamicCast(*target.ReferencedType()); if (!target_type) { ReportError("target of method call not a struct or class type"); } @@ -3333,6 +3440,9 @@ void ImplementationVisitor::GenerateBitFields( << " = 1 << " << field.offset << ", \\\n"; } header << " }; \\\n"; + header << " using Flags = base::Flags<Flag>; \\\n"; + header << " static constexpr int kFlagCount = " + << type->fields().size() << "; \\\n"; } header << "\n"; @@ -4035,7 +4145,7 @@ void ImplementationVisitor::GenerateClassDefinitions( structs_used_in_classes.insert(*field_as_struct); } } - if (type->ShouldExport()) { + if (type->ShouldExport() && !type->IsAbstract()) { factory_header << type->HandlifiedCppTypeName() << " New" << type->name() << "("; factory_impl << type->HandlifiedCppTypeName() << " Factory::New" diff --git a/chromium/v8/src/torque/implementation-visitor.h b/chromium/v8/src/torque/implementation-visitor.h index c980f3d59b1..14506d0bf5c 100644 --- a/chromium/v8/src/torque/implementation-visitor.h +++ b/chromium/v8/src/torque/implementation-visitor.h @@ -137,7 +137,7 @@ class LocationReference { return *bit_field_; } - const Type* ReferencedType() const { + base::Optional<const Type*> ReferencedType() const { if (IsHeapReference()) { return *TypeOracle::MatchReferenceGeneric(heap_reference().type()); } @@ -148,7 +148,10 @@ class LocationReference { if (IsBitFieldAccess()) { return bit_field_->name_and_type.type; } - return GetVisitResult().type(); + if (IsVariableAccess() || IsHeapSlice() || IsTemporary()) { + return GetVisitResult().type(); + } + return base::nullopt; } const VisitResult& GetVisitResult() const { @@ -498,6 +501,7 @@ class ImplementationVisitor { VisitResult GetBuiltinCode(Builtin* builtin); VisitResult Visit(LocationExpression* expr); + VisitResult Visit(FieldAccessExpression* expr); void VisitAllDeclarables(); void Visit(Declarable* delarable); @@ -783,9 +787,32 @@ class ImplementationVisitor { ReplaceFileContentsIfDifferent(file, content); } + const Identifier* TryGetSourceForBitfieldExpression( + const Expression* expr) const { + auto it = bitfield_expressions_.find(expr); + if (it == bitfield_expressions_.end()) return nullptr; + return it->second; + } + + void PropagateBitfieldMark(const Expression* original, + const Expression* derived) { + if (const Identifier* source = + TryGetSourceForBitfieldExpression(original)) { + bitfield_expressions_[derived] = source; + } + } + base::Optional<CfgAssembler> assembler_; NullOStream null_stream_; bool is_dry_run_; + + // Just for allowing us to emit warnings. After visiting an Expression, if + // that Expression is a bitfield load, plus an optional inversion or an + // equality check with a constant, then that Expression will be present in + // this map. The Identifier associated is the bitfield struct that contains + // the value to load. + std::unordered_map<const Expression*, const Identifier*> + bitfield_expressions_; }; void ReportAllUnusedMacros(); diff --git a/chromium/v8/src/torque/instance-type-generator.cc b/chromium/v8/src/torque/instance-type-generator.cc index 6e708f7fea6..2b53383f61a 100644 --- a/chromium/v8/src/torque/instance-type-generator.cc +++ b/chromium/v8/src/torque/instance-type-generator.cc @@ -436,11 +436,11 @@ void ImplementationVisitor::GenerateInstanceTypes( header << only_declared_range_instance_types.str(); header << "\n"; - std::stringstream torque_internal_class_list; - std::stringstream torque_internal_varsize_instance_type_list; - std::stringstream torque_internal_fixed_instance_type_list; - std::stringstream torque_internal_map_csa_list; - std::stringstream torque_internal_map_root_list; + std::stringstream torque_defined_class_list; + std::stringstream torque_defined_varsize_instance_type_list; + std::stringstream torque_defined_fixed_instance_type_list; + std::stringstream torque_defined_map_csa_list; + std::stringstream torque_defined_map_root_list; for (const ClassType* type : TypeOracle::GetClasses()) { std::string upper_case_name = type->name(); @@ -449,41 +449,40 @@ void ImplementationVisitor::GenerateInstanceTypes( CapifyStringWithUnderscores(type->name()) + "_TYPE"; if (type->IsExtern()) continue; - torque_internal_class_list << " V(" << upper_case_name << ") \\\n"; + torque_defined_class_list << " V(" << upper_case_name << ") \\\n"; if (type->IsAbstract()) continue; - torque_internal_map_csa_list << " V(" << upper_case_name << "Map, " - << lower_case_name << "_map, " + torque_defined_map_csa_list << " V(_, " << upper_case_name << "Map, " + << lower_case_name << "_map, " + << upper_case_name << ") \\\n"; + torque_defined_map_root_list << " V(Map, " << lower_case_name << "_map, " << upper_case_name << "Map) \\\n"; - torque_internal_map_root_list << " V(Map, " << lower_case_name - << "_map, " << upper_case_name - << "Map) \\\n"; - std::stringstream& list = - type->HasStaticSize() ? torque_internal_fixed_instance_type_list - : torque_internal_varsize_instance_type_list; + std::stringstream& list = type->HasStaticSize() + ? torque_defined_fixed_instance_type_list + : torque_defined_varsize_instance_type_list; list << " V(" << instance_type_name << ", " << upper_case_name << ", " << lower_case_name << ") \\\n"; } - header << "// Non-extern Torque classes.\n"; - header << "#define TORQUE_INTERNAL_CLASS_LIST(V) \\\n"; - header << torque_internal_class_list.str(); + header << "// Fully Torque-defined classes (both internal and exported).\n"; + header << "#define TORQUE_DEFINED_CLASS_LIST(V) \\\n"; + header << torque_defined_class_list.str(); header << "\n"; - header << "#define TORQUE_INTERNAL_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n"; - header << torque_internal_varsize_instance_type_list.str(); + header << "#define TORQUE_DEFINED_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n"; + header << torque_defined_varsize_instance_type_list.str(); header << "\n"; - header << "#define TORQUE_INTERNAL_FIXED_INSTANCE_TYPE_LIST(V) \\\n"; - header << torque_internal_fixed_instance_type_list.str(); + header << "#define TORQUE_DEFINED_FIXED_INSTANCE_TYPE_LIST(V) \\\n"; + header << torque_defined_fixed_instance_type_list.str(); header << "\n"; - header << "#define TORQUE_INTERNAL_INSTANCE_TYPE_LIST(V) \\\n"; - header << " TORQUE_INTERNAL_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n"; - header << " TORQUE_INTERNAL_FIXED_INSTANCE_TYPE_LIST(V) \\\n"; + header << "#define TORQUE_DEFINED_INSTANCE_TYPE_LIST(V) \\\n"; + header << " TORQUE_DEFINED_VARSIZE_INSTANCE_TYPE_LIST(V) \\\n"; + header << " TORQUE_DEFINED_FIXED_INSTANCE_TYPE_LIST(V) \\\n"; header << "\n"; - header << "#define TORQUE_INTERNAL_MAP_CSA_LIST(V) \\\n"; - header << torque_internal_map_csa_list.str(); + header << "#define TORQUE_DEFINED_MAP_CSA_LIST_GENERATOR(V, _) \\\n"; + header << torque_defined_map_csa_list.str(); header << "\n"; - header << "#define TORQUE_INTERNAL_MAP_ROOT_LIST(V) \\\n"; - header << torque_internal_map_root_list.str(); + header << "#define TORQUE_DEFINED_MAP_ROOT_LIST(V) \\\n"; + header << torque_defined_map_root_list.str(); header << "\n"; } std::string output_header_path = output_directory + "/" + file_name; diff --git a/chromium/v8/src/torque/instructions.h b/chromium/v8/src/torque/instructions.h index 4609e8c223e..528d5c742ee 100644 --- a/chromium/v8/src/torque/instructions.h +++ b/chromium/v8/src/torque/instructions.h @@ -166,11 +166,11 @@ inline std::ostream& operator<<(std::ostream& stream, << loc.GetParameterIndex() << ")"; case DefinitionLocation::Kind::kPhi: return stream << "DefinitionLocation::Phi(" << std::hex - << (uint64_t)loc.GetPhiBlock() << std::dec << ", " + << loc.GetPhiBlock() << std::dec << ", " << loc.GetPhiIndex() << ")"; case DefinitionLocation::Kind::kInstruction: return stream << "DefinitionLocation::Instruction(" << std::hex - << (uint64_t)loc.GetInstruction() << std::dec << ", " + << loc.GetInstruction() << std::dec << ", " << loc.GetInstructionIndex() << ")"; } } diff --git a/chromium/v8/src/torque/ls/message.h b/chromium/v8/src/torque/ls/message.h index 0d84d2ffafd..513a1e0d43a 100644 --- a/chromium/v8/src/torque/ls/message.h +++ b/chromium/v8/src/torque/ls/message.h @@ -82,8 +82,8 @@ class Message : public BaseJsonAccessor { JSON_STRING_ACCESSORS(jsonrpc) protected: - const JsonObject& object() const { return value_.ToObject(); } - JsonObject& object() { return value_.ToObject(); } + const JsonObject& object() const override { return value_.ToObject(); } + JsonObject& object() override { return value_.ToObject(); } private: JsonValue value_; @@ -96,8 +96,8 @@ class NestedJsonAccessor : public BaseJsonAccessor { public: explicit NestedJsonAccessor(JsonObject& object) : object_(object) {} - const JsonObject& object() const { return object_; } - JsonObject& object() { return object_; } + const JsonObject& object() const override { return object_; } + JsonObject& object() override { return object_; } private: JsonObject& object_; diff --git a/chromium/v8/src/torque/torque-compiler.cc b/chromium/v8/src/torque/torque-compiler.cc index fd717b2649b..20bc2973547 100644 --- a/chromium/v8/src/torque/torque-compiler.cc +++ b/chromium/v8/src/torque/torque-compiler.cc @@ -55,6 +55,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) { } TargetArchitecture::Scope target_architecture(options.force_32bit_output); TypeOracle::Scope type_oracle; + CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace()); // Two-step process of predeclaration + resolution allows to resolve type // declarations independent of the order they are given. diff --git a/chromium/v8/src/torque/torque-parser.cc b/chromium/v8/src/torque/torque-parser.cc index fa496ae6a09..a79f271eec8 100644 --- a/chromium/v8/src/torque/torque-parser.cc +++ b/chromium/v8/src/torque/torque-parser.cc @@ -855,7 +855,7 @@ base::Optional<ParseResult> MakeClassDeclaration( {ANNOTATION_GENERATE_PRINT, ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT, ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT, ANNOTATION_GENERATE_CPP_CLASS, ANNOTATION_GENERATE_BODY_DESCRIPTOR, - ANNOTATION_EXPORT_CPP_CLASS, + ANNOTATION_EXPORT_CPP_CLASS, ANNOTATION_DO_NOT_GENERATE_CAST, ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT, ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT}, {ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, @@ -874,6 +874,9 @@ base::Optional<ParseResult> MakeClassDeclaration( if (annotations.Contains(ANNOTATION_GENERATE_CPP_CLASS)) { flags |= ClassFlag::kGenerateCppClassDefinitions; } + if (annotations.Contains(ANNOTATION_DO_NOT_GENERATE_CAST)) { + flags |= ClassFlag::kDoNotGenerateCast; + } if (annotations.Contains(ANNOTATION_GENERATE_BODY_DESCRIPTOR)) { flags |= ClassFlag::kGenerateBodyDescriptor; } @@ -896,6 +899,7 @@ base::Optional<ParseResult> MakeClassDeclaration( flags |= ClassFlag::kIsShape; flags |= ClassFlag::kTransient; flags |= ClassFlag::kHasSameInstanceTypeAsParent; + flags |= ClassFlag::kDoNotGenerateCast; } else { DCHECK_EQ(kind, "class"); } @@ -934,9 +938,60 @@ base::Optional<ParseResult> MakeClassDeclaration( return true; }); - Declaration* result = MakeNode<ClassDeclaration>( + std::vector<Declaration*> result; + + result.push_back(MakeNode<ClassDeclaration>( name, flags, std::move(extends), std::move(generates), std::move(methods), - fields, MakeInstanceTypeConstraints(annotations)); + fields, MakeInstanceTypeConstraints(annotations))); + + if ((flags & ClassFlag::kDoNotGenerateCast) == 0 && + (flags & ClassFlag::kIsShape) == 0) { + ParameterList parameters; + parameters.names.push_back(MakeNode<Identifier>("obj")); + parameters.types.push_back( + MakeNode<BasicTypeExpression>(std::vector<std::string>{}, "HeapObject", + std::vector<TypeExpression*>{})); + LabelAndTypesVector labels; + labels.push_back(LabelAndTypes{MakeNode<Identifier>("CastError"), + std::vector<TypeExpression*>{}}); + + TypeExpression* class_type = + MakeNode<BasicTypeExpression>(std::vector<std::string>{}, name->value, + std::vector<TypeExpression*>{}); + + std::vector<std::string> namespace_qualification{ + TORQUE_INTERNAL_NAMESPACE_STRING}; + + IdentifierExpression* internal_downcast_target = + MakeNode<IdentifierExpression>( + namespace_qualification, + MakeNode<Identifier>("DownCastForTorqueClass"), + std::vector<TypeExpression*>{class_type}); + IdentifierExpression* internal_downcast_otherwise = + MakeNode<IdentifierExpression>(std::vector<std::string>{}, + MakeNode<Identifier>("CastError")); + + Expression* argument = MakeNode<IdentifierExpression>( + std::vector<std::string>{}, MakeNode<Identifier>("obj")); + + auto value = MakeCall(internal_downcast_target, base::nullopt, + std::vector<Expression*>{argument}, + std::vector<Statement*>{MakeNode<ExpressionStatement>( + internal_downcast_otherwise)}); + + auto cast_body = MakeNode<ReturnStatement>(value); + + std::vector<TypeExpression*> generic_parameters; + generic_parameters.push_back( + MakeNode<BasicTypeExpression>(std::vector<std::string>{}, name->value, + std::vector<TypeExpression*>{})); + + Declaration* specialization = MakeNode<SpecializationDeclaration>( + false, MakeNode<Identifier>("Cast"), generic_parameters, + std::move(parameters), class_type, std::move(labels), cast_body); + result.push_back(specialization); + } + return ParseResult{result}; } @@ -1602,6 +1657,17 @@ base::Optional<ParseResult> MakeRightShiftIdentifier( return ParseResult{MakeNode<Identifier>(str)}; } +base::Optional<ParseResult> MakeNamespaceQualification( + ParseResultIterator* child_results) { + bool global_namespace = child_results->NextAs<bool>(); + auto namespace_qualification = + child_results->NextAs<std::vector<std::string>>(); + if (global_namespace) { + namespace_qualification.insert(namespace_qualification.begin(), ""); + } + return ParseResult(std::move(namespace_qualification)); +} + base::Optional<ParseResult> MakeIdentifierExpression( ParseResultIterator* child_results) { auto namespace_qualification = @@ -1982,14 +2048,19 @@ struct TorqueGrammar : Grammar { // Result: std::vector<Annotation> Symbol* annotations = List<Annotation>(&annotation); + // Result: std::vector<std::string> + Symbol namespaceQualification = { + Rule({CheckIf(Token("::")), + List<std::string>(Sequence({&identifier, Token("::")}))}, + MakeNamespaceQualification)}; + // Result: TypeList Symbol* typeList = List<TypeExpression*>(&type, Token(",")); // Result: TypeExpression* Symbol simpleType = { Rule({Token("("), &type, Token(")")}), - Rule({List<std::string>(Sequence({&identifier, Token("::")})), - CheckIf(Token("constexpr")), &identifier, + Rule({&namespaceQualification, CheckIf(Token("constexpr")), &identifier, TryOrDefault<std::vector<TypeExpression*>>( &genericSpecializationTypeList)}, MakeBasicTypeExpression), @@ -2123,7 +2194,7 @@ struct TorqueGrammar : Grammar { // Result: Expression* Symbol identifierExpression = { - Rule({List<std::string>(Sequence({&identifier, Token("::")})), &name, + Rule({&namespaceQualification, &name, TryOrDefault<TypeList>(&genericSpecializationTypeList)}, MakeIdentifierExpression), }; @@ -2369,7 +2440,7 @@ struct TorqueGrammar : Grammar { Optional<std::string>( Sequence({Token("generates"), &externalString})), &optionalClassBody}, - AsSingletonVector<Declaration*, MakeClassDeclaration>()), + MakeClassDeclaration), Rule({annotations, Token("struct"), &name, TryOrDefault<GenericParameters>(&genericParameters), Token("{"), List<Declaration*>(&method), diff --git a/chromium/v8/src/torque/type-visitor.cc b/chromium/v8/src/torque/type-visitor.cc index 5b61baf3a83..453d71e4639 100644 --- a/chromium/v8/src/torque/type-visitor.cc +++ b/chromium/v8/src/torque/type-visitor.cc @@ -311,6 +311,16 @@ const ClassType* TypeVisitor::ComputeType( flags = flags | ClassFlag::kGeneratePrint | ClassFlag::kGenerateVerify | ClassFlag::kGenerateBodyDescriptor; } + if (!(flags & ClassFlag::kExtern) && + (flags & ClassFlag::kHasSameInstanceTypeAsParent)) { + Error("non-extern Torque-defined classes must have unique instance types"); + } + if ((flags & ClassFlag::kHasSameInstanceTypeAsParent) && + !(flags & ClassFlag::kDoNotGenerateCast || flags & ClassFlag::kIsShape)) { + Error( + "classes that inherit their instance type must be annotated with " + "@doNotGenerateCast"); + } return TypeOracle::GetClassType(super_type, decl->name->value, flags, generates, decl, alias); diff --git a/chromium/v8/src/torque/types.h b/chromium/v8/src/torque/types.h index c01d55ccff0..7d84ae6a045 100644 --- a/chromium/v8/src/torque/types.h +++ b/chromium/v8/src/torque/types.h @@ -104,6 +104,7 @@ struct RuntimeType { class V8_EXPORT_PRIVATE Type : public TypeBase { public: + Type& operator=(const Type& other) = delete; virtual bool IsSubtypeOf(const Type* supertype) const; // Default rendering for error messages etc. @@ -164,7 +165,6 @@ class V8_EXPORT_PRIVATE Type : public TypeBase { Type(TypeBase::Kind kind, const Type* parent, MaybeSpecializationKey specialized_from = base::nullopt); Type(const Type& other) V8_NOEXCEPT; - Type& operator=(const Type& other) = delete; void set_parent(const Type* t) { parent_ = t; } int Depth() const; virtual std::string ToExplicitString() const = 0; @@ -660,6 +660,9 @@ class ClassType final : public AggregateType { if (IsAbstract()) return false; return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern(); } + bool DoNotGenerateCast() const { + return flags_ & ClassFlag::kDoNotGenerateCast; + } bool IsTransient() const override { return flags_ & ClassFlag::kTransient; } bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; } bool HasSameInstanceTypeAsParent() const { diff --git a/chromium/v8/src/torque/utils.h b/chromium/v8/src/torque/utils.h index 689d242ab0d..52efe6564e7 100644 --- a/chromium/v8/src/torque/utils.h +++ b/chromium/v8/src/torque/utils.h @@ -47,6 +47,7 @@ std::string ToString(Args&&... args) { class V8_EXPORT_PRIVATE MessageBuilder { public: + MessageBuilder() = delete; MessageBuilder(const std::string& message, TorqueMessage::Kind kind); MessageBuilder& Position(SourcePosition position) { @@ -62,7 +63,6 @@ class V8_EXPORT_PRIVATE MessageBuilder { } private: - MessageBuilder() = delete; void Report() const; TorqueMessage message_; @@ -172,9 +172,7 @@ void PrintCommaSeparatedList(std::ostream& os, const T& list) { struct BottomOffset { size_t offset; - BottomOffset(std::nullptr_t zero = 0) // NOLINT(runtime/explicit) - : offset(0) {} - explicit BottomOffset(std::size_t offset) : offset(offset) {} + BottomOffset& operator=(std::size_t offset) { this->offset = offset; return *this; @@ -370,10 +368,10 @@ class IfDefScope { public: IfDefScope(std::ostream& os, std::string d); ~IfDefScope(); - - private: IfDefScope(const IfDefScope&) = delete; IfDefScope& operator=(const IfDefScope&) = delete; + + private: std::ostream& os_; std::string d_; }; @@ -383,10 +381,10 @@ class NamespaceScope { NamespaceScope(std::ostream& os, std::initializer_list<std::string> namespaces); ~NamespaceScope(); - - private: NamespaceScope(const NamespaceScope&) = delete; NamespaceScope& operator=(const NamespaceScope&) = delete; + + private: std::ostream& os_; std::vector<std::string> d_; }; @@ -395,10 +393,10 @@ class IncludeGuardScope { public: IncludeGuardScope(std::ostream& os, std::string file_name); ~IncludeGuardScope(); - - private: IncludeGuardScope(const IncludeGuardScope&) = delete; IncludeGuardScope& operator=(const IncludeGuardScope&) = delete; + + private: std::ostream& os_; std::string d_; }; @@ -407,10 +405,10 @@ class IncludeObjectMacrosScope { public: explicit IncludeObjectMacrosScope(std::ostream& os); ~IncludeObjectMacrosScope(); - - private: IncludeObjectMacrosScope(const IncludeObjectMacrosScope&) = delete; IncludeObjectMacrosScope& operator=(const IncludeObjectMacrosScope&) = delete; + + private: std::ostream& os_; }; |