Commit 4f4d73f2 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] Generate GC object visitors for Torque classes

In the process:

* Augment C++-generated Torque classes with SizeFor methods to
  calculate size of instances.

* Add a new "@generateBodyDescriptor" annotation that causes Torque to
  generate C++ BodyDescriptors code that can be used to visit objects
  compatible with existing V8 mechanisms, e.g. GC

* Fully automate C++ macro machinery so that adding non-extern Torque
  class doesn't require any C++ changes, including ensuring generation
  of instance types and proper boilerplate for validators and
  printers.

* Make handling of @export a true annotation, allowing the modifier to
  be used on class declarations.

* Add functionality such that classes with the @export annotation are
  available to be used from C++. Field accessors for exported classes
  are public and factory methods are generated to create instances of
  the objects from C++.

* Change the Torque compiler such that Non-exported classes implicitly
  have the @generateBodyDescriptor annotation added and causes both
  verifiers and printers to be generated.

* Switch non-extern Torque classes from using existing Struct-based
  machinery to being first-class classes that support more existing
  Torque class features.

Change-Id: Ic60e60c2c6bd7acd57f949bce086898ad14a3b03
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2007490
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66621}
parent f8301710
......@@ -1176,11 +1176,14 @@ template("run_torque") {
"bit-fields-tq.h",
"builtin-definitions-tq.h",
"interface-descriptors-tq.inc",
"factory-tq.cc",
"factory-tq.inc",
"field-offsets-tq.h",
"class-verifiers-tq.cc",
"class-verifiers-tq.h",
"enum-verifiers-tq.cc",
"objects-printer-tq.cc",
"objects-body-descriptors-tq-inl.h",
"class-definitions-tq.cc",
"class-definitions-tq-inl.h",
"class-definitions-tq.h",
......@@ -1302,6 +1305,7 @@ v8_source_set("torque_generated_definitions") {
"$target_gen_dir/torque-generated/class-definitions-tq.cc",
"$target_gen_dir/torque-generated/class-verifiers-tq.cc",
"$target_gen_dir/torque-generated/class-verifiers-tq.h",
"$target_gen_dir/torque-generated/factory-tq.cc",
"$target_gen_dir/torque-generated/objects-printer-tq.cc",
]
......
......@@ -148,7 +148,7 @@ namespace torque_internal {
type UninitializedHeapObject extends HeapObject;
extern macro AllocateAllowLOS(intptr): UninitializedHeapObject;
extern macro GetStructMap(constexpr InstanceType): Map;
extern macro GetInstanceTypeMap(constexpr InstanceType): Map;
macro Allocate(sizeInBytes: intptr, map: Map): UninitializedHeapObject {
assert(ValidAllocationSize(sizeInBytes, map));
......
......@@ -1635,9 +1635,10 @@ TNode<Float64T> CodeStubAssembler::LoadHeapNumberValue(
object, HeapNumber::kValueOffset, MachineType::Float64()));
}
TNode<Map> CodeStubAssembler::GetStructMap(InstanceType instance_type) {
TNode<Map> CodeStubAssembler::GetInstanceTypeMap(InstanceType instance_type) {
Handle<Map> map_handle(
Map::GetStructMap(ReadOnlyRoots(isolate()), instance_type), isolate());
Map::GetInstanceTypeMap(ReadOnlyRoots(isolate()), instance_type),
isolate());
return HeapConstant(map_handle);
}
......
......@@ -53,6 +53,9 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(TypedArraySpeciesProtector, typed_array_species_protector, \
TypedArraySpeciesProtector)
#define TORQUE_INTERNAL_CLASS_LIST_CSA_ADAPTER(V, NAME, Name, name) \
V(Name##Map, name##_map, Name##Map)
#define HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V) \
V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \
V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \
......@@ -174,7 +177,9 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(UndefinedValue, undefined_value, Undefined) \
V(uninitialized_symbol, uninitialized_symbol, UninitializedSymbol) \
V(WeakFixedArrayMap, weak_fixed_array_map, WeakFixedArrayMap) \
V(zero_string, zero_string, ZeroString)
V(zero_string, zero_string, ZeroString) \
TORQUE_INTERNAL_CLASS_LIST_GENERATOR(TORQUE_INTERNAL_CLASS_LIST_CSA_ADAPTER, \
V)
#define HEAP_IMMOVABLE_OBJECT_LIST(V) \
HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \
......@@ -1942,7 +1947,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Label* if_bailout);
TNode<Object> GetConstructor(TNode<Map> map);
TNode<Map> GetStructMap(InstanceType instance_type);
TNode<Map> GetInstanceTypeMap(InstanceType instance_type);
TNode<FixedArray> AllocateUninitializedFixedArray(intptr_t capacity) {
return UncheckedCast<FixedArray>(AllocateFixedArray(
......
......@@ -77,7 +77,7 @@ class PromiseRejectReactionJobTask;
class WasmDebugInfo;
class Zone;
#define MAKE_FORWARD_DECLARATION(V, NAME, Name, name) class Name;
TORQUE_STRUCT_LIST_GENERATOR(MAKE_FORWARD_DECLARATION, UNUSED)
TORQUE_INTERNAL_CLASS_LIST_GENERATOR(MAKE_FORWARD_DECLARATION, UNUSED)
#undef MAKE_FORWARD_DECLARATION
template <typename T>
......
......@@ -369,7 +369,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case PROMISE_REJECT_REACTION_JOB_TASK_TYPE:
case PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE:
#define MAKE_TORQUE_CLASS_TYPE(V) case V:
TORQUE_INTERNAL_INSTANCE_TYPES(MAKE_TORQUE_CLASS_TYPE)
TORQUE_INSTANCE_TYPES(MAKE_TORQUE_CLASS_TYPE)
#undef MAKE_TORQUE_CLASS_TYPE
UNREACHABLE();
}
......
......@@ -247,6 +247,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
// Every class that has its fields defined in a .tq file and corresponds
// to exactly one InstanceType value is included in the following list.
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
#undef MAKE_TORQUE_CASE
case ALLOCATION_SITE_TYPE:
......
......@@ -207,6 +207,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
// Every class that has its fields defined in a .tq file and corresponds
// to exactly one InstanceType value is included in the following list.
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
#undef MAKE_TORQUE_CASE
case ALLOCATION_SITE_TYPE:
......
......@@ -47,7 +47,7 @@ FactoryBase<OffThreadFactory>::NewHeapNumber<AllocationType::kOld>();
template <typename Impl>
Handle<Struct> FactoryBase<Impl>::NewStruct(InstanceType type,
AllocationType allocation) {
Map map = Map::GetStructMap(read_only_roots(), type);
Map map = Map::GetInstanceTypeMap(read_only_roots(), type);
int size = map.instance_size();
HeapObject result = AllocateRawWithImmortalMap(size, allocation, map);
Handle<Struct> str = handle(Struct::cast(result), isolate());
......
......@@ -103,6 +103,13 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
public:
inline ReadOnlyRoots read_only_roots();
template <typename T>
Handle<T> MakeHandle(T obj) {
return handle(obj, isolate());
}
#include "torque-generated/factory-tq.inc"
Handle<Oddball> NewOddball(Handle<Map> map, const char* to_string,
Handle<Object> to_number, const char* type_of,
byte kind);
......
......@@ -18,6 +18,7 @@
#include "src/objects/oddball.h"
#include "src/objects/ordered-hash-table.h"
#include "src/wasm/wasm-objects.h"
#include "torque-generated/objects-body-descriptors-tq-inl.h"
namespace v8 {
namespace internal {
......@@ -43,6 +44,7 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map map,
return visitor->Visit##TypeName( \
map, ConcreteVisitor::template Cast<TypeName>(object));
TYPED_VISITOR_ID_LIST(CASE)
TORQUE_VISITOR_ID_LIST(CASE)
#undef CASE
case kVisitShortcutCandidate:
return visitor->VisitShortcutCandidate(
......@@ -96,6 +98,7 @@ void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointer(
return static_cast<ResultType>(size); \
}
TYPED_VISITOR_ID_LIST(VISIT)
TORQUE_VISITOR_ID_LIST(VISIT)
#undef VISIT
template <typename ResultType, typename ConcreteVisitor>
......
......@@ -68,6 +68,7 @@ namespace internal {
#define FORWARD_DECLARE(TypeName) class TypeName;
TYPED_VISITOR_ID_LIST(FORWARD_DECLARE)
TORQUE_VISITOR_ID_LIST(FORWARD_DECLARE)
#undef FORWARD_DECLARE
// The base class for visitors that need to dispatch on object type. The default
......@@ -103,6 +104,7 @@ class HeapVisitor : public ObjectVisitor {
#define VISIT(TypeName) \
V8_INLINE ResultType Visit##TypeName(Map map, TypeName object);
TYPED_VISITOR_ID_LIST(VISIT)
TORQUE_VISITOR_ID_LIST(VISIT)
#undef VISIT
V8_INLINE ResultType VisitShortcutCandidate(Map map, ConsString object);
V8_INLINE ResultType VisitDataObject(Map map, HeapObject object);
......
......@@ -403,6 +403,18 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(SMALL_ORDERED_NAME_DICTIONARY_TYPE,
small_ordered_name_dictionary)
#define TORQUE_INTERNAL_CLASS_LIST_MAP_ALLOCATOR(V, NAME, Name, name) \
ALLOCATE_MAP(NAME, Name::kSize, name)
TORQUE_INTERNAL_FIXED_CLASS_LIST_GENERATOR(
TORQUE_INTERNAL_CLASS_LIST_MAP_ALLOCATOR, _);
#undef TORQUE_INTERNAL_CLASS_LIST_MAP_ALLOCATOR
#define TORQUE_INTERNAL_CLASS_LIST_MAP_ALLOCATOR(V, NAME, Name, name) \
ALLOCATE_VARSIZE_MAP(NAME, name)
TORQUE_INTERNAL_VARSIZE_CLASS_LIST_GENERATOR(
TORQUE_INTERNAL_CLASS_LIST_MAP_ALLOCATOR, _);
#undef TORQUE_INTERNAL_CLASS_LIST_MAP_ALLOCATOR
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, sloppy_arguments_elements)
ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
......
......@@ -24,6 +24,7 @@
#include "src/roots/roots.h"
#include "src/utils/ostreams.h"
#include "src/zone/zone-containers.h"
#include "torque-generated/field-offsets-tq.h"
namespace v8 {
namespace internal {
......@@ -74,7 +75,7 @@ void Map::PrintReconfiguration(Isolate* isolate, FILE* file,
os << "]\n";
}
Map Map::GetStructMap(ReadOnlyRoots roots, InstanceType type) {
Map Map::GetInstanceTypeMap(ReadOnlyRoots roots, InstanceType type) {
Map map;
switch (type) {
#define MAKE_CASE(TYPE, Name, name) \
......@@ -82,6 +83,12 @@ Map Map::GetStructMap(ReadOnlyRoots roots, InstanceType type) {
map = roots.name##_map(); \
break;
STRUCT_LIST(MAKE_CASE)
#undef MAKE_CASE
#define MAKE_CASE(_, TYPE, Name, name) \
case TYPE: \
map = roots.name##_map(); \
break;
TORQUE_INTERNAL_CLASS_LIST_GENERATOR(MAKE_CASE, _)
#undef MAKE_CASE
default:
UNREACHABLE();
......@@ -360,6 +367,12 @@ VisitorId Map::GetVisitorId(Map map) {
case SYNTHETIC_MODULE_TYPE:
return kVisitSyntheticModule;
#define MAKE_TQ_CASE(TYPE, Name) \
case TYPE: \
return kVisit##Name;
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TQ_CASE)
#undef MAKE_TQ_CASE
default:
UNREACHABLE();
}
......
......@@ -84,6 +84,13 @@ enum InstanceType : uint16_t;
V(WeakArray) \
V(WeakCell)
#define TORQUE_OBJECT_BODY_TO_VISITOR_ID_LIST_ADAPTER(V, TYPE, TypeName) \
V(TypeName)
#define TORQUE_VISITOR_ID_LIST(V) \
TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR( \
TORQUE_OBJECT_BODY_TO_VISITOR_ID_LIST_ADAPTER, V)
// Objects with the same visitor id are processed in the same way by
// the heap visitors. The visitor ids for data only objects must precede
// other visitor ids. We rely on kDataOnlyVisitorIdCount for quick check
......@@ -92,8 +99,9 @@ enum VisitorId {
#define VISITOR_ID_ENUM_DECL(id) kVisit##id,
DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) kDataOnlyVisitorIdCount,
POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
TORQUE_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
#undef VISITOR_ID_ENUM_DECL
kVisitorIdCount
kVisitorIdCount
};
enum class ObjectFields {
......@@ -794,7 +802,7 @@ class Map : public HeapObject {
inline bool CanTransition() const;
static Map GetStructMap(ReadOnlyRoots roots, InstanceType type);
static Map GetInstanceTypeMap(ReadOnlyRoots roots, InstanceType type);
#define DECL_TESTER(Type, ...) inline bool Is##Type##Map() const;
INSTANCE_TYPE_CHECKERS(DECL_TESTER)
......
......@@ -5,6 +5,10 @@
#ifndef V8_OBJECTS_OBJECT_LIST_MACROS_H_
#define V8_OBJECTS_OBJECT_LIST_MACROS_H_
#include "torque-generated/instance-types-tq.h"
#define TORQUE_INTERNAL_CLASS_NAMES_ADAPTER(V, NAME, Name, name) V(Name)
namespace v8 {
namespace internal {
......@@ -233,7 +237,8 @@ class ZoneForwardList;
V(WasmTableObject) \
V(WeakFixedArray) \
V(WeakArrayList) \
V(WeakCell)
V(WeakCell) \
TORQUE_INTERNAL_CLASS_LIST_GENERATOR(TORQUE_INTERNAL_CLASS_NAMES_ADAPTER, V)
#ifdef V8_INTL_SUPPORT
#define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \
......
......@@ -1100,6 +1100,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case SYNTHETIC_MODULE_TYPE:
return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3,
p4);
#define MAKE_TORQUE_BODY_DESCRIPTOR_APPLY(TYPE, TypeName) \
case TYPE: \
return Op::template apply<TypeName::BodyDescriptor>(p1, p2, p3, p4);
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_BODY_DESCRIPTOR_APPLY)
#undef MAKE_TORQUE_BODY_DESCRIPTOR_APPLY
default:
PrintF("Unknown type: %d\n", type);
UNREACHABLE();
......
......@@ -180,6 +180,10 @@ class SubclassBodyDescriptor final : public BodyDescriptorBase {
}
};
#define TORQUE_BODY_DESCRIPTOR_LIST_ADAPTER(V, TYPE, TypeName) V(TYPE, TypeName)
#define TORQUE_BODY_DESCRIPTOR_LIST(V) \
TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR(TORQUE_BODY_DESCRIPTOR_LIST_ADAPTER, V)
} // namespace internal
} // namespace v8
......
......@@ -159,9 +159,7 @@ namespace internal {
wasm_indirect_function_table) \
V(_, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData, wasm_js_function_data)
#define STRUCT_LIST_GENERATOR(V, _) \
STRUCT_LIST_GENERATOR_BASE(V, _) \
TORQUE_STRUCT_LIST_GENERATOR(V, _)
#define STRUCT_LIST_GENERATOR(V, _) STRUCT_LIST_GENERATOR_BASE(V, _)
// Adapts one STRUCT_LIST_GENERATOR entry to the STRUCT_LIST entry
#define STRUCT_LIST_ADAPTER(V, NAME, Name, name) V(NAME, Name, name)
......@@ -176,6 +174,15 @@ namespace internal {
// Produces (Map, struct_name_map, StructNameMap) entries
#define STRUCT_MAPS_LIST(V) STRUCT_LIST_GENERATOR(STRUCT_MAPS_LIST_ADAPTER, V)
// Adapts one STRUCT_LIST_GENERATOR entry to the STRUCT_LIST entry
#define TORQUE_INTERNAL_CLASS_LIST_MAPS_ADAPTER(V, NAME, Name, name) \
V(Map, name##_map, Name##Map)
// Produces (NAME, Name, name) entries.
#define TORQUE_INTERNAL_CLASS_MAPS_LIST(V) \
TORQUE_INTERNAL_CLASS_LIST_GENERATOR( \
TORQUE_INTERNAL_CLASS_LIST_MAPS_ADAPTER, V)
//
// The following macros define list of allocation size objects and list of
// their maps.
......
......@@ -125,6 +125,7 @@
#include "torque-generated/class-definitions-tq-inl.h"
#include "torque-generated/internal-class-definitions-tq-inl.h"
#include "torque-generated/objects-body-descriptors-tq-inl.h"
namespace v8 {
namespace internal {
......@@ -2276,6 +2277,14 @@ int HeapObject::SizeFromMap(Map map) const {
PreparseData data = PreparseData::unchecked_cast(*this);
return PreparseData::SizeFor(data.data_length(), data.children_length());
}
#define MAKE_TORQUE_SIZE_FOR(TYPE, TypeName) \
if (instance_type == TYPE) { \
TypeName instance = TypeName::unchecked_cast(*this); \
return TypeName::SizeFor(instance); \
}
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_SIZE_FOR)
#undef MAKE_TORQUE_SIZE_FOR
if (instance_type == CODE_TYPE) {
return Code::unchecked_cast(*this).CodeSize();
}
......
......@@ -302,14 +302,15 @@ class Symbol;
#define ACCESSOR_INFO_ROOT_LIST(V) \
ACCESSOR_INFO_LIST_GENERATOR(ACCESSOR_INFO_ROOT_LIST_ADAPTER, V)
#define READ_ONLY_ROOT_LIST(V) \
STRONG_READ_ONLY_ROOT_LIST(V) \
INTERNALIZED_STRING_ROOT_LIST(V) \
PRIVATE_SYMBOL_ROOT_LIST(V) \
PUBLIC_SYMBOL_ROOT_LIST(V) \
WELL_KNOWN_SYMBOL_ROOT_LIST(V) \
STRUCT_MAPS_LIST(V) \
ALLOCATION_SITE_MAPS_LIST(V) \
#define READ_ONLY_ROOT_LIST(V) \
STRONG_READ_ONLY_ROOT_LIST(V) \
INTERNALIZED_STRING_ROOT_LIST(V) \
PRIVATE_SYMBOL_ROOT_LIST(V) \
PUBLIC_SYMBOL_ROOT_LIST(V) \
WELL_KNOWN_SYMBOL_ROOT_LIST(V) \
STRUCT_MAPS_LIST(V) \
TORQUE_INTERNAL_CLASS_MAPS_LIST(V) \
ALLOCATION_SITE_MAPS_LIST(V) \
DATA_HANDLER_MAPS_LIST(V)
#define MUTABLE_ROOT_LIST(V) \
......
......@@ -552,8 +552,7 @@ void ImplementationVisitor::GenerateClassDebugReaders(
std::stringstream class_names;
std::unordered_set<const ClassType*> done;
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
for (const ClassType* type : TypeOracle::GetClasses()) {
GenerateClassDebugReader(*type, h_contents, cc_contents, visitor,
class_names, &done);
}
......
......@@ -71,6 +71,7 @@ static const char* const UNINITIALIZED_ITERATOR_TYPE_STRING =
"UninitializedIterator";
static const char* const GENERIC_TYPE_INSTANTIATION_NAMESPACE_STRING =
"_generic_type_instantiation_namespace";
static const char* const FIXED_ARRAY_BASE_TYPE_STRING = "FixedArrayBase";
static const char* const ANNOTATION_GENERATE_PRINT = "@generatePrint";
static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier";
......@@ -88,6 +89,9 @@ static const char* const ANNOTATION_INSTANCE_TYPE_VALUE =
"@apiExposedInstanceTypeValue";
static const char* const ANNOTATION_IF = "@if";
static const char* const ANNOTATION_IFNOT = "@ifnot";
static const char* const ANNOTATION_GENERATE_BODY_DESCRIPTOR =
"@generateBodyDescriptor";
static const char* const ANNOTATION_EXPORT_CPP_CLASS = "@export";
inline bool IsConstexprName(const std::string& name) {
return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) ==
......@@ -125,6 +129,8 @@ enum class ClassFlag {
kHighestInstanceTypeWithinParent = 1 << 9,
kLowestInstanceTypeWithinParent = 1 << 10,
kUndefinedLayout = 1 << 11,
kGenerateBodyDescriptor = 1 << 12,
kExport = 1 << 13,
};
using ClassFlags = base::Flags<ClassFlag>;
......
......@@ -35,15 +35,6 @@ class GlobalContext : public ContextualClass<GlobalContext> {
return Get().declarables_;
}
static void RegisterClass(const TypeAlias* alias) {
DCHECK(alias->ParentScope()->IsNamespace());
Get().classes_.push_back(alias);
}
using GlobalClassList = std::vector<const TypeAlias*>;
static const GlobalClassList& GetClasses() { return Get().classes_; }
static void AddCppInclude(std::string include_path) {
Get().cpp_includes_.insert(std::move(include_path));
}
......@@ -84,7 +75,6 @@ class GlobalContext : public ContextualClass<GlobalContext> {
std::vector<std::unique_ptr<Declarable>> declarables_;
std::set<std::string> cpp_includes_;
std::map<SourceId, PerFileStreams> generated_per_file_;
GlobalClassList classes_;
std::map<std::string, size_t> fresh_ids_;
friend class LanguageServerData;
......
This diff is collapsed.
......@@ -388,13 +388,13 @@ class ImplementationVisitor {
void GenerateBitFields(const std::string& output_directory);
void GeneratePrintDefinitions(const std::string& output_directory);
void GenerateClassDefinitions(const std::string& output_directory);
void GenerateBodyDescriptors(const std::string& output_directory);
void GenerateInstanceTypes(const std::string& output_directory);
void GenerateClassVerifiers(const std::string& output_directory);
void GenerateEnumVerifiers(const std::string& output_directory);
void GenerateClassDebugReaders(const std::string& output_directory);
void GenerateExportedMacrosAssembler(const std::string& output_directory);
void GenerateCSATypes(const std::string& output_directory);
void GenerateCppForInternalClasses(const std::string& output_directory);
VisitResult Visit(Expression* expr);
const Type* Visit(Statement* stmt);
......
......@@ -289,6 +289,8 @@ std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
// - fully_defined_single_instance_types: This list is pairs of class name and
// instance type, for classes which have defined layouts and a single
// corresponding instance type.
// - fully_defined_multiple_instance_types: This list is pairs of class name and
// instance type, for classes which have defined layouts and subclasses.
// - only_declared_single_instance_types: This list is pairs of class name and
// instance type, for classes which have a single corresponding instance type
// and do not have layout definitions in Torque.
......@@ -302,6 +304,7 @@ std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
std::ostream& values,
std::ostream& fully_defined_single_instance_types,
std::ostream& fully_defined_multiple_instance_types,
std::ostream& only_declared_single_instance_types,
std::ostream& fully_defined_range_instance_types,
std::ostream& only_declared_range_instance_types,
......@@ -331,6 +334,7 @@ void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
for (auto& child : root->children) {
PrintInstanceTypes(
child.get(), definitions, values, fully_defined_single_instance_types,
fully_defined_multiple_instance_types,
only_declared_single_instance_types, fully_defined_range_instance_types,
only_declared_range_instance_types, inner_indent);
}
......@@ -351,6 +355,11 @@ void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
: fully_defined_range_instance_types;
range_instance_types << " V(" << root->type->name() << ", FIRST_"
<< type_name << ", LAST_" << type_name << ") \\\n";
if (!root->type->IsExtern() && !root->type->IsAbstract() &&
!root->type->HasUndefinedLayout()) {
fully_defined_multiple_instance_types << " V(" << root->type->name()
<< ", " << type_name << ") \\\n";
}
}
}
}
......@@ -370,12 +379,14 @@ void ImplementationVisitor::GenerateInstanceTypes(
std::unique_ptr<InstanceTypeTree> instance_types = AssignInstanceTypes();
std::stringstream values_list;
std::stringstream fully_defined_single_instance_types;
std::stringstream fully_defined_multiple_instance_types;
std::stringstream only_declared_single_instance_types;
std::stringstream fully_defined_range_instance_types;
std::stringstream only_declared_range_instance_types;
if (instance_types != nullptr) {
PrintInstanceTypes(instance_types.get(), header, values_list,
fully_defined_single_instance_types,
fully_defined_multiple_instance_types,
only_declared_single_instance_types,
fully_defined_range_instance_types,
only_declared_range_instance_types, " ");
......@@ -394,6 +405,12 @@ void ImplementationVisitor::GenerateInstanceTypes(
header << fully_defined_single_instance_types.str();
header << "\n";
header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that have\n";
header << "// full Torque definitions and subclasses.\n";
header << "#define TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(V) \\\n";
header << fully_defined_multiple_instance_types.str();
header << "\n";
header << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n";
header << "// declared but not defined in Torque. These classes may\n";
header << "// correspond with actual C++ classes, but they are not\n";
......@@ -416,10 +433,9 @@ void ImplementationVisitor::GenerateInstanceTypes(
header << only_declared_range_instance_types.str();
header << "\n";
header << "// Instance types for Torque-internal classes.\n";
header << "#define TORQUE_INTERNAL_INSTANCE_TYPES(V) \\\n";
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
header << "// Instance types for non-extern Torque classes.\n";
header << "#define TORQUE_INSTANCE_TYPES(V) \\\n";
for (const ClassType* type : TypeOracle::GetClasses()) {
if (type->IsExtern()) continue;
std::string type_name =
CapifyStringWithUnderscores(type->name()) + "_TYPE";
......@@ -427,11 +443,11 @@ void ImplementationVisitor::GenerateInstanceTypes(
}
header << "\n";
header << "// Struct list entries for Torque-internal classes.\n";
header << "#define TORQUE_STRUCT_LIST_GENERATOR(V, _) \\\n";
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
header << "// Map list macros for non-extern Torque classes.\n";
header << "#define TORQUE_INTERNAL_VARSIZE_CLASS_LIST_GENERATOR(V, _) \\\n";
for (const ClassType* type : TypeOracle::GetClasses()) {
if (type->IsExtern()) continue;
if (!type->HasIndexedField()) continue;
std::string type_name =
CapifyStringWithUnderscores(type->name()) + "_TYPE";
std::string variable_name = SnakeifyString(type->name());
......@@ -439,6 +455,21 @@ void ImplementationVisitor::GenerateInstanceTypes(
<< variable_name << ") \\\n";
}
header << "\n";
header << "#define TORQUE_INTERNAL_FIXED_CLASS_LIST_GENERATOR(V, _) \\\n";
for (const ClassType* type : TypeOracle::GetClasses()) {
if (type->IsExtern()) continue;
if (type->HasIndexedField()) continue;
std::string type_name =
CapifyStringWithUnderscores(type->name()) + "_TYPE";
std::string variable_name = SnakeifyString(type->name());
header << " V(_, " << type_name << ", " << type->name() << ", "
<< variable_name << ") \\\n";
}
header << "\n";
header << "#define TORQUE_INTERNAL_CLASS_LIST_GENERATOR(V, _) \\\n";
header << " TORQUE_INTERNAL_VARSIZE_CLASS_LIST_GENERATOR(V, _) \\\n";
header << " TORQUE_INTERNAL_FIXED_CLASS_LIST_GENERATOR(V, _)\n";
header << "\n";
}
std::string output_header_path = output_directory + "/" + file_name;
WriteFile(output_header_path, header.str());
......
......@@ -88,10 +88,10 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
implementation_visitor.GenerateClassVerifiers(output_directory);
implementation_visitor.GenerateClassDebugReaders(output_directory);
implementation_visitor.GenerateEnumVerifiers(output_directory);
implementation_visitor.GenerateBodyDescriptors(output_directory);
implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
implementation_visitor.GenerateCSATypes(output_directory);
implementation_visitor.GenerateInstanceTypes(output_directory);
implementation_visitor.GenerateCppForInternalClasses(output_directory);
implementation_visitor.EndCSAFiles();
implementation_visitor.GenerateImplementation(output_directory);
......
......@@ -549,9 +549,24 @@ base::Optional<ParseResult> MakeIntrinsicDeclaration(
return ParseResult{result};
}
namespace {
bool HasExportAnnotation(ParseResultIterator* child_results,
const char* declaration) {
auto annotations = child_results->NextAs<std::vector<Annotation>>();
if (annotations.size()) {
if (annotations.size() > 1 || annotations[0].name->value != "@export") {
Error(declaration,
" declarations only support a single @export annotation");
}
return true;
}
return false;
}
} // namespace
base::Optional<ParseResult> MakeTorqueMacroDeclaration(
ParseResultIterator* child_results) {
auto export_to_csa = child_results->NextAs<bool>();
bool export_to_csa = HasExportAnnotation(child_results, "macro");
auto transitioning = child_results->NextAs<bool>();
auto operator_name = child_results->NextAs<base::Optional<std::string>>();
auto name = child_results->NextAs<Identifier*>();
......@@ -835,7 +850,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
child_results,
{ANNOTATION_GENERATE_PRINT, ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT,
ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT,
ANNOTATION_GENERATE_CPP_CLASS,
ANNOTATION_GENERATE_CPP_CLASS, ANNOTATION_GENERATE_BODY_DESCRIPTOR,
ANNOTATION_EXPORT_CPP_CLASS,
ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT,
ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT},
{ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE,
......@@ -854,6 +870,12 @@ base::Optional<ParseResult> MakeClassDeclaration(
if (annotations.Contains(ANNOTATION_GENERATE_CPP_CLASS)) {
flags |= ClassFlag::kGenerateCppClassDefinitions;
}
if (annotations.Contains(ANNOTATION_GENERATE_BODY_DESCRIPTOR)) {
flags |= ClassFlag::kGenerateBodyDescriptor;
}
if (annotations.Contains(ANNOTATION_EXPORT_CPP_CLASS)) {
flags |= ClassFlag::kExport;
}
if (annotations.Contains(ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT)) {
flags |= ClassFlag::kHighestInstanceTypeWithinParent;
}
......@@ -945,7 +967,8 @@ base::Optional<ParseResult> MakeSpecializationDeclaration(
base::Optional<ParseResult> MakeStructDeclaration(
ParseResultIterator* child_results) {
bool is_export = child_results->NextAs<bool>();
bool is_export = HasExportAnnotation(child_results, "Struct");
StructFlags flags = StructFlag::kNone;
if (is_export) flags |= StructFlag::kExport;
......@@ -2322,7 +2345,7 @@ struct TorqueGrammar : Grammar {
Sequence({Token("generates"), &externalString})),
&optionalClassBody},
AsSingletonVector<Declaration*, MakeClassDeclaration>()),
Rule({CheckIf(Token("@export")), Token("struct"), &name,
Rule({annotations, Token("struct"), &name,
TryOrDefault<GenericParameters>(&genericParameters), Token("{"),
List<Declaration*>(&method),
List<StructFieldExpression>(&structField), Token("}")},
......@@ -2363,7 +2386,7 @@ struct TorqueGrammar : Grammar {
Rule({Token("extern"), CheckIf(Token("transitioning")), Token("runtime"),
&name, &typeListMaybeVarArgs, &optionalReturnType, Token(";")},
AsSingletonVector<Declaration*, MakeExternalRuntime>()),
Rule({CheckIf(Token("@export")), CheckIf(Token("transitioning")),
Rule({annotations, CheckIf(Token("transitioning")),
Optional<std::string>(
Sequence({Token("operator"), &externalString})),
Token("macro"), &name,
......
......@@ -4,6 +4,7 @@
#include "src/torque/type-oracle.h"
#include "src/torque/type-visitor.h"
#include "src/torque/types.h"
namespace v8 {
namespace internal {
......@@ -68,6 +69,17 @@ Namespace* TypeOracle::CreateGenericTypeInstantiationNamespace() {
return Get().generic_type_instantiation_namespaces_.back().get();
}
// static
std::vector<const ClassType*> TypeOracle::GetClasses() {
std::vector<const ClassType*> result;
for (const std::unique_ptr<AggregateType>& t : Get().aggregate_types_) {
if (auto* class_type = ClassType::DynamicCast(t.get())) {
result.push_back(class_type);
}
}
return result;
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -293,6 +293,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(UNINITIALIZED_ITERATOR_TYPE_STRING);
}
static const Type* GetFixedArrayBaseType() {
return Get().GetBuiltinType(FIXED_ARRAY_BASE_TYPE_STRING);
}
static base::Optional<const Type*> ImplicitlyConvertableFrom(
const Type* to, const Type* from) {
while (from != nullptr) {
......@@ -315,6 +319,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
static const std::vector<std::unique_ptr<BitFieldStructType>>&
GetBitFieldStructTypes();
// By construction, this list of all classes is topologically sorted w.r.t.
// inheritance.
static std::vector<const ClassType*> GetClasses();
static void FinalizeAggregateTypes();
static size_t FreshTypeId() { return Get().next_type_id_++; }
......
......@@ -244,81 +244,83 @@ const StructType* TypeVisitor::ComputeType(
const ClassType* TypeVisitor::ComputeType(
ClassDeclaration* decl, MaybeSpecializationKey specialized_from) {
ClassType* new_class;
// TODO(sigurds): Remove this hack by introducing a declarable for classes.
const TypeAlias* alias =
Declarations::LookupTypeAlias(QualifiedName(decl->name->value));
GlobalContext::RegisterClass(alias);
DCHECK_EQ(*alias->delayed_, decl);
bool is_shape = decl->flags & ClassFlag::kIsShape;
if (is_shape && !(decl->flags & ClassFlag::kExtern)) {
ReportError("Shapes must be extern, add \"extern\" to the declaration.");
ClassFlags flags = decl->flags;
bool is_shape = flags & ClassFlag::kIsShape;
std::string generates = decl->name->value;
const Type* super_type = TypeVisitor::ComputeType(*decl->super);
if (is_shape) {
if (!(flags & ClassFlag::kExtern)) {
ReportError("Shapes must be extern, add \"extern\" to the declaration.");
}
if (flags & ClassFlag::kUndefinedLayout) {
ReportError("Shapes need to define their layout.");
}
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class ||
!super_class->IsSubtypeOf(TypeOracle::GetJSObjectType())) {
Error("Shapes need to extend a subclass of ",
*TypeOracle::GetJSObjectType())
.Throw();
}
// Shapes use their super class in CSA code since they have incomplete
// support for type-checks on the C++ side.
generates = super_class->name();
}
if (is_shape && decl->flags & ClassFlag::kUndefinedLayout) {
ReportError("Shapes need to define their layout.");
if (!decl->super) {
ReportError("Extern class must extend another type.");
}
if (decl->flags & ClassFlag::kExtern) {
if (!decl->super) {
ReportError("Extern class must extend another type.");
if (super_type != TypeOracle::GetStrongTaggedType()) {
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class) {
ReportError(
"class \"", decl->name->value,
"\" must extend either StrongTagged or an already declared class");
}
const Type* super_type = TypeVisitor::ComputeType(*decl->super);
if (super_type != TypeOracle::GetStrongTaggedType()) {
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class) {
ReportError(
"class \"", decl->name->value,
"\" must extend either StrongTagged or an already declared class");
}
if (super_class->HasUndefinedLayout() &&
!(decl->flags & ClassFlag::kUndefinedLayout)) {
Error("Class \"", decl->name->value,
"\" defines its layout but extends a class which does not")
.Position(decl->pos);
}
if (super_class->HasUndefinedLayout() &&
!(flags & ClassFlag::kUndefinedLayout)) {
Error("Class \"", decl->name->value,
"\" defines its layout but extends a class which does not")
.Position(decl->pos);
}
std::string generates = decl->name->value;
if (is_shape) {
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class ||
!super_class->IsSubtypeOf(TypeOracle::GetJSObjectType())) {
Error("Shapes need to extend a subclass of ",
*TypeOracle::GetJSObjectType())
.Throw();
}
// Shapes use their super class in CSA code since they have incomplete
// support for type-checks on the C++ side.
generates = super_class->name();
if ((flags & ClassFlag::kExport) &&
!(super_class->ShouldExport() || super_class->IsExtern())) {
Error("cannot export class ", decl->name,
" because superclass is neither @export or extern");
}
}
if ((flags & ClassFlag::kGenerateBodyDescriptor ||
flags & ClassFlag::kExport) &&
flags & ClassFlag::kUndefinedLayout) {
Error("Class \"", decl->name->value,
"\" requires a layout but doesn't have one");
}
if (flags & ClassFlag::kExtern) {
if (decl->generates) {
bool enforce_tnode_type = true;
generates = ComputeGeneratesType(decl->generates, enforce_tnode_type);
}
new_class = TypeOracle::GetClassType(super_type, decl->name->value,
decl->flags, generates, decl, alias);
} else {
if (!decl->super) {
ReportError("Intern class ", decl->name->value,
" must extend class Struct.");
}
const Type* super_type = TypeVisitor::ComputeType(*decl->super);
const ClassType* super_class = ClassType::DynamicCast(super_type);
const Type* struct_type =
Declarations::LookupGlobalType(QualifiedName("Struct"));
if (!super_class || super_class != struct_type) {
ReportError("Intern class ", decl->name->value,
" must extend class Struct.");
if (flags & ClassFlag::kExport) {
Error("cannot export a class that is marked extern");
}
} else {
if (decl->generates) {
ReportError("Only extern classes can specify a generated type.");
}
new_class = TypeOracle::GetClassType(
super_type, decl->name->value,
decl->flags | ClassFlag::kGeneratePrint | ClassFlag::kGenerateVerify,
decl->name->value, decl, alias);
if (super_type != TypeOracle::GetStrongTaggedType()) {
if (flags & ClassFlag::kUndefinedLayout) {
Error("non-external classes must have defined layouts");
}
}
flags = flags | ClassFlag::kGeneratePrint | ClassFlag::kGenerateVerify |
ClassFlag::kGenerateBodyDescriptor;
}
return new_class;
return TypeOracle::GetClassType(super_type, decl->name->value, flags,
generates, decl, alias);
}
const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
......@@ -406,17 +408,6 @@ void TypeVisitor::VisitClassFieldsAndMethods(
ReportError("in-object properties cannot be weak");
}
}
if (!(class_declaration->flags & ClassFlag::kExtern)) {
if (!field_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
ReportError(
"non-extern classes only support subtypes of type Object, but "
"found type ",
*field_type);
}
if (field_expression.weak) {
ReportError("non-extern classes do not support weak fields");
}
}
base::Optional<Expression*> array_length = field_expression.index;
const Field& field = class_type->RegisterField(
{field_expression.name_and_type.name->pos,
......
......@@ -67,6 +67,20 @@ std::string Type::SimpleName() const {
return *aliases_.begin();
}
// TODO(danno): HandlifiedCppTypeName should be used universally in Torque
// where the C++ type of a Torque object is required.
std::string Type::HandlifiedCppTypeName() const {
if (IsSubtypeOf(TypeOracle::GetTaggedType()) &&
!IsSubtypeOf(TypeOracle::GetSmiType())) {
base::Optional<const ClassType*> class_type = ClassSupertype();
std::string type =
class_type ? (*class_type)->GetGeneratedTNodeTypeName() : "Object";
return "Handle<" + type + ">";
} else {
return ConstexprVersion()->GetGeneratedTypeName();
}
}
bool Type::IsSubtypeOf(const Type* supertype) const {
if (supertype->IsTopType()) return true;
if (IsNever()) return true;
......@@ -517,24 +531,43 @@ void ClassType::GenerateAccessors() {
// For each field, construct AST snippets that implement a CSA accessor
// function. The implementation iterator will turn the snippets into code.
for (auto& field : fields_) {
if (field.index || field.name_and_type.type == TypeOracle::GetVoidType()) {
if (field.name_and_type.type == TypeOracle::GetVoidType()) {
continue;
}
CurrentSourcePosition::Scope position_activator(field.pos);
IdentifierExpression* parameter =
MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"o"}));
IdentifierExpression* index =
MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"i"}));
// Load accessor
std::string camel_field_name = CamelifyString(field.name_and_type.name);
std::string load_macro_name = "Load" + this->name() + camel_field_name;
// For now, only generate indexed accessors for simple types
if (field.index.has_value() && field.name_and_type.type->IsStructType()) {
continue;
}
Signature load_signature;
load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
load_signature.parameter_types.types.push_back(this);
if (field.index) {
load_signature.parameter_names.push_back(MakeNode<Identifier>("i"));
load_signature.parameter_types.types.push_back(
TypeOracle::GetIntPtrType());
}
load_signature.parameter_types.var_args = false;
load_signature.return_type = field.name_and_type.type;
Statement* load_body =
MakeNode<ReturnStatement>(MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)));
Expression* load_expression = MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name));
if (field.index) {
load_expression =
MakeNode<ElementAccessExpression>(load_expression, index);
}
Statement* load_body = MakeNode<ReturnStatement>(load_expression);
Declarations::DeclareMacro(load_macro_name, true, base::nullopt,
load_signature, load_body, base::nullopt);
......@@ -544,17 +577,25 @@ void ClassType::GenerateAccessors() {
std::string store_macro_name = "Store" + this->name() + camel_field_name;
Signature store_signature;
store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
store_signature.parameter_types.types.push_back(this);
if (field.index) {
store_signature.parameter_names.push_back(MakeNode<Identifier>("i"));
store_signature.parameter_types.types.push_back(
TypeOracle::GetIntPtrType());
}
store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
store_signature.parameter_types.types.push_back(field.name_and_type.type);
store_signature.parameter_types.var_args = false;
// TODO(danno): Store macros probably should return their value argument
store_signature.return_type = TypeOracle::GetVoidType();
Statement* store_body =
MakeNode<ExpressionStatement>(MakeNode<AssignmentExpression>(
MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)),
value));
Expression* store_expression = MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name));
if (field.index) {
store_expression =
MakeNode<ElementAccessExpression>(store_expression, index);
}
Statement* store_body = MakeNode<ExpressionStatement>(
MakeNode<AssignmentExpression>(store_expression, value));
Declarations::DeclareMacro(store_macro_name, true, base::nullopt,
store_signature, store_body, base::nullopt,
false);
......
......@@ -113,6 +113,8 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
// Used for naming generated code.
virtual std::string SimpleName() const;
std::string HandlifiedCppTypeName() const;
const Type* parent() const { return parent_; }
bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
......@@ -611,12 +613,15 @@ class ClassType final : public AggregateType {
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
bool ShouldGeneratePrint() const {
return (flags_ & ClassFlag::kGeneratePrint || !IsExtern()) &&
!HasUndefinedLayout();
return !IsExtern() ||
((flags_ & ClassFlag::kGeneratePrint) && !HasUndefinedLayout());
}
bool ShouldGenerateVerify() const {
return (flags_ & ClassFlag::kGenerateVerify || !IsExtern()) &&
!HasUndefinedLayout() && !IsShape();
return !IsExtern() || ((flags_ & ClassFlag::kGenerateVerify) &&
(!HasUndefinedLayout() && !IsShape()));
}
bool ShouldGenerateBodyDescriptor() const {
return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern();
}
bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
......@@ -624,8 +629,10 @@ class ClassType final : public AggregateType {
return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
}
bool GenerateCppClassDefinitions() const {
return flags_ & ClassFlag::kGenerateCppClassDefinitions || !IsExtern();
return flags_ & ClassFlag::kGenerateCppClassDefinitions || !IsExtern() ||
ShouldGenerateBodyDescriptor();
}
bool ShouldExport() const { return flags_ & ClassFlag::kExport; }
bool IsShape() const { return flags_ & ClassFlag::kIsShape; }
bool HasStaticSize() const;
bool HasIndexedField() const override;
......
......@@ -736,6 +736,35 @@ TEST(TestTestParentFrameArguments) {
asm_tester.GenerateCode();
}
TEST(TestFullyGeneratedClassFromCpp) {
CcTest::InitializeVM();
Isolate* isolate(CcTest::i_isolate());
i::HandleScope scope(isolate);
CodeAssemblerTester asm_tester(isolate, 1);
TestTorqueAssembler m(asm_tester.state());
{ m.Return(m.TestFullyGeneratedClassFromCpp()); }
FunctionTester ft(asm_tester.GenerateCode(), 0);
Handle<ExportedSubClass> result =
Handle<ExportedSubClass>::cast(ft.Call().ToHandleChecked());
CHECK_EQ(result->c_field(), 7);
CHECK_EQ(result->d_field(), 8);
CHECK_EQ(Smi::ToInt(result->e_field()), 9);
}
TEST(TestFullyGeneratedClassWithElements) {
CcTest::InitializeVM();
Isolate* isolate(CcTest::i_isolate());
i::HandleScope scope(isolate);
CodeAssemblerTester asm_tester(isolate, 1);
TestTorqueAssembler m(asm_tester.state());
{
m.TestFullyGeneratedClassWithElements();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -767,7 +767,7 @@ namespace test {
check(a.b.GetX() == 2);
}
class InternalClass extends Struct {
class InternalClass extends HeapObject {
macro Flip() labels NotASmi {
const tmp = Cast<Smi>(this.b) otherwise NotASmi;
this.b = this.a;
......@@ -833,7 +833,7 @@ namespace test {
return new FixedArray{map: kFixedArrayMap, length: 5, objects: ...i};
}
class SmiPair extends Struct {
class SmiPair extends HeapObject {
macro GetA():&Smi {
return & this.a;
}
......@@ -920,7 +920,7 @@ namespace test {
StaticAssert(1 + 2 == 3);
}
class SmiBox extends Struct {
class SmiBox extends HeapObject {
value: Smi;
unrelated: Smi;
}
......@@ -1120,4 +1120,108 @@ namespace test {
check(val3.d == 99);
check(val3.e == 1234);
}
@export
class ExportedSubClass extends ExportedSubClassBase {
c_field: int32;
d_field: int32;
e_field: Smi;
}
@export
class ExportedSubClassBase extends HeapObject {
a: HeapObject;
b: HeapObject;
}
class InternalClassWithSmiElements extends FixedArrayBase {
data: Smi;
object: Oddball;
entries[length]: Smi;
}
struct InternalClassStructElement {
a: Smi;
b: Smi;
}
class InternalClassWithStructElements extends HeapObject {
dummy1: int32;
dummy2: int32;
count: Smi;
data: Smi;
object: Object;
entries[count]: Smi;
more_entries[count]: InternalClassStructElement;
}
struct SmiGeneratorIterator {
macro Next(): Smi labels _NoMore {
return this.value++;
}
value: Smi;
}
struct InternalClassStructElementGeneratorIterator {
macro Next(): InternalClassStructElement labels _NoMore {
return InternalClassStructElement{a: this.value++, b: this.value++};
}
value: Smi;
}
@export
macro TestFullyGeneratedClassWithElements() {
// Test creation, initialization and access of a fully generated class with
// simple (Smi) elements
const length: Smi = Convert<Smi>(3);
const object1 = new InternalClassWithSmiElements{
length,
data: 0,
object: Undefined,
entries: ...SmiGeneratorIterator {
value: 11
}
};
assert(object1.length == 3);
assert(object1.data == 0);
assert(object1.object == Undefined);
assert(object1.entries[0] == 11);
assert(object1.entries[1] == 12);
assert(object1.entries[2] == 13);
// Test creation, initialization and access of a fully generated class
// with elements that are a struct.
const object2 = new InternalClassWithStructElements{
dummy1: 44,
dummy2: 45,
count: length,
data: 55,
object: Undefined,
entries: ...SmiGeneratorIterator{value: 3},
more_entries: ...InternalClassStructElementGeneratorIterator {
value: 1
}
};
assert(object2.dummy1 == 44);
assert(object2.dummy2 == 45);
assert(object2.count == 3);
assert(object2.data == 55);
assert(object2.object == Undefined);
assert(object2.entries[0] == 3);
assert(object2.entries[1] == 4);
assert(object2.entries[2] == 5);
assert(object2.more_entries[0].a == 1);
assert(object2.more_entries[0].b == 2);
assert(object2.more_entries[1].a == 3);
assert(object2.more_entries[1].b == 4);
assert(object2.more_entries[2].a == 5);
assert(object2.more_entries[2].b == 6);
}
@export
macro TestFullyGeneratedClassFromCpp(): ExportedSubClass {
return new
ExportedSubClass{a: Null, b: Null, c_field: 7, d_field: 8, e_field: 9};
}
}
......@@ -14,7 +14,7 @@
// https://github.com/python/cpython/blob/master/Objects/listsort.txt
namespace array {
class SortState extends Struct {
class SortState extends HeapObject {
macro Compare(implicit context: Context)(x: JSAny, y: JSAny): Number {
const sortCompare: CompareBuiltinFn = this.sortComparePtr;
return sortCompare(context, this.userCmpFn, x, y);
......
......@@ -69,6 +69,7 @@ v8_component("v8_debug_helper") {
sources = [
"$target_gen_dir/../../torque-generated/class-debug-readers-tq.cc",
"$target_gen_dir/../../torque-generated/class-debug-readers-tq.h",
"$target_gen_dir/../../torque-generated/instance-types-tq.h",
"$target_gen_dir/heap-constants-gen.cc",
"debug-helper-internal.cc",
"debug-helper-internal.h",
......
......@@ -104,6 +104,7 @@ TypedObject GetTypedObjectByInstanceType(uintptr_t address,
case i::INSTANCE_TYPE: \
return {type_source, std::make_unique<Tq##ClassName>(address)};
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(INSTANCE_TYPE_CASE)
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(INSTANCE_TYPE_CASE)
#undef INSTANCE_TYPE_CASE
default:
......
This diff is collapsed.
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