[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: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66621}
This commit is contained in:
Tobias Tebbi 2020-03-03 16:53:40 +01:00 committed by Commit Bot
parent f830171093
commit 4f4d73f225
40 changed files with 1206 additions and 413 deletions

View File

@ -1176,11 +1176,14 @@ template("run_torque") {
"bit-fields-tq.h", "bit-fields-tq.h",
"builtin-definitions-tq.h", "builtin-definitions-tq.h",
"interface-descriptors-tq.inc", "interface-descriptors-tq.inc",
"factory-tq.cc",
"factory-tq.inc",
"field-offsets-tq.h", "field-offsets-tq.h",
"class-verifiers-tq.cc", "class-verifiers-tq.cc",
"class-verifiers-tq.h", "class-verifiers-tq.h",
"enum-verifiers-tq.cc", "enum-verifiers-tq.cc",
"objects-printer-tq.cc", "objects-printer-tq.cc",
"objects-body-descriptors-tq-inl.h",
"class-definitions-tq.cc", "class-definitions-tq.cc",
"class-definitions-tq-inl.h", "class-definitions-tq-inl.h",
"class-definitions-tq.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-definitions-tq.cc",
"$target_gen_dir/torque-generated/class-verifiers-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/class-verifiers-tq.h",
"$target_gen_dir/torque-generated/factory-tq.cc",
"$target_gen_dir/torque-generated/objects-printer-tq.cc", "$target_gen_dir/torque-generated/objects-printer-tq.cc",
] ]

View File

@ -148,7 +148,7 @@ namespace torque_internal {
type UninitializedHeapObject extends HeapObject; type UninitializedHeapObject extends HeapObject;
extern macro AllocateAllowLOS(intptr): UninitializedHeapObject; extern macro AllocateAllowLOS(intptr): UninitializedHeapObject;
extern macro GetStructMap(constexpr InstanceType): Map; extern macro GetInstanceTypeMap(constexpr InstanceType): Map;
macro Allocate(sizeInBytes: intptr, map: Map): UninitializedHeapObject { macro Allocate(sizeInBytes: intptr, map: Map): UninitializedHeapObject {
assert(ValidAllocationSize(sizeInBytes, map)); assert(ValidAllocationSize(sizeInBytes, map));

View File

@ -1635,9 +1635,10 @@ TNode<Float64T> CodeStubAssembler::LoadHeapNumberValue(
object, HeapNumber::kValueOffset, MachineType::Float64())); object, HeapNumber::kValueOffset, MachineType::Float64()));
} }
TNode<Map> CodeStubAssembler::GetStructMap(InstanceType instance_type) { TNode<Map> CodeStubAssembler::GetInstanceTypeMap(InstanceType instance_type) {
Handle<Map> map_handle( Handle<Map> map_handle(
Map::GetStructMap(ReadOnlyRoots(isolate()), instance_type), isolate()); Map::GetInstanceTypeMap(ReadOnlyRoots(isolate()), instance_type),
isolate());
return HeapConstant(map_handle); return HeapConstant(map_handle);
} }

View File

