summaryrefslogtreecommitdiff
path: root/deps/v8/src/torque/implementation-visitor.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2021-08-29 14:20:49 +0200
committerMichaël Zasso <targos@protonmail.com>2021-08-30 21:02:51 +0200
commit50930a0fa08297d0ce7e67fa6594fe47937b99ff (patch)
tree96bd30c0c63790bc1992a2f241a3df94d563b283 /deps/v8/src/torque/implementation-visitor.cc
parentb63e449b2eade1111b52f6559669400a4e855903 (diff)
downloadnode-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.cc752
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"