diff options
author | Michaël Zasso <targos@protonmail.com> | 2021-08-29 14:20:49 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2021-08-30 21:02:51 +0200 |
commit | 50930a0fa08297d0ce7e67fa6594fe47937b99ff (patch) | |
tree | 96bd30c0c63790bc1992a2f241a3df94d563b283 /deps/v8/src/torque/implementation-visitor.cc | |
parent | b63e449b2eade1111b52f6559669400a4e855903 (diff) | |
download | node-new-50930a0fa08297d0ce7e67fa6594fe47937b99ff.tar.gz |
deps: update V8 to 9.3.345.16
PR-URL: https://github.com/nodejs/node/pull/39469
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/torque/implementation-visitor.cc')
-rw-r--r-- | deps/v8/src/torque/implementation-visitor.cc | 752 |
1 files changed, 379 insertions, 373 deletions
diff --git a/deps/v8/src/torque/implementation-visitor.cc b/deps/v8/src/torque/implementation-visitor.cc index b35a45d7b6..b814f0cc63 100644 --- a/deps/v8/src/torque/implementation-visitor.cc +++ b/deps/v8/src/torque/implementation-visitor.cc @@ -13,6 +13,7 @@ #include "src/torque/cc-generator.h" #include "src/torque/cfg.h" #include "src/torque/constants.h" +#include "src/torque/cpp-builder.h" #include "src/torque/csa-generator.h" #include "src/torque/declaration-visitor.h" #include "src/torque/global-context.h" @@ -28,6 +29,12 @@ namespace v8 { namespace internal { namespace torque { +// Sadly, 'using std::string_literals::operator""s;' is bugged in MSVC (see +// https://developercommunity.visualstudio.com/t/Incorrect-warning-when-using-standard-st/673948). +// TODO(nicohartmann@): Change to 'using std::string_literals::operator""s;' +// once this is fixed. +using namespace std::string_literals; // NOLINT(build/namespaces) + namespace { const char* BuiltinIncludesMarker = "// __BUILTIN_INCLUDES_MARKER__\n"; } // namespace @@ -72,61 +79,55 @@ void ImplementationVisitor::BeginGeneratedFiles() { } } - for (SourceId file : SourceFileMap::AllSources()) { - auto& streams = GlobalContext::GeneratedPerFile(file); + for (SourceId source : SourceFileMap::AllSources()) { + auto& streams = GlobalContext::GeneratedPerFile(source); // Output beginning of CSA .cc file. { - std::ostream& out = streams.csa_ccfile; + cpp::File& file = streams.csa_cc; for (const std::string& include_path : GlobalContext::CppIncludes()) { - out << "#include " << StringLiteralQuote(include_path) << "\n"; + file << "#include " << StringLiteralQuote(include_path) << "\n"; } - out << "// Required Builtins:\n"; - out << "#include \"torque-generated/" + - SourceFileMap::PathFromV8RootWithoutExtension(file) + - "-tq-csa.h\"\n"; + file << "// Required Builtins:\n"; + file << "#include \"torque-generated/" + + SourceFileMap::PathFromV8RootWithoutExtension(source) + + "-tq-csa.h\"\n"; // Now that required include files are collected while generting the file, // we only know the full set at the end. Insert a marker here that is // replaced with the list of includes at the very end. // TODO(nicohartmann@): This is not the most beautiful way to do this, // replace once the cpp file builder is available, where this can be // handled easily. - out << BuiltinIncludesMarker; - out << "\n"; + file << BuiltinIncludesMarker; + file << "\n"; - out << "namespace v8 {\n" - << "namespace internal {\n" - << "\n"; + streams.csa_cc.BeginNamespace("v8", "internal"); } // Output beginning of CSA .h file. { - std::ostream& out = streams.csa_headerfile; + cpp::File& file = streams.csa_header; std::string header_define = "V8_GEN_TORQUE_GENERATED_" + - UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_CSA_H_"; - out << "#ifndef " << header_define << "\n"; - out << "#define " << header_define << "\n\n"; - out << "#include \"src/builtins/torque-csa-header-includes.h\"\n"; - out << "\n"; + UnderlinifyPath(SourceFileMap::PathFromV8Root(source)) + "_CSA_H_"; + streams.csa_header.BeginIncludeGuard(header_define); + file << "#include \"src/builtins/torque-csa-header-includes.h\"\n"; + file << "\n"; - out << "namespace v8 {\n" - << "namespace internal {\n" - << "\n"; + streams.csa_header.BeginNamespace("v8", "internal"); } // Output beginning of class definition .cc file. { - std::ostream& out = streams.class_definition_ccfile; - if (contains_class_definitions.count(file) != 0) { - out << "#include \"" - << SourceFileMap::PathFromV8RootWithoutExtension(file) - << "-inl.h\"\n\n"; - out << "#include \"torque-generated/class-verifiers.h\"\n"; - out << "#include \"src/objects/instance-type-inl.h\"\n\n"; + cpp::File& file = streams.class_definition_cc; + if (contains_class_definitions.count(source) != 0) { + file << "#include \"" + << SourceFileMap::PathFromV8RootWithoutExtension(source) + << "-inl.h\"\n\n"; + file << "#include \"torque-generated/class-verifiers.h\"\n"; + file << "#include \"src/objects/instance-type-inl.h\"\n\n"; } - out << "namespace v8 {\n"; - out << "namespace internal {\n"; + streams.class_definition_cc.BeginNamespace("v8", "internal"); } } } @@ -134,35 +135,27 @@ void ImplementationVisitor::BeginGeneratedFiles() { void ImplementationVisitor::EndGeneratedFiles() { for (SourceId file : SourceFileMap::AllSources()) { auto& streams = GlobalContext::GeneratedPerFile(file); - { - std::ostream& out = streams.csa_ccfile; - out << "} // namespace internal\n" - << "} // namespace v8\n" - << "\n"; - } - { - std::ostream& out = streams.csa_headerfile; + // Output ending of CSA .cc file. + streams.csa_cc.EndNamespace("v8", "internal"); + // Output ending of CSA .h file. + { std::string header_define = "V8_GEN_TORQUE_GENERATED_" + UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_CSA_H_"; - out << "} // namespace internal\n" - << "} // namespace v8\n" - << "\n"; - out << "#endif // " << header_define << "\n"; + streams.csa_header.EndNamespace("v8", "internal"); + streams.csa_header.EndIncludeGuard(header_define); } - { - std::ostream& out = streams.class_definition_ccfile; - out << "} // namespace v8\n"; - out << "} // namespace internal\n"; - } + // Output ending of class definition .cc file. + streams.class_definition_cc.EndNamespace("v8", "internal"); } } void ImplementationVisitor::BeginDebugMacrosFile() { + // TODO(torque-builer): Can use builder for debug_macros_*_ std::ostream& source = debug_macros_cc_; std::ostream& header = debug_macros_h_; @@ -191,6 +184,7 @@ void ImplementationVisitor::BeginDebugMacrosFile() { } void ImplementationVisitor::EndDebugMacrosFile() { + // TODO(torque-builder): Can use builder for debug_macros_*_ std::ostream& source = debug_macros_cc_; std::ostream& header = debug_macros_h_; @@ -212,33 +206,31 @@ void ImplementationVisitor::Visit(NamespaceConstant* decl) { BindingsManagersScope bindings_managers_scope; - csa_headerfile() << " "; - GenerateFunctionDeclaration(csa_headerfile(), "", decl->external_name(), - signature, {}); - csa_headerfile() << ";\n"; + cpp::Function f = + GenerateFunction(nullptr, decl->external_name(), signature, {}); - GenerateFunctionDeclaration(csa_ccfile(), "", decl->external_name(), - signature, {}); - csa_ccfile() << " {\n"; - csa_ccfile() << " compiler::CodeAssembler ca_(state_);\n"; + f.PrintDeclaration(csa_headerfile()); - DCHECK(!signature.return_type->IsVoidOrNever()); + f.PrintDefinition(csa_ccfile(), [&](std::ostream& stream) { + stream << " compiler::CodeAssembler ca_(state_);\n"; - assembler_ = CfgAssembler(Stack<const Type*>{}); + DCHECK(!signature.return_type->IsVoidOrNever()); - VisitResult expression_result = Visit(decl->body()); - VisitResult return_result = - GenerateImplicitConvert(signature.return_type, expression_result); + assembler_ = CfgAssembler(Stack<const Type*>{}); - CSAGenerator csa_generator{assembler().Result(), csa_ccfile()}; - Stack<std::string> values = *csa_generator.EmitGraph(Stack<std::string>{}); + VisitResult expression_result = Visit(decl->body()); + VisitResult return_result = + GenerateImplicitConvert(signature.return_type, expression_result); - assembler_ = base::nullopt; + CSAGenerator csa_generator{assembler().Result(), stream}; + Stack<std::string> values = *csa_generator.EmitGraph(Stack<std::string>{}); - csa_ccfile() << " return "; - CSAGenerator::EmitCSAValue(return_result, values, csa_ccfile()); - csa_ccfile() << ";\n"; - csa_ccfile() << "}\n\n"; + assembler_ = base::nullopt; + + stream << " return "; + CSAGenerator::EmitCSAValue(return_result, values, stream); + stream << ";"; + }); } void ImplementationVisitor::Visit(TypeAlias* alias) { @@ -252,10 +244,28 @@ void ImplementationVisitor::Visit(TypeAlias* alias) { } } +class ImplementationVisitor::MacroInliningScope { + public: + MacroInliningScope(ImplementationVisitor* visitor, const Macro* macro) + : visitor_(visitor), macro_(macro) { + if (!visitor_->inlining_macros_.insert(macro).second) { + // Recursive macro expansion would just keep going until stack overflow. + // To avoid crashes, throw an error immediately. + ReportError("Recursive macro call to ", *macro); + } + } + ~MacroInliningScope() { visitor_->inlining_macros_.erase(macro_); } + + private: + ImplementationVisitor* visitor_; + const Macro* macro_; +}; + VisitResult ImplementationVisitor::InlineMacro( Macro* macro, base::Optional<LocationReference> this_reference, const std::vector<VisitResult>& arguments, const std::vector<Block*> label_blocks) { + MacroInliningScope macro_inlining_scope(this, macro); CurrentScope::Scope current_scope(macro); BindingsManagersScope bindings_managers_scope; CurrentCallable::Scope current_callable(macro); @@ -370,24 +380,23 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) { bool has_return_value = can_return && return_type != TypeOracle::GetVoidType(); - GenerateMacroFunctionDeclaration(csa_headerfile(), macro); - csa_headerfile() << ";\n"; + cpp::Function f = GenerateMacroFunctionDeclaration(macro); + f.PrintDeclaration(csa_headerfile()); + + cpp::File csa_cc(csa_ccfile()); // Avoid multiple-definition errors since it is possible for multiple // generated -inl.inc files to all contain function definitions for the same // Torque macro. + base::Optional<cpp::IncludeGuardScope> include_guard; if (output_type_ == OutputType::kCC) { - csa_ccfile() << "#ifndef V8_INTERNAL_DEFINED_" << macro->CCName() << "\n"; - csa_ccfile() << "#define V8_INTERNAL_DEFINED_" << macro->CCName() << "\n"; + include_guard.emplace(&csa_cc, "V8_INTERNAL_DEFINED_"s + macro->CCName()); } else if (output_type_ == OutputType::kCCDebug) { - csa_ccfile() << "#ifndef V8_INTERNAL_DEFINED_" << macro->CCDebugName() - << "\n"; - csa_ccfile() << "#define V8_INTERNAL_DEFINED_" << macro->CCDebugName() - << "\n"; + include_guard.emplace(&csa_cc, + "V8_INTERNAL_DEFINED_"s + macro->CCDebugName()); } - GenerateMacroFunctionDeclaration(csa_ccfile(), macro); - csa_ccfile() << " {\n"; + f.PrintBeginDefinition(csa_ccfile()); if (output_type_ == OutputType::kCC) { // For now, generated C++ is only for field offset computations. If we ever @@ -506,14 +515,9 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) { } csa_ccfile() << ";\n"; } - csa_ccfile() << "}\n"; - if (output_type_ == OutputType::kCC) { - csa_ccfile() << "#endif // V8_INTERNAL_DEFINED_" << macro->CCName() - << "\n"; - } else if (output_type_ == OutputType::kCCDebug) { - csa_ccfile() << "#endif // V8_INTERNAL_DEFINED_" << macro->CCDebugName() - << "\n"; - } + f.PrintEndDefinition(csa_ccfile()); + + include_guard.reset(); csa_ccfile() << "\n"; } @@ -1765,6 +1769,7 @@ void ImplementationVisitor::GenerateImplementation(const std::string& dir) { csa_cc.replace(pos, strlen(BuiltinIncludesMarker), std::move(includes)); } + // TODO(torque-builder): Pass file directly. WriteFile(base_filename + "-tq-csa.cc", std::move(csa_cc)); WriteFile(base_filename + "-tq-csa.h", streams.csa_headerfile.str()); WriteFile(base_filename + "-tq.inc", @@ -1781,63 +1786,66 @@ void ImplementationVisitor::GenerateImplementation(const std::string& dir) { WriteFile(dir + "/debug-macros.cc", debug_macros_cc_.str()); } -void ImplementationVisitor::GenerateMacroFunctionDeclaration(std::ostream& o, - Macro* macro) { - GenerateFunctionDeclaration(o, "", - output_type_ == OutputType::kCC - ? macro->CCName() - : output_type_ == OutputType::kCCDebug - ? macro->CCDebugName() - : macro->ExternalName(), - macro->signature(), macro->parameter_names()); +cpp::Function ImplementationVisitor::GenerateMacroFunctionDeclaration( + Macro* macro) { + return GenerateFunction(nullptr, + output_type_ == OutputType::kCC + ? macro->CCName() + : output_type_ == OutputType::kCCDebug + ? macro->CCDebugName() + : macro->ExternalName(), + macro->signature(), macro->parameter_names()); } -std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( - std::ostream& o, const std::string& macro_prefix, const std::string& name, - const Signature& signature, const NameVector& parameter_names, - bool pass_code_assembler_state) { - std::vector<std::string> generated_parameter_names; - if (output_type_ == OutputType::kCC) { - o << "inline "; - } +cpp::Function ImplementationVisitor::GenerateFunction( + cpp::Class* owner, const std::string& name, const Signature& signature, + const NameVector& parameter_names, bool pass_code_assembler_state, + std::vector<std::string>* generated_parameter_names) { + cpp::Function f(owner, name); + f.SetInline(output_type_ == OutputType::kCC); + + // Set return type. + // TODO(torque-builder): Consider an overload of SetReturnType that handles + // this. if (signature.return_type->IsVoidOrNever()) { - o << "void"; + f.SetReturnType("void"); + } else if (output_type_ == OutputType::kCCDebug) { + f.SetReturnType(std::string("Value<") + + signature.return_type->GetDebugType() + ">"); + } else if (output_type_ == OutputType::kCC) { + f.SetReturnType(signature.return_type->GetRuntimeType()); } else { - if (output_type_ == OutputType::kCCDebug) { - o << "Value<" << signature.return_type->GetDebugType() << ">"; - } else { - o << (output_type_ == OutputType::kCC - ? signature.return_type->GetRuntimeType() - : signature.return_type->GetGeneratedTypeName()); - } + DCHECK_EQ(output_type_, OutputType::kCSA); + f.SetReturnType(signature.return_type->GetGeneratedTypeName()); } - o << " " << macro_prefix << name << "("; - bool first = true; + bool ignore_first_parameter = true; if (output_type_ == OutputType::kCCDebug) { - first = false; - o << "d::MemoryAccessor accessor"; + f.AddParameter("d::MemoryAccessor", "accessor"); } else if (output_type_ == OutputType::kCSA && pass_code_assembler_state) { - first = false; - o << "compiler::CodeAssemblerState* state_"; + f.AddParameter("compiler::CodeAssemblerState*", "state_"); + } else { + ignore_first_parameter = false; } + // TODO(torque-builder): Consider an overload for AddParameter that handles + // this. DCHECK_GE(signature.types().size(), parameter_names.size()); - for (size_t i = 0; i < signature.types().size(); ++i) { - if (!first) o << ", "; - first = false; + for (std::size_t i = 0; i < signature.types().size(); ++i) { const Type* parameter_type = signature.types()[i]; - const std::string& generated_type_name = - output_type_ == OutputType::kCC - ? parameter_type->GetRuntimeType() - : output_type_ == OutputType::kCCDebug - ? parameter_type->GetDebugType() - : parameter_type->GetGeneratedTypeName(); - - generated_parameter_names.push_back(ExternalParameterName( - i < parameter_names.size() ? parameter_names[i]->value - : std::to_string(i))); - o << generated_type_name << " " << generated_parameter_names.back(); + std::string type; + if (output_type_ == OutputType::kCC) { + type = parameter_type->GetRuntimeType(); + } else if (output_type_ == OutputType::kCCDebug) { + type = parameter_type->GetDebugType(); + } else { + DCHECK_EQ(output_type_, OutputType::kCSA); + type = parameter_type->GetGeneratedTypeName(); + } + f.AddParameter(std::move(type), + ExternalParameterName(i < parameter_names.size() + ? parameter_names[i]->value + : std::to_string(i))); } for (const LabelDeclaration& label_info : signature.labels) { @@ -1845,11 +1853,8 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( output_type_ == OutputType::kCCDebug) { ReportError("Macros that generate runtime code can't have label exits"); } - if (!first) o << ", "; - first = false; - generated_parameter_names.push_back( - ExternalLabelName(label_info.name->value)); - o << "compiler::CodeAssemblerLabel* " << generated_parameter_names.back(); + f.AddParameter("compiler::CodeAssemblerLabel*", + ExternalLabelName(label_info.name->value)); size_t i = 0; for (const Type* type : label_info.types) { std::string generated_type_name; @@ -1860,16 +1865,20 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( generated_type_name += type->GetGeneratedTNodeTypeName(); generated_type_name += ">*"; } - o << ", "; - generated_parameter_names.push_back( - ExternalLabelParameterName(label_info.name->value, i)); - o << generated_type_name << " " << generated_parameter_names.back(); + f.AddParameter(generated_type_name, + ExternalLabelParameterName(label_info.name->value, i)); ++i; } } - o << ")"; - return generated_parameter_names; + if (generated_parameter_names) { + *generated_parameter_names = f.GetParameterNames(); + if (ignore_first_parameter) { + DCHECK(!generated_parameter_names->empty()); + generated_parameter_names->erase(generated_parameter_names->begin()); + } + } + return f; } namespace { @@ -2801,6 +2810,7 @@ VisitResult ImplementationVisitor::GenerateCall( } } + // TODO(torque-builder): Consider a function builder here. if (return_type->IsConstexpr()) { DCHECK_EQ(0, arguments.labels.size()); std::stringstream result; @@ -3500,7 +3510,6 @@ void ImplementationVisitor::GenerateBuiltinDefinitionsAndInterfaceDescriptors( interface_descriptors << " DECLARE_DEFAULT_DESCRIPTOR(" << descriptor_name << ")\n"; - interface_descriptors << "};\n\n"; } else { builtin_definitions << "TFJ(" << builtin->ExternalName(); @@ -3568,16 +3577,12 @@ std::string ToString(FieldSectionType type) { switch (type) { case FieldSectionType::kNoSection: return "NoSection"; - break; case FieldSectionType::kWeakSection: return "WeakFields"; - break; case FieldSectionType::kStrongSection: return "StrongFields"; - break; case FieldSectionType::kScalarSection: return "ScalarFields"; - break; } UNREACHABLE(); } @@ -3850,12 +3855,12 @@ namespace { class ClassFieldOffsetGenerator : public FieldOffsetsGenerator { public: ClassFieldOffsetGenerator(std::ostream& header, std::ostream& inline_header, - const ClassType* type, std::string gen_name_T) + const ClassType* type, std::string gen_name) : FieldOffsetsGenerator(type), hdr_(header), inl_(inline_header), previous_field_end_("P::kHeaderSize"), - gen_name_T_(gen_name_T) {} + gen_name_(gen_name) {} void WriteField(const Field& f, const std::string& size_string) override { std::string field = "k" + CamelifyString(f.name_and_type.name) + "Offset"; std::string field_end = field + "End"; @@ -3872,14 +3877,18 @@ class ClassFieldOffsetGenerator : public FieldOffsetsGenerator { std::string function_name = CamelifyString(f.name_and_type.name) + "Offset"; - hdr_ << " inline int " << function_name << "() const;\n"; - inl_ << "template <class D, class P>\n"; - inl_ << "int " << gen_name_T_ << "::" << function_name << "() const {\n"; - // Item 1 in a flattened slice is the offset. - inl_ << " return static_cast<int>(std::get<1>(" - << Callable::PrefixNameForCCOutput(type_->GetSliceMacroName(f)) - << "(*static_cast<const D*>(this))));\n"; - inl_ << "}\n\n"; + std::vector<cpp::TemplateParameter> params = {cpp::TemplateParameter("D"), + cpp::TemplateParameter("P")}; + cpp::Class owner(std::move(params), gen_name_); + + auto getter = cpp::Function::DefaultGetter("int", &owner, function_name); + getter.PrintDeclaration(hdr_); + getter.PrintDefinition(inl_, [&](std::ostream& stream) { + // Item 1 in a flattened slice is the offset. + stream << " return static_cast<int>(std::get<1>(" + << Callable::PrefixNameForCCOutput(type_->GetSliceMacroName(f)) + << "(*static_cast<const D*>(this))));\n"; + }); } void WriteMarker(const std::string& marker) override { hdr_ << " static constexpr int " << marker << " = " << previous_field_end_ @@ -3890,7 +3899,7 @@ class ClassFieldOffsetGenerator : public FieldOffsetsGenerator { std::ostream& hdr_; std::ostream& inl_; std::string previous_field_end_; - std::string gen_name_T_; + std::string gen_name_; }; class CppClassGenerator { @@ -3921,9 +3930,9 @@ class CppClassGenerator { // active struct fields. void GenerateFieldAccessors(const Field& class_field, std::vector<const Field*>& struct_fields); - void EmitLoadFieldStatement(const Field& class_field, + void EmitLoadFieldStatement(std::ostream& stream, const Field& class_field, std::vector<const Field*>& struct_fields); - void EmitStoreFieldStatement(const Field& class_field, + void EmitStoreFieldStatement(std::ostream& stream, const Field& class_field, std::vector<const Field*>& struct_fields); void GenerateClassCasts(); @@ -3971,16 +3980,20 @@ base::Optional<std::vector<Field>> GetOrderedUniqueIndexFields( } void CppClassGenerator::GenerateClass() { - hdr_ << "\n"; - hdr_ << "// Alias for HeapObject::Is" << name_ - << "() that avoids inlining.\n"; - hdr_ << "V8_EXPORT_PRIVATE bool Is" << name_ << "_NonInline(HeapObject o);\n"; - hdr_ << "\n"; + // Is<name>_NonInline(HeapObject) + { + cpp::Function f("Is"s + name_ + "_NonInline"); + f.SetDescription("Alias for HeapObject::Is"s + name_ + + "() that avoids inlining."); + f.SetExport(true); + f.SetReturnType("bool"); + f.AddParameter("HeapObject", "o"); - impl_ << "\n"; - impl_ << "bool Is" << name_ << "_NonInline(HeapObject o) {\n"; - impl_ << " return o.Is" << name_ << "();\n"; - impl_ << "}\n\n"; + f.PrintDeclaration(hdr_); + f.PrintDefinition(impl_, [&](std::ostream& stream) { + stream << " return o.Is" << name_ << "();"; + }); + } hdr_ << template_decl() << "\n"; hdr_ << "class " << gen_name_ << " : public P {\n"; @@ -4005,14 +4018,22 @@ void CppClassGenerator::GenerateClass() { GenerateClassCasts(); + std::vector<cpp::TemplateParameter> templateArgs = { + cpp::TemplateParameter("D"), cpp::TemplateParameter("P")}; + cpp::Class c(std::move(templateArgs), gen_name_); + if (type_->ShouldGeneratePrint()) { hdr_ << "\n DECL_PRINTER(" << name_ << ")\n"; } if (type_->ShouldGenerateVerify()) { IfDefScope hdr_scope(hdr_, "VERIFY_HEAP"); - hdr_ << " V8_EXPORT_PRIVATE void " << name_ - << "Verify(Isolate* isolate);\n"; + // V8_EXPORT_PRIVATE void Verify(Isolate*); + cpp::Function f(&c, name_ + "Verify"); + f.SetExport(); + f.SetReturnType("void"); + f.AddParameter("Isolate*", "isolate"); + f.PrintDeclaration(hdr_); IfDefScope impl_scope(impl_, "VERIFY_HEAP"); impl_ << "\ntemplate <>\n"; @@ -4025,7 +4046,7 @@ void CppClassGenerator::GenerateClass() { } hdr_ << "\n"; - ClassFieldOffsetGenerator g(hdr_, inl_, type_, gen_name_T_); + ClassFieldOffsetGenerator g(hdr_, inl_, type_, gen_name_); for (auto f : type_->fields()) { CurrentSourcePosition::Scope scope(f.pos); g.RecordOffsetFor(f); @@ -4042,58 +4063,69 @@ void CppClassGenerator::GenerateClass() { const Field& last_field = type_->LastField(); std::string last_field_item_size = std::get<1>(*SizeOf(last_field.name_and_type.type)); - hdr_ << " inline int AllocatedSize() const;\n\n"; - inl_ << "template <class D, class P>\n"; - inl_ << "int " << gen_name_T_ << "::AllocatedSize() const {\n"; - inl_ << " auto slice = " - << Callable::PrefixNameForCCOutput( - type_->GetSliceMacroName(last_field)) - << "(*static_cast<const D*>(this));\n"; - inl_ << " return static_cast<int>(std::get<1>(slice)) + " - << last_field_item_size - << " * static_cast<int>(std::get<2>(slice));\n"; - inl_ << "}\n\n"; + + // int AllocatedSize() const + { + cpp::Function f = + cpp::Function::DefaultGetter("int", &c, "AllocatedSize"); + f.PrintDeclaration(hdr_, 2); + + f.PrintDefinition(inl_, [&](std::ostream& stream) { + stream << " auto slice = " + << Callable::PrefixNameForCCOutput( + type_->GetSliceMacroName(last_field)) + << "(*static_cast<const D*>(this));\n"; + stream << " return static_cast<int>(std::get<1>(slice)) + " + << last_field_item_size + << " * static_cast<int>(std::get<2>(slice));\n"; + }); + } } else if (type_->ShouldGenerateBodyDescriptor() || (!type_->IsAbstract() && !type_->IsSubtypeOf(TypeOracle::GetJSObjectType()))) { - hdr_ << " V8_INLINE static constexpr int32_t SizeFor("; - bool first = true; + cpp::Function f(&c, "SizeFor"); + f.SetReturnType("int32_t"); + f.SetFlags(cpp::Function::kStatic | cpp::Function::kConstexpr | + cpp::Function::kV8Inline); for (const Field& field : *index_fields) { - if (!first) hdr_ << ", "; - hdr_ << "int " << field.name_and_type.name; - first = false; - } - hdr_ << ") {\n"; - if (index_fields->empty()) { - hdr_ << " DCHECK(kHeaderSize == kSize && kHeaderSize == " - << *type_->size().SingleValue() << ");\n"; - } - hdr_ << " int32_t size = kHeaderSize;\n"; - for (const Field& field : type_->ComputeAllFields()) { - if (field.index) { - auto index_name_and_type = - *ExtractSimpleFieldArraySize(*type_, field.index->expr); - size_t field_size = 0; - std::tie(field_size, std::ignore) = field.GetFieldSizeInformation(); - hdr_ << " size += " << index_name_and_type.name << " * " - << field_size << ";\n"; - } - } - if (type_->size().Alignment() < TargetArchitecture::TaggedSize()) { - hdr_ << " size = OBJECT_POINTER_ALIGN(size);\n"; + f.AddParameter("int", field.name_and_type.name); } - hdr_ << " return size;\n"; - hdr_ << " }\n\n"; - hdr_ << " V8_INLINE int32_t AllocatedSize() const {\n"; - hdr_ << " return SizeFor("; - first = true; - for (auto field : *index_fields) { - if (!first) hdr_ << ", "; - hdr_ << "this->" << field.name_and_type.name << "()"; - first = false; + f.PrintInlineDefinition(hdr_, [&](std::ostream& stream) { + if (index_fields->empty()) { + stream << " DCHECK(kHeaderSize == kSize && kHeaderSize == " + << *type_->size().SingleValue() << ");\n"; + } + stream << " int32_t size = kHeaderSize;\n"; + for (const Field& field : type_->ComputeAllFields()) { + if (field.index) { + auto index_name_and_type = + *ExtractSimpleFieldArraySize(*type_, field.index->expr); + stream << " size += " << index_name_and_type.name << " * " + << std::get<0>(field.GetFieldSizeInformation()) << ";\n"; + } + } + if (type_->size().Alignment() < TargetArchitecture::TaggedSize()) { + stream << " size = OBJECT_POINTER_ALIGN(size);\n"; + } + stream << " return size;\n"; + }); + + // V8_INLINE int32_t AllocatedSize() const + { + cpp::Function f = + cpp::Function::DefaultGetter("int32_t", &c, "AllocatedSize"); + f.SetFlag(cpp::Function::kV8Inline); + f.PrintInlineDefinition(hdr_, [&](std::ostream& stream) { + stream << " return SizeFor("; + bool first = true; + for (auto field : *index_fields) { + if (!first) stream << ", "; + stream << "this->" << field.name_and_type.name << "()"; + first = false; + } + stream << ");\n"; + }); } - hdr_ << ");\n }\n"; - hdr_ << "\n"; } hdr_ << " friend class Factory;\n\n"; @@ -4103,18 +4135,42 @@ void CppClassGenerator::GenerateClass() { hdr_ << "};\n\n"; if (type_->ShouldGenerateFullClassDefinition()) { + // If this class extends from another class which is defined in the same tq + // file, and that other class doesn't generate a full class definition, then + // the resulting .inc file would be uncompilable due to ordering + // requirements: the generated file must go before the hand-written + // definition of the base class, but it must also go after that same + // hand-written definition. + base::Optional<const ClassType*> parent = type_->parent()->ClassSupertype(); + while (parent) { + if ((*parent)->GenerateCppClassDefinitions() && + !(*parent)->ShouldGenerateFullClassDefinition() && + (*parent)->AttributedToFile() == type_->AttributedToFile()) { + Error("Exported ", *type_, + " cannot be in the same file as its parent extern ", **parent); + } + parent = (*parent)->parent()->ClassSupertype(); + } + GenerateClassExport(type_, hdr_, inl_); } } void CppClassGenerator::GenerateClassCasts() { - hdr_ << " V8_INLINE static D cast(Object object) {\n"; - hdr_ << " return D(object.ptr());\n"; - hdr_ << " }\n"; - - hdr_ << " V8_INLINE static D unchecked_cast(Object object) {\n"; - hdr_ << " return bit_cast<D>(object);\n"; - hdr_ << " }\n"; + cpp::Function f("cast"); + f.SetFlags(cpp::Function::kV8Inline | cpp::Function::kStatic); + f.SetReturnType("D"); + f.AddParameter("Object", "object"); + + // V8_INLINE static D cast(Object) + f.PrintInlineDefinition(hdr_, [](std::ostream& stream) { + stream << " return D(object.ptr());\n"; + }); + // V8_INLINE static D unchecked_cast(Object) + f.SetName("unchecked_cast"); + f.PrintInlineDefinition(hdr_, [](std::ostream& stream) { + stream << " return bit_cast<D>(object);\n"; + }); } void CppClassGenerator::GenerateClassConstructors() { @@ -4250,134 +4306,82 @@ void CppClassGenerator::GenerateFieldAccessors( hdr_ << " // Torque type: " << field_type->ToString() << "\n"; } - hdr_ << " inline " << type_name << " " << name << "(" - << (indexed ? "int i" : ""); - switch (class_field.read_synchronization) { - case FieldSynchronization::kNone: - break; - case FieldSynchronization::kRelaxed: - hdr_ << (indexed ? ", RelaxedLoadTag" : "RelaxedLoadTag"); - break; - case FieldSynchronization::kAcquireRelease: - hdr_ << (indexed ? ", AcquireLoadTag" : "AcquireLoadTag"); - break; - } - hdr_ << ") const;\n"; - if (can_contain_heap_objects) { - hdr_ << " inline " << type_name << " " << name - << "(PtrComprCageBase cage_base" << (indexed ? ", int i" : ""); + std::vector<cpp::TemplateParameter> templateParameters = { + cpp::TemplateParameter("D"), cpp::TemplateParameter("P")}; + cpp::Class owner(std::move(templateParameters), gen_name_); + + // getter + { + auto getter = cpp::Function::DefaultGetter(type_name, &owner, name); + if (indexed) { + getter.AddParameter("int", "i"); + } + const char* tag_argument; switch (class_field.read_synchronization) { case FieldSynchronization::kNone: + tag_argument = ""; break; case FieldSynchronization::kRelaxed: - hdr_ << ", RelaxedLoadTag"; + getter.AddParameter("RelaxedLoadTag"); + tag_argument = ", kRelaxedLoad"; break; case FieldSynchronization::kAcquireRelease: - hdr_ << ", AcquireLoadTag"; + getter.AddParameter("AcquireLoadTag"); + tag_argument = ", kAcquireLoad"; break; } - hdr_ << ") const;\n"; - } - hdr_ << " inline void set_" << name << "(" << (indexed ? "int i, " : "") - << type_name << " value"; - switch (class_field.write_synchronization) { - case FieldSynchronization::kNone: - break; - case FieldSynchronization::kRelaxed: - hdr_ << ", RelaxedStoreTag"; - break; - case FieldSynchronization::kAcquireRelease: - hdr_ << ", ReleaseStoreTag"; - break; + getter.PrintDeclaration(hdr_); + + // For tagged data, generate the extra getter that derives an + // PtrComprCageBase from the current object's pointer. + if (can_contain_heap_objects) { + getter.PrintDefinition(inl_, [&](auto& stream) { + stream + << " PtrComprCageBase cage_base = GetPtrComprCageBase(*this);\n"; + stream << " return " << gen_name_ << "::" << name << "(cage_base" + << (indexed ? ", i" : "") << tag_argument << ");\n"; + }); + + getter.InsertParameter(0, "PtrComprCageBase", "cage_base"); + getter.PrintDeclaration(hdr_); + } + + getter.PrintDefinition(inl_, [&](auto& stream) { + stream << " " << type_name << " value;\n"; + EmitLoadFieldStatement(stream, class_field, struct_fields); + stream << " return value;\n"; + }); } - hdr_ << (can_contain_heap_objects - ? ", WriteBarrierMode mode = UPDATE_WRITE_BARRIER" - : "") - << ");\n\n"; - - // For tagged data, generate the extra getter that derives an PtrComprCageBase - // from the current object's pointer. - if (can_contain_heap_objects) { - inl_ << "template <class D, class P>\n"; - inl_ << type_name << " " << gen_name_ << "<D, P>::" << name << "(" - << (indexed ? "int i" : ""); - switch (class_field.read_synchronization) { - case FieldSynchronization::kNone: - break; - case FieldSynchronization::kRelaxed: - inl_ << (indexed ? ", RelaxedLoadTag" : "RelaxedLoadTag"); - break; - case FieldSynchronization::kAcquireRelease: - inl_ << (indexed ? ", AcquireLoadTag" : "AcquireLoadTag"); - break; + + // setter + { + auto setter = cpp::Function::DefaultSetter( + &owner, std::string("set_") + name, type_name, "value"); + if (indexed) { + setter.InsertParameter(0, "int", "i"); } - inl_ << ") const {\n"; - inl_ << " PtrComprCageBase cage_base = GetPtrComprCageBase(*this);\n"; - inl_ << " return " << gen_name_ << "::" << name << "(cage_base" - << (indexed ? ", i" : ""); - switch (class_field.read_synchronization) { + switch (class_field.write_synchronization) { case FieldSynchronization::kNone: break; case FieldSynchronization::kRelaxed: - inl_ << ", kRelaxedLoad"; + setter.AddParameter("RelaxedStoreTag"); break; case FieldSynchronization::kAcquireRelease: - inl_ << ", kAcquireLoad"; + setter.AddParameter("ReleaseStoreTag"); break; } - inl_ << ");\n"; - inl_ << "}\n"; - } + if (can_contain_heap_objects) { + setter.AddParameter("WriteBarrierMode", "mode", "UPDATE_WRITE_BARRIER"); + } + setter.PrintDeclaration(hdr_); - // Generate the getter implementation. - inl_ << "template <class D, class P>\n"; - inl_ << type_name << " " << gen_name_ << "<D, P>::" << name << "("; - if (can_contain_heap_objects) inl_ << "PtrComprCageBase cage_base"; - if (can_contain_heap_objects && indexed) inl_ << ", "; - if (indexed) inl_ << "int i"; - switch (class_field.read_synchronization) { - case FieldSynchronization::kNone: - break; - case FieldSynchronization::kRelaxed: - inl_ << ((can_contain_heap_objects || indexed) ? ", RelaxedLoadTag" - : "RelaxedLoadTag"); - break; - case FieldSynchronization::kAcquireRelease: - inl_ << ((can_contain_heap_objects || indexed) ? ", AcquireLoadTag" - : "AcquireLoadTag"); - break; + setter.PrintDefinition(inl_, [&](auto& stream) { + EmitStoreFieldStatement(stream, class_field, struct_fields); + }); } - inl_ << ") const {\n"; - - inl_ << " " << type_name << " value;\n"; - EmitLoadFieldStatement(class_field, struct_fields); - inl_ << " return value;\n"; - inl_ << "}\n"; - // Generate the setter implementation. - inl_ << "template <class D, class P>\n"; - inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "("; - if (indexed) { - inl_ << "int i, "; - } - inl_ << type_name << " value"; - switch (class_field.write_synchronization) { - case FieldSynchronization::kNone: - break; - case FieldSynchronization::kRelaxed: - inl_ << ", RelaxedStoreTag"; - break; - case FieldSynchronization::kAcquireRelease: - inl_ << ", ReleaseStoreTag"; - break; - } - if (can_contain_heap_objects) { - inl_ << ", WriteBarrierMode mode"; - } - inl_ << ") {\n"; - EmitStoreFieldStatement(class_field, struct_fields); - inl_ << "}\n\n"; + hdr_ << "\n"; } std::string CppClassGenerator::GetFieldOffsetForAccessor(const Field& f) { @@ -4415,7 +4419,8 @@ bool CppClassGenerator::CanContainHeapObjects(const Type* t) { } void CppClassGenerator::EmitLoadFieldStatement( - const Field& class_field, std::vector<const Field*>& struct_fields) { + std::ostream& stream, const Field& class_field, + std::vector<const Field*>& struct_fields) { const Field& innermost_field = struct_fields.empty() ? class_field : *struct_fields.back(); const Type* field_type = innermost_field.name_and_type.type; @@ -4434,13 +4439,13 @@ void CppClassGenerator::EmitLoadFieldStatement( std::string offset = field_offset; if (class_field.index) { const char* index = class_field.index->optional ? "0" : "i"; - GenerateBoundsDCheck(inl_, index, type_, class_field); - inl_ << " int offset = " << field_offset << " + " << index << " * " - << class_field_size << ";\n"; + GenerateBoundsDCheck(stream, index, type_, class_field); + stream << " int offset = " << field_offset << " + " << index << " * " + << class_field_size << ";\n"; offset = "offset"; } - inl_ << " value = "; + stream << " value = "; if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { if (class_field.read_synchronization == @@ -4450,8 +4455,8 @@ void CppClassGenerator::EmitLoadFieldStatement( FieldSynchronization::kRelaxed) { ReportError("Torque doesn't support @cppRelaxedRead on untagged data"); } - inl_ << "this->template ReadField<" << type_name << ">(" << offset - << ");\n"; + stream << "this->template ReadField<" << type_name << ">(" << offset + << ");\n"; } else { const char* load; switch (class_field.read_synchronization) { @@ -4470,19 +4475,20 @@ void CppClassGenerator::EmitLoadFieldStatement( const char* postfix = is_smi ? ".value()" : ""; const char* optional_cage_base = is_smi ? "" : "cage_base, "; - inl_ << "TaggedField<" << load_type << ">::" << load << "(" - << optional_cage_base << "*this, " << offset << ")" << postfix - << ";\n"; + stream << "TaggedField<" << load_type << ">::" << load << "(" + << optional_cage_base << "*this, " << offset << ")" << postfix + << ";\n"; } if (CanContainHeapObjects(field_type)) { - inl_ << " DCHECK(" << GenerateRuntimeTypeCheck(field_type, "value") - << ");\n"; + stream << " DCHECK(" << GenerateRuntimeTypeCheck(field_type, "value") + << ");\n"; } } void CppClassGenerator::EmitStoreFieldStatement( - const Field& class_field, std::vector<const Field*>& struct_fields) { + std::ostream& stream, const Field& class_field, + std::vector<const Field*>& struct_fields) { const Field& innermost_field = struct_fields.empty() ? class_field : *struct_fields.back(); const Type* field_type = innermost_field.name_and_type.type; @@ -4501,15 +4507,15 @@ void CppClassGenerator::EmitStoreFieldStatement( std::string offset = field_offset; if (class_field.index) { const char* index = class_field.index->optional ? "0" : "i"; - GenerateBoundsDCheck(inl_, index, type_, class_field); - inl_ << " int offset = " << field_offset << " + " << index << " * " - << class_field_size << ";\n"; + GenerateBoundsDCheck(stream, index, type_, class_field); + stream << " int offset = " << field_offset << " + " << index << " * " + << class_field_size << ";\n"; offset = "offset"; } if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { - inl_ << " this->template WriteField<" << type_name << ">(" << offset - << ", value);\n"; + stream << " this->template WriteField<" << type_name << ">(" << offset + << ", value);\n"; } else { bool strong_pointer = field_type->IsSubtypeOf(TypeOracle::GetObjectType()); bool is_smi = field_type->IsSubtypeOf(TypeOracle::GetSmiType()); @@ -4536,17 +4542,17 @@ void CppClassGenerator::EmitStoreFieldStatement( const std::string value_to_write = is_smi ? "Smi::FromInt(value)" : "value"; if (!is_smi) { - inl_ << " SLOW_DCHECK(" << GenerateRuntimeTypeCheck(field_type, "value") - << ");\n"; + stream << " SLOW_DCHECK(" + << GenerateRuntimeTypeCheck(field_type, "value") << ");\n"; } - inl_ << " " << write_macro << "(*this, " << offset << ", " - << value_to_write << ");\n"; + stream << " " << write_macro << "(*this, " << offset << ", " + << value_to_write << ");\n"; if (!is_smi) { const char* write_barrier = strong_pointer ? "CONDITIONAL_WRITE_BARRIER" : "CONDITIONAL_WEAK_WRITE_BARRIER"; - inl_ << " " << write_barrier << "(*this, " << offset - << ", value, mode);\n"; + stream << " " << write_barrier << "(*this, " << offset + << ", value, mode);\n"; } } } @@ -5223,11 +5229,14 @@ void ImplementationVisitor::GenerateExportedMacrosAssembler( cc_contents << "#include \"src/objects/fixed-array-inl.h\"\n"; cc_contents << "#include \"src/objects/free-space.h\"\n"; cc_contents << "#include \"src/objects/js-regexp-string-iterator.h\"\n"; + cc_contents << "#include \"src/objects/js-weak-refs.h\"\n"; cc_contents << "#include \"src/objects/ordered-hash-table.h\"\n"; cc_contents << "#include \"src/objects/property-descriptor-object.h\"\n"; + cc_contents << "#include \"src/objects/stack-frame-info.h\"\n"; cc_contents << "#include \"src/objects/swiss-name-dictionary.h\"\n"; cc_contents << "#include \"src/objects/synthetic-module.h\"\n"; cc_contents << "#include \"src/objects/template-objects.h\"\n"; + cc_contents << "#include \"src/objects/torque-defined-classes.h\"\n"; { IfDefScope intl_scope(cc_contents, "V8_INTL_SUPPORT"); cc_contents << "#include \"src/objects/js-break-iterator.h\"\n"; @@ -5266,23 +5275,20 @@ void ImplementationVisitor::GenerateExportedMacrosAssembler( TorqueMacro* macro = TorqueMacro::DynamicCast(declarable.get()); if (!(macro && macro->IsExportedToCSA())) continue; - h_contents << " "; - GenerateFunctionDeclaration(h_contents, "", macro->ReadableName(), - macro->signature(), macro->parameter_names(), - false); - h_contents << ";\n"; - - std::vector<std::string> parameter_names = GenerateFunctionDeclaration( - cc_contents, - "TorqueGeneratedExportedMacrosAssembler::", macro->ReadableName(), - macro->signature(), macro->parameter_names(), false); - cc_contents << "{\n"; - cc_contents << "return " << macro->ExternalName() << "(state_"; - for (auto& name : parameter_names) { - cc_contents << ", " << name; - } - cc_contents << ");\n"; - cc_contents << "}\n"; + cpp::Class assembler("TorqueGeneratedExportedMacrosAssembler"); + std::vector<std::string> generated_parameter_names; + cpp::Function f = GenerateFunction( + &assembler, macro->ReadableName(), macro->signature(), + macro->parameter_names(), false, &generated_parameter_names); + + f.PrintDeclaration(h_contents); + f.PrintDefinition(cc_contents, [&](std::ostream& stream) { + stream << "return " << macro->ExternalName() << "(state_"; + for (const auto& name : generated_parameter_names) { + stream << ", " << name; + } + stream << ");"; + }); } h_contents << " private:\n" |