diff options
Diffstat (limited to 'deps/v8/src/torque')
22 files changed, 820 insertions, 244 deletions
diff --git a/deps/v8/src/torque/ast.h b/deps/v8/src/torque/ast.h index 5ce25cf13a..fcbb02124d 100644 --- a/deps/v8/src/torque/ast.h +++ b/deps/v8/src/torque/ast.h @@ -90,7 +90,8 @@ namespace torque { AST_STATEMENT_NODE_KIND_LIST(V) \ AST_DECLARATION_NODE_KIND_LIST(V) \ V(Identifier) \ - V(LabelBlock) + V(LabelBlock) \ + V(ClassBody) struct AstNode { public: @@ -792,6 +793,12 @@ struct TypeDeclaration : Declaration { Identifier* name; }; +struct InstanceTypeConstraints { + InstanceTypeConstraints() : value(-1), num_flags_bits(-1) {} + int value; + int num_flags_bits; +}; + struct AbstractTypeDeclaration : TypeDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(AbstractTypeDeclaration) AbstractTypeDeclaration(SourcePosition pos, Identifier* name, bool transient, @@ -1069,24 +1076,38 @@ struct StructDeclaration : TypeDeclaration { bool IsGeneric() const { return !generic_parameters.empty(); } }; +struct ClassBody : AstNode { + DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassBody) + ClassBody(SourcePosition pos, std::vector<Declaration*> methods, + std::vector<ClassFieldExpression> fields) + : AstNode(kKind, pos), + methods(std::move(methods)), + fields(std::move(fields)) {} + std::vector<Declaration*> methods; + std::vector<ClassFieldExpression> fields; +}; + struct ClassDeclaration : TypeDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration) ClassDeclaration(SourcePosition pos, Identifier* name, ClassFlags flags, base::Optional<TypeExpression*> super, base::Optional<std::string> generates, std::vector<Declaration*> methods, - std::vector<ClassFieldExpression> fields) + std::vector<ClassFieldExpression> fields, + InstanceTypeConstraints instance_type_constraints) : TypeDeclaration(kKind, pos, name), flags(flags), super(super), generates(std::move(generates)), methods(std::move(methods)), - fields(std::move(fields)) {} + fields(std::move(fields)), + instance_type_constraints(std::move(instance_type_constraints)) {} ClassFlags flags; base::Optional<TypeExpression*> super; base::Optional<std::string> generates; std::vector<Declaration*> methods; std::vector<ClassFieldExpression> fields; + InstanceTypeConstraints instance_type_constraints; }; struct CppIncludeDeclaration : Declaration { diff --git a/deps/v8/src/torque/class-debug-reader-generator.cc b/deps/v8/src/torque/class-debug-reader-generator.cc index 6abdffcc91..fca2409959 100644 --- a/deps/v8/src/torque/class-debug-reader-generator.cc +++ b/deps/v8/src/torque/class-debug-reader-generator.cc @@ -10,12 +10,20 @@ namespace v8 { namespace internal { namespace torque { +const char* tq_object_override_decls = + R"( std::vector<std::unique_ptr<ObjectProperty>> GetProperties( + d::MemoryAccessor accessor) const override; + const char* GetName() const override; + void Visit(TqObjectVisitor* visitor) const override; + bool IsSuperclassOf(const TqObject* other) const override; +)"; + namespace { void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, std::ostream& cc_contents, std::ostream& visitor, std::unordered_set<const ClassType*>* done) { // Make sure each class only gets generated once. - if (!type.IsExtern() || !done->insert(&type).second) return; + if (!done->insert(&type).second) return; const ClassType* super_type = type.GetSuperClass(); // We must emit the classes in dependency order. If the super class hasn't @@ -25,6 +33,10 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, done); } + // Classes with undefined layout don't grant any particular value here and may + // not correspond with actual C++ classes, so skip them. + if (type.HasUndefinedLayout()) return; + const std::string name = type.name(); const std::string super_name = super_type == nullptr ? "Object" : super_type->name(); @@ -32,10 +44,7 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, h_contents << " public:\n"; h_contents << " inline Tq" << name << "(uintptr_t address) : Tq" << super_name << "(address) {}\n"; - h_contents << " std::vector<std::unique_ptr<ObjectProperty>> " - "GetProperties(d::MemoryAccessor accessor) const override;\n"; - h_contents << " const char* GetName() const override;\n"; - h_contents << " void Visit(TqObjectVisitor* visitor) const override;\n"; + h_contents << tq_object_override_decls; cc_contents << "\nconst char* Tq" << name << "::GetName() const {\n"; cc_contents << " return \"v8::internal::" << name << "\";\n"; @@ -46,6 +55,13 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, cc_contents << " visitor->Visit" << name << "(this);\n"; cc_contents << "}\n"; + cc_contents << "\nbool Tq" << name + << "::IsSuperclassOf(const TqObject* other) const {\n"; + cc_contents + << " return GetName() != other->GetName() && dynamic_cast<const Tq" + << name << "*>(other) != nullptr;\n"; + cc_contents << "}\n"; + visitor << " virtual void Visit" << name << "(const Tq" << name << "* object) {\n"; visitor << " Visit" << super_name << "(object);\n"; @@ -71,9 +87,10 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, if (is_field_tagged) { field_value_type = "uintptr_t"; field_value_type_compressed = "i::Tagged_t"; - field_cc_type = "v8::internal::" + (field_class_type.has_value() - ? (*field_class_type)->name() - : "Object"); + field_cc_type = "v8::internal::" + + (field_class_type.has_value() + ? (*field_class_type)->GetGeneratedTNodeTypeName() + : "Object"); field_cc_type_compressed = COMPRESS_POINTERS_BOOL ? "v8::internal::TaggedValue" : field_cc_type; } else { @@ -107,7 +124,7 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, std::string index_param; std::string index_offset; if (field.index) { - const Type* index_type = (*field.index)->name_and_type.type; + const Type* index_type = field.index->type; std::string index_type_name; std::string index_value; if (index_type == TypeOracle::GetSmiType()) { @@ -129,18 +146,17 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, } get_props_impl << " Value<" << index_type_name << "> indexed_field_count = Get" - << CamelifyString((*field.index)->name_and_type.name) + << CamelifyString(field.index->name) << "Value(accessor);\n"; indexed_field_info = ", " + index_value + ", GetArrayKind(indexed_field_count.validity)"; index_param = ", size_t offset"; index_offset = " + offset * sizeof(value)"; } - get_props_impl - << " result.push_back(v8::base::make_unique<ObjectProperty>(\"" - << field_name << "\", \"" << field_cc_type_compressed << "\", \"" - << field_cc_type << "\", " << address_getter << "()" - << indexed_field_info << "));\n"; + get_props_impl << " result.push_back(std::make_unique<ObjectProperty>(\"" + << field_name << "\", \"" << field_cc_type_compressed + << "\", \"" << field_cc_type << "\", " << address_getter + << "()" << indexed_field_info << "));\n"; h_contents << " uintptr_t " << address_getter << "() const;\n"; h_contents << " Value<" << field_value_type << "> " << field_getter @@ -158,7 +174,8 @@ void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, << address_getter << "()" << index_offset << ", reinterpret_cast<uint8_t*>(&value), sizeof(value));\n"; cc_contents << " return {validity, " - << (is_field_tagged ? "Decompress(value, address_)" : "value") + << (is_field_tagged ? "EnsureDecompressed(value, address_)" + : "value") << "};\n"; cc_contents << "}\n"; } @@ -192,6 +209,11 @@ void ImplementationVisitor::GenerateClassDebugReaders( h_contents << "\n#include \"tools/debug_helper/debug-helper-internal.h\"\n\n"; + h_contents << "// Unset a windgi.h macro that causes conflicts.\n"; + h_contents << "#ifdef GetBValue\n"; + h_contents << "#undef GetBValue\n"; + h_contents << "#endif\n\n"; + cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n"; cc_contents << "#include \"include/v8-internal.h\"\n\n"; cc_contents << "namespace i = v8::internal;\n\n"; diff --git a/deps/v8/src/torque/constants.h b/deps/v8/src/torque/constants.h index efbbf9588e..ebfbab0cba 100644 --- a/deps/v8/src/torque/constants.h +++ b/deps/v8/src/torque/constants.h @@ -55,6 +55,25 @@ static const char* const REFERENCE_TYPE_STRING = "Reference"; static const char* const SLICE_TYPE_STRING = "Slice"; static const char* const STRUCT_NAMESPACE_STRING = "_struct"; +static const char* const ANNOTATION_GENERATE_PRINT = "@generatePrint"; +static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier"; +static const char* const ANNOTATION_ABSTRACT = "@abstract"; +static const char* const ANNOTATION_INSTANTIATED_ABSTRACT_CLASS = + "@dirtyInstantiatedAbstractClass"; +static const char* const ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT = + "@hasSameInstanceTypeAsParent"; +static const char* const ANNOTATION_GENERATE_CPP_CLASS = "@generateCppClass"; +static const char* const ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT = + "@highestInstanceTypeWithinParentClassRange"; +static const char* const ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT = + "@lowestInstanceTypeWithinParentClassRange"; +static const char* const ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE = + "@reserveBitsInInstanceType"; +static const char* const ANNOTATION_INSTANCE_TYPE_VALUE = + "@apiExposedInstanceTypeValue"; +static const char* const ANNOTATION_IF = "@if"; +static const char* const ANNOTATION_IFNOT = "@ifnot"; + inline bool IsConstexprName(const std::string& name) { return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) == CONSTEXPR_TYPE_PREFIX; @@ -80,7 +99,10 @@ enum class ClassFlag { kInstantiatedAbstractClass = 1 << 5, kHasSameInstanceTypeAsParent = 1 << 6, kGenerateCppClassDefinitions = 1 << 7, - kHasIndexedField = 1 << 8 + kHasIndexedField = 1 << 8, + kHighestInstanceTypeWithinParent = 1 << 9, + kLowestInstanceTypeWithinParent = 1 << 10, + kUndefinedLayout = 1 << 11, }; using ClassFlags = base::Flags<ClassFlag>; diff --git a/deps/v8/src/torque/csa-generator.cc b/deps/v8/src/torque/csa-generator.cc index 7925783914..2a10e4f353 100644 --- a/deps/v8/src/torque/csa-generator.cc +++ b/deps/v8/src/torque/csa-generator.cc @@ -41,7 +41,7 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) { Stack<std::string> stack; for (const Type* t : block->InputTypes()) { stack.Push(FreshNodeName()); - out_ << " compiler::TNode<" << t->GetGeneratedTNodeTypeName() << "> " + out_ << " TNode<" << t->GetGeneratedTNodeTypeName() << "> " << stack.Top() << ";\n"; } out_ << " ca_.Bind(&" << BlockName(block); @@ -56,14 +56,10 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) { } void CSAGenerator::EmitSourcePosition(SourcePosition pos, bool always_emit) { - std::string file = SourceFileMap::AbsolutePath(pos.source); + const std::string& file = SourceFileMap::AbsolutePath(pos.source); if (always_emit || !previous_position_.CompareStartIgnoreColumn(pos)) { // Lines in Torque SourcePositions are zero-based, while the // CodeStubAssembler and downwind systems are one-based. - for (auto& c : file) { - if (c == '\\') - c = '/'; - } out_ << " ca_.SetSourcePosition(\"" << file << "\", " << (pos.start.line + 1) << ");\n"; previous_position_ = pos; @@ -123,8 +119,8 @@ void CSAGenerator::EmitInstruction( for (const Type* lowered : LowerType(type)) { results.push_back(FreshNodeName()); stack->Push(results.back()); - out_ << " compiler::TNode<" << lowered->GetGeneratedTNodeTypeName() - << "> " << stack->Top() << ";\n"; + out_ << " TNode<" << lowered->GetGeneratedTNodeTypeName() << "> " + << stack->Top() << ";\n"; out_ << " USE(" << stack->Top() << ");\n"; } out_ << " "; @@ -179,7 +175,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, for (const Type* type : LowerType(return_type)) { results.push_back(FreshNodeName()); stack->Push(results.back()); - out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> " + out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> " << stack->Top() << ";\n"; out_ << " USE(" << stack->Top() << ");\n"; } @@ -302,7 +298,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, for (const Type* type : LowerType(return_type)) { results.push_back(FreshNodeName()); stack->Push(results.back()); - out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() << "> " + out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> " << stack->Top() << ";\n"; out_ << " USE(" << stack->Top() << ");\n"; } @@ -354,8 +350,8 @@ void CSAGenerator::EmitInstruction( for (const Type* type : LowerType(instruction.macro->signature().return_type)) { results.push_back(FreshNodeName()); - out_ << " compiler::TNode<" << type->GetGeneratedTNodeTypeName() - << "> " << results.back() << ";\n"; + out_ << " TNode<" << type->GetGeneratedTNodeTypeName() << "> " + << results.back() << ";\n"; out_ << " USE(" << results.back() << ");\n"; } } @@ -453,9 +449,8 @@ void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction, } else { std::string result_name = FreshNodeName(); if (result_types.size() == 1) { - out_ << " compiler::TNode<" - << result_types[0]->GetGeneratedTNodeTypeName() << "> " - << result_name << ";\n"; + out_ << " TNode<" << result_types[0]->GetGeneratedTNodeTypeName() + << "> " << result_name << ";\n"; } std::string catch_name = PreCallableExceptionPreparation(instruction.catch_block); @@ -503,8 +498,7 @@ void CSAGenerator::EmitInstruction( stack->Push(FreshNodeName()); std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName(); - out_ << " compiler::TNode<" << generated_type << "> " << stack->Top() - << " = "; + out_ << " TNode<" << generated_type << "> " << stack->Top() << " = "; if (generated_type != "Object") out_ << "TORQUE_CAST("; out_ << "CodeStubAssembler(state_).CallBuiltinPointer(Builtins::" "CallableFor(ca_." @@ -543,8 +537,7 @@ void CSAGenerator::PostCallableExceptionPreparation( if (!return_type->IsNever()) { out_ << " ca_.Goto(&" << catch_name << "_skip);\n"; } - out_ << " compiler::TNode<Object> " << catch_name - << "_exception_object;\n"; + out_ << " TNode<Object> " << catch_name << "_exception_object;\n"; out_ << " ca_.Bind(&" << catch_name << "__label, &" << catch_name << "_exception_object);\n"; out_ << " ca_.Goto(&" << block_name; @@ -579,9 +572,8 @@ void CSAGenerator::EmitInstruction(const CallRuntimeInstruction& instruction, } else { std::string result_name = FreshNodeName(); if (result_types.size() == 1) { - out_ << " compiler::TNode<" - << result_types[0]->GetGeneratedTNodeTypeName() << "> " - << result_name << ";\n"; + out_ << " TNode<" << result_types[0]->GetGeneratedTNodeTypeName() + << "> " << result_name << ";\n"; } std::string catch_name = PreCallableExceptionPreparation(instruction.catch_block); @@ -722,10 +714,9 @@ void CSAGenerator::EmitInstruction( std::string offset_name = FreshNodeName(); stack->Push(offset_name); - out_ << " compiler::TNode<IntPtrT> " << offset_name - << " = ca_.IntPtrConstant("; - out_ << field.aggregate->GetGeneratedTNodeTypeName() << "::k" - << CamelifyString(field.name_and_type.name) << "Offset"; + out_ << " TNode<IntPtrT> " << offset_name << " = ca_.IntPtrConstant("; + out_ << field.aggregate->GetGeneratedTNodeTypeName() << "::k" + << CamelifyString(field.name_and_type.name) << "Offset"; out_ << ");\n" << " USE(" << stack->Top() << ");\n"; } @@ -776,8 +767,8 @@ void CSAGenerator::EmitCSAValue(VisitResult result, out << "}"; } else { DCHECK_EQ(1, result.stack_range().Size()); - out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName() - << ">{" << values.Peek(result.stack_range().begin()) << "}"; + out << "TNode<" << result.type()->GetGeneratedTNodeTypeName() << ">{" + << values.Peek(result.stack_range().begin()) << "}"; } } diff --git a/deps/v8/src/torque/declaration-visitor.cc b/deps/v8/src/torque/declaration-visitor.cc index f762337463..c2fa1af98e 100644 --- a/deps/v8/src/torque/declaration-visitor.cc +++ b/deps/v8/src/torque/declaration-visitor.cc @@ -93,20 +93,6 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl, } } - if (TorqueBuiltinDeclaration::DynamicCast(decl)) { - for (size_t i = 0; i < signature.types().size(); ++i) { - const Type* type = signature.types()[i]; - if (!type->IsSubtypeOf(TypeOracle::GetTaggedType())) { - const Identifier* id = signature.parameter_names.size() > i - ? signature.parameter_names[i] - : nullptr; - Error("Untagged argument ", id ? (id->value + " ") : "", "at position ", - i, " to builtin ", decl->name, " is not supported.") - .Position(id ? id->pos : decl->pos); - } - } - } - if (const StructType* struct_type = StructType::DynamicCast(signature.return_type)) { Error("Builtins ", decl->name, " cannot return structs ", diff --git a/deps/v8/src/torque/declarations.h b/deps/v8/src/torque/declarations.h index 240680fa1e..f3d2544ae1 100644 --- a/deps/v8/src/torque/declarations.h +++ b/deps/v8/src/torque/declarations.h @@ -5,6 +5,7 @@ #ifndef V8_TORQUE_DECLARATIONS_H_ #define V8_TORQUE_DECLARATIONS_H_ +#include <memory> #include <string> #include "src/torque/declarable.h" diff --git a/deps/v8/src/torque/earley-parser.h b/deps/v8/src/torque/earley-parser.h index 9f7ba6a7ae..43ad6eb452 100644 --- a/deps/v8/src/torque/earley-parser.h +++ b/deps/v8/src/torque/earley-parser.h @@ -6,6 +6,7 @@ #define V8_TORQUE_EARLEY_PARSER_H_ #include <map> +#include <memory> #include <vector> #include "src/base/optional.h" @@ -82,6 +83,7 @@ enum class ParseResultHolderBase::TypeId { kTypeswitchCase, kStdVectorOfTypeswitchCase, kStdVectorOfIdentifierPtr, + kOptionalClassBody, kJsonValue, kJsonMember, @@ -248,7 +250,7 @@ class Symbol { size_t rule_number() const { return rules_.size(); } void AddRule(const Rule& rule) { - rules_.push_back(base::make_unique<Rule>(rule)); + rules_.push_back(std::make_unique<Rule>(rule)); rules_.back()->SetLeftHandSide(this); } diff --git a/deps/v8/src/torque/global-context.cc b/deps/v8/src/torque/global-context.cc index 13503038c5..e236de5a93 100644 --- a/deps/v8/src/torque/global-context.cc +++ b/deps/v8/src/torque/global-context.cc @@ -19,7 +19,7 @@ GlobalContext::GlobalContext(Ast ast) CurrentSourcePosition::Scope current_source_position( SourcePosition{CurrentSourceFile::Get(), {-1, -1}, {-1, -1}}); default_namespace_ = - RegisterDeclarable(base::make_unique<Namespace>(kBaseNamespaceName)); + RegisterDeclarable(std::make_unique<Namespace>(kBaseNamespaceName)); } TargetArchitecture::TargetArchitecture(bool force_32bit) diff --git a/deps/v8/src/torque/global-context.h b/deps/v8/src/torque/global-context.h index e1106adbd1..940325b51a 100644 --- a/deps/v8/src/torque/global-context.h +++ b/deps/v8/src/torque/global-context.h @@ -6,6 +6,7 @@ #define V8_TORQUE_GLOBAL_CONTEXT_H_ #include <map> +#include <memory> #include "src/common/globals.h" #include "src/torque/ast.h" diff --git a/deps/v8/src/torque/implementation-visitor.cc b/deps/v8/src/torque/implementation-visitor.cc index 8f36afd020..0c50a70099 100644 --- a/deps/v8/src/torque/implementation-visitor.cc +++ b/deps/v8/src/torque/implementation-visitor.cc @@ -526,7 +526,6 @@ void ImplementationVisitor::Visit(Builtin* builtin) { source_out() << " USE(" << parameter0 << ");\n"; for (size_t i = 1; i < signature.parameter_names.size(); ++i) { - const std::string& parameter_name = signature.parameter_names[i]->value; const Type* type = signature.types()[i]; const bool mark_as_used = signature.implicit_count > i; std::string var = AddParameter(i, builtin, ¶meters, ¶meter_types, @@ -534,8 +533,8 @@ void ImplementationVisitor::Visit(Builtin* builtin) { source_out() << " " << type->GetGeneratedTypeName() << " " << var << " = " << "UncheckedCast<" << type->GetGeneratedTNodeTypeName() - << ">(Parameter(Descriptor::k" - << CamelifyString(parameter_name) << "));\n"; + << ">(Parameter(Descriptor::ParameterIndex<" << (i - 1) + << ">()));\n"; source_out() << " USE(" << var << ");\n"; } } @@ -1008,48 +1007,40 @@ const Type* ImplementationVisitor::Visit(AssertStatement* stmt) { #if defined(DEBUG) do_check = true; #endif - if (do_check) { - // CSA_ASSERT & co. are not used here on purpose for two reasons. First, - // Torque allows and handles two types of expressions in the if protocol - // automagically, ones that return TNode<BoolT> and those that use the - // BranchIf(..., Label* true, Label* false) idiom. Because the machinery to - // handle this is embedded in the expression handling and to it's not - // possible to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH - // isn't trivial up-front. Secondly, on failure, the assert text should be - // the corresponding Torque code, not the -gen.cc code, which would be the - // case when using CSA_ASSERT_XXX. - Block* true_block = assembler().NewBlock(assembler().CurrentStack()); - Block* false_block = assembler().NewBlock(assembler().CurrentStack(), true); - GenerateExpressionBranch(stmt->expression, true_block, false_block); + Block* resume_block; + + if (!do_check) { + Block* unreachable_block = assembler().NewBlock(assembler().CurrentStack()); + resume_block = assembler().NewBlock(assembler().CurrentStack()); + assembler().Goto(resume_block); + assembler().Bind(unreachable_block); + } + + // CSA_ASSERT & co. are not used here on purpose for two reasons. First, + // Torque allows and handles two types of expressions in the if protocol + // automagically, ones that return TNode<BoolT> and those that use the + // BranchIf(..., Label* true, Label* false) idiom. Because the machinery to + // handle this is embedded in the expression handling and to it's not + // possible to make the decision to use CSA_ASSERT or CSA_ASSERT_BRANCH + // isn't trivial up-front. Secondly, on failure, the assert text should be + // the corresponding Torque code, not the -gen.cc code, which would be the + // case when using CSA_ASSERT_XXX. + Block* true_block = assembler().NewBlock(assembler().CurrentStack()); + Block* false_block = assembler().NewBlock(assembler().CurrentStack(), true); + GenerateExpressionBranch(stmt->expression, true_block, false_block); - assembler().Bind(false_block); + assembler().Bind(false_block); - assembler().Emit(AbortInstruction{ - AbortInstruction::Kind::kAssertionFailure, - "Torque assert '" + FormatAssertSource(stmt->source) + "' failed"}); + assembler().Emit(AbortInstruction{ + AbortInstruction::Kind::kAssertionFailure, + "Torque assert '" + FormatAssertSource(stmt->source) + "' failed"}); - assembler().Bind(true_block); - } else { - // Visit the expression so bindings only used in asserts are marked - // as such. Otherwise they might be wrongly reported as unused bindings - // in release builds. - stmt->expression->VisitAllSubExpressions([](Expression* expression) { - if (auto id = IdentifierExpression::DynamicCast(expression)) { - ValueBindingsManager::Get().TryLookup(id->name->value); - } else if (auto call = CallExpression::DynamicCast(expression)) { - for (Identifier* label : call->labels) { - LabelBindingsManager::Get().TryLookup(label->value); - } - // TODO(szuend): In case the call expression resolves to a macro - // callable, mark the macro as used as well. - } else if (auto call = CallMethodExpression::DynamicCast(expression)) { - for (Identifier* label : call->labels) { - LabelBindingsManager::Get().TryLookup(label->value); - } - // TODO(szuend): Mark the underlying macro as used. - } - }); + assembler().Bind(true_block); + + if (!do_check) { + assembler().Bind(resume_block); } + return TypeOracle::GetVoidType(); } @@ -1214,16 +1205,16 @@ InitializerResults ImplementationVisitor::VisitInitializerResults( result.names.push_back(initializer.name); Expression* e = initializer.expression; const Field& field = class_type->LookupField(initializer.name->value); - auto field_index = field.index; + bool has_index = field.index.has_value(); if (SpreadExpression* s = SpreadExpression::DynamicCast(e)) { - if (!field_index) { + if (!has_index) { ReportError( "spread expressions can only be used to initialize indexed class " "fields ('", initializer.name->value, "' is not)"); } e = s->spreadee; - } else if (field_index) { + } else if (has_index) { ReportError("the indexed class field '", initializer.name->value, "' must be initialized with a spread operator"); } @@ -1261,7 +1252,7 @@ void ImplementationVisitor::InitializeClass( void ImplementationVisitor::InitializeFieldFromSpread( VisitResult object, const Field& field, const InitializerResults& initializer_results) { - NameAndType index = (*field.index)->name_and_type; + const NameAndType& index = *field.index; VisitResult iterator = initializer_results.field_value_map.at(field.name_and_type.name); VisitResult length = initializer_results.field_value_map.at(index.name); @@ -1289,15 +1280,14 @@ VisitResult ImplementationVisitor::AddVariableObjectSize( } VisitResult index_field_size = VisitResult(TypeOracle::GetConstInt31Type(), "kTaggedSize"); - VisitResult initializer_value = initializer_results.field_value_map.at( - (*current_field->index)->name_and_type.name); + VisitResult initializer_value = + initializer_results.field_value_map.at(current_field->index->name); Arguments args; args.parameters.push_back(object_size); args.parameters.push_back(initializer_value); args.parameters.push_back(index_field_size); - object_size = - GenerateCall("%AddIndexedFieldSizeToObjectSize", args, - {(*current_field->index)->name_and_type.type}, false); + object_size = GenerateCall("%AddIndexedFieldSizeToObjectSize", args, + {current_field->index->type}, false); } ++current_field; } @@ -1860,12 +1850,12 @@ LocationReference ImplementationVisitor::GetLocationReference( { StackScope length_scope(this); // Get a reference to the length - const Field* index_field = field.index.value(); + const NameAndType& index_field = field.index.value(); GenerateCopy(object_result); - assembler().Emit(CreateFieldReferenceInstruction{ - object_result.type(), index_field->name_and_type.name}); + assembler().Emit(CreateFieldReferenceInstruction{object_result.type(), + index_field.name}); VisitResult length_reference( - TypeOracle::GetReferenceType(index_field->name_and_type.type), + TypeOracle::GetReferenceType(index_field.type), assembler().TopRange(2)); // Load the length from the reference and convert it to intptr @@ -2670,13 +2660,34 @@ void ImplementationVisitor::Visit(Declarable* declarable) { } } -void ImplementationVisitor::GenerateBuiltinDefinitions( +std::string MachineTypeString(const Type* type) { + if (type->IsSubtypeOf(TypeOracle::GetSmiType())) { + return "MachineType::TaggedSigned()"; + } + if (type->IsSubtypeOf(TypeOracle::GetHeapObjectType())) { + return "MachineType::TaggedPointer()"; + } + if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) { + return "MachineType::AnyTagged()"; + } + return "MachineTypeOf<" + type->GetGeneratedTNodeTypeName() + ">::value"; +} + +void ImplementationVisitor::GenerateBuiltinDefinitionsAndInterfaceDescriptors( const std::string& output_directory) { - std::stringstream new_contents_stream; - std::string file_name = "builtin-definitions-tq.h"; + std::stringstream builtin_definitions; + std::string builtin_definitions_file_name = "builtin-definitions-tq.h"; + + // This file contains plain interface descriptor definitions and has to be + // included in the middle of interface-descriptors.h. Thus it is not a normal + // header file and uses the .inc suffix instead of the .h suffix. + std::stringstream interface_descriptors; + std::string interface_descriptors_file_name = "interface-descriptors-tq.inc"; { - IncludeGuardScope include_guard(new_contents_stream, file_name); - new_contents_stream + IncludeGuardScope builtin_definitions_include_guard( + builtin_definitions, builtin_definitions_file_name); + + builtin_definitions << "\n" "#define BUILTIN_LIST_FROM_TORQUE(CPP, TFJ, TFC, TFS, TFH, " "ASM) " @@ -2684,40 +2695,67 @@ void ImplementationVisitor::GenerateBuiltinDefinitions( for (auto& declarable : GlobalContext::AllDeclarables()) { Builtin* builtin = Builtin::DynamicCast(declarable.get()); if (!builtin || builtin->IsExternal()) continue; - size_t firstParameterIndex = 1; - bool declareParameters = true; if (builtin->IsStub()) { - new_contents_stream << "TFS(" << builtin->ExternalName(); + builtin_definitions << "TFC(" << builtin->ExternalName() << ", " + << builtin->ExternalName(); + std::string descriptor_name = builtin->ExternalName() + "Descriptor"; + constexpr size_t kFirstNonContextParameter = 1; + size_t parameter_count = + builtin->parameter_names().size() - kFirstNonContextParameter; + + interface_descriptors << "class " << descriptor_name + << " : public TorqueInterfaceDescriptor<" + << parameter_count << "> {\n"; + interface_descriptors << " DECLARE_DESCRIPTOR_WITH_BASE(" + << descriptor_name + << ", TorqueInterfaceDescriptor)\n"; + + interface_descriptors << " MachineType ReturnType() override {\n"; + interface_descriptors + << " return " + << MachineTypeString(builtin->signature().return_type) << ";\n"; + interface_descriptors << " }\n"; + + interface_descriptors << " std::array<MachineType, " << parameter_count + << "> ParameterTypes() override {\n"; + interface_descriptors << " return {"; + for (size_t i = kFirstNonContextParameter; + i < builtin->parameter_names().size(); ++i) { + bool last = i + 1 == builtin->parameter_names().size(); + const Type* type = builtin->signature().parameter_types.types[i]; + interface_descriptors << MachineTypeString(type) + << (last ? "" : ", "); + } + interface_descriptors << "};\n"; + + interface_descriptors << " }\n"; + interface_descriptors << "};\n\n"; } else { - new_contents_stream << "TFJ(" << builtin->ExternalName(); + builtin_definitions << "TFJ(" << builtin->ExternalName(); if (builtin->IsVarArgsJavaScript()) { - new_contents_stream + builtin_definitions << ", SharedFunctionInfo::kDontAdaptArgumentsSentinel"; - declareParameters = false; } else { DCHECK(builtin->IsFixedArgsJavaScript()); // FixedArg javascript builtins need to offer the parameter // count. int parameter_count = static_cast<int>(builtin->signature().ExplicitCount()); - new_contents_stream << ", " << parameter_count; + builtin_definitions << ", " << parameter_count; // And the receiver is explicitly declared. - new_contents_stream << ", kReceiver"; - firstParameterIndex = builtin->signature().implicit_count; - } - } - if (declareParameters) { - for (size_t i = firstParameterIndex; - i < builtin->parameter_names().size(); ++i) { - Identifier* parameter = builtin->parameter_names()[i]; - new_contents_stream << ", k" << CamelifyString(parameter->value); + builtin_definitions << ", kReceiver"; + for (size_t i = builtin->signature().implicit_count; + i < builtin->parameter_names().size(); ++i) { + Identifier* parameter = builtin->parameter_names()[i]; + builtin_definitions << ", k" << CamelifyString(parameter->value); + } } } - new_contents_stream << ") \\\n"; + builtin_definitions << ") \\\n"; } - new_contents_stream << "\n"; + builtin_definitions << "\n"; - new_contents_stream + builtin_definitions << "#define TORQUE_FUNCTION_POINTER_TYPE_TO_BUILTIN_MAP(V) \\\n"; for (const BuiltinPointerType* type : TypeOracle::AllBuiltinPointerTypes()) { @@ -2728,13 +2766,15 @@ void ImplementationVisitor::GenerateBuiltinDefinitions( SourcePosition{CurrentSourceFile::Get(), {-1, -1}, {-1, -1}}); ReportError("unable to find any builtin with type \"", *type, "\""); } - new_contents_stream << " V(" << type->function_pointer_type_id() << "," + builtin_definitions << " V(" << type->function_pointer_type_id() << "," << example_builtin->ExternalName() << ")\\\n"; } - new_contents_stream << "\n"; + builtin_definitions << "\n"; } - std::string new_contents(new_contents_stream.str()); - WriteFile(output_directory + "/" + file_name, new_contents); + WriteFile(output_directory + "/" + builtin_definitions_file_name, + builtin_definitions.str()); + WriteFile(output_directory + "/" + interface_descriptors_file_name, + interface_descriptors.str()); } namespace { @@ -2894,40 +2934,8 @@ class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator { private: std::ostream& out_; }; -} // namespace - -void ImplementationVisitor::GenerateInstanceTypes( - const std::string& output_directory) { - std::stringstream header; - std::string file_name = "instance-types-tq.h"; - { - IncludeGuardScope(header, file_name); - header << "#define TORQUE_DEFINED_INSTANCE_TYPES(V) \\\n"; - for (const TypeAlias* alias : GlobalContext::GetClasses()) { - const ClassType* type = ClassType::DynamicCast(alias->type()); - if (type->IsExtern()) continue; - std::string type_name = - CapifyStringWithUnderscores(type->name()) + "_TYPE"; - header << " V(" << type_name << ") \\\n"; - } - header << "\n\n"; - - header << "#define TORQUE_STRUCT_LIST_GENERATOR(V, _) \\\n"; - for (const TypeAlias* alias : GlobalContext::GetClasses()) { - const ClassType* type = ClassType::DynamicCast(alias->type()); - if (type->IsExtern()) continue; - std::string type_name = - CapifyStringWithUnderscores(type->name()) + "_TYPE"; - std::string variable_name = SnakeifyString(type->name()); - header << " V(_, " << type_name << ", " << type->name() << ", " - << variable_name << ") \\\n"; - } - header << "\n"; - } - std::string output_header_path = output_directory + "/" + file_name; - WriteFile(output_header_path, header.str()); -} +} // namespace void ImplementationVisitor::GenerateCppForInternalClasses( const std::string& output_directory) { @@ -3148,7 +3156,7 @@ void CppClassGenerator::GenerateClassConstructors() { if (type_->IsInstantiatedAbstractClass()) { // This is a hack to prevent wrong instance type checks. inl_ << " // Instance check omitted because class is annotated with " - "@dirtyInstantiatedAbstractClass.\n"; + << ANNOTATION_INSTANTIATED_ABSTRACT_CLASS << ".\n"; } else { inl_ << " SLOW_DCHECK(this->Is" << name_ << "());\n"; } @@ -3241,7 +3249,8 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) { const std::string offset = "k" + CamelifyString(name) + "Offset"; base::Optional<const ClassType*> class_type = field_type->ClassSupertype(); - std::string type = class_type ? (*class_type)->name() : "Object"; + std::string type = + class_type ? (*class_type)->GetGeneratedTNodeTypeName() : "Object"; // Generate declarations in header. if (!class_type && field_type != TypeOracle::GetObjectType()) { @@ -3302,7 +3311,6 @@ void ImplementationVisitor::GenerateClassDefinitions( { IncludeGuardScope header_guard(header, basename + ".h"); - header << "#include \"src/objects/heap-number.h\"\n"; header << "#include \"src/objects/objects.h\"\n"; header << "#include \"src/objects/smi.h\"\n"; header << "#include \"torque-generated/field-offsets-tq.h\"\n"; @@ -3314,9 +3322,11 @@ void ImplementationVisitor::GenerateClassDefinitions( IncludeGuardScope inline_header_guard(inline_header, basename + "-inl.h"); inline_header << "#include \"torque-generated/class-definitions-tq.h\"\n\n"; inline_header << "#include \"src/objects/js-promise.h\"\n"; + inline_header << "#include \"src/objects/js-weak-refs.h\"\n"; inline_header << "#include \"src/objects/module.h\"\n"; inline_header << "#include \"src/objects/objects-inl.h\"\n"; - inline_header << "#include \"src/objects/script.h\"\n\n"; + inline_header << "#include \"src/objects/script.h\"\n"; + inline_header << "#include \"src/objects/shared-function-info.h\"\n\n"; IncludeObjectMacrosScope inline_header_macros(inline_header); NamespaceScope inline_header_namespaces(inline_header, {"v8", "internal"}); @@ -3328,6 +3338,7 @@ void ImplementationVisitor::GenerateClassDefinitions( implementation << "#include \"src/objects/embedder-data-array-inl.h\"\n"; implementation << "#include \"src/objects/js-generator-inl.h\"\n"; implementation << "#include \"src/objects/js-regexp-inl.h\"\n"; + implementation << "#include \"src/objects/js-weak-refs-inl.h\"\n"; implementation << "#include \"src/objects/js-regexp-string-iterator-inl.h\"\n"; implementation << "#include \"src/objects/literal-objects-inl.h\"\n"; @@ -3346,7 +3357,7 @@ void ImplementationVisitor::GenerateClassDefinitions( // Generate forward declarations for every class. for (const TypeAlias* alias : GlobalContext::GetClasses()) { const ClassType* type = ClassType::DynamicCast(alias->type()); - header << "class " << type->name() << ";\n"; + header << "class " << type->GetGeneratedTNodeTypeName() << ";\n"; } for (const TypeAlias* alias : GlobalContext::GetClasses()) { @@ -3439,13 +3450,13 @@ void GenerateClassFieldVerifier(const std::string& class_name, if (!field_type->IsSubtypeOf(TypeOracle::GetObjectType())) return; if (f.index) { - if ((*f.index)->name_and_type.type != TypeOracle::GetSmiType()) { + if (f.index->type != TypeOracle::GetSmiType()) { ReportError("Non-SMI values are not (yet) supported as indexes."); } // We already verified the index field because it was listed earlier, so we // can assume it's safe to read here. cc_contents << " for (int i = 0; i < TaggedField<Smi, " << class_name - << "::k" << CamelifyString((*f.index)->name_and_type.name) + << "::k" << CamelifyString(f.index->name) << "Offset>::load(o).value(); ++i) {\n"; } else { cc_contents << " {\n"; diff --git a/deps/v8/src/torque/implementation-visitor.h b/deps/v8/src/torque/implementation-visitor.h index eb1a6c4452..e1ebfeeb17 100644 --- a/deps/v8/src/torque/implementation-visitor.h +++ b/deps/v8/src/torque/implementation-visitor.h @@ -5,6 +5,7 @@ #ifndef V8_TORQUE_IMPLEMENTATION_VISITOR_H_ #define V8_TORQUE_IMPLEMENTATION_VISITOR_H_ +#include <memory> #include <string> #include "src/base/macros.h" @@ -260,7 +261,7 @@ class BlockBindings { void Add(std::string name, T value, bool mark_as_used = false) { ReportErrorIfAlreadyBound(name); auto binding = - base::make_unique<Binding<T>>(manager_, name, std::move(value)); + std::make_unique<Binding<T>>(manager_, name, std::move(value)); if (mark_as_used) binding->SetUsed(); bindings_.push_back(std::move(binding)); } @@ -268,7 +269,7 @@ class BlockBindings { void Add(const Identifier* name, T value, bool mark_as_used = false) { ReportErrorIfAlreadyBound(name->value); auto binding = - base::make_unique<Binding<T>>(manager_, name, std::move(value)); + std::make_unique<Binding<T>>(manager_, name, std::move(value)); if (mark_as_used) binding->SetUsed(); bindings_.push_back(std::move(binding)); } @@ -342,7 +343,8 @@ bool IsCompatibleSignature(const Signature& sig, const TypeVector& types, class ImplementationVisitor { public: - void GenerateBuiltinDefinitions(const std::string& output_directory); + void GenerateBuiltinDefinitionsAndInterfaceDescriptors( + const std::string& output_directory); void GenerateClassFieldOffsets(const std::string& output_directory); void GeneratePrintDefinitions(const std::string& output_directory); void GenerateClassDefinitions(const std::string& output_directory); diff --git a/deps/v8/src/torque/instance-type-generator.cc b/deps/v8/src/torque/instance-type-generator.cc new file mode 100644 index 0000000000..275e706485 --- /dev/null +++ b/deps/v8/src/torque/instance-type-generator.cc @@ -0,0 +1,376 @@ +// Copyright 2019 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/implementation-visitor.h" + +namespace v8 { +namespace internal { +namespace torque { + +namespace { + +// Contains all necessary state for a single class type during the process of +// assigning instance types, and provides a convenient way to access the list of +// types that inherit from this one. +struct InstanceTypeTree { + explicit InstanceTypeTree(const ClassType* type) + : type(type), + parent(nullptr), + start(INT_MAX), + end(INT_MIN), + value(-1), + num_values(0), + num_own_values(0) {} + const ClassType* type; + InstanceTypeTree* parent; + std::vector<std::unique_ptr<InstanceTypeTree>> children; + int start; // Start of range for this and subclasses, or INT_MAX. + int end; // End of range for this and subclasses, or INT_MIN. + int value; // Assigned value for this class itself, or -1 when unassigned. + int num_values; // Number of values assigned for this and subclasses. + int num_own_values; // How many values this needs (not including subclasses). +}; + +// Assembles all class types into a tree, but doesn't yet attempt to assign +// instance types for them. +std::unique_ptr<InstanceTypeTree> BuildInstanceTypeTree() { + // First, build InstanceTypeTree instances for every class but don't try to + // attach them to their subclasses yet. + std::unordered_map<const ClassType*, InstanceTypeTree*> map_by_type; + std::vector<std::unique_ptr<InstanceTypeTree>> unparented_types; + for (auto& p : GlobalContext::AllDeclarables()) { + if (const TypeAlias* alias = TypeAlias::DynamicCast(p.get())) { + const Type* type = alias->type(); + const ClassType* class_type = ClassType::DynamicCast(type); + if (class_type == nullptr) { + continue; + } + auto& map_slot = map_by_type[class_type]; + if (map_slot != nullptr) { + continue; // We already encountered this type. + } + std::unique_ptr<InstanceTypeTree> type_tree = + std::make_unique<InstanceTypeTree>(class_type); + map_slot = type_tree.get(); + unparented_types.push_back(std::move(type_tree)); + } + } + + // Second, assemble them all into a tree following the inheritance hierarchy. + std::unique_ptr<InstanceTypeTree> root; + for (auto& type_tree : unparented_types) { + const ClassType* parent = type_tree->type->GetSuperClass(); + if (parent == nullptr) { + if (root != nullptr) + Error("Expected only one root class type. Found: ", root->type->name(), + " and ", type_tree->type->name()) + .Position(type_tree->type->GetPosition()); + root = std::move(type_tree); + } else { + map_by_type[parent]->children.push_back(std::move(type_tree)); + } + } + return root; +} + +// Propagates constraints about instance types from children to their parents. +void PropagateInstanceTypeConstraints(InstanceTypeTree* root) { + for (auto& child : root->children) { + PropagateInstanceTypeConstraints(child.get()); + if (child->start < root->start) root->start = child->start; + if (child->end > root->end) root->end = child->end; + root->num_values += child->num_values; + } + const InstanceTypeConstraints& constraints = + root->type->GetInstanceTypeConstraints(); + if ((!root->type->IsAbstract() || + root->type->IsInstantiatedAbstractClass()) && + !root->type->HasSameInstanceTypeAsParent()) { + root->num_own_values = 1; + } + root->num_values += root->num_own_values; + if (constraints.num_flags_bits != -1) { + // Children won't get any types assigned; must be done manually in C++. + root->children.clear(); + root->num_values = 1 << constraints.num_flags_bits; + root->num_own_values = root->num_values; + root->start = 0; + root->end = root->num_values - 1; + } + if (constraints.value != -1) { + if (root->num_own_values != 1) { + Error("Instance type value requested for abstract class ", + root->type->name()) + .Position(root->type->GetPosition()); + } + root->value = constraints.value; + if (constraints.value < root->start) root->start = constraints.value; + if (constraints.value > root->end) root->end = constraints.value; + } +} + +// Assigns values for the type itself, not including any children. Returns the +// next available value. +int SelectOwnValues(InstanceTypeTree* root, int start_value) { + if (root->value == -1) { + root->value = start_value; + } else if (root->value < start_value) { + Error("Failed to assign instance type ", root->value, " to ", + root->type->name()) + .Position(root->type->GetPosition()); + } + return root->value + root->num_own_values; +} + +// Sorting function for types that don't have specific values they must include. +// Prioritizes bigger type ranges (those with more subtypes) first, and +// then sorts alphabetically within each size category. +struct CompareUnconstrainedTypes { + constexpr bool operator()(const InstanceTypeTree* a, + const InstanceTypeTree* b) const { + return (a->num_values > b->num_values) + ? true + : (a->num_values < b->num_values) + ? false + : std::less<std::string>()(a->type->name(), + b->type->name()); + } +}; + +// Assigns concrete values for every instance type range, and sorts the children +// at each layer of the tree into increasing order. Appends the newly-assigned +// tree to the destination vector. Returns the first unassigned value after +// those that have been used. +int SolveInstanceTypeConstraints( + std::unique_ptr<InstanceTypeTree> root, int start_value, + std::vector<std::unique_ptr<InstanceTypeTree>>* destination) { + if (root->start < start_value) { + Error("Failed to assign instance type ", root->start, " to ", + root->type->name()) + .Position(root->type->GetPosition()); + } + + // First, separate the children into four groups: + // - The one child that must go first, if it exists; + // - Children with specific value requirements ("constrained"); + // - Children without specific value requirements ("unconstrained"); + // - The one child that must go last, if it exists. + std::unique_ptr<InstanceTypeTree> lowest_child; + std::unique_ptr<InstanceTypeTree> highest_child; + std::multimap<int, std::unique_ptr<InstanceTypeTree>> + constrained_children_by_start; + // Using std::map because you can't std::move out of a std::set until C++17. + std::map<InstanceTypeTree*, std::unique_ptr<InstanceTypeTree>, + CompareUnconstrainedTypes> + unconstrained_children_by_size; + for (auto& child : root->children) { + if (child->type->IsHighestInstanceTypeWithinParent()) { + if (highest_child) { + Error("Two classes requested to be the highest instance type: ", + highest_child->type->name(), " and ", child->type->name(), + " within range for parent class ", root->type->name()) + .Position(child->type->GetPosition()); + } + if (child->type->IsLowestInstanceTypeWithinParent()) { + Error( + "Class requested to be both highest and lowest instance type " + "within its parent range: ", + child->type->name()) + .Position(child->type->GetPosition()); + } + highest_child = std::move(child); + } else if (child->type->IsLowestInstanceTypeWithinParent()) { + if (lowest_child) { + Error("Two classes requested to be the lowest instance type: ", + lowest_child->type->name(), " and ", child->type->name(), + " within range for parent class ", root->type->name()) + .Position(child->type->GetPosition()); + } + lowest_child = std::move(child); + } else if (child->start > child->end) { + unconstrained_children_by_size.insert( + std::make_pair(child.get(), std::move(child))); + } else { + constrained_children_by_start.insert( + std::make_pair(child->start, std::move(child))); + } + } + root->children.clear(); + + bool own_type_pending = root->num_own_values > 0; + + // Second, iterate and place the children in ascending order. + if (lowest_child != nullptr) { + start_value = SolveInstanceTypeConstraints(std::move(lowest_child), + start_value, &root->children); + } + for (auto& constrained_child_pair : constrained_children_by_start) { + // Select the next constrained child type in ascending order. + std::unique_ptr<InstanceTypeTree> constrained_child = + std::move(constrained_child_pair.second); + + // Try to place the root type before the constrained child type if it fits. + if (own_type_pending) { + if ((root->value != -1 && root->value < constrained_child->start) || + (root->value == -1 && + start_value + root->num_own_values <= constrained_child->start)) { + start_value = SelectOwnValues(root.get(), start_value); + own_type_pending = false; + } + } + + // Try to find any unconstrained children that fit before the constrained + // one. This simple greedy algorithm just puts the biggest unconstrained + // children in first, which might not fill the space as efficiently as + // possible but is good enough for our needs. + for (auto it = unconstrained_children_by_size.begin(); + it != unconstrained_children_by_size.end();) { + if (it->second->num_values + start_value <= constrained_child->start) { + start_value = SolveInstanceTypeConstraints( + std::move(it->second), start_value, &root->children); + it = unconstrained_children_by_size.erase(it); + } else { + ++it; + } + } + + // Place the constrained child type. + start_value = SolveInstanceTypeConstraints(std::move(constrained_child), + start_value, &root->children); + } + if (own_type_pending) { + start_value = SelectOwnValues(root.get(), start_value); + own_type_pending = false; + } + for (auto& child_pair : unconstrained_children_by_size) { + start_value = SolveInstanceTypeConstraints(std::move(child_pair.second), + start_value, &root->children); + } + if (highest_child != nullptr) { + start_value = SolveInstanceTypeConstraints(std::move(highest_child), + start_value, &root->children); + } + + // Finally, set the range for this class to include all placed subclasses. + root->end = start_value - 1; + root->start = + root->children.empty() ? start_value : root->children.front()->start; + if (root->value != -1 && root->value < root->start) { + root->start = root->value; + } + root->num_values = root->end - root->start + 1; + + if (root->num_values > 0) { + destination->push_back(std::move(root)); + } + return start_value; +} + +std::unique_ptr<InstanceTypeTree> SolveInstanceTypeConstraints( + std::unique_ptr<InstanceTypeTree> root) { + std::vector<std::unique_ptr<InstanceTypeTree>> destination; + SolveInstanceTypeConstraints(std::move(root), 0, &destination); + return destination.empty() ? nullptr : std::move(destination.front()); +} + +std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() { + std::unique_ptr<InstanceTypeTree> root = BuildInstanceTypeTree(); + if (root != nullptr) { + PropagateInstanceTypeConstraints(root.get()); + root = SolveInstanceTypeConstraints(std::move(root)); + } + return root; +} + +// Prints items in macro lists for the given type and its descendants. +// - definitions: This list is pairs of instance type name and assigned value, +// such as V(ODDBALL_TYPE, 67). It includes FIRST_* and LAST_* items for each +// type that has more than one associated InstanceType. Items within those +// ranges are indented for readability. +// - values: This list is just instance type names, like V(ODDBALL_TYPE). It +// does not include any FIRST_* and LAST_* range markers. +void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions, + std::ostream& values, const std::string& indent) { + std::string type_name = + CapifyStringWithUnderscores(root->type->name()) + "_TYPE"; + std::string inner_indent = indent; + + if (root->num_values > 1) { + definitions << indent << "V(FIRST_" << type_name << ", " << root->start + << ") \\\n"; + inner_indent += " "; + } + if (root->num_own_values == 1) { + definitions << inner_indent << "V(" << type_name << ", " << root->value + << ") \\\n"; + values << " V(" << type_name << ") \\\n"; + } + for (auto& child : root->children) { + PrintInstanceTypes(child.get(), definitions, values, inner_indent); + } + // We can't emit LAST_STRING_TYPE because it's not a valid flags combination. + // So if the class type has multiple own values, which only happens when using + // ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, then omit the end marker. + if (root->num_values > 1 && root->num_own_values <= 1) { + definitions << indent << "V(LAST_" << type_name << ", " << root->end + << ") \\\n"; + } +} + +} // namespace + +void ImplementationVisitor::GenerateInstanceTypes( + const std::string& output_directory) { + std::stringstream header; + std::string file_name = "instance-types-tq.h"; + { + IncludeGuardScope guard(header, file_name); + + header << "// Instance types for all classes except for those that use " + "InstanceType as flags.\n"; + header << "#define TORQUE_ASSIGNED_INSTANCE_TYPES(V) \\\n"; + std::unique_ptr<InstanceTypeTree> instance_types = AssignInstanceTypes(); + std::stringstream values_list; + if (instance_types != nullptr) { + PrintInstanceTypes(instance_types.get(), header, values_list, " "); + } + header << "\n\n"; + + header << "// Instance types for all classes except for those that use " + "InstanceType as flags.\n"; + header << "#define TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(V) \\\n"; + header << values_list.str(); + header << "\n\n"; + + header << "// Instance types for Torque-internal classes.\n"; + header << "#define TORQUE_INTERNAL_INSTANCE_TYPES(V) \\\n"; + for (const TypeAlias* alias : GlobalContext::GetClasses()) { + const ClassType* type = ClassType::DynamicCast(alias->type()); + if (type->IsExtern()) continue; + std::string type_name = + CapifyStringWithUnderscores(type->name()) + "_TYPE"; + header << " V(" << type_name << ") \\\n"; + } + header << "\n\n"; + + header << "// Struct list entries for Torque-internal classes.\n"; + header << "#define TORQUE_STRUCT_LIST_GENERATOR(V, _) \\\n"; + for (const TypeAlias* alias : GlobalContext::GetClasses()) { + const ClassType* type = ClassType::DynamicCast(alias->type()); + if (type->IsExtern()) continue; + std::string type_name = + CapifyStringWithUnderscores(type->name()) + "_TYPE"; + std::string variable_name = SnakeifyString(type->name()); + header << " V(_, " << type_name << ", " << type->name() << ", " + << variable_name << ") \\\n"; + } + header << "\n"; + } + std::string output_header_path = output_directory + "/" + file_name; + WriteFile(output_header_path, header.str()); +} + +} // namespace torque +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/torque/ls/json.h b/deps/v8/src/torque/ls/json.h index 43d9f7ab11..1a033cf614 100644 --- a/deps/v8/src/torque/ls/json.h +++ b/deps/v8/src/torque/ls/json.h @@ -6,11 +6,11 @@ #define V8_TORQUE_LS_JSON_H_ #include <map> +#include <memory> #include <string> #include <vector> #include "src/base/logging.h" -#include "src/base/template-utils.h" namespace v8 { namespace internal { @@ -44,7 +44,7 @@ struct JsonValue { static JsonValue From(JsonObject object) { JsonValue result; result.tag = JsonValue::OBJECT; - result.object_ = base::make_unique<JsonObject>(std::move(object)); + result.object_ = std::make_unique<JsonObject>(std::move(object)); return result; } @@ -65,7 +65,7 @@ struct JsonValue { static JsonValue From(JsonArray array) { JsonValue result; result.tag = JsonValue::ARRAY; - result.array_ = base::make_unique<JsonArray>(std::move(array)); + result.array_ = std::make_unique<JsonArray>(std::move(array)); return result; } diff --git a/deps/v8/src/torque/ls/message-handler.cc b/deps/v8/src/torque/ls/message-handler.cc index 6ec124b5a2..becc97c9dc 100644 --- a/deps/v8/src/torque/ls/message-handler.cc +++ b/deps/v8/src/torque/ls/message-handler.cc @@ -87,6 +87,8 @@ void ResetCompilationErrorDiagnostics(MessageWriter writer) { class DiagnosticCollector { public: void AddTorqueMessage(const TorqueMessage& message) { + if (!ShouldAddMessageOfKind(message.kind)) return; + SourceId id = message.position ? message.position->source : SourceId::Invalid(); auto& notification = GetOrCreateNotificationForSource(id); @@ -120,6 +122,20 @@ class DiagnosticCollector { return notification; } + bool ShouldAddMessageOfKind(TorqueMessage::Kind kind) { + // An error can easily cause a lot of false positive lint messages, due to + // unused variables, macros, etc. Thus we suppress subsequent lint messages + // when there are errors. + switch (kind) { + case TorqueMessage::Kind::kError: + suppress_lint_messages_ = true; + return true; + case TorqueMessage::Kind::kLint: + if (suppress_lint_messages_) return false; + return true; + } + } + void PopulateRangeFromSourcePosition(Range range, const SourcePosition& position) { range.start().set_line(position.start.line); @@ -138,6 +154,7 @@ class DiagnosticCollector { } std::map<SourceId, PublishDiagnosticsNotification> notifications_; + bool suppress_lint_messages_ = false; }; void SendCompilationDiagnostics(const TorqueCompilerResult& result, diff --git a/deps/v8/src/torque/server-data.h b/deps/v8/src/torque/server-data.h index 04cd0b317f..b80d1b67f4 100644 --- a/deps/v8/src/torque/server-data.h +++ b/deps/v8/src/torque/server-data.h @@ -6,6 +6,7 @@ #define V8_TORQUE_SERVER_DATA_H_ #include <map> +#include <memory> #include <vector> #include "src/base/macros.h" @@ -47,12 +48,12 @@ class LanguageServerData : public ContextualClass<LanguageServerData> { static void SetGlobalContext(GlobalContext global_context) { Get().global_context_ = - base::make_unique<GlobalContext>(std::move(global_context)); + std::make_unique<GlobalContext>(std::move(global_context)); Get().PrepareAllDeclarableSymbols(); } static void SetTypeOracle(TypeOracle type_oracle) { - Get().type_oracle_ = base::make_unique<TypeOracle>(std::move(type_oracle)); + Get().type_oracle_ = std::make_unique<TypeOracle>(std::move(type_oracle)); } static const Symbols& SymbolsForSourceId(SourceId id) { diff --git a/deps/v8/src/torque/torque-compiler.cc b/deps/v8/src/torque/torque-compiler.cc index 3968b001fb..6d2b14fc18 100644 --- a/deps/v8/src/torque/torque-compiler.cc +++ b/deps/v8/src/torque/torque-compiler.cc @@ -79,7 +79,8 @@ void CompileCurrentAst(TorqueCompilerOptions options) { ReportAllUnusedMacros(); - implementation_visitor.GenerateBuiltinDefinitions(output_directory); + implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors( + output_directory); implementation_visitor.GenerateClassFieldOffsets(output_directory); implementation_visitor.GeneratePrintDefinitions(output_directory); implementation_visitor.GenerateClassDefinitions(output_directory); diff --git a/deps/v8/src/torque/torque-parser.cc b/deps/v8/src/torque/torque-parser.cc index d9973dde3c..3639bef97c 100644 --- a/deps/v8/src/torque/torque-parser.cc +++ b/deps/v8/src/torque/torque-parser.cc @@ -214,6 +214,10 @@ template <> V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<std::vector<Identifier*>>::id = ParseResultTypeId::kStdVectorOfIdentifierPtr; +template <> +V8_EXPORT_PRIVATE const ParseResultTypeId + ParseResultHolder<base::Optional<ClassBody*>>::id = + ParseResultTypeId::kOptionalClassBody; namespace { @@ -675,7 +679,9 @@ class AnnotationSet { Lint("Annotation ", a.name->value, error_message) .Position(a.name->pos); } - map_[a.name->value].push_back(*a.param); + if (!map_.insert({a.name->value, {*a.param, a.name->pos}}).second) { + Lint("Duplicate annotation ", a.name->value).Position(a.name->pos); + } } else { if (allowed_without_param.find(a.name->value) == allowed_without_param.end()) { @@ -693,41 +699,104 @@ class AnnotationSet { } } - bool Contains(const std::string& s) { return set_.find(s) != set_.end(); } - const std::vector<std::string>& GetParams(const std::string& s) { - return map_[s]; + bool Contains(const std::string& s) const { + return set_.find(s) != set_.end(); + } + base::Optional<std::pair<std::string, SourcePosition>> GetParam( + const std::string& s) const { + auto it = map_.find(s); + return it == map_.end() + ? base::Optional<std::pair<std::string, SourcePosition>>() + : it->second; } private: std::set<std::string> set_; - std::map<std::string, std::vector<std::string>> map_; + std::map<std::string, std::pair<std::string, SourcePosition>> map_; }; +int GetAnnotationValue(const AnnotationSet& annotations, const char* name, + int default_value) { + auto value_and_pos = annotations.GetParam(name); + if (!value_and_pos.has_value()) return default_value; + const std::string& value = value_and_pos->first; + SourcePosition pos = value_and_pos->second; + if (value.empty()) { + Error("Annotation ", name, " requires an integer parameter").Position(pos); + } + size_t num_chars_converted = 0; + int result = default_value; + try { + result = std::stoi(value, &num_chars_converted, 0); + } catch (const std::invalid_argument&) { + Error("Expected an integer for annotation ", name).Position(pos); + return result; + } catch (const std::out_of_range&) { + Error("Integer out of 32-bit range in annotation ", name).Position(pos); + return result; + } + if (num_chars_converted != value.size()) { + Error("Parameter for annotation ", name, + " must be an integer with no trailing characters") + .Position(pos); + } + return result; +} + +InstanceTypeConstraints MakeInstanceTypeConstraints( + const AnnotationSet& annotations) { + InstanceTypeConstraints result; + result.value = + GetAnnotationValue(annotations, ANNOTATION_INSTANCE_TYPE_VALUE, -1); + result.num_flags_bits = GetAnnotationValue( + annotations, ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, -1); + return result; +} + +base::Optional<ParseResult> MakeClassBody(ParseResultIterator* child_results) { + auto methods = child_results->NextAs<std::vector<Declaration*>>(); + auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>(); + base::Optional<ClassBody*> result = + MakeNode<ClassBody>(std::move(methods), std::move(fields)); + return ParseResult(result); +} + base::Optional<ParseResult> MakeClassDeclaration( ParseResultIterator* child_results) { AnnotationSet annotations( child_results, - {"@generatePrint", "@noVerifier", "@abstract", - "@dirtyInstantiatedAbstractClass", "@hasSameInstanceTypeAsParent", - "@generateCppClass"}, - {}); + {ANNOTATION_GENERATE_PRINT, ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT, + ANNOTATION_INSTANTIATED_ABSTRACT_CLASS, + ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT, + ANNOTATION_GENERATE_CPP_CLASS, + ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT, + ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT}, + {ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, + ANNOTATION_INSTANCE_TYPE_VALUE}); ClassFlags flags = ClassFlag::kNone; - bool generate_print = annotations.Contains("@generatePrint"); + bool generate_print = annotations.Contains(ANNOTATION_GENERATE_PRINT); if (generate_print) flags |= ClassFlag::kGeneratePrint; - bool generate_verify = !annotations.Contains("@noVerifier"); + bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER); if (generate_verify) flags |= ClassFlag::kGenerateVerify; - if (annotations.Contains("@abstract")) { + if (annotations.Contains(ANNOTATION_ABSTRACT)) { flags |= ClassFlag::kAbstract; } - if (annotations.Contains("@dirtyInstantiatedAbstractClass")) { + if (annotations.Contains(ANNOTATION_INSTANTIATED_ABSTRACT_CLASS)) { flags |= ClassFlag::kInstantiatedAbstractClass; } - if (annotations.Contains("@hasSameInstanceTypeAsParent")) { + if (annotations.Contains(ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT)) { flags |= ClassFlag::kHasSameInstanceTypeAsParent; } - if (annotations.Contains("@generateCppClass")) { + if (annotations.Contains(ANNOTATION_GENERATE_CPP_CLASS)) { flags |= ClassFlag::kGenerateCppClassDefinitions; } + if (annotations.Contains(ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT)) { + flags |= ClassFlag::kHighestInstanceTypeWithinParent; + } + if (annotations.Contains(ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT)) { + flags |= ClassFlag::kLowestInstanceTypeWithinParent; + } + auto is_extern = child_results->NextAs<bool>(); if (is_extern) flags |= ClassFlag::kExtern; auto transient = child_results->NextAs<bool>(); @@ -741,8 +810,15 @@ base::Optional<ParseResult> MakeClassDeclaration( ReportError("Expected type name in extends clause."); } auto generates = child_results->NextAs<base::Optional<std::string>>(); - auto methods = child_results->NextAs<std::vector<Declaration*>>(); - auto fields_raw = child_results->NextAs<std::vector<ClassFieldExpression>>(); + auto body = child_results->NextAs<base::Optional<ClassBody*>>(); + std::vector<Declaration*> methods; + std::vector<ClassFieldExpression> fields_raw; + if (body.has_value()) { + methods = (*body)->methods; + fields_raw = (*body)->fields; + } else { + flags |= ClassFlag::kUndefinedLayout; + } // Filter to only include fields that should be present based on decoration. std::vector<ClassFieldExpression> fields; @@ -751,8 +827,9 @@ base::Optional<ParseResult> MakeClassDeclaration( [](const ClassFieldExpression& exp) { for (const ConditionalAnnotation& condition : exp.conditions) { if (condition.type == ConditionalAnnotationType::kPositive - ? !BuildFlags::GetFlag(condition.condition, "@if") - : BuildFlags::GetFlag(condition.condition, "@ifnot")) { + ? !BuildFlags::GetFlag(condition.condition, ANNOTATION_IF) + : BuildFlags::GetFlag(condition.condition, + ANNOTATION_IFNOT)) { return false; } } @@ -761,7 +838,7 @@ base::Optional<ParseResult> MakeClassDeclaration( Declaration* result = MakeNode<ClassDeclaration>( name, flags, std::move(extends), std::move(generates), std::move(methods), - fields); + fields, MakeInstanceTypeConstraints(annotations)); return ParseResult{result}; } @@ -1358,14 +1435,21 @@ base::Optional<ParseResult> MakeAnnotation(ParseResultIterator* child_results) { } base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) { - AnnotationSet annotations(child_results, {"@noVerifier"}, {"@if", "@ifnot"}); - bool generate_verify = !annotations.Contains("@noVerifier"); + AnnotationSet annotations(child_results, {ANNOTATION_NO_VERIFIER}, + {ANNOTATION_IF, ANNOTATION_IFNOT}); + bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER); std::vector<ConditionalAnnotation> conditions; - for (const std::string& condition : annotations.GetParams("@if")) { - conditions.push_back({condition, ConditionalAnnotationType::kPositive}); + base::Optional<std::pair<std::string, SourcePosition>> if_condition = + annotations.GetParam(ANNOTATION_IF); + base::Optional<std::pair<std::string, SourcePosition>> ifnot_condition = + annotations.GetParam(ANNOTATION_IFNOT); + if (if_condition.has_value()) { + conditions.push_back( + {if_condition->first, ConditionalAnnotationType::kPositive}); } - for (const std::string& condition : annotations.GetParams("@ifnot")) { - conditions.push_back({condition, ConditionalAnnotationType::kNegative}); + if (ifnot_condition.has_value()) { + conditions.push_back( + {ifnot_condition->first, ConditionalAnnotationType::kNegative}); } auto weak = child_results->NextAs<bool>(); auto const_qualified = child_results->NextAs<bool>(); @@ -1892,6 +1976,13 @@ struct TorqueGrammar : Grammar { &block}, MakeMethodDeclaration)}; + // Result: base::Optional<ClassBody*> + Symbol optionalClassBody = { + Rule({Token("{"), List<Declaration*>(&method), + List<ClassFieldExpression>(&classField), Token("}")}, + MakeClassBody), + Rule({Token(";")}, YieldDefaultValue<base::Optional<ClassBody*>>)}; + // Result: std::vector<Declaration*> Symbol declaration = { Rule({Token("const"), &name, Token(":"), &type, Token("="), expression, @@ -1905,8 +1996,7 @@ struct TorqueGrammar : Grammar { Optional<TypeExpression*>(Sequence({Token("extends"), &type})), Optional<std::string>( Sequence({Token("generates"), &externalString})), - Token("{"), List<Declaration*>(&method), - List<ClassFieldExpression>(&classField), Token("}")}, + &optionalClassBody}, AsSingletonVector<Declaration*, MakeClassDeclaration>()), Rule({Token("struct"), &name, TryOrDefault<GenericParameters>(&genericParameters), Token("{"), diff --git a/deps/v8/src/torque/type-oracle.h b/deps/v8/src/torque/type-oracle.h index 643c78c030..03aad34d2a 100644 --- a/deps/v8/src/torque/type-oracle.h +++ b/deps/v8/src/torque/type-oracle.h @@ -5,6 +5,8 @@ #ifndef V8_TORQUE_TYPE_ORACLE_H_ #define V8_TORQUE_TYPE_ORACLE_H_ +#include <memory> + #include "src/torque/contextual.h" #include "src/torque/declarable.h" #include "src/torque/declarations.h" diff --git a/deps/v8/src/torque/type-visitor.cc b/deps/v8/src/torque/type-visitor.cc index 9b5c96ee40..b45452058d 100644 --- a/deps/v8/src/torque/type-visitor.cc +++ b/deps/v8/src/torque/type-visitor.cc @@ -165,6 +165,12 @@ const ClassType* TypeVisitor::ComputeType(ClassDeclaration* decl) { "class \"", decl->name->value, "\" must extend either Tagged or an already declared class"); } + if (super_class->HasUndefinedLayout() && + !(decl->flags & ClassFlag::kUndefinedLayout)) { + Error("Class \"", decl->name->value, + "\" defines its layout but extends a class which does not") + .Position(decl->pos); + } } std::string generates = decl->name->value; @@ -282,8 +288,9 @@ void TypeVisitor::VisitClassFieldsAndMethods( "only one indexable field is currently supported per class"); } seen_indexed_field = true; - const Field* index_field = - &(class_type->LookupFieldInternal(*field_expression.index)); + const NameAndType& index_field = + class_type->LookupFieldInternal(*field_expression.index) + .name_and_type; class_type->RegisterField( {field_expression.name_and_type.name->pos, class_type, diff --git a/deps/v8/src/torque/types.cc b/deps/v8/src/torque/types.cc index fe792401f6..022649e065 100644 --- a/deps/v8/src/torque/types.cc +++ b/deps/v8/src/torque/types.cc @@ -50,7 +50,9 @@ bool Type::IsSubtypeOf(const Type* supertype) const { base::Optional<const ClassType*> Type::ClassSupertype() const { for (const Type* t = this; t != nullptr; t = t->parent()) { - if (auto* class_type = ClassType::DynamicCast(t)) return class_type; + if (auto* class_type = ClassType::DynamicCast(t)) { + return class_type; + } } return base::nullopt; } @@ -86,7 +88,7 @@ bool Type::IsAbstractName(const std::string& name) const { std::string Type::GetGeneratedTypeName() const { std::string result = GetGeneratedTypeNameImpl(); - if (result.empty() || result == "compiler::TNode<>") { + if (result.empty() || result == "TNode<>") { ReportError("Generated type is required for type '", ToString(), "'. Use 'generates' clause in definition."); } @@ -382,7 +384,7 @@ std::string ClassType::GetGeneratedTNodeTypeNameImpl() const { std::string ClassType::GetGeneratedTypeNameImpl() const { return IsConstexpr() ? GetGeneratedTNodeTypeName() - : "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">"; + : "TNode<" + GetGeneratedTNodeTypeName() + ">"; } std::string ClassType::ToExplicitString() const { @@ -404,11 +406,11 @@ void ClassType::Finalize() const { if (const ClassType* super_class = ClassType::DynamicCast(parent())) { if (super_class->HasIndexedField()) flags_ |= ClassFlag::kHasIndexedField; if (!super_class->IsAbstract() && !HasSameInstanceTypeAsParent()) { - Error( - "Super class must either be abstract (annotate super class with " - "@abstract) " - "or this class must have the same instance type as the super class " - "(annotate this class with @hasSameInstanceTypeAsParent).") + Error("Super class must either be abstract (annotate super class with ", + ANNOTATION_ABSTRACT, + ") or this class must have the same instance type as the super " + "class (annotate this class with ", + ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT, ").") .Position(this->decl_->name->pos); } } diff --git a/deps/v8/src/torque/types.h b/deps/v8/src/torque/types.h index d2198d50c3..0102cf31d5 100644 --- a/deps/v8/src/torque/types.h +++ b/deps/v8/src/torque/types.h @@ -156,7 +156,7 @@ struct Field { SourcePosition pos; const AggregateType* aggregate; - base::Optional<const Field*> index; + base::Optional<NameAndType> index; NameAndType name_and_type; size_t offset; bool is_weak; @@ -204,8 +204,7 @@ class AbstractType final : public Type { return "AT" + str; } std::string GetGeneratedTypeNameImpl() const override { - return IsConstexpr() ? generated_type_ - : "compiler::TNode<" + generated_type_ + ">"; + return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">"; } std::string GetGeneratedTNodeTypeNameImpl() const override; bool IsConstexpr() const override { @@ -316,7 +315,7 @@ class V8_EXPORT_PRIVATE UnionType final : public Type { std::string ToExplicitString() const override; std::string MangledName() const override; std::string GetGeneratedTypeNameImpl() const override { - return "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">"; + return "TNode<" + GetGeneratedTNodeTypeName() + ">"; } std::string GetGeneratedTNodeTypeNameImpl() const override; @@ -514,10 +513,12 @@ class ClassType final : public AggregateType { std::string GetGeneratedTNodeTypeNameImpl() const override; bool IsExtern() const { return flags_ & ClassFlag::kExtern; } bool ShouldGeneratePrint() const { - return flags_ & ClassFlag::kGeneratePrint || !IsExtern(); + return (flags_ & ClassFlag::kGeneratePrint || !IsExtern()) && + !HasUndefinedLayout(); } bool ShouldGenerateVerify() const { - return flags_ & ClassFlag::kGenerateVerify || !IsExtern(); + return (flags_ & ClassFlag::kGenerateVerify || !IsExtern()) && + !HasUndefinedLayout(); } bool IsTransient() const override { return flags_ & ClassFlag::kTransient; } bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; } @@ -549,6 +550,20 @@ class ClassType final : public AggregateType { std::vector<Field> ComputeAllFields() const; + const InstanceTypeConstraints& GetInstanceTypeConstraints() const { + return decl_->instance_type_constraints; + } + bool IsHighestInstanceTypeWithinParent() const { + return flags_ & ClassFlag::kHighestInstanceTypeWithinParent; + } + bool IsLowestInstanceTypeWithinParent() const { + return flags_ & ClassFlag::kLowestInstanceTypeWithinParent; + } + bool HasUndefinedLayout() const { + return flags_ & ClassFlag::kUndefinedLayout; + } + SourcePosition GetPosition() const { return decl_->pos; } + private: friend class TypeOracle; friend class TypeVisitor; diff --git a/deps/v8/src/torque/utils.cc b/deps/v8/src/torque/utils.cc index 38862b31b0..4e757ac9e8 100644 --- a/deps/v8/src/torque/utils.cc +++ b/deps/v8/src/torque/utils.cc @@ -212,19 +212,25 @@ bool IsValidTypeName(const std::string& s) { } std::string CapifyStringWithUnderscores(const std::string& camellified_string) { + // Special case: JSAbc yields JS_ABC, not JSABC, for any Abc. + size_t js_position = camellified_string.find("JS"); + std::string result; - bool previousWasLower = false; - for (auto current : camellified_string) { - if (previousWasLower && isupper(current)) { + bool previousWasLowerOrDigit = false; + for (size_t index = 0; index < camellified_string.size(); ++index) { + char current = camellified_string[index]; + if ((previousWasLowerOrDigit && isupper(current)) || + (js_position != std::string::npos && + index == js_position + strlen("JS"))) { result += "_"; } if (current == '.' || current == '-') { result += "_"; - previousWasLower = false; + previousWasLowerOrDigit = false; continue; } result += toupper(current); - previousWasLower = (islower(current)); + previousWasLowerOrDigit = islower(current) || isdigit(current); } return result; } |