Commit 50ac6264 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque]: Allow circular class/struct references

Bug: v8:7793
Change-Id: I28a60cdbce211fadf3b749b582a81ae78ff76548
Reviewed-on: https://chromium-review.googlesource.com/c/1435945
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59150}
parent 7599cc9a
......@@ -22,7 +22,7 @@ type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi';
type PositiveSmi extends Smi generates 'TNode<Smi>';
class HeapObject extends Tagged {
map_untyped: Tagged;
map: Map;
}
type Object = Smi | HeapObject;
......@@ -55,13 +55,6 @@ type Numeric = Number | BigInt;
type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex';
type Map extends HeapObject generates 'TNode<Map>';
// The accessors for HeapObject's map cannot be declared before Map
// is declared because forward declarations are not (yet) supported.
// TODO(danno): Make circular references in classes possible. One way to do that
// would be to pre-process all class declarations and create bindings for them
// with an uninitialized class type, and then process them later properly
extern operator '.map' macro LoadMap(HeapObject): Map;
extern transitioning operator '.map=' macro StoreMap(HeapObject, Map);
// These intrinsics should never be called from Torque code. They're used
// internally by the 'new' operator and only declared here because it's simpler
......@@ -75,14 +68,15 @@ type FixedDoubleArray extends FixedArrayBase
generates 'TNode<FixedDoubleArray>';
class JSReceiver extends HeapObject {
properties_or_hash: Object;
properties_or_hash: FixedArrayBase | Smi;
}
type Constructor extends JSReceiver generates 'TNode<JSReceiver>';
type JSProxy extends JSReceiver generates 'TNode<JSProxy>';
class JSObject extends JSReceiver {
constructor(map: Tagged, properties: Object, elements: FixedArrayBase) {
constructor(
map: Map, properties: FixedArrayBase | Smi, elements: FixedArrayBase) {
super(map, properties);
this.elements = elements;
}
......
This diff is collapsed.
......@@ -93,8 +93,20 @@ class DeclarationVisitor : public FileVisitor {
base::Optional<const CallableNodeSignature*> signature,
base::Optional<Statement*> body);
void FinalizeStructsAndClasses();
private:
void DeclareSpecializedTypes(const SpecializationKey& key);
void FinalizeStructFieldsAndMethods(StructType* struct_type,
StructDeclaration* struct_declaration);
void FinalizeClassFieldsAndMethods(ClassType* class_type,
ClassDeclaration* class_declaration);
std::vector<std::tuple<Scope*, StructDeclaration*, StructType*>>
struct_declarations_;
std::vector<std::tuple<Scope*, ClassDeclaration*, ClassType*>>
class_declarations_;
};
} // namespace torque
......
......@@ -167,50 +167,17 @@ void Declarations::DeclareType(const std::string& name, const Type* type,
Declare(name, std::unique_ptr<TypeAlias>(new TypeAlias(type, redeclaration)));
}
StructType* Declarations::DeclareStruct(const std::string& name,
const std::vector<Field>& fields) {
StructType* new_type = TypeOracle::GetStructType(name, fields);
StructType* Declarations::DeclareStruct(const std::string& name) {
StructType* new_type = TypeOracle::GetStructType(name);
DeclareType(name, new_type, false);
return new_type;
}
ClassType* Declarations::DeclareClass(const Type* super_type,
const std::string& name, bool transient,
const std::string& generates,
std::vector<Field> fields, size_t size) {
std::vector<Field> this_struct_fields;
size_t struct_offset = 0;
const StructType* super_struct_type = nullptr;
// In order to ensure "atomicity" of object allocation, a class'
// constructors operate on a per-class internal struct rather than the class
// directly until the constructor has successfully completed and all class
// members are available. Create the appropriate struct type for use in the
// class' constructors, including a '_super' field in the struct that
// contains the values constructed by calls to super constructors.
if (const ClassType* super_class = ClassType::DynamicCast(super_type)) {
super_struct_type = super_class->struct_type();
this_struct_fields.push_back(
{CurrentSourcePosition::Get(),
{kConstructorStructSuperFieldName, super_struct_type},
struct_offset,
false});
struct_offset += LoweredSlotCount(super_struct_type);
}
for (auto& field : fields) {
const Type* field_type = field.name_and_type.type;
this_struct_fields.push_back({field.pos,
{field.name_and_type.name, field_type},
struct_offset,
false});
struct_offset += LoweredSlotCount(field_type);
}
StructType* this_struct_type = DeclareStruct(
kClassConstructorThisStructPrefix + name, this_struct_fields);
const std::string& generates) {
ClassType* new_type =
TypeOracle::GetClassType(super_type, name, transient, generates,
std::move(fields), this_struct_type, size);
this_struct_type->SetDerivedFrom(new_type);
TypeOracle::GetClassType(super_type, name, transient, generates);
DeclareType(name, new_type, false);
return new_type;
}
......
......@@ -81,12 +81,10 @@ class Declarations {
static void DeclareType(const std::string& name, const Type* type,
bool redeclaration);
static StructType* DeclareStruct(const std::string& name,
const std::vector<Field>& fields);
static StructType* DeclareStruct(const std::string& name);
static ClassType* DeclareClass(const Type* super, const std::string& name,
bool transient, const std::string& generates,
std::vector<Field> fields, size_t size);
bool transient, const std::string& generates);
static Macro* CreateMacro(std::string external_name,
std::string readable_name,
......
......@@ -1247,12 +1247,7 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
// Output the code to generate an unitialized object of the class size in the
// GC heap.
VisitResult raw_object_map =
ProjectStructField(new_struct_result, "map_untyped");
Arguments map_cast_arguments;
map_cast_arguments.parameters.push_back(raw_object_map);
VisitResult object_map = GenerateCall("%RawDownCast", map_cast_arguments,
{TypeOracle::GetMapType()}, false);
VisitResult object_map = ProjectStructField(new_struct_result, "map");
Arguments size_arguments;
size_arguments.parameters.push_back(object_map);
VisitResult object_size = GenerateCall("%GetAllocationBaseSize",
......
......@@ -55,25 +55,28 @@ int WrappedMain(int argc, const char** argv) {
TypeOracle::Scope type_oracle;
if (output_directory.length() != 0) {
DeclarationVisitor().Visit(GlobalContext::Get().ast());
DeclarationVisitor declaration_visitor;
ImplementationVisitor visitor;
declaration_visitor.Visit(GlobalContext::Get().ast());
declaration_visitor.FinalizeStructsAndClasses();
ImplementationVisitor implementation_visitor;
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
visitor.BeginNamespaceFile(n);
implementation_visitor.BeginNamespaceFile(n);
}
visitor.VisitAllDeclarables();
implementation_visitor.VisitAllDeclarables();
std::string output_header_path = output_directory;
output_header_path += "/builtin-definitions-from-dsl.h";
visitor.GenerateBuiltinDefinitions(output_header_path);
implementation_visitor.GenerateBuiltinDefinitions(output_header_path);
output_header_path = output_directory + "/class-definitions-from-dsl.h";
visitor.GenerateClassDefinitions(output_header_path);
implementation_visitor.GenerateClassDefinitions(output_header_path);
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
visitor.EndNamespaceFile(n);
visitor.GenerateImplementation(output_directory, n);
implementation_visitor.EndNamespaceFile(n);
implementation_visitor.GenerateImplementation(output_directory, n);
}
}
......
......@@ -28,20 +28,16 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result;
}
static StructType* GetStructType(const std::string& name,
const std::vector<Field>& fields) {
StructType* result = new StructType(CurrentNamespace(), name, fields);
static StructType* GetStructType(const std::string& name) {
StructType* result = new StructType(CurrentNamespace(), name);
Get().struct_types_.push_back(std::unique_ptr<StructType>(result));
return result;
}
static ClassType* GetClassType(const Type* parent, const std::string& name,
bool transient, const std::string& generates,
const std::vector<Field>& fields,
StructType* this_struct, size_t size) {
bool transient, const std::string& generates) {
ClassType* result =
new ClassType(parent, CurrentNamespace(), name, transient, generates,
fields, this_struct, size);
new ClassType(parent, CurrentNamespace(), name, transient, generates);
Get().struct_types_.push_back(std::unique_ptr<ClassType>(result));
return result;
}
......
......@@ -402,6 +402,8 @@ class AggregateType : public Type {
return "_method_" + name_ + "_" + name;
}
void RegisterField(Field field) { fields_.push_back(field); }
void RegisterMethod(Method* method) { methods_.push_back(method); }
std::vector<Method*> Constructors() const;
const std::vector<Method*>& Methods() const { return methods_; }
......@@ -411,8 +413,8 @@ class AggregateType : public Type {
protected:
AggregateType(Kind kind, const Type* parent, Namespace* nspace,
const std::string& name, const std::vector<Field>& fields)
: Type(kind, parent), namespace_(nspace), name_(name), fields_(fields) {}
const std::string& name)
: Type(kind, parent), namespace_(nspace), name_(name) {}
void CheckForDuplicateFields();
......@@ -438,9 +440,8 @@ class StructType final : public AggregateType {
private:
friend class TypeOracle;
StructType(Namespace* nspace, const std::string& name,
const std::vector<Field>& fields)
: AggregateType(Kind::kStructType, nullptr, nspace, name, fields) {
StructType(Namespace* nspace, const std::string& name)
: AggregateType(Kind::kStructType, nullptr, nspace, name) {
CheckForDuplicateFields();
}
......@@ -464,17 +465,17 @@ class ClassType final : public AggregateType {
if (parent() == nullptr) return nullptr;
return parent()->IsClassType() ? ClassType::DynamicCast(parent()) : nullptr;
}
void SetSize(size_t size) { size_ = size; }
void SetThisStruct(StructType* this_struct) { this_struct_ = this_struct; }
private:
friend class TypeOracle;
ClassType(const Type* parent, Namespace* nspace, const std::string& name,
bool transient, const std::string& generates,
const std::vector<Field>& fields, StructType* this_struct,
size_t size)
: AggregateType(Kind::kClassType, parent, nspace, name, fields),
this_struct_(this_struct),
bool transient, const std::string& generates)
: AggregateType(Kind::kClassType, parent, nspace, name),
this_struct_(nullptr),
transient_(transient),
size_(size),
size_(0),
generates_(generates) {
CheckForDuplicateFields();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment