[torque] Add @generatePrint annotation
The new @generatePrint annotation automatically generates ...Print methods for objects from their Torque class definition. While this is mostly geared towards objects derived from Struct, it works on any Torque class. Bug: v8:7793 Change-Id: Iaa772879d397b95c7853dafdd9f09a85dbde8e35 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1557152 Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#60708}
This commit is contained in:
parent
cdeb88e37e
commit
a667b6b319
22
BUILD.gn
22
BUILD.gn
@ -1021,6 +1021,7 @@ action("run_torque") {
|
||||
outputs = [
|
||||
"$target_gen_dir/torque-generated/builtin-definitions-from-dsl.h",
|
||||
"$target_gen_dir/torque-generated/class-definitions-from-dsl.h",
|
||||
"$target_gen_dir/torque-generated/objects-printer-from-dsl.cc",
|
||||
]
|
||||
foreach(namespace, torque_namespaces) {
|
||||
outputs += [
|
||||
@ -1067,6 +1068,26 @@ v8_source_set("torque_generated_initializers") {
|
||||
configs = [ ":internal_config" ]
|
||||
}
|
||||
|
||||
v8_source_set("torque_generated_definitions") {
|
||||
visibility = [ ":*" ] # Only targets in this file can depend on this.
|
||||
|
||||
deps = [
|
||||
":run_torque",
|
||||
]
|
||||
|
||||
if (v8_enable_i18n_support) {
|
||||
public_deps = [
|
||||
"//third_party/icu",
|
||||
]
|
||||
}
|
||||
|
||||
sources = [
|
||||
"$target_gen_dir/torque-generated/objects-printer-from-dsl.cc",
|
||||
]
|
||||
|
||||
configs = [ ":internal_config" ]
|
||||
}
|
||||
|
||||
action("generate_bytecode_builtins_list") {
|
||||
script = "tools/run.py"
|
||||
outputs = [
|
||||
@ -3096,6 +3117,7 @@ v8_source_set("v8_base") {
|
||||
|
||||
defines = []
|
||||
deps = [
|
||||
":torque_generated_definitions",
|
||||
":v8_headers",
|
||||
":v8_libbase",
|
||||
":v8_libsampler",
|
||||
|
@ -114,12 +114,16 @@ type NaN extends HeapNumber;
|
||||
|
||||
extern class Struct extends HeapObject {}
|
||||
|
||||
@generatePrint
|
||||
extern class Tuple2 extends Struct {
|
||||
value_1: Object;
|
||||
value_2: Object;
|
||||
value1: Object;
|
||||
value2: Object;
|
||||
}
|
||||
|
||||
extern class Tuple3 extends Tuple2 { value_3: Object; }
|
||||
@generatePrint
|
||||
extern class Tuple3 extends Tuple2 {
|
||||
value3: Object;
|
||||
}
|
||||
|
||||
// A direct string can be accessed directly through CSA without going into the
|
||||
// C++ runtime. See also: ToDirectStringAssembler.
|
||||
|
@ -1766,21 +1766,6 @@ void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) { // NOLINT
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void Tuple2::Tuple2Print(std::ostream& os) { // NOLINT
|
||||
PrintHeader(os, "Tuple2");
|
||||
os << "\n - value1: " << Brief(value1());
|
||||
os << "\n - value2: " << Brief(value2());
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void Tuple3::Tuple3Print(std::ostream& os) { // NOLINT
|
||||
PrintHeader(os, "Tuple3");
|
||||
os << "\n - value1: " << Brief(value1());
|
||||
os << "\n - value2: " << Brief(value2());
|
||||
os << "\n - value3: " << Brief(value3());
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void ClassPositions::ClassPositionsPrint(std::ostream& os) { // NOLINT
|
||||
PrintHeader(os, "ClassPositions");
|
||||
os << "\n - start position: " << start();
|
||||
|
@ -922,13 +922,15 @@ struct StructDeclaration : Declaration {
|
||||
struct ClassDeclaration : Declaration {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration)
|
||||
ClassDeclaration(SourcePosition pos, Identifier* name, bool is_extern,
|
||||
bool transient, base::Optional<std::string> super,
|
||||
bool generate_print, bool transient,
|
||||
base::Optional<std::string> super,
|
||||
base::Optional<std::string> generates,
|
||||
std::vector<Declaration*> methods,
|
||||
std::vector<ClassFieldExpression> fields)
|
||||
: Declaration(kKind, pos),
|
||||
name(name),
|
||||
is_extern(is_extern),
|
||||
generate_print(generate_print),
|
||||
transient(transient),
|
||||
super(std::move(super)),
|
||||
generates(std::move(generates)),
|
||||
@ -936,6 +938,7 @@ struct ClassDeclaration : Declaration {
|
||||
fields(std::move(fields)) {}
|
||||
Identifier* name;
|
||||
bool is_extern;
|
||||
bool generate_print;
|
||||
bool transient;
|
||||
base::Optional<std::string> super;
|
||||
base::Optional<std::string> generates;
|
||||
|
@ -303,7 +303,8 @@ void DeclarationVisitor::Visit(ClassDeclaration* decl) {
|
||||
}
|
||||
|
||||
new_class = Declarations::DeclareClass(
|
||||
super_type, decl->name, decl->is_extern, decl->transient, generates);
|
||||
super_type, decl->name, decl->is_extern, decl->generate_print,
|
||||
decl->transient, generates);
|
||||
} else {
|
||||
if (decl->super) {
|
||||
ReportError("Only extern classes can inherit.");
|
||||
@ -311,9 +312,9 @@ void DeclarationVisitor::Visit(ClassDeclaration* decl) {
|
||||
if (decl->generates) {
|
||||
ReportError("Only extern classes can specify a generated type.");
|
||||
}
|
||||
new_class = Declarations::DeclareClass(TypeOracle::GetTaggedType(),
|
||||
decl->name, decl->is_extern,
|
||||
decl->transient, "FixedArray");
|
||||
new_class = Declarations::DeclareClass(
|
||||
TypeOracle::GetTaggedType(), decl->name, decl->is_extern,
|
||||
decl->generate_print, decl->transient, "FixedArray");
|
||||
}
|
||||
GlobalContext::RegisterClass(decl->name->value, new_class);
|
||||
class_declarations_.push_back(
|
||||
|
@ -195,10 +195,10 @@ StructType* Declarations::DeclareStruct(const Identifier* name) {
|
||||
|
||||
ClassType* Declarations::DeclareClass(const Type* super_type,
|
||||
const Identifier* name, bool is_extern,
|
||||
bool transient,
|
||||
bool generate_print, bool transient,
|
||||
const std::string& generates) {
|
||||
ClassType* new_type = TypeOracle::GetClassType(
|
||||
super_type, name->value, is_extern, transient, generates);
|
||||
super_type, name->value, is_extern, generate_print, transient, generates);
|
||||
DeclareType(name, new_type, false);
|
||||
return new_type;
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ class Declarations {
|
||||
static StructType* DeclareStruct(const Identifier* name);
|
||||
|
||||
static ClassType* DeclareClass(const Type* super, const Identifier* name,
|
||||
bool is_extern, bool transient,
|
||||
const std::string& generates);
|
||||
bool is_extern, bool generate_print,
|
||||
bool transient, const std::string& generates);
|
||||
|
||||
static Macro* CreateMacro(std::string external_name,
|
||||
std::string readable_name,
|
||||
|
@ -2871,6 +2871,48 @@ void ImplementationVisitor::GenerateClassDefinitions(std::string& file_name) {
|
||||
ReplaceFileContentsIfDifferent(file_name, new_contents);
|
||||
}
|
||||
|
||||
void ImplementationVisitor::GeneratePrintDefinitions(std::string& file_name) {
|
||||
std::stringstream new_contents_stream;
|
||||
|
||||
new_contents_stream << "#ifdef OBJECT_PRINT\n\n";
|
||||
|
||||
new_contents_stream << "#include \"src/objects.h\"\n\n";
|
||||
new_contents_stream << "#include <iosfwd>\n\n";
|
||||
new_contents_stream << "#include \"src/objects/struct-inl.h\"\n\n";
|
||||
|
||||
new_contents_stream << "namespace v8 {\n";
|
||||
new_contents_stream << "namespace internal {\n\n";
|
||||
|
||||
for (auto i : GlobalContext::GetClasses()) {
|
||||
ClassType* type = i.second;
|
||||
if (!type->ShouldGeneratePrint()) continue;
|
||||
|
||||
new_contents_stream << "void " << type->name() << "::" << type->name()
|
||||
<< "Print(std::ostream& os) {\n";
|
||||
new_contents_stream << " PrintHeader(os, \"" << type->name() << "\");\n";
|
||||
auto hierarchy = type->GetHierarchy();
|
||||
std::map<std::string, const AggregateType*> field_names;
|
||||
for (const AggregateType* aggregate_type : hierarchy) {
|
||||
for (const Field& f : aggregate_type->fields()) {
|
||||
if (f.name_and_type.name == "map") continue;
|
||||
new_contents_stream << " os << \"\\n - " << f.name_and_type.name
|
||||
<< ": \" << "
|
||||
<< "Brief(" << f.name_and_type.name << "());\n";
|
||||
}
|
||||
}
|
||||
new_contents_stream << " os << \"\\n\";\n";
|
||||
new_contents_stream << "}\n\n";
|
||||
}
|
||||
|
||||
new_contents_stream << "} // namespace internal\"\n";
|
||||
new_contents_stream << "} // namespace v8\"\n";
|
||||
|
||||
new_contents_stream << "\n#endif // OBJECT_PRINT\n\n";
|
||||
|
||||
std::string new_contents(new_contents_stream.str());
|
||||
ReplaceFileContentsIfDifferent(file_name, new_contents);
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -257,6 +257,7 @@ class ImplementationVisitor : public FileVisitor {
|
||||
public:
|
||||
void GenerateBuiltinDefinitions(std::string& file_name);
|
||||
void GenerateClassDefinitions(std::string& file_name);
|
||||
void GeneratePrintDefinitions(std::string& file_name);
|
||||
|
||||
VisitResult Visit(Expression* expr);
|
||||
const Type* Visit(Statement* stmt);
|
||||
|
@ -74,6 +74,10 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
|
||||
output_header_path = output_directory + "/class-definitions-from-dsl.h";
|
||||
implementation_visitor.GenerateClassDefinitions(output_header_path);
|
||||
|
||||
std::string output_source_path =
|
||||
output_directory + "/objects-printer-from-dsl.cc";
|
||||
implementation_visitor.GeneratePrintDefinitions(output_source_path);
|
||||
|
||||
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
|
||||
implementation_visitor.EndNamespaceFile(n);
|
||||
implementation_visitor.GenerateImplementation(output_directory, n);
|
||||
|
@ -572,6 +572,7 @@ base::Optional<ParseResult> MakeMethodDeclaration(
|
||||
|
||||
base::Optional<ParseResult> MakeClassDeclaration(
|
||||
ParseResultIterator* child_results) {
|
||||
auto generate_print = child_results->NextAs<bool>();
|
||||
auto is_extern = child_results->NextAs<bool>();
|
||||
auto transient = child_results->NextAs<bool>();
|
||||
auto name = child_results->NextAs<Identifier*>();
|
||||
@ -583,8 +584,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
|
||||
auto methods = child_results->NextAs<std::vector<Declaration*>>();
|
||||
auto fields = child_results->NextAs<std::vector<ClassFieldExpression>>();
|
||||
Declaration* result = MakeNode<ClassDeclaration>(
|
||||
name, is_extern, transient, std::move(extends), std::move(generates),
|
||||
std::move(methods), fields);
|
||||
name, is_extern, generate_print, transient, std::move(extends),
|
||||
std::move(generates), std::move(methods), fields);
|
||||
return ParseResult{result};
|
||||
}
|
||||
|
||||
@ -1636,8 +1637,8 @@ struct TorqueGrammar : Grammar {
|
||||
Rule({Token("const"), &name, Token(":"), &type, Token("generates"),
|
||||
&externalString, Token(";")},
|
||||
MakeExternConstDeclaration),
|
||||
Rule({CheckIf(Token("extern")), CheckIf(Token("transient")),
|
||||
Token("class"), &name,
|
||||
Rule({CheckIf(Token("@generatePrint")), CheckIf(Token("extern")),
|
||||
CheckIf(Token("transient")), Token("class"), &name,
|
||||
Optional<std::string>(Sequence({Token("extends"), &identifier})),
|
||||
Optional<std::string>(
|
||||
Sequence({Token("generates"), &externalString})),
|
||||
|
@ -35,10 +35,11 @@ class TypeOracle : public ContextualClass<TypeOracle> {
|
||||
}
|
||||
|
||||
static ClassType* GetClassType(const Type* parent, const std::string& name,
|
||||
bool is_extern, bool transient,
|
||||
const std::string& generates) {
|
||||
ClassType* result = new ClassType(parent, CurrentNamespace(), name,
|
||||
is_extern, transient, generates);
|
||||
bool is_extern, bool generate_print,
|
||||
bool transient, const std::string& generates) {
|
||||
ClassType* result =
|
||||
new ClassType(parent, CurrentNamespace(), name, is_extern,
|
||||
generate_print, transient, generates);
|
||||
Get().struct_types_.push_back(std::unique_ptr<ClassType>(result));
|
||||
return result;
|
||||
}
|
||||
|
@ -288,10 +288,12 @@ std::string StructType::ToExplicitString() const {
|
||||
}
|
||||
|
||||
ClassType::ClassType(const Type* parent, Namespace* nspace,
|
||||
const std::string& name, bool is_extern, bool transient,
|
||||
const std::string& name, bool is_extern,
|
||||
bool generate_print, bool transient,
|
||||
const std::string& generates)
|
||||
: AggregateType(Kind::kClassType, parent, nspace, name),
|
||||
is_extern_(is_extern),
|
||||
generate_print_(generate_print),
|
||||
transient_(transient),
|
||||
size_(0),
|
||||
has_indexed_field_(false),
|
||||
|
@ -471,6 +471,7 @@ class ClassType final : public AggregateType {
|
||||
std::string GetGeneratedTypeNameImpl() const override;
|
||||
std::string GetGeneratedTNodeTypeNameImpl() const override;
|
||||
bool IsExtern() const { return is_extern_; }
|
||||
bool ShouldGeneratePrint() const { return generate_print_; }
|
||||
bool IsTransient() const override { return transient_; }
|
||||
bool HasIndexedField() const override;
|
||||
size_t size() const { return size_; }
|
||||
@ -490,9 +491,11 @@ class ClassType final : public AggregateType {
|
||||
private:
|
||||
friend class TypeOracle;
|
||||
ClassType(const Type* parent, Namespace* nspace, const std::string& name,
|
||||
bool is_extern, bool transient, const std::string& generates);
|
||||
bool is_extern, bool generate_print, bool transient,
|
||||
const std::string& generates);
|
||||
|
||||
bool is_extern_;
|
||||
bool generate_print_;
|
||||
bool transient_;
|
||||
size_t size_;
|
||||
bool has_indexed_field_;
|
||||
|
Loading…
Reference in New Issue
Block a user