@ -53,6 +53,9 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(TypedArraySpeciesProtector, typed_array_species_protector, \ V(TypedArraySpeciesProtector, typed_array_species_protector, \
TypedArraySpeciesProtector) 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) \ #define HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V) \
V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \ V(AccessorInfoMap, accessor_info_map, AccessorInfoMap) \
V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \ V(AccessorPairMap, accessor_pair_map, AccessorPairMap) \
@ -174,7 +177,9 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(UndefinedValue, undefined_value, Undefined) \ V(UndefinedValue, undefined_value, Undefined) \
V(uninitialized_symbol, uninitialized_symbol, UninitializedSymbol) \ V(uninitialized_symbol, uninitialized_symbol, UninitializedSymbol) \
V(WeakFixedArrayMap, weak_fixed_array_map, WeakFixedArrayMap) \ 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) \ #define HEAP_IMMOVABLE_OBJECT_LIST(V) \
HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \ HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \
@ -1942,7 +1947,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
Label* if_bailout); Label* if_bailout);
TNode<Object> GetConstructor(TNode<Map> map); TNode<Object> GetConstructor(TNode<Map> map);
TNode<Map> GetStructMap(InstanceType instance_type); TNode<Map> GetInstanceTypeMap(InstanceType instance_type);
TNode<FixedArray> AllocateUninitializedFixedArray(intptr_t capacity) { TNode<FixedArray> AllocateUninitializedFixedArray(intptr_t capacity) {
return UncheckedCast<FixedArray>(AllocateFixedArray( return UncheckedCast<FixedArray>(AllocateFixedArray(

View File

@ -77,7 +77,7 @@ class PromiseRejectReactionJobTask;
class WasmDebugInfo; class WasmDebugInfo;
class Zone; class Zone;
#define MAKE_FORWARD_DECLARATION(V, NAME, Name, name) class Name; #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 #undef MAKE_FORWARD_DECLARATION
template <typename T> template <typename T>

View File

@ -369,7 +369,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case PROMISE_REJECT_REACTION_JOB_TASK_TYPE: case PROMISE_REJECT_REACTION_JOB_TASK_TYPE:
case PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE: case PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE:
#define MAKE_TORQUE_CLASS_TYPE(V) case V: #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 #undef MAKE_TORQUE_CLASS_TYPE
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -247,6 +247,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
// Every class that has its fields defined in a .tq file and corresponds // Every class that has its fields defined in a .tq file and corresponds
// to exactly one InstanceType value is included in the following list. // to exactly one InstanceType value is included in the following list.
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE) TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
#undef MAKE_TORQUE_CASE #undef MAKE_TORQUE_CASE
case ALLOCATION_SITE_TYPE: case ALLOCATION_SITE_TYPE:

View File

@ -207,6 +207,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
// Every class that has its fields defined in a .tq file and corresponds // Every class that has its fields defined in a .tq file and corresponds
// to exactly one InstanceType value is included in the following list. // to exactly one InstanceType value is included in the following list.
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE) TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
#undef MAKE_TORQUE_CASE #undef MAKE_TORQUE_CASE
case ALLOCATION_SITE_TYPE: case ALLOCATION_SITE_TYPE:

View File

@ -47,7 +47,7 @@ FactoryBase<OffThreadFactory>::NewHeapNumber<AllocationType::kOld>();
template <typename Impl> template <typename Impl>
Handle<Struct> FactoryBase<Impl>::NewStruct(InstanceType type, Handle<Struct> FactoryBase<Impl>::NewStruct(InstanceType type,
AllocationType allocation) { AllocationType allocation) {
Map map = Map::GetStructMap(read_only_roots(), type); Map map = Map::GetInstanceTypeMap(read_only_roots(), type);
int size = map.instance_size(); int size = map.instance_size();
HeapObject result = AllocateRawWithImmortalMap(size, allocation, map); HeapObject result = AllocateRawWithImmortalMap(size, allocation, map);
Handle<Struct> str = handle(Struct::cast(result), isolate()); Handle<Struct> str = handle(Struct::cast(result), isolate());

View File

@ -103,6 +103,13 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
public: public:
inline ReadOnlyRoots read_only_roots(); 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<Oddball> NewOddball(Handle<Map> map, const char* to_string,
Handle<Object> to_number, const char* type_of, Handle<Object> to_number, const char* type_of,
byte kind); byte kind);

View File

@ -18,6 +18,7 @@
#include "src/objects/oddball.h" #include "src/objects/oddball.h"
#include "src/objects/ordered-hash-table.h" #include "src/objects/ordered-hash-table.h"
#include "src/wasm/wasm-objects.h" #include "src/wasm/wasm-objects.h"
#include "torque-generated/objects-body-descriptors-tq-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -43,6 +44,7 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map map,
return visitor->Visit##TypeName( \ return visitor->Visit##TypeName( \
map, ConcreteVisitor::template Cast<TypeName>(object)); map, ConcreteVisitor::template Cast<TypeName>(object));
TYPED_VISITOR_ID_LIST(CASE) TYPED_VISITOR_ID_LIST(CASE)
TORQUE_VISITOR_ID_LIST(CASE)
#undef CASE #undef CASE
case kVisitShortcutCandidate: case kVisitShortcutCandidate:
return visitor->VisitShortcutCandidate( return visitor->VisitShortcutCandidate(
@ -96,6 +98,7 @@ void HeapVisitor<ResultType, ConcreteVisitor>::VisitMapPointer(
return static_cast<ResultType>(size); \ return static_cast<ResultType>(size); \
} }
TYPED_VISITOR_ID_LIST(VISIT) TYPED_VISITOR_ID_LIST(VISIT)
TORQUE_VISITOR_ID_LIST(VISIT)
#undef VISIT #undef VISIT
template <typename ResultType, typename ConcreteVisitor> template <typename ResultType, typename ConcreteVisitor>

View File

@ -68,6 +68,7 @@ namespace internal {
#define FORWARD_DECLARE(TypeName) class TypeName; #define FORWARD_DECLARE(TypeName) class TypeName;
TYPED_VISITOR_ID_LIST(FORWARD_DECLARE) TYPED_VISITOR_ID_LIST(FORWARD_DECLARE)
TORQUE_VISITOR_ID_LIST(FORWARD_DECLARE)
#undef FORWARD_DECLARE #undef FORWARD_DECLARE
// The base class for visitors that need to dispatch on object type. The default // 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) \ #define VISIT(TypeName) \
V8_INLINE ResultType Visit##TypeName(Map map, TypeName object); V8_INLINE ResultType Visit##TypeName(Map map, TypeName object);
TYPED_VISITOR_ID_LIST(VISIT) TYPED_VISITOR_ID_LIST(VISIT)
TORQUE_VISITOR_ID_LIST(VISIT)
#undef VISIT #undef VISIT
V8_INLINE ResultType VisitShortcutCandidate(Map map, ConsString object); V8_INLINE ResultType VisitShortcutCandidate(Map map, ConsString object);
V8_INLINE ResultType VisitDataObject(Map map, HeapObject object); V8_INLINE ResultType VisitDataObject(Map map, HeapObject object);

View File

@ -403,6 +403,18 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(SMALL_ORDERED_NAME_DICTIONARY_TYPE, ALLOCATE_VARSIZE_MAP(SMALL_ORDERED_NAME_DICTIONARY_TYPE,
small_ordered_name_dictionary) 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(FIXED_ARRAY_TYPE, sloppy_arguments_elements)
ALLOCATE_VARSIZE_MAP(CODE_TYPE, code) ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)

View File

@ -24,6 +24,7 @@
#include "src/roots/roots.h" #include "src/roots/roots.h"
#include "src/utils/ostreams.h" #include "src/utils/ostreams.h"
#include "src/zone/zone-containers.h" #include "src/zone/zone-containers.h"
#include "torque-generated/field-offsets-tq.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -74,7 +75,7 @@ void Map::PrintReconfiguration(Isolate* isolate, FILE* file,
os << "]\n"; os << "]\n";
} }
Map Map::GetStructMap(ReadOnlyRoots roots, InstanceType type) { Map Map::GetInstanceTypeMap(ReadOnlyRoots roots, InstanceType type) {
Map map; Map map;
switch (type) { switch (type) {
#define MAKE_CASE(TYPE, Name, name) \ #define MAKE_CASE(TYPE, Name, name) \
@ -82,6 +83,12 @@ Map Map::GetStructMap(ReadOnlyRoots roots, InstanceType type) {
map = roots.name##_map(); \ map = roots.name##_map(); \
break; break;
STRUCT_LIST(MAKE_CASE) 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 #undef MAKE_CASE
default: default:
UNREACHABLE(); UNREACHABLE();
@ -360,6 +367,12 @@ VisitorId Map::GetVisitorId(Map map) {
case SYNTHETIC_MODULE_TYPE: case SYNTHETIC_MODULE_TYPE:
return kVisitSyntheticModule; 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: default:
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -84,6 +84,13 @@ enum InstanceType : uint16_t;
V(WeakArray) \ V(WeakArray) \
V(WeakCell) 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 // 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 // the heap visitors. The visitor ids for data only objects must precede
// other visitor ids. We rely on kDataOnlyVisitorIdCount for quick check // other visitor ids. We rely on kDataOnlyVisitorIdCount for quick check
@ -92,6 +99,7 @@ enum VisitorId {
#define VISITOR_ID_ENUM_DECL(id) kVisit##id, #define VISITOR_ID_ENUM_DECL(id) kVisit##id,
DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) kDataOnlyVisitorIdCount, DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) kDataOnlyVisitorIdCount,
POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
TORQUE_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
#undef VISITOR_ID_ENUM_DECL #undef VISITOR_ID_ENUM_DECL
kVisitorIdCount kVisitorIdCount
}; };
@ -794,7 +802,7 @@ class Map : public HeapObject {
inline bool CanTransition() const; 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; #define DECL_TESTER(Type, ...) inline bool Is##Type##Map() const;
INSTANCE_TYPE_CHECKERS(DECL_TESTER) INSTANCE_TYPE_CHECKERS(DECL_TESTER)

View File

@ -5,6 +5,10 @@
#ifndef V8_OBJECTS_OBJECT_LIST_MACROS_H_ #ifndef V8_OBJECTS_OBJECT_LIST_MACROS_H_
#define 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 v8 {
namespace internal { namespace internal {
@ -233,7 +237,8 @@ class ZoneForwardList;
V(WasmTableObject) \ V(WasmTableObject) \
V(WeakFixedArray) \ V(WeakFixedArray) \
V(WeakArrayList) \ V(WeakArrayList) \
V(WeakCell) V(WeakCell) \
TORQUE_INTERNAL_CLASS_LIST_GENERATOR(TORQUE_INTERNAL_CLASS_NAMES_ADAPTER, V)
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \ #define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \

View File

@ -1100,6 +1100,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case SYNTHETIC_MODULE_TYPE: case SYNTHETIC_MODULE_TYPE:
return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3, return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3,
p4); 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: default:
PrintF("Unknown type: %d\n", type); PrintF("Unknown type: %d\n", type);
UNREACHABLE(); UNREACHABLE();

View File

@ -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 internal
} // namespace v8 } // namespace v8

View File

@ -159,9 +159,7 @@ namespace internal {
wasm_indirect_function_table) \ wasm_indirect_function_table) \
V(_, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData, wasm_js_function_data) V(_, WASM_JS_FUNCTION_DATA_TYPE, WasmJSFunctionData, wasm_js_function_data)
#define STRUCT_LIST_GENERATOR(V, _) \ #define STRUCT_LIST_GENERATOR(V, _) STRUCT_LIST_GENERATOR_BASE(V, _)
STRUCT_LIST_GENERATOR_BASE(V, _) \
TORQUE_STRUCT_LIST_GENERATOR(V, _)
// Adapts one STRUCT_LIST_GENERATOR entry to the STRUCT_LIST entry // Adapts one STRUCT_LIST_GENERATOR entry to the STRUCT_LIST entry
#define STRUCT_LIST_ADAPTER(V, NAME, Name, name) V(NAME, Name, name) #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 // Produces (Map, struct_name_map, StructNameMap) entries
#define STRUCT_MAPS_LIST(V) STRUCT_LIST_GENERATOR(STRUCT_MAPS_LIST_ADAPTER, V) #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 // The following macros define list of allocation size objects and list of
// their maps. // their maps.

View File

@ -125,6 +125,7 @@
#include "torque-generated/class-definitions-tq-inl.h" #include "torque-generated/class-definitions-tq-inl.h"
#include "torque-generated/internal-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 v8 {
namespace internal { namespace internal {
@ -2276,6 +2277,14 @@ int HeapObject::SizeFromMap(Map map) const {
PreparseData data = PreparseData::unchecked_cast(*this); PreparseData data = PreparseData::unchecked_cast(*this);
return PreparseData::SizeFor(data.data_length(), data.children_length()); 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) { if (instance_type == CODE_TYPE) {
return Code::unchecked_cast(*this).CodeSize(); return Code::unchecked_cast(*this).CodeSize();
} }

View File

@ -309,6 +309,7 @@ class Symbol;
PUBLIC_SYMBOL_ROOT_LIST(V) \ PUBLIC_SYMBOL_ROOT_LIST(V) \
WELL_KNOWN_SYMBOL_ROOT_LIST(V) \ WELL_KNOWN_SYMBOL_ROOT_LIST(V) \
STRUCT_MAPS_LIST(V) \ STRUCT_MAPS_LIST(V) \
TORQUE_INTERNAL_CLASS_MAPS_LIST(V) \
ALLOCATION_SITE_MAPS_LIST(V) \ ALLOCATION_SITE_MAPS_LIST(V) \
DATA_HANDLER_MAPS_LIST(V) DATA_HANDLER_MAPS_LIST(V)

View File

@ -552,8 +552,7 @@ void ImplementationVisitor::GenerateClassDebugReaders(
std::stringstream class_names; std::stringstream class_names;
std::unordered_set<const ClassType*> done; std::unordered_set<const ClassType*> done;
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
GenerateClassDebugReader(*type, h_contents, cc_contents, visitor, GenerateClassDebugReader(*type, h_contents, cc_contents, visitor,
class_names, &done); class_names, &done);
} }

View File

@ -71,6 +71,7 @@ static const char* const UNINITIALIZED_ITERATOR_TYPE_STRING =
"UninitializedIterator"; "UninitializedIterator";
static const char* const GENERIC_TYPE_INSTANTIATION_NAMESPACE_STRING = static const char* const GENERIC_TYPE_INSTANTIATION_NAMESPACE_STRING =
"_generic_type_instantiation_namespace"; "_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_GENERATE_PRINT = "@generatePrint";
static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier"; static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier";
@ -88,6 +89,9 @@ static const char* const ANNOTATION_INSTANCE_TYPE_VALUE =
"@apiExposedInstanceTypeValue"; "@apiExposedInstanceTypeValue";
static const char* const ANNOTATION_IF = "@if"; static const char* const ANNOTATION_IF = "@if";
static const char* const ANNOTATION_IFNOT = "@ifnot"; 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) { inline bool IsConstexprName(const std::string& name) {
return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) == return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) ==
@ -125,6 +129,8 @@ enum class ClassFlag {
kHighestInstanceTypeWithinParent = 1 << 9, kHighestInstanceTypeWithinParent = 1 << 9,
kLowestInstanceTypeWithinParent = 1 << 10, kLowestInstanceTypeWithinParent = 1 << 10,
kUndefinedLayout = 1 << 11, kUndefinedLayout = 1 << 11,
kGenerateBodyDescriptor = 1 << 12,
kExport = 1 << 13,
}; };
using ClassFlags = base::Flags<ClassFlag>; using ClassFlags = base::Flags<ClassFlag>;

View File

@ -35,15 +35,6 @@ class GlobalContext : public ContextualClass<GlobalContext> {
return Get().declarables_; 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) { static void AddCppInclude(std::string include_path) {
Get().cpp_includes_.insert(std::move(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::vector<std::unique_ptr<Declarable>> declarables_;
std::set<std::string> cpp_includes_; std::set<std::string> cpp_includes_;
std::map<SourceId, PerFileStreams> generated_per_file_; std::map<SourceId, PerFileStreams> generated_per_file_;
GlobalClassList classes_;
std::map<std::string, size_t> fresh_ids_; std::map<std::string, size_t> fresh_ids_;
friend class LanguageServerData; friend class LanguageServerData;

View File

@ -1482,7 +1482,7 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
VisitResult(TypeOracle::GetConstexprInstanceTypeType(), VisitResult(TypeOracle::GetConstexprInstanceTypeType(),
CapifyStringWithUnderscores(class_type->name()) + "_TYPE")); CapifyStringWithUnderscores(class_type->name()) + "_TYPE"));
object_map = GenerateCall( object_map = GenerateCall(
QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, "GetStructMap"), QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, "GetInstanceTypeMap"),
get_struct_map_arguments, {}, false); get_struct_map_arguments, {}, false);
CurrentSourcePosition::Scope current_pos(expr->pos); CurrentSourcePosition::Scope current_pos(expr->pos);
initializer_results.names.insert(initializer_results.names.begin(), initializer_results.names.insert(initializer_results.names.begin(),
@ -3061,9 +3061,9 @@ class FieldOffsetsGenerator {
UpdateSection(f); UpdateSection(f);
// Emit kHeaderSize before any indexed field. // Emit kHeaderSize before any indexed field.
// TODO(tebbi): Generalize this code to work with multiple indexed fields. if (f.index.has_value() && !header_size_emitted_) {
if (f.index.has_value()) {
WriteMarker("kHeaderSize"); WriteMarker("kHeaderSize");
header_size_emitted_ = true;
} }
// We don't know statically how much space an indexed field takes, so report // We don't know statically how much space an indexed field takes, so report
@ -3165,6 +3165,7 @@ class FieldOffsetsGenerator {
FieldSectionType current_section_ = FieldSectionType::kNoSection; FieldSectionType current_section_ = FieldSectionType::kNoSection;
FieldSections completed_sections_ = FieldSectionType::kNoSection; FieldSections completed_sections_ = FieldSectionType::kNoSection;
bool is_finished_ = false; bool is_finished_ = false;
bool header_size_emitted_ = false;
}; };
class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator { class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator {
@ -3187,47 +3188,22 @@ class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator {
std::ostream& out_; std::ostream& out_;
}; };
} // namespace void GenerateClassExport(const ClassType* type, std::ostream& header,
std::ostream& inl_header) {
void ImplementationVisitor::GenerateCppForInternalClasses(
const std::string& output_directory) {
std::stringstream header;
std::stringstream inl;
std::string base_name = "internal-class-definitions-tq";
{
IncludeGuardScope header_guard(header, base_name + ".h");
header << "#include \"src/objects/objects.h\"\n";
header << "#include \"src/objects/struct.h\"\n";
header << "#include \"src/objects/js-objects.h\"\n";
header << "#include \"src/utils/utils.h\"\n";
header << "#include \"torque-generated/class-definitions-tq.h\"\n";
IncludeObjectMacrosScope header_macros(header);
NamespaceScope header_namespaces(header, {"v8", "internal"});
IncludeGuardScope inl_guard(inl, base_name + "-inl.h");
inl << "#include \"torque-generated/" << base_name << ".h\"\n";
inl << "#include \"torque-generated/class-definitions-tq-inl.h\"\n";
IncludeObjectMacrosScope inl_macros(inl);
NamespaceScope inl_namespaces(inl, {"v8", "internal"});
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
if (type->IsExtern()) continue;
const ClassType* super = type->GetSuperClass(); const ClassType* super = type->GetSuperClass();
std::string parent = "TorqueGenerated" + type->name() + "<" + std::string parent = "TorqueGenerated" + type->name() + "<" + type->name() +
type->name() + ", " + super->name() + ">"; ", " + super->name() + ">";
header << "class " << type->name() << " : public " << parent << " {\n"; header << "class " << type->name() << " : public " << parent << " {\n";
header << " public:\n"; header << " public:\n";
if (type->ShouldGenerateBodyDescriptor()) {
header << " class BodyDescriptor;\n";
}
header << " TQ_OBJECT_CONSTRUCTORS(" << type->name() << ")\n"; header << " TQ_OBJECT_CONSTRUCTORS(" << type->name() << ")\n";
header << "};\n\n"; header << "};\n\n";
inl_header << "TQ_OBJECT_CONSTRUCTORS_IMPL(" << type->name() << ")\n";
}
inl << "TQ_OBJECT_CONSTRUCTORS_IMPL(" << type->name() << ")\n"; } // namespace
}
}
std::string dir_basename = output_directory + "/" + base_name;
WriteFile(dir_basename + ".h", header.str());
WriteFile(dir_basename + "-inl.h", inl.str());
}
void ImplementationVisitor::GenerateClassFieldOffsets( void ImplementationVisitor::GenerateClassFieldOffsets(
const std::string& output_directory) { const std::string& output_directory) {
@ -3236,9 +3212,7 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
{ {
IncludeGuardScope include_guard(header, file_name); IncludeGuardScope include_guard(header, file_name);
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
// TODO(danno): Remove this once all classes use ClassFieldOffsetGenerator // TODO(danno): Remove this once all classes use ClassFieldOffsetGenerator
// to generate field offsets without the use of macros. // to generate field offsets without the use of macros.
if (!type->GenerateCppClassDefinitions() && !type->HasUndefinedLayout()) { if (!type->GenerateCppClassDefinitions() && !type->HasUndefinedLayout()) {
@ -3251,6 +3225,16 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
header << "\n"; header << "\n";
} }
} }
header << "#define TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR(V, _)\\\n";
for (const ClassType* type : TypeOracle::GetClasses()) {
if (type->ShouldGenerateBodyDescriptor()) {
std::string type_name =
CapifyStringWithUnderscores(type->name()) + "_TYPE";
header << "V(_, " << type_name << ", " << type->name() << ")\\\n";
}
}
header << "\n";
} }
const std::string output_header_path = output_directory + "/" + file_name; const std::string output_header_path = output_directory + "/" + file_name;
WriteFile(output_header_path, header.str()); WriteFile(output_header_path, header.str());
@ -3366,6 +3350,29 @@ class CppClassGenerator {
std::ostream& impl_; std::ostream& impl_;
}; };
base::Optional<std::vector<Field>> GetOrderedUniqueIndexFields(
const ClassType& type) {
std::vector<Field> result;
std::set<std::string> index_names;
for (const Field& field : type.ComputeAllFields()) {
if (field.index) {
auto name_and_type = ExtractSimpleFieldArraySize(type, *field.index);
if (!name_and_type) {
return base::nullopt;
}
index_names.insert(name_and_type->name);
}
}
for (const Field& field : type.ComputeAllFields()) {
if (index_names.count(field.name_and_type.name) != 0) {
result.push_back(field);
}
}
return result;
}
void CppClassGenerator::GenerateClass() { void CppClassGenerator::GenerateClass() {
hdr_ << template_decl() << "\n"; hdr_ << template_decl() << "\n";
hdr_ << "class " << gen_name_ << " : public P {\n"; hdr_ << "class " << gen_name_ << " : public P {\n";
@ -3375,10 +3382,16 @@ void CppClassGenerator::GenerateClass() {
<< " \"Pass in " << super_->name() << " \"Pass in " << super_->name()
<< " as second template parameter for " << gen_name_ << ".\");\n"; << " as second template parameter for " << gen_name_ << ".\");\n";
hdr_ << " public: \n"; hdr_ << " public: \n";
hdr_ << " using Super = P;\n"; hdr_ << " using Super = P;\n\n";
if (!type_->ShouldExport() && !type_->IsExtern()) {
hdr_ << " protected: // not extern or @export\n";
}
for (const Field& f : type_->fields()) { for (const Field& f : type_->fields()) {
GenerateFieldAccessor(f); GenerateFieldAccessor(f);
} }
if (!type_->ShouldExport() && !type_->IsExtern()) {
hdr_ << " public:\n";
}
GenerateClassCasts(); GenerateClassCasts();
@ -3410,9 +3423,82 @@ void CppClassGenerator::GenerateClass() {
g.Finish(); g.Finish();
hdr_ << "\n"; hdr_ << "\n";
auto index_fields = GetOrderedUniqueIndexFields(*type_);
if (!index_fields.has_value()) {
hdr_ << " // SizeFor implementations not generated due to complex array "
"lengths\n\n";
} else if (!type_->IsAbstract() &&
!type_->IsSubtypeOf(TypeOracle::GetJSObjectType())) {
hdr_ << " V8_INLINE static constexpr int32_t SizeFor(";
bool first = true;
for (const Field& field : *index_fields) {
if (!first) hdr_ << ", ";
hdr_ << field.name_and_type.type->HandlifiedCppTypeName() << " "
<< 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);
size_t field_size = 0;
std::tie(field_size, std::ignore) = field.GetFieldSizeInformation();
hdr_ << " size += ";
auto index_field = std::find_if(
index_fields->begin(), index_fields->end(),
[&](const Field& field) {
return field.name_and_type.name == index_name_and_type.name;
});
if (index_field->name_and_type.type->IsSubtypeOf(
TypeOracle::GetSmiType())) {
hdr_ << "Smi::ToInt(" << index_name_and_type.name << ")";
} else {
hdr_ << index_name_and_type.name;
}
hdr_ << " * " << field_size << ";\n";
}
}
hdr_ << " return size;\n";
hdr_ << " }\n\n";
hdr_ << " V8_INLINE static constexpr int32_t SizeFor(D o) {\n";
hdr_ << " return SizeFor(";
first = true;
for (auto field : *index_fields) {
if (!first) hdr_ << ", ";
// Subclasses of FixedArrayBase need to use the synchronized length
// accessor to be consistent (theoretically, FixedArrayBase classes
// can concurrently change size e.g. through left-trimming, although
// in practice this won't happen for Torque-generated classes) as well as
// explicitly convert to a Smi, since the C++-side accessors are
// int-based.
if (field.aggregate == TypeOracle::GetFixedArrayBaseType() &&
field.name_and_type.name == "length") {
hdr_ << "Smi::FromInt(o.synchronized_length())";
} else {
hdr_ << "o." << field.name_and_type.name << "()";
}
first = false;
}
hdr_ << ");\n }\n";
hdr_ << "\n";
}
hdr_ << " friend class Factory;\n\n";
GenerateClassConstructors(); GenerateClassConstructors();
hdr_ << "};\n\n"; hdr_ << "};\n\n";
if (!type_->IsExtern()) {
GenerateClassExport(type_, hdr_, inl_);
}
} }
void CppClassGenerator::GenerateClassCasts() { void CppClassGenerator::GenerateClassCasts() {
@ -3448,7 +3534,11 @@ void CppClassGenerator::GenerateClassConstructors() {
// TODO(sigurds): Keep in sync with DECL_ACCESSORS and ACCESSORS macro. // TODO(sigurds): Keep in sync with DECL_ACCESSORS and ACCESSORS macro.
void CppClassGenerator::GenerateFieldAccessor(const Field& f) { void CppClassGenerator::GenerateFieldAccessor(const Field& f) {
const Type* field_type = f.name_and_type.type; const Type* field_type = f.name_and_type.type;
if (field_type == TypeOracle::GetVoidType() || f.index.has_value()) return; if (field_type == TypeOracle::GetVoidType()) return;
// TODO(danno): Support generation of struct accessors
if (f.name_and_type.type->IsStructType()) return;
if (!f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) { if (!f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
return GenerateFieldAccessorForUntagged(f); return GenerateFieldAccessorForUntagged(f);
} }
@ -3460,7 +3550,8 @@ void CppClassGenerator::GenerateFieldAccessor(const Field& f) {
} }
Error("Generation of field accessor for ", type_->name(), Error("Generation of field accessor for ", type_->name(),
":: ", f.name_and_type.name, " : ", *field_type, " is not supported.") "::", f.name_and_type.name, " failed (type ", *field_type,
" is not supported).")
.Position(f.pos); .Position(f.pos);
} }
@ -3479,24 +3570,53 @@ void CppClassGenerator::GenerateFieldAccessorForUntagged(const Field& f) {
} }
const std::string& name = f.name_and_type.name; const std::string& name = f.name_and_type.name;
const std::string type = constexpr_version->GetGeneratedTypeName(); const std::string type = constexpr_version->GetGeneratedTypeName();
const std::string offset = "k" + CamelifyString(name) + "Offset"; std::string offset = "k" + CamelifyString(name) + "Offset";
// Generate declarations in header. // Generate declarations in header.
if (f.index) {
hdr_ << " inline " << type << " " << name << "(int i) const;\n";
hdr_ << " inline void set_" << name << "(int i, " << type
<< " value);\n\n";
} else {
hdr_ << " inline " << type << " " << name << "() const;\n"; hdr_ << " inline " << type << " " << name << "() const;\n";
hdr_ << " inline void set_" << name << "(" << type << " value);\n\n"; hdr_ << " inline void set_" << name << "(" << type << " value);\n\n";
}
// Generate implementation in inline header. // Generate implementation in inline header.
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << type << " " << gen_name_ << "<D, P>::" << name << "() const {\n"; inl_ << type << " " << gen_name_ << "<D, P>::" << name << "(";
if (f.index) {
inl_ << "int i";
}
inl_ << ") const {\n";
if (f.index) {
size_t field_size;
std::string size_string;
std::tie(field_size, size_string) = f.GetFieldSizeInformation();
inl_ << " int offset = " << offset << " + i * " << field_size << ";\n";
inl_ << " return this->template ReadField<" << type << ">(offset);\n";
} else {
inl_ << " return this->template ReadField<" << type << ">(" << offset inl_ << " return this->template ReadField<" << type << ">(" << offset
<< ");\n"; << ");\n";
}
inl_ << "}\n"; inl_ << "}\n";
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "(" << type inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "(";
<< " value) {\n"; if (f.index) {
inl_ << "int i, ";
}
inl_ << type << " value) {\n";
if (f.index) {
size_t field_size;
std::string size_string;
std::tie(field_size, size_string) = f.GetFieldSizeInformation();
inl_ << " int offset = " << offset << " + i * " << field_size << ";\n";
inl_ << " this->template WriteField<" << type << ">(offset, value);\n";
} else {
inl_ << " this->template WriteField<" << type << ">(" << offset inl_ << " this->template WriteField<" << type << ">(" << offset
<< ", value);\n"; << ", value);\n";
}
inl_ << "}\n\n"; inl_ << "}\n\n";
} }
@ -3507,20 +3627,43 @@ void CppClassGenerator::GenerateFieldAccessorForSmi(const Field& f) {
const std::string offset = "k" + CamelifyString(name) + "Offset"; const std::string offset = "k" + CamelifyString(name) + "Offset";
// Generate declarations in header. // Generate declarations in header.
if (f.index) {
hdr_ << " inline " << type << " " << name << "(int i) const;\n";
hdr_ << " inline void set_" << name << "(int i, " << type
<< " value);\n\n";
}
hdr_ << " inline " << type << " " << name << "() const;\n"; hdr_ << " inline " << type << " " << name << "() const;\n";
hdr_ << " inline void set_" << name << "(" << type << " value);\n\n"; hdr_ << " inline void set_" << name << "(" << type << " value);\n\n";
// Generate implementation in inline header. // Generate implementation in inline header.
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << type << " " << gen_name_ << "<D, P>::" << name << "() const {\n"; inl_ << type << " " << gen_name_ << "<D, P>::" << name << "(";
if (f.index) {
inl_ << "int i";
}
inl_ << ") const {\n";
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " return this->template ReadField<Smi>(offset);\n";
inl_ << "}\n";
} else {
inl_ << " return TaggedField<Smi, " << offset << ">::load(*this);\n"; inl_ << " return TaggedField<Smi, " << offset << ">::load(*this);\n";
inl_ << "}\n"; inl_ << "}\n";
}
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "(" << type inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "(";
<< " value) {\n"; if (f.index) {
inl_ << "int i, ";
}
inl_ << type << " value) {\n";
inl_ << " DCHECK(value.IsSmi());\n"; inl_ << " DCHECK(value.IsSmi());\n";
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " WRITE_FIELD(*this, offset, value);\n";
} else {
inl_ << " WRITE_FIELD(*this, " << offset << ", value);\n"; inl_ << " WRITE_FIELD(*this, " << offset << ", value);\n";
}
inl_ << "}\n\n"; inl_ << "}\n\n";
} }
@ -3538,11 +3681,13 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
if (!class_type && field_type != TypeOracle::GetObjectType()) { if (!class_type && field_type != TypeOracle::GetObjectType()) {
hdr_ << " // Torque type: " << field_type->ToString() << "\n"; hdr_ << " // Torque type: " << field_type->ToString() << "\n";
} }
hdr_ << " inline " << type << " " << name << "() const;\n";
hdr_ << " inline " << type << " " << name hdr_ << " inline " << type << " " << name << "(" << (f.index ? "int i" : "")
<< "(const Isolate* isolate) const;\n"; << ") const;\n";
hdr_ << " inline void set_" << name << "(" << type hdr_ << " inline " << type << " " << name << "(const Isolate* isolates"
<< " value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);\n\n"; << (f.index ? ", int i" : "") << ") const;\n";
hdr_ << " inline void set_" << name << "(" << (f.index ? "int i, " : "")
<< type << " value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);\n\n";
std::string type_check; std::string type_check;
for (const RuntimeType& runtime_type : field_type->GetRuntimeTypes()) { for (const RuntimeType& runtime_type : field_type->GetRuntimeTypes()) {
@ -3552,36 +3697,89 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
// Generate implementation in inline header. // Generate implementation in inline header.
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << type << " " << gen_name_ << "<D, P>::" << name << "() const {\n"; inl_ << type << " " << gen_name_ << "<D, P>::" << name << "("
<< (f.index ? "int i" : "") << ") const {\n";
inl_ << " const Isolate* isolate = GetIsolateForPtrCompr(*this);\n"; inl_ << " const Isolate* isolate = GetIsolateForPtrCompr(*this);\n";
inl_ << " return " << gen_name_ << "::" << name << "(isolate);\n"; inl_ << " return " << gen_name_ << "::" << name << "(isolate"
<< (f.index ? ", i" : "") << ");\n";
inl_ << "}\n"; inl_ << "}\n";
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << type << " " << gen_name_ << "<D, P>::" << name inl_ << type << " " << gen_name_ << "<D, P>::" << name
<< "(const Isolate* isolate) const {\n"; << "(const Isolate* isolate" << (f.index ? ", int i" : "")
<< ") const {\n";
if (class_type) { if (class_type) {
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " return " << type
<< "::cast(RELAXED_READ_FIELD(*this, offset));\n";
} else {
inl_ << " return TaggedField<" << type << ", " << offset inl_ << " return TaggedField<" << type << ", " << offset
<< ">::load(isolate, *this);\n"; << ">::load(isolate, *this);\n";
}
} else { } else {
// TODO(tebbi): load value as HeapObject when possible // TODO(tebbi): load value as HeapObject when possible
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " Object value = Object::cast(RELAXED_READ_FIELD(*this, "
"offset));\n";
} else {
inl_ << " Object value = TaggedField<Object, " << offset inl_ << " Object value = TaggedField<Object, " << offset
<< ">::load(isolate, *this);\n"; << ">::load(isolate, *this);\n";
}
inl_ << " DCHECK(" << type_check << ");\n"; inl_ << " DCHECK(" << type_check << ");\n";
inl_ << " return value;\n"; inl_ << " return value;\n";
} }
inl_ << "}\n"; inl_ << "}\n";
inl_ << "template <class D, class P>\n"; inl_ << "template <class D, class P>\n";
inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "(" << type inl_ << "void " << gen_name_ << "<D, P>::set_" << name << "(";
<< " value, WriteBarrierMode mode) {\n"; if (f.index) {
inl_ << "int i, ";
}
inl_ << type << " value, WriteBarrierMode mode) {\n";
inl_ << " SLOW_DCHECK(" << type_check << ");\n"; inl_ << " SLOW_DCHECK(" << type_check << ");\n";
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " WRITE_FIELD(*this, offset, value);\n";
} else {
inl_ << " WRITE_FIELD(*this, " << offset << ", value);\n"; inl_ << " WRITE_FIELD(*this, " << offset << ", value);\n";
}
inl_ << " CONDITIONAL_WRITE_BARRIER(*this, " << offset inl_ << " CONDITIONAL_WRITE_BARRIER(*this, " << offset
<< ", value, mode);\n"; << ", value, mode);\n";
inl_ << "}\n\n"; inl_ << "}\n\n";
} }
void EmitClassDefinitionHeadersIncludes(const std::string& basename,
std::stringstream& header,
std::stringstream& inline_header) {
header << "#include \"src/objects/fixed-array.h\"\n";
header << "#include \"src/objects/objects.h\"\n";
header << "#include \"src/objects/smi.h\"\n";
header << "#include \"torque-generated/field-offsets-tq.h\"\n";
header << "#include <type_traits>\n\n";
inline_header << "#include \"torque-generated/class-definitions-tq.h\"\n";
inline_header << "#include "
"\"torque-generated/objects-body-descriptors-tq-inl.h\"\n\n";
inline_header << "#include \"src/objects/js-promise.h\"\n";
inline_header << "#include \"src/objects/js-weak-refs.h\"\n";
inline_header << "#include \"src/objects/module.h\"\n";
inline_header << "#include \"src/objects/objects-inl.h\"\n";
inline_header << "#include \"src/objects/script.h\"\n";
inline_header << "#include \"src/objects/shared-function-info.h\"\n";
inline_header << "#include \"src/objects/tagged-field.h\"\n\n";
}
void EmitClassDefinitionHeadersForwardDeclarations(std::stringstream& header) {
// Generate forward declarations for every class.
for (const ClassType* type : TypeOracle::GetClasses()) {
header << "class " << type->GetGeneratedTNodeTypeName() << ";\n";
}
header << "using BuiltinPtr = Smi;\n\n";
}
void GenerateStructLayoutDescription(std::ostream& header, void GenerateStructLayoutDescription(std::ostream& header,
const StructType* type) { const StructType* type) {
header << "struct TorqueGenerated" << CamelifyString(type->name()) header << "struct TorqueGenerated" << CamelifyString(type->name())
@ -3599,32 +3797,70 @@ void GenerateStructLayoutDescription(std::ostream& header,
void ImplementationVisitor::GenerateClassDefinitions( void ImplementationVisitor::GenerateClassDefinitions(
const std::string& output_directory) { const std::string& output_directory) {
std::stringstream header; std::stringstream external_header;
std::stringstream inline_header; std::stringstream inline_external_header;
std::stringstream internal_header;
std::stringstream inline_internal_header;
std::stringstream implementation; std::stringstream implementation;
std::stringstream factory_header;
std::stringstream factory_impl;
std::string basename = "class-definitions-tq"; std::string basename = "class-definitions-tq";
std::string internal_basename = "internal-" + basename;
std::string file_basename = output_directory + "/" + basename; std::string file_basename = output_directory + "/" + basename;
std::string internal_file_basename =
output_directory + "/" + internal_basename;
std::string factory_basename = "factory-tq";
std::string factory_file_basename = output_directory + "/" + factory_basename;
{ {
IncludeGuardScope header_guard(header, basename + ".h"); IncludeGuardScope header_guard(external_header, basename + ".h");
header << "#include \"src/objects/objects.h\"\n";
header << "#include \"src/objects/smi.h\"\n";
header << "#include \"torque-generated/field-offsets-tq.h\"\n";
header << "#include <type_traits>\n\n";
IncludeObjectMacrosScope header_macros(header);
NamespaceScope header_namespaces(header, {"v8", "internal"});
header << "using BuiltinPtr = Smi;\n\n";
IncludeGuardScope inline_header_guard(inline_header, basename + "-inl.h"); IncludeGuardScope inline_header_guard(inline_external_header,
inline_header << "#include \"torque-generated/class-definitions-tq.h\"\n\n"; basename + "-inl.h");
inline_header << "#include \"src/objects/js-promise.h\"\n";
inline_header << "#include \"src/objects/js-weak-refs.h\"\n"; IncludeGuardScope internal_header_guard(internal_header,
inline_header << "#include \"src/objects/module.h\"\n"; internal_basename + ".h");
inline_header << "#include \"src/objects/objects-inl.h\"\n";
inline_header << "#include \"src/objects/script.h\"\n"; IncludeGuardScope internal_inline_header_guard(
inline_header << "#include \"src/objects/shared-function-info.h\"\n\n"; inline_internal_header, internal_basename + "-inl.h");
IncludeObjectMacrosScope inline_header_macros(inline_header);
NamespaceScope inline_header_namespaces(inline_header, {"v8", "internal"}); external_header
<< "#include \"torque-generated/internal-class-definitions-tq.h\"\n";
EmitClassDefinitionHeadersIncludes(basename, external_header,
inline_external_header);
EmitClassDefinitionHeadersIncludes(internal_basename, internal_header,
inline_internal_header);
IncludeObjectMacrosScope header_macros(external_header);
IncludeObjectMacrosScope inline_header_macros(inline_external_header);
IncludeObjectMacrosScope internal_header_macros(internal_header);
IncludeObjectMacrosScope internal_inline_header_macros(
inline_internal_header);
NamespaceScope header_namespaces(external_header, {"v8", "internal"});
NamespaceScope inline_header_namespaces(inline_external_header,
{"v8", "internal"});
NamespaceScope internal_header_namespaces(internal_header,
{"v8", "internal"});
NamespaceScope internal_inline_header_namespaces(inline_internal_header,
{"v8", "internal"});
EmitClassDefinitionHeadersForwardDeclarations(external_header);
EmitClassDefinitionHeadersForwardDeclarations(internal_header);
factory_impl << "#include \"src/heap/factory.h\"\n";
factory_impl << "#include \"src/heap/factory-inl.h\"\n";
factory_impl << "#include \"src/heap/heap.h\"\n";
factory_impl << "#include \"src/heap/heap-inl.h\"\n";
factory_impl << "#include \"src/execution/isolate.h\"\n\n";
factory_impl
<< "#include "
"\"torque-generated/internal-class-definitions-tq-inl.h\"\n\n";
NamespaceScope factory_impl_namespaces(factory_impl, {"v8", "internal"});
factory_impl << "\n";
implementation implementation
<< "#include \"torque-generated/class-definitions-tq.h\"\n\n"; << "#include \"torque-generated/class-definitions-tq.h\"\n\n";
@ -3652,16 +3888,16 @@ void ImplementationVisitor::GenerateClassDefinitions(
NamespaceScope implementation_namespaces(implementation, NamespaceScope implementation_namespaces(implementation,
{"v8", "internal"}); {"v8", "internal"});
// Generate forward declarations for every class.
for (const TypeAlias* alias : GlobalContext::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
header << "class " << type->GetGeneratedTNodeTypeName() << ";\n";
}
std::unordered_set<const StructType*> structs_used_in_classes; std::unordered_set<const StructType*> structs_used_in_classes;
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type()); std::stringstream& header = (type->IsExtern() || type->ShouldExport())
? external_header
: internal_header;
std::stringstream& inline_header =
(type->IsExtern() || type->ShouldExport()) ? inline_external_header
: inline_internal_header;
if (type->GenerateCppClassDefinitions()) { if (type->GenerateCppClassDefinitions()) {
CppClassGenerator g(type, header, inline_header, implementation); CppClassGenerator g(type, header, inline_header, implementation);
g.GenerateClass(); g.GenerateClass();
@ -3673,17 +3909,92 @@ void ImplementationVisitor::GenerateClassDefinitions(
structs_used_in_classes.insert(field_as_struct); structs_used_in_classes.insert(field_as_struct);
} }
} }
if (type->ShouldExport()) {
factory_header << type->HandlifiedCppTypeName() << " New"
<< type->name() << "(";
factory_impl << type->HandlifiedCppTypeName() << " Factory::New"
<< type->name() << "(";
for (const Field& f : type->ComputeAllFields()) {
if (f.name_and_type.name == "map") continue;
if (!f.index) {
std::string type_string =
f.name_and_type.type->HandlifiedCppTypeName();
factory_header << type_string << " " << f.name_and_type.name
<< ", ";
factory_impl << type_string << " " << f.name_and_type.name << ", ";
}
}
factory_header << "AllocationType allocation_type);\n";
factory_impl << "AllocationType allocation_type) {\n";
factory_impl << " int size = ";
const ClassType* super = type->GetSuperClass();
std::string gen_name = "TorqueGenerated" + type->name();
std::string gen_name_T =
gen_name + "<" + type->name() + ", " + super->name() + ">";
factory_impl << gen_name_T << "::SizeFor(";
bool first = true;
auto index_fields = GetOrderedUniqueIndexFields(*type);
CHECK(index_fields.has_value());
for (auto index_field : *index_fields) {
if (!first) {
factory_impl << ", ";
}
factory_impl << index_field.name_and_type.name;
first = false;
}
factory_impl << ");\n";
factory_impl << " ReadOnlyRoots roots(isolate());\n";
factory_impl << " HeapObject result =\n";
factory_impl << " "
"isolate()->heap()->AllocateRawWith<Heap::kRetryOrFail>"
"(size, allocation_type);\n";
factory_impl << " result.set_map_after_allocation(roots."
<< SnakeifyString(type->name())
<< "_map(), SKIP_WRITE_BARRIER);\n";
factory_impl << " " << type->HandlifiedCppTypeName()
<< " result_handle(" << type->name()
<< "::cast(result), isolate());\n";
for (const Field& f : type->ComputeAllFields()) {
if (f.name_and_type.name == "map") continue;
if (!f.index) {
factory_impl << " result_handle->set_"
<< SnakeifyString(f.name_and_type.name) << "(";
if (f.name_and_type.type->IsSubtypeOf(
TypeOracle::GetTaggedType()) &&
!f.name_and_type.type->IsSubtypeOf(TypeOracle::GetSmiType())) {
factory_impl << "*" << f.name_and_type.name
<< ", SKIP_WRITE_BARRIER";
} else {
factory_impl << f.name_and_type.name;
}
factory_impl << ");\n";
}
}
factory_impl << " return result_handle;\n";
factory_impl << "}\n\n";
}
} }
for (const StructType* type : structs_used_in_classes) { for (const StructType* type : structs_used_in_classes) {
if (type != TypeOracle::GetFloat64OrHoleType()) { if (type != TypeOracle::GetFloat64OrHoleType()) {
GenerateStructLayoutDescription(header, type); GenerateStructLayoutDescription(external_header, type);
} }
} }
} }
WriteFile(file_basename + ".h", header.str()); WriteFile(file_basename + ".h", external_header.str());
WriteFile(file_basename + "-inl.h", inline_header.str()); WriteFile(file_basename + "-inl.h", inline_external_header.str());
WriteFile(file_basename + ".cc", implementation.str()); WriteFile(file_basename + ".cc", implementation.str());
WriteFile(internal_file_basename + ".h", internal_header.str());
WriteFile(internal_file_basename + "-inl.h", inline_internal_header.str());
WriteFile(factory_file_basename + ".inc", factory_header.str());
WriteFile(factory_file_basename + ".cc", factory_impl.str());
} }
namespace { namespace {
@ -3700,10 +4011,19 @@ void GeneratePrintDefinitionsForClass(std::ostream& impl, const ClassType* type,
for (const AggregateType* aggregate_type : hierarchy) { for (const AggregateType* aggregate_type : hierarchy) {
for (const Field& f : aggregate_type->fields()) { for (const Field& f : aggregate_type->fields()) {
if (f.name_and_type.name == "map") continue; if (f.name_and_type.name == "map") continue;
if (!f.index.has_value()) {
if ((aggregate_type == TypeOracle::GetFixedArrayBaseType() &&
f.name_and_type.name == "length") ||
!f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
impl << " os << \"\\n - " << f.name_and_type.name << ": \" << "
<< "this->" << f.name_and_type.name << "();\n";
} else {
impl << " os << \"\\n - " << f.name_and_type.name << ": \" << " impl << " os << \"\\n - " << f.name_and_type.name << ": \" << "
<< "Brief(this->" << f.name_and_type.name << "());\n"; << "Brief(this->" << f.name_and_type.name << "());\n";
} }
} }
}
}
impl << " os << \"\\n\";\n"; impl << " os << \"\\n\";\n";
impl << "}\n\n"; impl << "}\n\n";
} }
@ -3725,8 +4045,7 @@ void ImplementationVisitor::GeneratePrintDefinitions(
NamespaceScope impl_namespaces(impl, {"v8", "internal"}); NamespaceScope impl_namespaces(impl, {"v8", "internal"});
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
if (!type->ShouldGeneratePrint()) continue; if (!type->ShouldGeneratePrint()) continue;
if (type->GenerateCppClassDefinitions()) { if (type->GenerateCppClassDefinitions()) {
@ -3748,6 +4067,142 @@ void ImplementationVisitor::GeneratePrintDefinitions(
WriteFile(output_directory + "/" + file_name, new_contents); WriteFile(output_directory + "/" + file_name, new_contents);
} }
void ImplementationVisitor::GenerateBodyDescriptors(
const std::string& output_directory) {
std::string file_name = "objects-body-descriptors-tq-inl";
std::stringstream h_contents;
{
IncludeGuardScope include_guard(h_contents, file_name + ".h");
h_contents << "\n#include \"src/objects/objects-body-descriptors.h\"\n";
h_contents << "\n#include \"torque-generated/class-definitions-tq.h\"\n";
h_contents
<< "\n#include \"torque-generated/internal-class-definitions-tq.h\"\n";
h_contents << "\n#include "
"\"torque-generated/internal-class-definitions-tq-inl.h\"\n";
NamespaceScope h_namespaces(h_contents, {"v8", "internal"});
for (const ClassType* type : TypeOracle::GetClasses()) {
std::string name = type->name();
if (!type->ShouldGenerateBodyDescriptor()) continue;
const ClassType* super_class = type->GetSuperClass();
std::string super_name = super_class->name();
h_contents << "class " << name
<< "::BodyDescriptor final : public BodyDescriptorBase {\n";
h_contents << " public:\n";
h_contents << " static bool IsValidSlot(Map map, HeapObject obj, int "
"offset) {\n";
if (super_class == TypeOracle::GetHeapObjectType() ||
super_class == TypeOracle::GetFixedArrayBaseType()) {
h_contents << " if (offset < " << super_name
<< "::kHeaderSize) return true;\n";
} else {
h_contents << " if (" << super_name
<< "::BodyDescriptor::IsValidSlot(map, obj, offset)) return "
"true;\n";
}
h_contents << " return offset >= " << name
<< "::kStartOfStrongFieldsOffset"
<< " && offset < " << name << ""
<< "::kEndOfStrongFieldsOffset;\n";
h_contents << " }\n\n";
h_contents << " template <typename ObjectVisitor>\n";
h_contents << " static inline void IterateBody(Map map, HeapObject obj, "
"int object_size, ObjectVisitor* v) {\n";
// There may be MaybeObjects embedded in the strong pointer section, which
// are not suppored.
for (auto& f : type->fields()) {
for (const Type* t : LowerType(f.name_and_type.type)) {
if (t->IsSubtypeOf(TypeOracle::GetTaggedType()) &&
!t->IsSubtypeOf(TypeOracle::GetObjectType())) {
Error("Cannot generate body descriptor for field ",
f.name_and_type.name, " of class ", name, " because ", *t,
" can contain tagged weak pointers.");
}
}
}
if (super_class != TypeOracle::GetHeapObjectType() &&
super_class != TypeOracle::GetFixedArrayBaseType()) {
h_contents
<< " " << super_name
<< "::BodyDescriptor::IterateBody(map, obj, object_size, v);\n";
}
h_contents << " if (" << name
<< "::kStartOfStrongFieldsOffset != " << name
<< "::kEndOfStrongFieldsOffset) {\n";
h_contents << " IteratePointers(obj, " << name
<< "::kStartOfStrongFieldsOffset, " << name
<< "::kEndOfStrongFieldsOffset, v);\n";
h_contents << " }\n";
h_contents << " if (" << name
<< "::kStartOfWeakFieldsOffset != " << name
<< "::kEndOfWeakFieldsOffset) {\n";
h_contents << " IterateCustomWeakPointers(obj, " << name
<< "::kStartOfWeakFieldsOffset, " << name
<< "::kEndOfWeakFieldsOffset, v);\n";
h_contents << " }\n";
// Since all of the index fields are at the end of the object and must
// only be Tagged values, emit only a single IteratePointers from the
// beginning of the first indexed field to the end of the object.
bool first_index_seen = false;
for (const Field& field : type->ComputeAllFields()) {
if (field.index && !first_index_seen) {
std::string indexed_field_name =
CamelifyString(field.name_and_type.name);
if (field.name_and_type.type->IsSubtypeOf(
TypeOracle::GetObjectType())) {
h_contents << " BodyDescriptorBase::IteratePointers(obj, "
<< name << "::k" << indexed_field_name << "Offset, "
<< name << "::SizeFor(" << name << "::cast(obj)), v);\n";
} else {
Error(
"generating body descriptors for indexed fields not subtype of "
"Object isn't (yet) supported");
}
first_index_seen = true;
}
if (first_index_seen) {
for (const Type* t : LowerType(field.name_and_type.type)) {
if (!t->IsSubtypeOf(TypeOracle::GetObjectType())) {
Error("cannot generate class body descriptor for \"",
type->name(),
"\", all fields of including and after the first indexed "
"member must no comprised only of subtypes of Object "
"(field \"",
field.name_and_type.name, "\" is not)");
}
}
}
}
h_contents << " }\n\n";
h_contents
<< " static inline int SizeOf(Map map, HeapObject raw_object) {\n";
h_contents << " " << name << " object = " << name
<< "::cast(raw_object);\n";
h_contents << " return " << name << "::SizeFor(object);\n";
h_contents << " }\n\n";
h_contents << "};\n";
}
}
WriteFile(output_directory + "/" + file_name + ".h", h_contents.str());
}
namespace { namespace {
// Generate verification code for a single piece of class data, which might be // Generate verification code for a single piece of class data, which might be
@ -3909,8 +4364,7 @@ void ImplementationVisitor::GenerateClassVerifiers(
// Generate forward declarations to avoid including any headers. // Generate forward declarations to avoid including any headers.
h_contents << "class Isolate;\n"; h_contents << "class Isolate;\n";
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
if (!type->ShouldGenerateVerify()) continue; if (!type->ShouldGenerateVerify()) continue;
h_contents << "class " << type->name() << ";\n"; h_contents << "class " << type->name() << ";\n";
} }
@ -3920,8 +4374,7 @@ void ImplementationVisitor::GenerateClassVerifiers(
h_contents << "class " << verifier_class << "{\n"; h_contents << "class " << verifier_class << "{\n";
h_contents << " public:\n"; h_contents << " public:\n";
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
std::string name = type->name(); std::string name = type->name();
if (!type->ShouldGenerateVerify()) continue; if (!type->ShouldGenerateVerify()) continue;

View File

@ -388,13 +388,13 @@ class ImplementationVisitor {
void GenerateBitFields(const std::string& output_directory); void GenerateBitFields(const std::string& output_directory);
void GeneratePrintDefinitions(const std::string& output_directory); void GeneratePrintDefinitions(const std::string& output_directory);
void GenerateClassDefinitions(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 GenerateInstanceTypes(const std::string& output_directory);
void GenerateClassVerifiers(const std::string& output_directory); void GenerateClassVerifiers(const std::string& output_directory);
void GenerateEnumVerifiers(const std::string& output_directory); void GenerateEnumVerifiers(const std::string& output_directory);
void GenerateClassDebugReaders(const std::string& output_directory); void GenerateClassDebugReaders(const std::string& output_directory);
void GenerateExportedMacrosAssembler(const std::string& output_directory); void GenerateExportedMacrosAssembler(const std::string& output_directory);
void GenerateCSATypes(const std::string& output_directory); void GenerateCSATypes(const std::string& output_directory);
void GenerateCppForInternalClasses(const std::string& output_directory);
VisitResult Visit(Expression* expr); VisitResult Visit(Expression* expr);
const Type* Visit(Statement* stmt); const Type* Visit(Statement* stmt);

View File

@ -289,6 +289,8 @@ std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
// - fully_defined_single_instance_types: This list is pairs of class name and // - fully_defined_single_instance_types: This list is pairs of class name and
// instance type, for classes which have defined layouts and a single // instance type, for classes which have defined layouts and a single
// corresponding instance type. // 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 // - only_declared_single_instance_types: This list is pairs of class name and
// instance type, for classes which have a single corresponding instance type // instance type, for classes which have a single corresponding instance type
// and do not have layout definitions in Torque. // and do not have layout definitions in Torque.
@ -302,6 +304,7 @@ std::unique_ptr<InstanceTypeTree> AssignInstanceTypes() {
void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions, void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
std::ostream& values, std::ostream& values,
std::ostream& fully_defined_single_instance_types, std::ostream& fully_defined_single_instance_types,
std::ostream& fully_defined_multiple_instance_types,
std::ostream& only_declared_single_instance_types, std::ostream& only_declared_single_instance_types,
std::ostream& fully_defined_range_instance_types, std::ostream& fully_defined_range_instance_types,
std::ostream& only_declared_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) { for (auto& child : root->children) {
PrintInstanceTypes( PrintInstanceTypes(
child.get(), definitions, values, fully_defined_single_instance_types, 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_single_instance_types, fully_defined_range_instance_types,
only_declared_range_instance_types, inner_indent); only_declared_range_instance_types, inner_indent);
} }
@ -351,6 +355,11 @@ void PrintInstanceTypes(InstanceTypeTree* root, std::ostream& definitions,
: fully_defined_range_instance_types; : fully_defined_range_instance_types;
range_instance_types << " V(" << root->type->name() << ", FIRST_" range_instance_types << " V(" << root->type->name() << ", FIRST_"
<< type_name << ", LAST_" << type_name << ") \\\n"; << 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::unique_ptr<InstanceTypeTree> instance_types = AssignInstanceTypes();
std::stringstream values_list; std::stringstream values_list;
std::stringstream fully_defined_single_instance_types; std::stringstream fully_defined_single_instance_types;
std::stringstream fully_defined_multiple_instance_types;
std::stringstream only_declared_single_instance_types; std::stringstream only_declared_single_instance_types;
std::stringstream fully_defined_range_instance_types; std::stringstream fully_defined_range_instance_types;
std::stringstream only_declared_range_instance_types; std::stringstream only_declared_range_instance_types;
if (instance_types != nullptr) { if (instance_types != nullptr) {
PrintInstanceTypes(instance_types.get(), header, values_list, PrintInstanceTypes(instance_types.get(), header, values_list,
fully_defined_single_instance_types, fully_defined_single_instance_types,
fully_defined_multiple_instance_types,
only_declared_single_instance_types, only_declared_single_instance_types,
fully_defined_range_instance_types, fully_defined_range_instance_types,
only_declared_range_instance_types, " "); only_declared_range_instance_types, " ");
@ -394,6 +405,12 @@ void ImplementationVisitor::GenerateInstanceTypes(
header << fully_defined_single_instance_types.str(); header << fully_defined_single_instance_types.str();
header << "\n"; 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 << "// Pairs of (ClassName, INSTANCE_TYPE) for classes that are\n";
header << "// declared but not defined in Torque. These classes may\n"; header << "// declared but not defined in Torque. These classes may\n";
header << "// correspond with actual C++ classes, but they are not\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 << only_declared_range_instance_types.str();
header << "\n"; header << "\n";
header << "// Instance types for Torque-internal classes.\n"; header << "// Instance types for non-extern Torque classes.\n";
header << "#define TORQUE_INTERNAL_INSTANCE_TYPES(V) \\\n"; header << "#define TORQUE_INSTANCE_TYPES(V) \\\n";
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
if (type->IsExtern()) continue; if (type->IsExtern()) continue;
std::string type_name = std::string type_name =
CapifyStringWithUnderscores(type->name()) + "_TYPE"; CapifyStringWithUnderscores(type->name()) + "_TYPE";
@ -427,11 +443,11 @@ void ImplementationVisitor::GenerateInstanceTypes(
} }
header << "\n"; header << "\n";
header << "// Struct list entries for Torque-internal classes.\n"; header << "// Map list macros for non-extern Torque classes.\n";
header << "#define TORQUE_STRUCT_LIST_GENERATOR(V, _) \\\n"; header << "#define TORQUE_INTERNAL_VARSIZE_CLASS_LIST_GENERATOR(V, _) \\\n";
for (const TypeAlias* alias : GlobalContext::GetClasses()) { for (const ClassType* type : TypeOracle::GetClasses()) {
const ClassType* type = ClassType::DynamicCast(alias->type());
if (type->IsExtern()) continue; if (type->IsExtern()) continue;
if (!type->HasIndexedField()) continue;
std::string type_name = std::string type_name =
CapifyStringWithUnderscores(type->name()) + "_TYPE"; CapifyStringWithUnderscores(type->name()) + "_TYPE";
std::string variable_name = SnakeifyString(type->name()); std::string variable_name = SnakeifyString(type->name());
@ -439,6 +455,21 @@ void ImplementationVisitor::GenerateInstanceTypes(
<< variable_name << ") \\\n"; << variable_name << ") \\\n";
} }
header << "\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; std::string output_header_path = output_directory + "/" + file_name;
WriteFile(output_header_path, header.str()); WriteFile(output_header_path, header.str());

View File

@ -88,10 +88,10 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
implementation_visitor.GenerateClassVerifiers(output_directory); implementation_visitor.GenerateClassVerifiers(output_directory);
implementation_visitor.GenerateClassDebugReaders(output_directory); implementation_visitor.GenerateClassDebugReaders(output_directory);
implementation_visitor.GenerateEnumVerifiers(output_directory); implementation_visitor.GenerateEnumVerifiers(output_directory);
implementation_visitor.GenerateBodyDescriptors(output_directory);
implementation_visitor.GenerateExportedMacrosAssembler(output_directory); implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
implementation_visitor.GenerateCSATypes(output_directory); implementation_visitor.GenerateCSATypes(output_directory);
implementation_visitor.GenerateInstanceTypes(output_directory); implementation_visitor.GenerateInstanceTypes(output_directory);
implementation_visitor.GenerateCppForInternalClasses(output_directory);
implementation_visitor.EndCSAFiles(); implementation_visitor.EndCSAFiles();
implementation_visitor.GenerateImplementation(output_directory); implementation_visitor.GenerateImplementation(output_directory);

View File

@ -549,9 +549,24 @@ base::Optional<ParseResult> MakeIntrinsicDeclaration(
return ParseResult{result}; 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( base::Optional<ParseResult> MakeTorqueMacroDeclaration(
ParseResultIterator* child_results) { 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 transitioning = child_results->NextAs<bool>();
auto operator_name = child_results->NextAs<base::Optional<std::string>>(); auto operator_name = child_results->NextAs<base::Optional<std::string>>();
auto name = child_results->NextAs<Identifier*>(); auto name = child_results->NextAs<Identifier*>();
@ -835,7 +850,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
child_results, child_results,
{ANNOTATION_GENERATE_PRINT, ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT, {ANNOTATION_GENERATE_PRINT, ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT,
ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT, 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_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT,
ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT}, ANNOTATION_LOWEST_INSTANCE_TYPE_WITHIN_PARENT},
{ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE, {ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE,
@ -854,6 +870,12 @@ base::Optional<ParseResult> MakeClassDeclaration(
if (annotations.Contains(ANNOTATION_GENERATE_CPP_CLASS)) { if (annotations.Contains(ANNOTATION_GENERATE_CPP_CLASS)) {
flags |= ClassFlag::kGenerateCppClassDefinitions; 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)) { if (annotations.Contains(ANNOTATION_HIGHEST_INSTANCE_TYPE_WITHIN_PARENT)) {
flags |= ClassFlag::kHighestInstanceTypeWithinParent; flags |= ClassFlag::kHighestInstanceTypeWithinParent;
} }
@ -945,7 +967,8 @@ base::Optional<ParseResult> MakeSpecializationDeclaration(
base::Optional<ParseResult> MakeStructDeclaration( base::Optional<ParseResult> MakeStructDeclaration(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
bool is_export = child_results->NextAs<bool>(); bool is_export = HasExportAnnotation(child_results, "Struct");
StructFlags flags = StructFlag::kNone; StructFlags flags = StructFlag::kNone;
if (is_export) flags |= StructFlag::kExport; if (is_export) flags |= StructFlag::kExport;
@ -2322,7 +2345,7 @@ struct TorqueGrammar : Grammar {
Sequence({Token("generates"), &externalString})), Sequence({Token("generates"), &externalString})),
&optionalClassBody}, &optionalClassBody},
AsSingletonVector<Declaration*, MakeClassDeclaration>()), AsSingletonVector<Declaration*, MakeClassDeclaration>()),
Rule({CheckIf(Token("@export")), Token("struct"), &name, Rule({annotations, Token("struct"), &name,
TryOrDefault<GenericParameters>(&genericParameters), Token("{"), TryOrDefault<GenericParameters>(&genericParameters), Token("{"),
List<Declaration*>(&method), List<Declaration*>(&method),
List<StructFieldExpression>(&structField), Token("}")}, List<StructFieldExpression>(&structField), Token("}")},
@ -2363,7 +2386,7 @@ struct TorqueGrammar : Grammar {
Rule({Token("extern"), CheckIf(Token("transitioning")), Token("runtime"), Rule({Token("extern"), CheckIf(Token("transitioning")), Token("runtime"),
&name, &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, &name, &typeListMaybeVarArgs, &optionalReturnType, Token(";")},
AsSingletonVector<Declaration*, MakeExternalRuntime>()), AsSingletonVector<Declaration*, MakeExternalRuntime>()),
Rule({CheckIf(Token("@export")), CheckIf(Token("transitioning")), Rule({annotations, CheckIf(Token("transitioning")),
Optional<std::string>( Optional<std::string>(
Sequence({Token("operator"), &externalString})), Sequence({Token("operator"), &externalString})),
Token("macro"), &name, Token("macro"), &name,

View File

@ -4,6 +4,7 @@
#include "src/torque/type-oracle.h" #include "src/torque/type-oracle.h"
#include "src/torque/type-visitor.h" #include "src/torque/type-visitor.h"
#include "src/torque/types.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -68,6 +69,17 @@ Namespace* TypeOracle::CreateGenericTypeInstantiationNamespace() {
return Get().generic_type_instantiation_namespaces_.back().get(); 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 torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -293,6 +293,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Get().GetBuiltinType(UNINITIALIZED_ITERATOR_TYPE_STRING); 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( static base::Optional<const Type*> ImplicitlyConvertableFrom(
const Type* to, const Type* from) { const Type* to, const Type* from) {
while (from != nullptr) { while (from != nullptr) {
@ -315,6 +319,10 @@ class TypeOracle : public ContextualClass<TypeOracle> {
static const std::vector<std::unique_ptr<BitFieldStructType>>& static const std::vector<std::unique_ptr<BitFieldStructType>>&
GetBitFieldStructTypes(); 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 void FinalizeAggregateTypes();
static size_t FreshTypeId() { return Get().next_type_id_++; } static size_t FreshTypeId() { return Get().next_type_id_++; }

View File

@ -244,41 +244,21 @@ const StructType* TypeVisitor::ComputeType(
const ClassType* TypeVisitor::ComputeType( const ClassType* TypeVisitor::ComputeType(
ClassDeclaration* decl, MaybeSpecializationKey specialized_from) { ClassDeclaration* decl, MaybeSpecializationKey specialized_from) {
ClassType* new_class;
// TODO(sigurds): Remove this hack by introducing a declarable for classes. // TODO(sigurds): Remove this hack by introducing a declarable for classes.
const TypeAlias* alias = const TypeAlias* alias =
Declarations::LookupTypeAlias(QualifiedName(decl->name->value)); Declarations::LookupTypeAlias(QualifiedName(decl->name->value));
GlobalContext::RegisterClass(alias);
DCHECK_EQ(*alias->delayed_, decl); DCHECK_EQ(*alias->delayed_, decl);
bool is_shape = decl->flags & ClassFlag::kIsShape; ClassFlags flags = decl->flags;
if (is_shape && !(decl->flags & ClassFlag::kExtern)) { 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."); ReportError("Shapes must be extern, add \"extern\" to the declaration.");
} }
if (is_shape && decl->flags & ClassFlag::kUndefinedLayout) { if (flags & ClassFlag::kUndefinedLayout) {
ReportError("Shapes need to define their layout."); ReportError("Shapes need to define their layout.");
} }
if (decl->flags & ClassFlag::kExtern) {
if (!decl->super) {
ReportError("Extern class must extend another type.");
}
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);
}
}
std::string generates = decl->name->value;
if (is_shape) {
const ClassType* super_class = ClassType::DynamicCast(super_type); const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class || if (!super_class ||
!super_class->IsSubtypeOf(TypeOracle::GetJSObjectType())) { !super_class->IsSubtypeOf(TypeOracle::GetJSObjectType())) {
@ -290,35 +270,57 @@ const ClassType* TypeVisitor::ComputeType(
// support for type-checks on the C++ side. // support for type-checks on the C++ side.
generates = super_class->name(); generates = super_class->name();
} }
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");
}
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);
}
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) { if (decl->generates) {
bool enforce_tnode_type = true; bool enforce_tnode_type = true;
generates = ComputeGeneratesType(decl->generates, enforce_tnode_type); generates = ComputeGeneratesType(decl->generates, enforce_tnode_type);
} }
if (flags & ClassFlag::kExport) {
new_class = TypeOracle::GetClassType(super_type, decl->name->value, Error("cannot export a class that is marked extern");
decl->flags, generates, decl, alias); }
} else { } 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 (decl->generates) { if (decl->generates) {
ReportError("Only extern classes can specify a generated type."); ReportError("Only extern classes can specify a generated type.");
} }
new_class = TypeOracle::GetClassType( if (super_type != TypeOracle::GetStrongTaggedType()) {
super_type, decl->name->value, if (flags & ClassFlag::kUndefinedLayout) {
decl->flags | ClassFlag::kGeneratePrint | ClassFlag::kGenerateVerify, Error("non-external classes must have defined layouts");
decl->name->value, decl, alias);
} }
return new_class; }
flags = flags | ClassFlag::kGeneratePrint | ClassFlag::kGenerateVerify |
ClassFlag::kGenerateBodyDescriptor;
}
return TypeOracle::GetClassType(super_type, decl->name->value, flags,
generates, decl, alias);
} }
const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) { const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
@ -406,17 +408,6 @@ void TypeVisitor::VisitClassFieldsAndMethods(
ReportError("in-object properties cannot be weak"); 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; base::Optional<Expression*> array_length = field_expression.index;
const Field& field = class_type->RegisterField( const Field& field = class_type->RegisterField(
{field_expression.name_and_type.name->pos, {field_expression.name_and_type.name->pos,

View File

@ -67,6 +67,20 @@ std::string Type::SimpleName() const {
return *aliases_.begin(); 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 { bool Type::IsSubtypeOf(const Type* supertype) const {
if (supertype->IsTopType()) return true; if (supertype->IsTopType()) return true;
if (IsNever()) return true; if (IsNever()) return true;
@ -517,24 +531,43 @@ void ClassType::GenerateAccessors() {
// For each field, construct AST snippets that implement a CSA accessor // For each field, construct AST snippets that implement a CSA accessor
// function. The implementation iterator will turn the snippets into code. // function. The implementation iterator will turn the snippets into code.
for (auto& field : fields_) { for (auto& field : fields_) {
if (field.index || field.name_and_type.type == TypeOracle::GetVoidType()) { if (field.name_and_type.type == TypeOracle::GetVoidType()) {
continue; continue;
} }
CurrentSourcePosition::Scope position_activator(field.pos); CurrentSourcePosition::Scope position_activator(field.pos);
IdentifierExpression* parameter = IdentifierExpression* parameter =
MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"o"})); MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"o"}));
IdentifierExpression* index =
MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"i"}));
// Load accessor // Load accessor
std::string camel_field_name = CamelifyString(field.name_and_type.name); std::string camel_field_name = CamelifyString(field.name_and_type.name);
std::string load_macro_name = "Load" + this->name() + camel_field_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; Signature load_signature;
load_signature.parameter_names.push_back(MakeNode<Identifier>("o")); load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
load_signature.parameter_types.types.push_back(this); 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.parameter_types.var_args = false;
load_signature.return_type = field.name_and_type.type; load_signature.return_type = field.name_and_type.type;
Statement* load_body =
MakeNode<ReturnStatement>(MakeNode<FieldAccessExpression>( Expression* load_expression = MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name))); 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, Declarations::DeclareMacro(load_macro_name, true, base::nullopt,
load_signature, load_body, 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; std::string store_macro_name = "Store" + this->name() + camel_field_name;
Signature store_signature; Signature store_signature;
store_signature.parameter_names.push_back(MakeNode<Identifier>("o")); 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); 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.types.push_back(field.name_and_type.type);
store_signature.parameter_types.var_args = false; store_signature.parameter_types.var_args = false;
// TODO(danno): Store macros probably should return their value argument // TODO(danno): Store macros probably should return their value argument
store_signature.return_type = TypeOracle::GetVoidType(); store_signature.return_type = TypeOracle::GetVoidType();
Statement* store_body = Expression* store_expression = MakeNode<FieldAccessExpression>(
MakeNode<ExpressionStatement>(MakeNode<AssignmentExpression>( parameter, MakeNode<Identifier>(field.name_and_type.name));
MakeNode<FieldAccessExpression>( if (field.index) {
parameter, MakeNode<Identifier>(field.name_and_type.name)), store_expression =
value)); MakeNode<ElementAccessExpression>(store_expression, index);
}
Statement* store_body = MakeNode<ExpressionStatement>(
MakeNode<AssignmentExpression>(store_expression, value));
Declarations::DeclareMacro(store_macro_name, true, base::nullopt, Declarations::DeclareMacro(store_macro_name, true, base::nullopt,
store_signature, store_body, base::nullopt, store_signature, store_body, base::nullopt,
false); false);

View File

@ -113,6 +113,8 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
// Used for naming generated code. // Used for naming generated code.
virtual std::string SimpleName() const; virtual std::string SimpleName() const;
std::string HandlifiedCppTypeName() const;
const Type* parent() const { return parent_; } const Type* parent() const { return parent_; }
bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); } bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); } bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
@ -611,12 +613,15 @@ class ClassType final : public AggregateType {
std::string GetGeneratedTNodeTypeNameImpl() const override; std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsExtern() const { return flags_ & ClassFlag::kExtern; } bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
bool ShouldGeneratePrint() const { bool ShouldGeneratePrint() const {
return (flags_ & ClassFlag::kGeneratePrint || !IsExtern()) && return !IsExtern() ||
!HasUndefinedLayout(); ((flags_ & ClassFlag::kGeneratePrint) && !HasUndefinedLayout());
} }
bool ShouldGenerateVerify() const { bool ShouldGenerateVerify() const {
return (flags_ & ClassFlag::kGenerateVerify || !IsExtern()) && return !IsExtern() || ((flags_ & ClassFlag::kGenerateVerify) &&
!HasUndefinedLayout() && !IsShape(); (!HasUndefinedLayout() && !IsShape()));
}
bool ShouldGenerateBodyDescriptor() const {
return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern();
} }
bool IsTransient() const override { return flags_ & ClassFlag::kTransient; } bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; } bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
@ -624,8 +629,10 @@ class ClassType final : public AggregateType {
return flags_ & ClassFlag::kHasSameInstanceTypeAsParent; return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
} }
bool GenerateCppClassDefinitions() const { 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 IsShape() const { return flags_ & ClassFlag::kIsShape; }
bool HasStaticSize() const; bool HasStaticSize() const;
bool HasIndexedField() const override; bool HasIndexedField() const override;

View File

@ -736,6 +736,35 @@ TEST(TestTestParentFrameArguments) {
asm_tester.GenerateCode(); 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 compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -767,7 +767,7 @@ namespace test {
check(a.b.GetX() == 2); check(a.b.GetX() == 2);
} }
class InternalClass extends Struct { class InternalClass extends HeapObject {
macro Flip() labels NotASmi { macro Flip() labels NotASmi {
const tmp = Cast<Smi>(this.b) otherwise NotASmi; const tmp = Cast<Smi>(this.b) otherwise NotASmi;
this.b = this.a; this.b = this.a;
@ -833,7 +833,7 @@ namespace test {
return new FixedArray{map: kFixedArrayMap, length: 5, objects: ...i}; return new FixedArray{map: kFixedArrayMap, length: 5, objects: ...i};
} }
class SmiPair extends Struct { class SmiPair extends HeapObject {
macro GetA():&Smi { macro GetA():&Smi {
return & this.a; return & this.a;
} }
@ -920,7 +920,7 @@ namespace test {
StaticAssert(1 + 2 == 3); StaticAssert(1 + 2 == 3);
} }
class SmiBox extends Struct { class SmiBox extends HeapObject {
value: Smi; value: Smi;
unrelated: Smi; unrelated: Smi;
} }
@ -1120,4 +1120,108 @@ namespace test {
check(val3.d == 99); check(val3.d == 99);
check(val3.e == 1234); 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};
}
} }

View File

@ -14,7 +14,7 @@
// https://github.com/python/cpython/blob/master/Objects/listsort.txt // https://github.com/python/cpython/blob/master/Objects/listsort.txt
namespace array { namespace array {
class SortState extends Struct { class SortState extends HeapObject {
macro Compare(implicit context: Context)(x: JSAny, y: JSAny): Number { macro Compare(implicit context: Context)(x: JSAny, y: JSAny): Number {
const sortCompare: CompareBuiltinFn = this.sortComparePtr; const sortCompare: CompareBuiltinFn = this.sortComparePtr;
return sortCompare(context, this.userCmpFn, x, y); return sortCompare(context, this.userCmpFn, x, y);

View File

@ -69,6 +69,7 @@ v8_component("v8_debug_helper") {
sources = [ sources = [
"$target_gen_dir/../../torque-generated/class-debug-readers-tq.cc", "$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/class-debug-readers-tq.h",
"$target_gen_dir/../../torque-generated/instance-types-tq.h",
"$target_gen_dir/heap-constants-gen.cc", "$target_gen_dir/heap-constants-gen.cc",
"debug-helper-internal.cc", "debug-helper-internal.cc",
"debug-helper-internal.h", "debug-helper-internal.h",

View File

@ -104,6 +104,7 @@ TypedObject GetTypedObjectByInstanceType(uintptr_t address,
case i::INSTANCE_TYPE: \ case i::INSTANCE_TYPE: \
return {type_source, std::make_unique<Tq##ClassName>(address)}; return {type_source, std::make_unique<Tq##ClassName>(address)};
TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(INSTANCE_TYPE_CASE) TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(INSTANCE_TYPE_CASE)
TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(INSTANCE_TYPE_CASE)
#undef INSTANCE_TYPE_CASE #undef INSTANCE_TYPE_CASE
default: default:

View File

@ -29,8 +29,8 @@ INSTANCE_TYPES = {
65: "BIG_INT_BASE_TYPE", 65: "BIG_INT_BASE_TYPE",
66: "HEAP_NUMBER_TYPE", 66: "HEAP_NUMBER_TYPE",
67: "ODDBALL_TYPE", 67: "ODDBALL_TYPE",
68: "SOURCE_TEXT_MODULE_TYPE", 68: "EXPORTED_SUB_CLASS_BASE_TYPE",
69: "SYNTHETIC_MODULE_TYPE", 69: "EXPORTED_SUB_CLASS_TYPE",
70: "FOREIGN_TYPE", 70: "FOREIGN_TYPE",
71: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE", 71: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
72: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE", 72: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
@ -60,84 +60,88 @@ INSTANCE_TYPES = {
96: "FEEDBACK_CELL_TYPE", 96: "FEEDBACK_CELL_TYPE",
97: "FUNCTION_TEMPLATE_RARE_DATA_TYPE", 97: "FUNCTION_TEMPLATE_RARE_DATA_TYPE",
98: "INTERCEPTOR_INFO_TYPE", 98: "INTERCEPTOR_INFO_TYPE",
99: "INTERNAL_CLASS_TYPE", 99: "INTERPRETER_DATA_TYPE",
100: "INTERPRETER_DATA_TYPE", 100: "PROMISE_CAPABILITY_TYPE",
101: "PROMISE_CAPABILITY_TYPE", 101: "PROMISE_REACTION_TYPE",
102: "PROMISE_REACTION_TYPE", 102: "PROPERTY_DESCRIPTOR_OBJECT_TYPE",
103: "PROPERTY_DESCRIPTOR_OBJECT_TYPE", 103: "PROTOTYPE_INFO_TYPE",
104: "PROTOTYPE_INFO_TYPE", 104: "SCRIPT_TYPE",
105: "SCRIPT_TYPE", 105: "SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE",
106: "SMI_BOX_TYPE", 106: "STACK_FRAME_INFO_TYPE",
107: "SMI_PAIR_TYPE", 107: "STACK_TRACE_FRAME_TYPE",
108: "SORT_STATE_TYPE", 108: "TEMPLATE_OBJECT_DESCRIPTION_TYPE",
109: "SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE", 109: "TUPLE2_TYPE",
110: "STACK_FRAME_INFO_TYPE", 110: "WASM_CAPI_FUNCTION_DATA_TYPE",
111: "STACK_TRACE_FRAME_TYPE", 111: "WASM_DEBUG_INFO_TYPE",
112: "TEMPLATE_OBJECT_DESCRIPTION_TYPE", 112: "WASM_EXCEPTION_TAG_TYPE",
113: "TUPLE2_TYPE", 113: "WASM_EXPORTED_FUNCTION_DATA_TYPE",
114: "WASM_CAPI_FUNCTION_DATA_TYPE", 114: "WASM_INDIRECT_FUNCTION_TABLE_TYPE",
115: "WASM_DEBUG_INFO_TYPE", 115: "WASM_JS_FUNCTION_DATA_TYPE",
116: "WASM_EXCEPTION_TAG_TYPE", 116: "FIXED_ARRAY_TYPE",
117: "WASM_EXPORTED_FUNCTION_DATA_TYPE", 117: "HASH_TABLE_TYPE",
118: "WASM_INDIRECT_FUNCTION_TABLE_TYPE", 118: "EPHEMERON_HASH_TABLE_TYPE",
119: "WASM_JS_FUNCTION_DATA_TYPE", 119: "GLOBAL_DICTIONARY_TYPE",
120: "FIXED_ARRAY_TYPE", 120: "NAME_DICTIONARY_TYPE",
121: "HASH_TABLE_TYPE", 121: "NUMBER_DICTIONARY_TYPE",
122: "EPHEMERON_HASH_TABLE_TYPE", 122: "ORDERED_HASH_MAP_TYPE",
123: "GLOBAL_DICTIONARY_TYPE", 123: "ORDERED_HASH_SET_TYPE",
124: "NAME_DICTIONARY_TYPE", 124: "ORDERED_NAME_DICTIONARY_TYPE",
125: "NUMBER_DICTIONARY_TYPE", 125: "SIMPLE_NUMBER_DICTIONARY_TYPE",
126: "ORDERED_HASH_MAP_TYPE", 126: "STRING_TABLE_TYPE",
127: "ORDERED_HASH_SET_TYPE", 127: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
128: "ORDERED_NAME_DICTIONARY_TYPE", 128: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
129: "SIMPLE_NUMBER_DICTIONARY_TYPE", 129: "SCOPE_INFO_TYPE",
130: "STRING_TABLE_TYPE", 130: "SCRIPT_CONTEXT_TABLE_TYPE",
131: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE", 131: "BYTE_ARRAY_TYPE",
132: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE", 132: "BYTECODE_ARRAY_TYPE",
133: "SCOPE_INFO_TYPE", 133: "FIXED_DOUBLE_ARRAY_TYPE",
134: "SCRIPT_CONTEXT_TABLE_TYPE", 134: "INTERNAL_CLASS_WITH_SMI_ELEMENTS_TYPE",
135: "BYTE_ARRAY_TYPE", 135: "AWAIT_CONTEXT_TYPE",
136: "BYTECODE_ARRAY_TYPE", 136: "BLOCK_CONTEXT_TYPE",
137: "FIXED_DOUBLE_ARRAY_TYPE", 137: "CATCH_CONTEXT_TYPE",
138: "AWAIT_CONTEXT_TYPE", 138: "DEBUG_EVALUATE_CONTEXT_TYPE",
139: "BLOCK_CONTEXT_TYPE", 139: "EVAL_CONTEXT_TYPE",
140: "CATCH_CONTEXT_TYPE", 140: "FUNCTION_CONTEXT_TYPE",
141: "DEBUG_EVALUATE_CONTEXT_TYPE", 141: "MODULE_CONTEXT_TYPE",
142: "EVAL_CONTEXT_TYPE", 142: "NATIVE_CONTEXT_TYPE",
143: "FUNCTION_CONTEXT_TYPE", 143: "SCRIPT_CONTEXT_TYPE",
144: "MODULE_CONTEXT_TYPE", 144: "WITH_CONTEXT_TYPE",
145: "NATIVE_CONTEXT_TYPE", 145: "SMALL_ORDERED_HASH_MAP_TYPE",
146: "SCRIPT_CONTEXT_TYPE", 146: "SMALL_ORDERED_HASH_SET_TYPE",
147: "WITH_CONTEXT_TYPE", 147: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
148: "SMALL_ORDERED_HASH_MAP_TYPE", 148: "SOURCE_TEXT_MODULE_TYPE",
149: "SMALL_ORDERED_HASH_SET_TYPE", 149: "SYNTHETIC_MODULE_TYPE",
150: "SMALL_ORDERED_NAME_DICTIONARY_TYPE", 150: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
151: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE", 151: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
152: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE", 152: "WEAK_FIXED_ARRAY_TYPE",
153: "WEAK_FIXED_ARRAY_TYPE", 153: "TRANSITION_ARRAY_TYPE",
154: "TRANSITION_ARRAY_TYPE", 154: "CELL_TYPE",
155: "CELL_TYPE", 155: "CODE_TYPE",
156: "CODE_TYPE", 156: "CODE_DATA_CONTAINER_TYPE",
157: "CODE_DATA_CONTAINER_TYPE", 157: "COVERAGE_INFO_TYPE",
158: "COVERAGE_INFO_TYPE", 158: "DESCRIPTOR_ARRAY_TYPE",
159: "DESCRIPTOR_ARRAY_TYPE", 159: "EMBEDDER_DATA_ARRAY_TYPE",
160: "EMBEDDER_DATA_ARRAY_TYPE", 160: "FEEDBACK_METADATA_TYPE",
161: "FEEDBACK_METADATA_TYPE", 161: "FEEDBACK_VECTOR_TYPE",
162: "FEEDBACK_VECTOR_TYPE", 162: "FILLER_TYPE",
163: "FILLER_TYPE", 163: "FREE_SPACE_TYPE",
164: "FREE_SPACE_TYPE", 164: "INTERNAL_CLASS_TYPE",
165: "MAP_TYPE", 165: "INTERNAL_CLASS_WITH_STRUCT_ELEMENTS_TYPE",
166: "PREPARSE_DATA_TYPE", 166: "MAP_TYPE",
167: "PROPERTY_ARRAY_TYPE", 167: "PREPARSE_DATA_TYPE",
168: "PROPERTY_CELL_TYPE", 168: "PROPERTY_ARRAY_TYPE",
169: "SHARED_FUNCTION_INFO_TYPE", 169: "PROPERTY_CELL_TYPE",
170: "WEAK_ARRAY_LIST_TYPE", 170: "SHARED_FUNCTION_INFO_TYPE",
171: "WEAK_CELL_TYPE", 171: "SMI_BOX_TYPE",
172: "JS_PROXY_TYPE", 172: "SMI_PAIR_TYPE",
173: "SORT_STATE_TYPE",
174: "WEAK_ARRAY_LIST_TYPE",
175: "WEAK_CELL_TYPE",
176: "JS_PROXY_TYPE",
1057: "JS_OBJECT_TYPE", 1057: "JS_OBJECT_TYPE",
173: "JS_GLOBAL_OBJECT_TYPE", 177: "JS_GLOBAL_OBJECT_TYPE",
174: "JS_GLOBAL_PROXY_TYPE", 178: "JS_GLOBAL_PROXY_TYPE",
175: "JS_MODULE_NAMESPACE_TYPE", 179: "JS_MODULE_NAMESPACE_TYPE",
1040: "JS_SPECIAL_API_OBJECT_TYPE", 1040: "JS_SPECIAL_API_OBJECT_TYPE",
1041: "JS_PRIMITIVE_WRAPPER_TYPE", 1041: "JS_PRIMITIVE_WRAPPER_TYPE",
1042: "JS_MAP_KEY_ITERATOR_TYPE", 1042: "JS_MAP_KEY_ITERATOR_TYPE",
@ -194,78 +198,78 @@ INSTANCE_TYPES = {
# List of known V8 maps. # List of known V8 maps.
KNOWN_MAPS = { KNOWN_MAPS = {
("read_only_space", 0x00121): (164, "FreeSpaceMap"), ("read_only_space", 0x00121): (163, "FreeSpaceMap"),
("read_only_space", 0x00149): (165, "MetaMap"), ("read_only_space", 0x00149): (166, "MetaMap"),
("read_only_space", 0x0018d): (67, "NullMap"), ("read_only_space", 0x0018d): (67, "NullMap"),
("read_only_space", 0x001c5): (159, "DescriptorArrayMap"), ("read_only_space", 0x001c5): (158, "DescriptorArrayMap"),
("read_only_space", 0x001f5): (153, "WeakFixedArrayMap"), ("read_only_space", 0x001f5): (152, "WeakFixedArrayMap"),
("read_only_space", 0x0021d): (163, "OnePointerFillerMap"), ("read_only_space", 0x0021d): (162, "OnePointerFillerMap"),
("read_only_space", 0x00245): (163, "TwoPointerFillerMap"), ("read_only_space", 0x00245): (162, "TwoPointerFillerMap"),
("read_only_space", 0x00289): (67, "UninitializedMap"), ("read_only_space", 0x00289): (67, "UninitializedMap"),
("read_only_space", 0x002cd): (8, "OneByteInternalizedStringMap"), ("read_only_space", 0x002cd): (8, "OneByteInternalizedStringMap"),
("read_only_space", 0x00329): (67, "UndefinedMap"), ("read_only_space", 0x00329): (67, "UndefinedMap"),
("read_only_space", 0x0035d): (66, "HeapNumberMap"), ("read_only_space", 0x0035d): (66, "HeapNumberMap"),
("read_only_space", 0x003a1): (67, "TheHoleMap"), ("read_only_space", 0x003a1): (67, "TheHoleMap"),
("read_only_space", 0x00401): (67, "BooleanMap"), ("read_only_space", 0x00401): (67, "BooleanMap"),
("read_only_space", 0x00489): (135, "ByteArrayMap"), ("read_only_space", 0x00489): (131, "ByteArrayMap"),
("read_only_space", 0x004b1): (120, "FixedArrayMap"), ("read_only_space", 0x004b1): (116, "FixedArrayMap"),
("read_only_space", 0x004d9): (120, "FixedCOWArrayMap"), ("read_only_space", 0x004d9): (116, "FixedCOWArrayMap"),
("read_only_space", 0x00501): (121, "HashTableMap"), ("read_only_space", 0x00501): (117, "HashTableMap"),
("read_only_space", 0x00529): (64, "SymbolMap"), ("read_only_space", 0x00529): (64, "SymbolMap"),
("read_only_space", 0x00551): (40, "OneByteStringMap"), ("read_only_space", 0x00551): (40, "OneByteStringMap"),
("read_only_space", 0x00579): (133, "ScopeInfoMap"), ("read_only_space", 0x00579): (129, "ScopeInfoMap"),
("read_only_space", 0x005a1): (169, "SharedFunctionInfoMap"), ("read_only_space", 0x005a1): (170, "SharedFunctionInfoMap"),
("read_only_space", 0x005c9): (156, "CodeMap"), ("read_only_space", 0x005c9): (155, "CodeMap"),
("read_only_space", 0x005f1): (155, "CellMap"), ("read_only_space", 0x005f1): (154, "CellMap"),
("read_only_space", 0x00619): (168, "GlobalPropertyCellMap"), ("read_only_space", 0x00619): (169, "GlobalPropertyCellMap"),
("read_only_space", 0x00641): (70, "ForeignMap"), ("read_only_space", 0x00641): (70, "ForeignMap"),
("read_only_space", 0x00669): (154, "TransitionArrayMap"), ("read_only_space", 0x00669): (153, "TransitionArrayMap"),
("read_only_space", 0x00691): (45, "ThinOneByteStringMap"), ("read_only_space", 0x00691): (45, "ThinOneByteStringMap"),
("read_only_space", 0x006b9): (162, "FeedbackVectorMap"), ("read_only_space", 0x006b9): (161, "FeedbackVectorMap"),
("read_only_space", 0x0070d): (67, "ArgumentsMarkerMap"), ("read_only_space", 0x0070d): (67, "ArgumentsMarkerMap"),
("read_only_space", 0x0076d): (67, "ExceptionMap"), ("read_only_space", 0x0076d): (67, "ExceptionMap"),
("read_only_space", 0x007c9): (67, "TerminationExceptionMap"), ("read_only_space", 0x007c9): (67, "TerminationExceptionMap"),
("read_only_space", 0x00831): (67, "OptimizedOutMap"), ("read_only_space", 0x00831): (67, "OptimizedOutMap"),
("read_only_space", 0x00891): (67, "StaleRegisterMap"), ("read_only_space", 0x00891): (67, "StaleRegisterMap"),
("read_only_space", 0x008d5): (134, "ScriptContextTableMap"), ("read_only_space", 0x008d5): (130, "ScriptContextTableMap"),
("read_only_space", 0x008fd): (131, "ClosureFeedbackCellArrayMap"), ("read_only_space", 0x008fd): (127, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x00925): (161, "FeedbackMetadataArrayMap"), ("read_only_space", 0x00925): (160, "FeedbackMetadataArrayMap"),
("read_only_space", 0x0094d): (120, "ArrayListMap"), ("read_only_space", 0x0094d): (116, "ArrayListMap"),
("read_only_space", 0x00975): (65, "BigIntMap"), ("read_only_space", 0x00975): (65, "BigIntMap"),
("read_only_space", 0x0099d): (132, "ObjectBoilerplateDescriptionMap"), ("read_only_space", 0x0099d): (128, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x009c5): (136, "BytecodeArrayMap"), ("read_only_space", 0x009c5): (132, "BytecodeArrayMap"),
("read_only_space", 0x009ed): (157, "CodeDataContainerMap"), ("read_only_space", 0x009ed): (156, "CodeDataContainerMap"),
("read_only_space", 0x00a15): (158, "CoverageInfoMap"), ("read_only_space", 0x00a15): (157, "CoverageInfoMap"),
("read_only_space", 0x00a3d): (137, "FixedDoubleArrayMap"), ("read_only_space", 0x00a3d): (133, "FixedDoubleArrayMap"),
("read_only_space", 0x00a65): (123, "GlobalDictionaryMap"), ("read_only_space", 0x00a65): (119, "GlobalDictionaryMap"),
("read_only_space", 0x00a8d): (96, "ManyClosuresCellMap"), ("read_only_space", 0x00a8d): (96, "ManyClosuresCellMap"),
("read_only_space", 0x00ab5): (120, "ModuleInfoMap"), ("read_only_space", 0x00ab5): (116, "ModuleInfoMap"),
("read_only_space", 0x00add): (124, "NameDictionaryMap"), ("read_only_space", 0x00add): (120, "NameDictionaryMap"),
("read_only_space", 0x00b05): (96, "NoClosuresCellMap"), ("read_only_space", 0x00b05): (96, "NoClosuresCellMap"),
("read_only_space", 0x00b2d): (125, "NumberDictionaryMap"), ("read_only_space", 0x00b2d): (121, "NumberDictionaryMap"),
("read_only_space", 0x00b55): (96, "OneClosureCellMap"), ("read_only_space", 0x00b55): (96, "OneClosureCellMap"),
("read_only_space", 0x00b7d): (126, "OrderedHashMapMap"), ("read_only_space", 0x00b7d): (122, "OrderedHashMapMap"),
("read_only_space", 0x00ba5): (127, "OrderedHashSetMap"), ("read_only_space", 0x00ba5): (123, "OrderedHashSetMap"),
("read_only_space", 0x00bcd): (128, "OrderedNameDictionaryMap"), ("read_only_space", 0x00bcd): (124, "OrderedNameDictionaryMap"),
("read_only_space", 0x00bf5): (166, "PreparseDataMap"), ("read_only_space", 0x00bf5): (167, "PreparseDataMap"),
("read_only_space", 0x00c1d): (167, "PropertyArrayMap"), ("read_only_space", 0x00c1d): (168, "PropertyArrayMap"),
("read_only_space", 0x00c45): (92, "SideEffectCallHandlerInfoMap"), ("read_only_space", 0x00c45): (92, "SideEffectCallHandlerInfoMap"),
("read_only_space", 0x00c6d): (92, "SideEffectFreeCallHandlerInfoMap"), ("read_only_space", 0x00c6d): (92, "SideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x00c95): (92, "NextCallSideEffectFreeCallHandlerInfoMap"), ("read_only_space", 0x00c95): (92, "NextCallSideEffectFreeCallHandlerInfoMap"),
("read_only_space", 0x00cbd): (129, "SimpleNumberDictionaryMap"), ("read_only_space", 0x00cbd): (125, "SimpleNumberDictionaryMap"),
("read_only_space", 0x00ce5): (120, "SloppyArgumentsElementsMap"), ("read_only_space", 0x00ce5): (116, "SloppyArgumentsElementsMap"),
("read_only_space", 0x00d0d): (148, "SmallOrderedHashMapMap"), ("read_only_space", 0x00d0d): (145, "SmallOrderedHashMapMap"),
("read_only_space", 0x00d35): (149, "SmallOrderedHashSetMap"), ("read_only_space", 0x00d35): (146, "SmallOrderedHashSetMap"),
("read_only_space", 0x00d5d): (150, "SmallOrderedNameDictionaryMap"), ("read_only_space", 0x00d5d): (147, "SmallOrderedNameDictionaryMap"),
("read_only_space", 0x00d85): (68, "SourceTextModuleMap"), ("read_only_space", 0x00d85): (148, "SourceTextModuleMap"),
("read_only_space", 0x00dad): (130, "StringTableMap"), ("read_only_space", 0x00dad): (126, "StringTableMap"),
("read_only_space", 0x00dd5): (69, "SyntheticModuleMap"), ("read_only_space", 0x00dd5): (149, "SyntheticModuleMap"),
("read_only_space", 0x00dfd): (152, "UncompiledDataWithoutPreparseDataMap"), ("read_only_space", 0x00dfd): (151, "UncompiledDataWithoutPreparseDataMap"),
("read_only_space", 0x00e25): (151, "UncompiledDataWithPreparseDataMap"), ("read_only_space", 0x00e25): (150, "UncompiledDataWithPreparseDataMap"),
("read_only_space", 0x00e4d): (170, "WeakArrayListMap"), ("read_only_space", 0x00e4d): (174, "WeakArrayListMap"),
("read_only_space", 0x00e75): (122, "EphemeronHashTableMap"), ("read_only_space", 0x00e75): (118, "EphemeronHashTableMap"),
("read_only_space", 0x00e9d): (160, "EmbedderDataArrayMap"), ("read_only_space", 0x00e9d): (159, "EmbedderDataArrayMap"),
("read_only_space", 0x00ec5): (171, "WeakCellMap"), ("read_only_space", 0x00ec5): (175, "WeakCellMap"),
("read_only_space", 0x00eed): (32, "StringMap"), ("read_only_space", 0x00eed): (32, "StringMap"),
("read_only_space", 0x00f15): (41, "ConsOneByteStringMap"), ("read_only_space", 0x00f15): (41, "ConsOneByteStringMap"),
("read_only_space", 0x00f3d): (33, "ConsStringMap"), ("read_only_space", 0x00f3d): (33, "ConsStringMap"),
@ -305,36 +309,40 @@ KNOWN_MAPS = {
("read_only_space", 0x0357d): (93, "ClassPositionsMap"), ("read_only_space", 0x0357d): (93, "ClassPositionsMap"),
("read_only_space", 0x035a5): (94, "DebugInfoMap"), ("read_only_space", 0x035a5): (94, "DebugInfoMap"),
("read_only_space", 0x035cd): (97, "FunctionTemplateRareDataMap"), ("read_only_space", 0x035cd): (97, "FunctionTemplateRareDataMap"),
("read_only_space", 0x035f5): (100, "InterpreterDataMap"), ("read_only_space", 0x035f5): (99, "InterpreterDataMap"),
("read_only_space", 0x0361d): (101, "PromiseCapabilityMap"), ("read_only_space", 0x0361d): (100, "PromiseCapabilityMap"),
("read_only_space", 0x03645): (102, "PromiseReactionMap"), ("read_only_space", 0x03645): (101, "PromiseReactionMap"),
("read_only_space", 0x0366d): (103, "PropertyDescriptorObjectMap"), ("read_only_space", 0x0366d): (102, "PropertyDescriptorObjectMap"),
("read_only_space", 0x03695): (104, "PrototypeInfoMap"), ("read_only_space", 0x03695): (103, "PrototypeInfoMap"),
("read_only_space", 0x036bd): (105, "ScriptMap"), ("read_only_space", 0x036bd): (104, "ScriptMap"),
("read_only_space", 0x036e5): (109, "SourceTextModuleInfoEntryMap"), ("read_only_space", 0x036e5): (105, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x0370d): (110, "StackFrameInfoMap"), ("read_only_space", 0x0370d): (106, "StackFrameInfoMap"),
("read_only_space", 0x03735): (111, "StackTraceFrameMap"), ("read_only_space", 0x03735): (107, "StackTraceFrameMap"),
("read_only_space", 0x0375d): (112, "TemplateObjectDescriptionMap"), ("read_only_space", 0x0375d): (108, "TemplateObjectDescriptionMap"),
("read_only_space", 0x03785): (113, "Tuple2Map"), ("read_only_space", 0x03785): (109, "Tuple2Map"),
("read_only_space", 0x037ad): (114, "WasmCapiFunctionDataMap"), ("read_only_space", 0x037ad): (110, "WasmCapiFunctionDataMap"),
("read_only_space", 0x037d5): (115, "WasmDebugInfoMap"), ("read_only_space", 0x037d5): (111, "WasmDebugInfoMap"),
("read_only_space", 0x037fd): (116, "WasmExceptionTagMap"), ("read_only_space", 0x037fd): (112, "WasmExceptionTagMap"),
("read_only_space", 0x03825): (117, "WasmExportedFunctionDataMap"), ("read_only_space", 0x03825): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x0384d): (118, "WasmIndirectFunctionTableMap"), ("read_only_space", 0x0384d): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x03875): (119, "WasmJSFunctionDataMap"), ("read_only_space", 0x03875): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x0389d): (99, "InternalClassMap"), ("read_only_space", 0x0389d): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x038c5): (107, "SmiPairMap"), ("read_only_space", 0x038c5): (165, "InternalClassWithStructElementsMap"),
("read_only_space", 0x038ed): (106, "SmiBoxMap"), ("read_only_space", 0x038ed): (164, "InternalClassMap"),
("read_only_space", 0x03915): (108, "SortStateMap"), ("read_only_space", 0x03915): (172, "SmiPairMap"),
("read_only_space", 0x0393d): (85, "AllocationSiteWithWeakNextMap"), ("read_only_space", 0x0393d): (171, "SmiBoxMap"),
("read_only_space", 0x03965): (85, "AllocationSiteWithoutWeakNextMap"), ("read_only_space", 0x03965): (68, "ExportedSubClassBaseMap"),
("read_only_space", 0x0398d): (76, "LoadHandler1Map"), ("read_only_space", 0x0398d): (69, "ExportedSubClassMap"),
("read_only_space", 0x039b5): (76, "LoadHandler2Map"), ("read_only_space", 0x039b5): (173, "SortStateMap"),
("read_only_space", 0x039dd): (76, "LoadHandler3Map"), ("read_only_space", 0x039dd): (85, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x03a05): (77, "StoreHandler0Map"), ("read_only_space", 0x03a05): (85, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x03a2d): (77, "StoreHandler1Map"), ("read_only_space", 0x03a2d): (76, "LoadHandler1Map"),
("read_only_space", 0x03a55): (77, "StoreHandler2Map"), ("read_only_space", 0x03a55): (76, "LoadHandler2Map"),
("read_only_space", 0x03a7d): (77, "StoreHandler3Map"), ("read_only_space", 0x03a7d): (76, "LoadHandler3Map"),
("read_only_space", 0x03aa5): (77, "StoreHandler0Map"),
("read_only_space", 0x03acd): (77, "StoreHandler1Map"),
("read_only_space", 0x03af5): (77, "StoreHandler2Map"),
("read_only_space", 0x03b1d): (77, "StoreHandler3Map"),
("map_space", 0x00121): (1057, "ExternalMap"), ("map_space", 0x00121): (1057, "ExternalMap"),
("map_space", 0x00149): (1073, "JSMessageObjectMap"), ("map_space", 0x00149): (1073, "JSMessageObjectMap"),
} }