[torque] improve GC visitors
Summary of changes: - GC visitors no longer rely on superclass visitors, but instead visit everything themselves. This enables generating better code. - Try to match simple body descriptors to reduce the amount of generated code. - Turn SizeFor(instance) into an AllocatedSize() method. - Remove the special handling of resizable object sizes from Torque and instead overwrite AllocatedSize in classes that need special handling in C++. - Split the visitor id lists depending on whether the class has pointer fields. - Turn Torque-generated body descriptors into an .inc file to simplify includes. - Fix generated size functions to properly align the size. - Generate GC visitors (and C++ class definitions) for all string classes and FixedArray, WeakFixedArray, and WeakArrayList. - Store generated instance types in Torque class types. This is only used to determine if a type has a single instance type in this CL. Bug: v8:7793 Change-Id: I4d362e96b047c305bd6d065247734957b8958c42 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2110014 Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#67542}
This commit is contained in:
parent
0d44905481
commit
f1400e43f1
2
BUILD.gn
2
BUILD.gn
@ -1211,7 +1211,7 @@ template("run_torque") {
|
||||
"class-verifiers-tq.h",
|
||||
"enum-verifiers-tq.cc",
|
||||
"objects-printer-tq.cc",
|
||||
"objects-body-descriptors-tq-inl.h",
|
||||
"objects-body-descriptors-tq-inl.inc",
|
||||
"class-definitions-tq.cc",
|
||||
"class-definitions-tq-inl.h",
|
||||
"class-definitions-tq.h",
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "src/objects/oddball.h"
|
||||
#include "src/objects/ordered-hash-table.h"
|
||||
#include "src/wasm/wasm-objects.h"
|
||||
#include "torque-generated/objects-body-descriptors-tq-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -61,8 +60,6 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map map,
|
||||
return visitor->VisitStruct(map, object);
|
||||
case kVisitFreeSpace:
|
||||
return visitor->VisitFreeSpace(map, FreeSpace::cast(object));
|
||||
case kVisitWeakArray:
|
||||
return visitor->VisitWeakArray(map, object);
|
||||
case kDataOnlyVisitorIdCount:
|
||||
case kVisitorIdCount:
|
||||
UNREACHABLE();
|
||||
@ -169,19 +166,6 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
|
||||
return static_cast<ResultType>(object.size());
|
||||
}
|
||||
|
||||
template <typename ResultType, typename ConcreteVisitor>
|
||||
ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitWeakArray(
|
||||
Map map, HeapObject object) {
|
||||
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
|
||||
if (!visitor->ShouldVisit(object)) return ResultType();
|
||||
int size = WeakArrayBodyDescriptor::SizeOf(map, object);
|
||||
if (visitor->ShouldVisitMapPointer()) {
|
||||
visitor->VisitMapPointer(object);
|
||||
}
|
||||
WeakArrayBodyDescriptor::IterateBody(map, object, size, visitor);
|
||||
return size;
|
||||
}
|
||||
|
||||
template <typename ConcreteVisitor>
|
||||
int NewSpaceVisitor<ConcreteVisitor>::VisitNativeContext(Map map,
|
||||
NativeContext object) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/objects/map.h"
|
||||
#include "src/objects/objects.h"
|
||||
#include "src/objects/visitors.h"
|
||||
#include "torque-generated/field-offsets-tq.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -21,7 +22,6 @@ namespace internal {
|
||||
V(Cell) \
|
||||
V(Code) \
|
||||
V(CodeDataContainer) \
|
||||
V(ConsString) \
|
||||
V(Context) \
|
||||
V(CoverageInfo) \
|
||||
V(DataHandler) \
|
||||
@ -31,7 +31,6 @@ namespace internal {
|
||||
V(FeedbackCell) \
|
||||
V(FeedbackMetadata) \
|
||||
V(FeedbackVector) \
|
||||
V(FixedArray) \
|
||||
V(FixedDoubleArray) \
|
||||
V(JSArrayBuffer) \
|
||||
V(JSDataView) \
|
||||
@ -48,17 +47,13 @@ namespace internal {
|
||||
V(PropertyArray) \
|
||||
V(PropertyCell) \
|
||||
V(PrototypeInfo) \
|
||||
V(SeqOneByteString) \
|
||||
V(SeqTwoByteString) \
|
||||
V(SharedFunctionInfo) \
|
||||
V(SlicedString) \
|
||||
V(SmallOrderedHashMap) \
|
||||
V(SmallOrderedHashSet) \
|
||||
V(SmallOrderedNameDictionary) \
|
||||
V(SourceTextModule) \
|
||||
V(Symbol) \
|
||||
V(SyntheticModule) \
|
||||
V(ThinString) \
|
||||
V(TransitionArray) \
|
||||
V(UncompiledDataWithoutPreparseData) \
|
||||
V(UncompiledDataWithPreparseData) \
|
||||
@ -113,7 +108,6 @@ class HeapVisitor : public ObjectVisitor {
|
||||
V8_INLINE ResultType VisitJSApiObject(Map map, JSObject object);
|
||||
V8_INLINE ResultType VisitStruct(Map map, HeapObject object);
|
||||
V8_INLINE ResultType VisitFreeSpace(Map map, FreeSpace object);
|
||||
V8_INLINE ResultType VisitWeakArray(Map map, HeapObject object);
|
||||
|
||||
template <typename T>
|
||||
static V8_INLINE T Cast(HeapObject object);
|
||||
|
@ -195,6 +195,19 @@ void FixedArray::CopyElements(Isolate* isolate, int dst_index, FixedArray src,
|
||||
isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
|
||||
}
|
||||
|
||||
// Due to left- and right-trimming, concurrent visitors need to read the length
|
||||
// with acquire semantics.
|
||||
// TODO(ulan): Acquire should not be needed anymore.
|
||||
inline int FixedArray::AllocatedSize() {
|
||||
return SizeFor(synchronized_length());
|
||||
}
|
||||
inline int WeakFixedArray::AllocatedSize() {
|
||||
return SizeFor(synchronized_length());
|
||||
}
|
||||
inline int WeakArrayList::AllocatedSize() {
|
||||
return SizeFor(synchronized_capacity());
|
||||
}
|
||||
|
||||
// Perform a binary search in a fixed array.
|
||||
template <SearchMode search_mode, typename T>
|
||||
int BinarySearch(T* array, Name name, int valid_entries,
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "src/handles/maybe-handles.h"
|
||||
#include "src/objects/instance-type.h"
|
||||
#include "src/objects/objects.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "torque-generated/class-definitions-tq.h"
|
||||
|
||||
@ -15,8 +16,6 @@
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
using WeakArrayBodyDescriptor =
|
||||
FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>;
|
||||
|
||||
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
|
||||
V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
|
||||
@ -182,7 +181,9 @@ class FixedArray
|
||||
// Dispatched behavior.
|
||||
DECL_PRINTER(FixedArray)
|
||||
|
||||
using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
|
||||
int AllocatedSize();
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
static constexpr int kObjectsOffset = kHeaderSize;
|
||||
|
||||
@ -280,16 +281,19 @@ class WeakFixedArray
|
||||
DECL_PRINTER(WeakFixedArray)
|
||||
DECL_VERIFIER(WeakFixedArray)
|
||||
|
||||
using BodyDescriptor = WeakArrayBodyDescriptor;
|
||||
class BodyDescriptor;
|
||||
|
||||
static const int kMaxLength =
|
||||
(FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
|
||||
static_assert(Internals::IsValidSmi(kMaxLength),
|
||||
"WeakFixedArray maxLength not a Smi");
|
||||
|
||||
int AllocatedSize();
|
||||
|
||||
protected:
|
||||
static int OffsetOfElementAt(int index) {
|
||||
return kHeaderSize + index * kTaggedSize;
|
||||
STATIC_ASSERT(kObjectsOffset == SizeFor(0));
|
||||
return SizeFor(index);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -360,8 +364,9 @@ class WeakArrayList
|
||||
// Get and set the capacity using acquire loads and release stores.
|
||||
DECL_SYNCHRONIZED_INT_ACCESSORS(capacity)
|
||||
|
||||
int AllocatedSize();
|
||||
|
||||
using BodyDescriptor = WeakArrayBodyDescriptor;
|
||||
class BodyDescriptor;
|
||||
|
||||
static const int kMaxCapacity =
|
||||
(FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
|
||||
|
@ -9,6 +9,7 @@ extern class FixedArrayBase extends HeapObject {
|
||||
const length: Smi;
|
||||
}
|
||||
|
||||
@generateBodyDescriptor
|
||||
@generateCppClass
|
||||
extern class FixedArray extends FixedArrayBase {
|
||||
objects[length]: Object;
|
||||
@ -21,6 +22,7 @@ extern class FixedDoubleArray extends FixedArrayBase {
|
||||
floats[length]: float64_or_hole;
|
||||
}
|
||||
|
||||
@generateBodyDescriptor
|
||||
@generateCppClass
|
||||
extern class WeakFixedArray extends HeapObject {
|
||||
const length: Smi;
|
||||
@ -41,6 +43,7 @@ extern class ArrayList extends FixedArray {
|
||||
extern class TemplateList extends FixedArray {
|
||||
}
|
||||
|
||||
@generateBodyDescriptor
|
||||
@generateCppClass
|
||||
extern class WeakArrayList extends HeapObject {
|
||||
const capacity: Smi;
|
||||
|
@ -142,7 +142,6 @@ VisitorId Map::GetVisitorId(Map map) {
|
||||
case EMBEDDER_DATA_ARRAY_TYPE:
|
||||
return kVisitEmbedderDataArray;
|
||||
|
||||
case FIXED_ARRAY_TYPE:
|
||||
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
|
||||
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
|
||||
case HASH_TABLE_TYPE:
|
||||
@ -175,10 +174,6 @@ VisitorId Map::GetVisitorId(Map map) {
|
||||
case EPHEMERON_HASH_TABLE_TYPE:
|
||||
return kVisitEphemeronHashTable;
|
||||
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
case WEAK_ARRAY_LIST_TYPE:
|
||||
return kVisitWeakArray;
|
||||
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
return kVisitFixedDoubleArray;
|
||||
|
||||
@ -373,7 +368,7 @@ VisitorId Map::GetVisitorId(Map map) {
|
||||
#define MAKE_TQ_CASE(TYPE, Name) \
|
||||
case TYPE: \
|
||||
return kVisit##Name;
|
||||
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TQ_CASE)
|
||||
TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(MAKE_TQ_CASE)
|
||||
#undef MAKE_TQ_CASE
|
||||
|
||||
default:
|
||||
|
@ -28,9 +28,7 @@ enum InstanceType : uint16_t;
|
||||
V(CoverageInfo) \
|
||||
V(DataObject) \
|
||||
V(FeedbackMetadata) \
|
||||
V(FixedDoubleArray) \
|
||||
V(SeqOneByteString) \
|
||||
V(SeqTwoByteString)
|
||||
V(FixedDoubleArray)
|
||||
|
||||
#define POINTER_VISITOR_ID_LIST(V) \
|
||||
V(AllocationSite) \
|
||||
@ -38,7 +36,6 @@ enum InstanceType : uint16_t;
|
||||
V(Cell) \
|
||||
V(Code) \
|
||||
V(CodeDataContainer) \
|
||||
V(ConsString) \
|
||||
V(Context) \
|
||||
V(DataHandler) \
|
||||
V(DescriptorArray) \
|
||||
@ -46,7 +43,6 @@ enum InstanceType : uint16_t;
|
||||
V(EphemeronHashTable) \
|
||||
V(FeedbackCell) \
|
||||
V(FeedbackVector) \
|
||||
V(FixedArray) \
|
||||
V(FreeSpace) \
|
||||
V(JSApiObject) \
|
||||
V(JSArrayBuffer) \
|
||||
@ -66,7 +62,6 @@ enum InstanceType : uint16_t;
|
||||
V(PrototypeInfo) \
|
||||
V(SharedFunctionInfo) \
|
||||
V(ShortcutCandidate) \
|
||||
V(SlicedString) \
|
||||
V(SmallOrderedHashMap) \
|
||||
V(SmallOrderedHashSet) \
|
||||
V(SmallOrderedNameDictionary) \
|
||||
@ -74,7 +69,6 @@ enum InstanceType : uint16_t;
|
||||
V(Struct) \
|
||||
V(Symbol) \
|
||||
V(SyntheticModule) \
|
||||
V(ThinString) \
|
||||
V(TransitionArray) \
|
||||
V(UncompiledDataWithoutPreparseData) \
|
||||
V(UncompiledDataWithPreparseData) \
|
||||
@ -82,15 +76,11 @@ enum InstanceType : uint16_t;
|
||||
V(WasmIndirectFunctionTable) \
|
||||
V(WasmInstanceObject) \
|
||||
V(WasmStruct) \
|
||||
V(WeakArray) \
|
||||
V(WeakCell)
|
||||
|
||||
#define TORQUE_OBJECT_BODY_TO_VISITOR_ID_LIST_ADAPTER(V, TYPE, TypeName) \
|
||||
V(TypeName)
|
||||
|
||||
#define TORQUE_VISITOR_ID_LIST(V) \
|
||||
TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR( \
|
||||
TORQUE_OBJECT_BODY_TO_VISITOR_ID_LIST_ADAPTER, V)
|
||||
#define TORQUE_VISITOR_ID_LIST(V) \
|
||||
TORQUE_DATA_ONLY_VISITOR_ID_LIST(V) \
|
||||
TORQUE_POINTER_VISITOR_ID_LIST(V)
|
||||
|
||||
// Objects with the same visitor id are processed in the same way by
|
||||
// the heap visitors. The visitor ids for data only objects must precede
|
||||
@ -98,9 +88,11 @@ enum InstanceType : uint16_t;
|
||||
// of whether an object contains only data or may contain pointers.
|
||||
enum VisitorId {
|
||||
#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)
|
||||
TORQUE_DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
|
||||
kDataOnlyVisitorIdCount,
|
||||
POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
|
||||
TORQUE_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
|
||||
TORQUE_POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
|
||||
#undef VISITOR_ID_ENUM_DECL
|
||||
kVisitorIdCount
|
||||
};
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "src/objects/transitions.h"
|
||||
#include "src/wasm/wasm-objects-inl.h"
|
||||
|
||||
#include "torque-generated/class-definitions-tq-inl.h"
|
||||
#include "torque-generated/internal-class-definitions-tq-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
@ -681,34 +684,6 @@ class Code::BodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
class SeqOneByteString::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
||||
ObjectVisitor* v) {}
|
||||
|
||||
static inline int SizeOf(Map map, HeapObject obj) {
|
||||
SeqOneByteString string = SeqOneByteString::cast(obj);
|
||||
return SeqOneByteString::SizeFor(string.synchronized_length());
|
||||
}
|
||||
};
|
||||
|
||||
class SeqTwoByteString::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
||||
ObjectVisitor* v) {}
|
||||
|
||||
static inline int SizeOf(Map map, HeapObject obj) {
|
||||
SeqTwoByteString string = SeqTwoByteString::cast(obj);
|
||||
return SeqTwoByteString::SizeFor(string.synchronized_length());
|
||||
}
|
||||
};
|
||||
|
||||
class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
||||
@ -923,7 +898,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
|
||||
case EMBEDDER_DATA_ARRAY_TYPE:
|
||||
return Op::template apply<EmbedderDataArray::BodyDescriptor>(p1, p2, p3,
|
||||
p4);
|
||||
case FIXED_ARRAY_TYPE:
|
||||
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
|
||||
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
|
||||
case HASH_TABLE_TYPE:
|
||||
@ -953,10 +927,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
|
||||
return Op::template apply<Context::BodyDescriptor>(p1, p2, p3, p4);
|
||||
case NATIVE_CONTEXT_TYPE:
|
||||
return Op::template apply<NativeContext::BodyDescriptor>(p1, p2, p3, p4);
|
||||
case WEAK_FIXED_ARRAY_TYPE:
|
||||
return Op::template apply<WeakFixedArray::BodyDescriptor>(p1, p2, p3, p4);
|
||||
case WEAK_ARRAY_LIST_TYPE:
|
||||
return Op::template apply<WeakArrayList::BodyDescriptor>(p1, p2, p3, p4);
|
||||
case FIXED_DOUBLE_ARRAY_TYPE:
|
||||
return ReturnType();
|
||||
case FEEDBACK_METADATA_TYPE:
|
||||
@ -1129,10 +1099,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
|
||||
case SYNTHETIC_MODULE_TYPE:
|
||||
return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3,
|
||||
p4);
|
||||
// TODO(tebbi): Avoid duplicated cases when the body descriptors are identical.
|
||||
#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)
|
||||
TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(
|
||||
MAKE_TORQUE_BODY_DESCRIPTOR_APPLY)
|
||||
#undef MAKE_TORQUE_BODY_DESCRIPTOR_APPLY
|
||||
|
||||
default:
|
||||
@ -1193,6 +1165,8 @@ class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
#include "torque-generated/objects-body-descriptors-tq-inl.inc"
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -74,15 +74,14 @@ class BodyDescriptorBase {
|
||||
ObjectVisitor* v);
|
||||
};
|
||||
|
||||
// This class describes a body of an object of a fixed size
|
||||
// in which all pointer fields are located in the [start_offset, end_offset)
|
||||
// interval.
|
||||
template <int start_offset, int end_offset, int size>
|
||||
class FixedBodyDescriptor final : public BodyDescriptorBase {
|
||||
// This class describes a body of an object in which all pointer fields are
|
||||
// located in the [start_offset, end_offset) interval.
|
||||
// All pointers have to be strong.
|
||||
template <int start_offset, int end_offset>
|
||||
class FixedRangeBodyDescriptor : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
static const int kEndOffset = end_offset;
|
||||
static const int kSize = size;
|
||||
|
||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
|
||||
return offset >= kStartOffset && offset < kEndOffset;
|
||||
@ -99,14 +98,30 @@ class FixedBodyDescriptor final : public BodyDescriptorBase {
|
||||
IterateBody(map, obj, v);
|
||||
}
|
||||
|
||||
private:
|
||||
static inline int SizeOf(Map map, HeapObject object) {
|
||||
// Has to be implemented by the subclass.
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
|
||||
// This class describes a body of an object of a fixed size
|
||||
// in which all pointer fields are located in the [start_offset, end_offset)
|
||||
// interval.
|
||||
// All pointers have to be strong.
|
||||
template <int start_offset, int end_offset, int size>
|
||||
class FixedBodyDescriptor
|
||||
: public FixedRangeBodyDescriptor<start_offset, end_offset> {
|
||||
public:
|
||||
static const int kSize = size;
|
||||
static inline int SizeOf(Map map, HeapObject object) { return kSize; }
|
||||
};
|
||||
|
||||
// This class describes a body of an object of a variable size
|
||||
// in which all pointer fields are located in the [start_offset, object_size)
|
||||
// interval.
|
||||
// This class describes a body of an object in which all pointer fields are
|
||||
// located in the [start_offset, object_size) interval.
|
||||
// All pointers have to be strong.
|
||||
template <int start_offset>
|
||||
class FlexibleBodyDescriptor final : public BodyDescriptorBase {
|
||||
class SuffixRangeBodyDescriptor : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
|
||||
@ -120,13 +135,30 @@ class FlexibleBodyDescriptor final : public BodyDescriptorBase {
|
||||
IteratePointers(obj, start_offset, object_size, v);
|
||||
}
|
||||
|
||||
private:
|
||||
static inline int SizeOf(Map map, HeapObject object) {
|
||||
// Has to be implemented by the subclass.
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
|
||||
// This class describes a body of an object of a variable size
|
||||
// in which all pointer fields are located in the [start_offset, object_size)
|
||||
// interval.
|
||||
// All pointers have to be strong.
|
||||
template <int start_offset>
|
||||
class FlexibleBodyDescriptor : public SuffixRangeBodyDescriptor<start_offset> {
|
||||
public:
|
||||
static inline int SizeOf(Map map, HeapObject object);
|
||||
};
|
||||
|
||||
using StructBodyDescriptor = FlexibleBodyDescriptor<HeapObject::kHeaderSize>;
|
||||
|
||||
// This class describes a body of an object in which all pointer fields are
|
||||
// located in the [start_offset, object_size) interval.
|
||||
// Pointers may be strong or may be MaybeObject-style weak pointers.
|
||||
template <int start_offset>
|
||||
class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase {
|
||||
class SuffixRangeWeakBodyDescriptor : public BodyDescriptorBase {
|
||||
public:
|
||||
static const int kStartOffset = start_offset;
|
||||
|
||||
@ -140,9 +172,40 @@ class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase {
|
||||
IterateMaybeWeakPointers(obj, start_offset, object_size, v);
|
||||
}
|
||||
|
||||
private:
|
||||
static inline int SizeOf(Map map, HeapObject object) {
|
||||
// Has to be implemented by the subclass.
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
|
||||
// This class describes a body of an object of a variable size
|
||||
// in which all pointer fields are located in the [start_offset, object_size)
|
||||
// interval.
|
||||
// Pointers may be strong or may be MaybeObject-style weak pointers.
|
||||
template <int start_offset>
|
||||
class FlexibleWeakBodyDescriptor
|
||||
: public SuffixRangeWeakBodyDescriptor<start_offset> {
|
||||
public:
|
||||
static inline int SizeOf(Map map, HeapObject object);
|
||||
};
|
||||
|
||||
// This class describes a body of an object without any pointers.
|
||||
class DataOnlyBodyDescriptor : public BodyDescriptorBase {
|
||||
public:
|
||||
static bool IsValidSlot(Map map, HeapObject obj, int offset) { return false; }
|
||||
|
||||
template <typename ObjectVisitor>
|
||||
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
||||
ObjectVisitor* v) {}
|
||||
|
||||
private:
|
||||
static inline int SizeOf(Map map, HeapObject object) {
|
||||
// Has to be implemented by the subclass.
|
||||
UNREACHABLE();
|
||||
}
|
||||
};
|
||||
|
||||
// This class describes a body of an object which has a parent class that also
|
||||
// has a body descriptor. This represents a union of the parent's body
|
||||
// descriptor, and a new descriptor for the child -- so, both parent and child's
|
||||
@ -180,10 +243,6 @@ class SubclassBodyDescriptor final : public BodyDescriptorBase {
|
||||
}
|
||||
};
|
||||
|
||||
#define TORQUE_BODY_DESCRIPTOR_LIST_ADAPTER(V, TYPE, TypeName) V(TYPE, TypeName)
|
||||
#define TORQUE_BODY_DESCRIPTOR_LIST(V) \
|
||||
TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR(TORQUE_BODY_DESCRIPTOR_LIST_ADAPTER, V)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -126,7 +126,6 @@
|
||||
|
||||
#include "torque-generated/class-definitions-tq-inl.h"
|
||||
#include "torque-generated/internal-class-definitions-tq-inl.h"
|
||||
#include "torque-generated/objects-body-descriptors-tq-inl.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -2278,12 +2277,11 @@ int HeapObject::SizeFromMap(Map map) const {
|
||||
PreparseData data = PreparseData::unchecked_cast(*this);
|
||||
return PreparseData::SizeFor(data.data_length(), data.children_length());
|
||||
}
|
||||
#define MAKE_TORQUE_SIZE_FOR(TYPE, TypeName) \
|
||||
if (instance_type == TYPE) { \
|
||||
TypeName instance = TypeName::unchecked_cast(*this); \
|
||||
return TypeName::SizeFor(instance); \
|
||||
#define MAKE_TORQUE_SIZE_FOR(TYPE, TypeName) \
|
||||
if (instance_type == TYPE) { \
|
||||
return TypeName::unchecked_cast(*this).AllocatedSize(); \
|
||||
}
|
||||
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_SIZE_FOR)
|
||||
TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_SIZE_FOR)
|
||||
#undef MAKE_TORQUE_SIZE_FOR
|
||||
|
||||
if (instance_type == CODE_TYPE) {
|
||||
|
@ -569,12 +569,13 @@ void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
|
||||
WriteField<uint16_t>(kHeaderSize + index * kShortSize, value);
|
||||
}
|
||||
|
||||
int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) {
|
||||
return SizeFor(length());
|
||||
// Due to ThinString rewriting, concurrent visitors need to read the length with
|
||||
// acquire semantics.
|
||||
inline int SeqOneByteString::AllocatedSize() {
|
||||
return SizeFor(synchronized_length());
|
||||
}
|
||||
|
||||
int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) {
|
||||
return SizeFor(length());
|
||||
inline int SeqTwoByteString::AllocatedSize() {
|
||||
return SizeFor(synchronized_length());
|
||||
}
|
||||
|
||||
void SlicedString::set_parent(String parent, WriteBarrierMode mode) {
|
||||
|
@ -558,16 +558,13 @@ class SeqOneByteString
|
||||
// instance.
|
||||
inline int SeqOneByteStringSize(InstanceType instance_type);
|
||||
|
||||
// Computes the size for an OneByteString instance of a given length.
|
||||
static int SizeFor(int length) {
|
||||
return OBJECT_POINTER_ALIGN(kHeaderSize + length * kCharSize);
|
||||
}
|
||||
|
||||
// Maximal memory usage for a single sequential one-byte string.
|
||||
static const int kMaxCharsSize = kMaxLength;
|
||||
static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxCharsSize + kHeaderSize);
|
||||
STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength);
|
||||
|
||||
int AllocatedSize();
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
TQ_OBJECT_CONSTRUCTORS(SeqOneByteString)
|
||||
@ -599,17 +596,14 @@ class SeqTwoByteString
|
||||
// instance.
|
||||
inline int SeqTwoByteStringSize(InstanceType instance_type);
|
||||
|
||||
// Computes the size for a TwoByteString instance of a given length.
|
||||
static int SizeFor(int length) {
|
||||
return OBJECT_POINTER_ALIGN(kHeaderSize + length * kShortSize);
|
||||
}
|
||||
|
||||
// Maximal memory usage for a single sequential two-byte string.
|
||||
static const int kMaxCharsSize = kMaxLength * 2;
|
||||
static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxCharsSize + kHeaderSize);
|
||||
STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize) / sizeof(uint16_t)) >=
|
||||
String::kMaxLength);
|
||||
|
||||
int AllocatedSize();
|
||||
|
||||
class BodyDescriptor;
|
||||
|
||||
TQ_OBJECT_CONSTRUCTORS(SeqTwoByteString)
|
||||
@ -639,7 +633,7 @@ class ConsString : public TorqueGeneratedConsString<ConsString, String> {
|
||||
// Minimum length for a cons string.
|
||||
static const int kMinLength = 13;
|
||||
|
||||
using BodyDescriptor = FixedBodyDescriptor<kFirstOffset, kSize, kSize>;
|
||||
class BodyDescriptor;
|
||||
|
||||
DECL_VERIFIER(ConsString)
|
||||
|
||||
@ -661,7 +655,7 @@ class ThinString : public TorqueGeneratedThinString<ThinString, String> {
|
||||
|
||||
DECL_VERIFIER(ThinString)
|
||||
|
||||
using BodyDescriptor = FixedBodyDescriptor<kActualOffset, kSize, kSize>;
|
||||
class BodyDescriptor;
|
||||
|
||||
TQ_OBJECT_CONSTRUCTORS(ThinString)
|
||||
};
|
||||
@ -688,7 +682,7 @@ class SlicedString : public TorqueGeneratedSlicedString<SlicedString, String> {
|
||||
// Minimum length for a sliced string.
|
||||
static const int kMinLength = 13;
|
||||
|
||||
using BodyDescriptor = FixedBodyDescriptor<kParentOffset, kSize, kSize>;
|
||||
class BodyDescriptor;
|
||||
|
||||
DECL_VERIFIER(SlicedString)
|
||||
|
||||
|
@ -10,12 +10,14 @@ extern class String extends Name {
|
||||
}
|
||||
|
||||
@generateCppClass
|
||||
@generateBodyDescriptor
|
||||
extern class ConsString extends String {
|
||||
first: String;
|
||||
second: String;
|
||||
}
|
||||
|
||||
@abstract
|
||||
@generateBodyDescriptor
|
||||
extern class ExternalString extends String {
|
||||
resource: RawPtr;
|
||||
resource_data: RawPtr;
|
||||
@ -28,27 +30,30 @@ extern class ExternalTwoByteString extends ExternalString {}
|
||||
extern class InternalizedString extends String {
|
||||
}
|
||||
|
||||
// TODO(v8:8983): Add declaration for variable-sized region.
|
||||
@abstract
|
||||
@generateCppClass
|
||||
extern class SeqString extends String {
|
||||
}
|
||||
@generateCppClass
|
||||
@generateBodyDescriptor
|
||||
extern class SeqOneByteString extends SeqString {
|
||||
chars[length]: char8;
|
||||
}
|
||||
@generateCppClass
|
||||
@generateBodyDescriptor
|
||||
extern class SeqTwoByteString extends SeqString {
|
||||
chars[length]: char16;
|
||||
}
|
||||
|
||||
@generateCppClass
|
||||
@generateBodyDescriptor
|
||||
extern class SlicedString extends String {
|
||||
parent: String;
|
||||
offset: Smi;
|
||||
}
|
||||
|
||||
@generateCppClass
|
||||
@generateBodyDescriptor
|
||||
extern class ThinString extends String {
|
||||
actual: String;
|
||||
}
|
||||
|
@ -127,7 +127,6 @@ enum class ClassFlag {
|
||||
kIsShape = 1 << 5,
|
||||
kHasSameInstanceTypeAsParent = 1 << 6,
|
||||
kGenerateCppClassDefinitions = 1 << 7,
|
||||
kHasIndexedField = 1 << 8,
|
||||
kHighestInstanceTypeWithinParent = 1 << 9,
|
||||
kLowestInstanceTypeWithinParent = 1 << 10,
|
||||
kUndefinedLayout = 1 << 11,
|
||||
|
@ -67,6 +67,14 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
return Get().generated_per_file_[file];
|
||||
}
|
||||
|
||||
static void SetInstanceTypesInitialized() {
|
||||
DCHECK(!Get().instance_types_initialized_);
|
||||
Get().instance_types_initialized_ = true;
|
||||
}
|
||||
static bool IsInstanceTypesInitialized() {
|
||||
return Get().instance_types_initialized_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool collect_language_server_data_;
|
||||
bool force_assert_statements_;
|
||||
@ -76,6 +84,7 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
std::set<std::string> cpp_includes_;
|
||||
std::map<SourceId, PerFileStreams> generated_per_file_;
|
||||
std::map<std::string, size_t> fresh_ids_;
|
||||
bool instance_types_initialized_ = false;
|
||||
|
||||
friend class LanguageServerData;
|
||||
};
|
||||
|
@ -3268,12 +3268,28 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
|
||||
}
|
||||
}
|
||||
|
||||
header << "#define TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR(V, _)\\\n";
|
||||
header << "#define TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(V)\\\n";
|
||||
for (const ClassType* type : TypeOracle::GetClasses()) {
|
||||
if (type->ShouldGenerateBodyDescriptor()) {
|
||||
if (type->ShouldGenerateBodyDescriptor() && type->OwnInstanceType()) {
|
||||
std::string type_name =
|
||||
CapifyStringWithUnderscores(type->name()) + "_TYPE";
|
||||
header << "V(_, " << type_name << ", " << type->name() << ")\\\n";
|
||||
header << "V(" << type_name << "," << type->name() << ")\\\n";
|
||||
}
|
||||
}
|
||||
header << "\n";
|
||||
|
||||
header << "#define TORQUE_DATA_ONLY_VISITOR_ID_LIST(V)\\\n";
|
||||
for (const ClassType* type : TypeOracle::GetClasses()) {
|
||||
if (type->ShouldGenerateBodyDescriptor() && type->HasNoPointerSlots()) {
|
||||
header << "V(" << type->name() << ")\\\n";
|
||||
}
|
||||
}
|
||||
header << "\n";
|
||||
|
||||
header << "#define TORQUE_POINTER_VISITOR_ID_LIST(V)\\\n";
|
||||
for (const ClassType* type : TypeOracle::GetClasses()) {
|
||||
if (type->ShouldGenerateBodyDescriptor() && !type->HasNoPointerSlots()) {
|
||||
header << "V(" << type->name() << ")\\\n";
|
||||
}
|
||||
}
|
||||
header << "\n";
|
||||
@ -3494,26 +3510,18 @@ void CppClassGenerator::GenerateClass() {
|
||||
hdr_ << " size += " << index_name_and_type.name << " * "
|
||||
<< field_size << ";\n";
|
||||
}
|
||||
if (type_->size().Alignment() < TargetArchitecture::TaggedSize()) {
|
||||
hdr_ << " size = OBJECT_POINTER_ALIGN(size);\n";
|
||||
}
|
||||
}
|
||||
hdr_ << " return size;\n";
|
||||
hdr_ << " }\n\n";
|
||||
hdr_ << " V8_INLINE static constexpr int32_t SizeFor(D o) {\n";
|
||||
hdr_ << " V8_INLINE int32_t AllocatedSize() {\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_ << "o.synchronized_length()";
|
||||
} else {
|
||||
hdr_ << "o." << field.name_and_type.name << "()";
|
||||
}
|
||||
hdr_ << "this->" << field.name_and_type.name << "()";
|
||||
first = false;
|
||||
}
|
||||
hdr_ << ");\n }\n";
|
||||
@ -3854,8 +3862,6 @@ void EmitClassDefinitionHeadersIncludes(const std::string& basename,
|
||||
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";
|
||||
@ -4168,140 +4174,174 @@ void ImplementationVisitor::GeneratePrintDefinitions(
|
||||
WriteFile(output_directory + "/" + file_name, new_contents);
|
||||
}
|
||||
|
||||
base::Optional<std::string> MatchSimpleBodyDescriptor(const ClassType* type) {
|
||||
std::vector<ObjectSlotKind> slots = type->ComputeHeaderSlotKinds();
|
||||
if (!type->HasStaticSize()) {
|
||||
slots.push_back(*type->ComputeArraySlotKind());
|
||||
}
|
||||
|
||||
// Skip the map slot.
|
||||
size_t i = 1;
|
||||
while (i < slots.size() && slots[i] == ObjectSlotKind::kNoPointer) ++i;
|
||||
if (i == slots.size()) return "DataOnlyBodyDescriptor";
|
||||
bool has_weak_pointers = false;
|
||||
size_t start_index = i;
|
||||
for (; i < slots.size(); ++i) {
|
||||
if (slots[i] == ObjectSlotKind::kStrongPointer) {
|
||||
continue;
|
||||
} else if (slots[i] == ObjectSlotKind::kMaybeObjectPointer) {
|
||||
has_weak_pointers = true;
|
||||
} else if (slots[i] == ObjectSlotKind::kNoPointer) {
|
||||
break;
|
||||
} else {
|
||||
return base::nullopt;
|
||||
}
|
||||
}
|
||||
size_t end_index = i;
|
||||
for (; i < slots.size(); ++i) {
|
||||
if (slots[i] != ObjectSlotKind::kNoPointer) return base::nullopt;
|
||||
}
|
||||
size_t start_offset = start_index * TargetArchitecture::TaggedSize();
|
||||
size_t end_offset = end_index * TargetArchitecture::TaggedSize();
|
||||
// We pick a suffix-range body descriptor even in cases where the object size
|
||||
// is fixed, to reduce the amount of code executed for object visitation.
|
||||
if (end_index == slots.size()) {
|
||||
return ToString("SuffixRange", has_weak_pointers ? "Weak" : "",
|
||||
"BodyDescriptor<", start_offset, ">");
|
||||
}
|
||||
if (!has_weak_pointers) {
|
||||
return ToString("FixedRangeDescriptor<", start_offset, ", ", end_offset,
|
||||
", ", *type->size().SingleValue(), ">");
|
||||
}
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
void ImplementationVisitor::GenerateBodyDescriptors(
|
||||
const std::string& output_directory) {
|
||||
std::string file_name = "objects-body-descriptors-tq-inl";
|
||||
std::string file_name = "objects-body-descriptors-tq-inl.inc";
|
||||
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";
|
||||
bool has_array_fields = !type->HasStaticSize();
|
||||
std::vector<ObjectSlotKind> header_slot_kinds =
|
||||
type->ComputeHeaderSlotKinds();
|
||||
base::Optional<ObjectSlotKind> array_slot_kind =
|
||||
type->ComputeArraySlotKind();
|
||||
DCHECK_EQ(has_array_fields, array_slot_kind.has_value());
|
||||
|
||||
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";
|
||||
h_contents << "class " << name << "::BodyDescriptor final : public ";
|
||||
if (auto descriptor_name = MatchSimpleBodyDescriptor(type)) {
|
||||
h_contents << *descriptor_name << " {\n";
|
||||
h_contents << " public:\n";
|
||||
} else {
|
||||
h_contents << " if (" << super_name
|
||||
<< "::BodyDescriptor::IsValidSlot(map, obj, offset)) return "
|
||||
"true;\n";
|
||||
}
|
||||
h_contents << "BodyDescriptorBase {\n";
|
||||
h_contents << " public:\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.");
|
||||
}
|
||||
h_contents << " static bool IsValidSlot(Map map, HeapObject obj, int "
|
||||
"offset) {\n";
|
||||
if (has_array_fields) {
|
||||
h_contents << " if (offset < kHeaderSize) {\n";
|
||||
}
|
||||
}
|
||||
h_contents << " bool valid_slots[] = {";
|
||||
for (ObjectSlotKind slot : header_slot_kinds) {
|
||||
h_contents << (slot != ObjectSlotKind::kNoPointer ? "1" : "0") << ",";
|
||||
}
|
||||
h_contents << "};\n"
|
||||
<< " return valid_slots[static_cast<unsigned "
|
||||
"int>(offset)/kTaggedSize];\n";
|
||||
if (has_array_fields) {
|
||||
h_contents << " }\n";
|
||||
bool array_is_tagged = *array_slot_kind != ObjectSlotKind::kNoPointer;
|
||||
h_contents << " return " << (array_is_tagged ? "true" : "false")
|
||||
<< ";\n";
|
||||
}
|
||||
h_contents << " }\n\n";
|
||||
|
||||
if (super_class != TypeOracle::GetHeapObjectType() &&
|
||||
super_class != TypeOracle::GetFixedArrayBaseType()) {
|
||||
h_contents << " template <typename ObjectVisitor>\n";
|
||||
h_contents
|
||||
<< " " << super_name
|
||||
<< "::BodyDescriptor::IterateBody(map, obj, object_size, v);\n";
|
||||
}
|
||||
<< " static inline void IterateBody(Map map, HeapObject obj, "
|
||||
"int object_size, ObjectVisitor* v) {\n";
|
||||
|
||||
h_contents << " if (" << name
|
||||
<< "::kStartOfStrongFieldsOffset != " << name
|
||||
<< "::kEndOfStrongFieldsOffset) {\n";
|
||||
h_contents << " IteratePointers(obj, " << name
|
||||
<< "::kStartOfStrongFieldsOffset, " << name
|
||||
<< "::kEndOfStrongFieldsOffset, v);\n";
|
||||
h_contents << " }\n";
|
||||
std::vector<ObjectSlotKind> slots = std::move(header_slot_kinds);
|
||||
if (has_array_fields) slots.push_back(*array_slot_kind);
|
||||
|
||||
h_contents << " if (" << name
|
||||
<< "::kStartOfWeakFieldsOffset != " << name
|
||||
<< "::kEndOfWeakFieldsOffset) {\n";
|
||||
h_contents << " IterateCustomWeakPointers(obj, " << name
|
||||
<< "::kStartOfWeakFieldsOffset, " << name
|
||||
<< "::kEndOfWeakFieldsOffset, v);\n";
|
||||
h_contents << " }\n";
|
||||
// Skip the map slot.
|
||||
slots.erase(slots.begin());
|
||||
size_t start_offset = TargetArchitecture::TaggedSize();
|
||||
|
||||
// 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)");
|
||||
size_t end_offset = start_offset;
|
||||
ObjectSlotKind section_kind;
|
||||
for (size_t i = 0; i <= slots.size(); ++i) {
|
||||
base::Optional<ObjectSlotKind> next_section_kind;
|
||||
bool finished_section = false;
|
||||
if (i == 0) {
|
||||
next_section_kind = slots[i];
|
||||
} else if (i < slots.size()) {
|
||||
if (auto combined = Combine(section_kind, slots[i])) {
|
||||
next_section_kind = *combined;
|
||||
} else {
|
||||
next_section_kind = slots[i];
|
||||
finished_section = true;
|
||||
}
|
||||
} else {
|
||||
finished_section = true;
|
||||
}
|
||||
if (finished_section) {
|
||||
bool is_array_slot = i == slots.size() && has_array_fields;
|
||||
bool multiple_slots =
|
||||
is_array_slot ||
|
||||
(end_offset - start_offset > TargetArchitecture::TaggedSize());
|
||||
base::Optional<std::string> iterate_command;
|
||||
switch (section_kind) {
|
||||
case ObjectSlotKind::kStrongPointer:
|
||||
iterate_command = "IteratePointer";
|
||||
break;
|
||||
case ObjectSlotKind::kMaybeObjectPointer:
|
||||
iterate_command = "IterateMaybeWeakPointer";
|
||||
break;
|
||||
case ObjectSlotKind::kCustomWeakPointer:
|
||||
iterate_command = "IterateCustomWeakPointer";
|
||||
break;
|
||||
case ObjectSlotKind::kNoPointer:
|
||||
break;
|
||||
}
|
||||
if (iterate_command) {
|
||||
if (multiple_slots) *iterate_command += "s";
|
||||
h_contents << " " << *iterate_command << "(obj, "
|
||||
<< start_offset;
|
||||
if (multiple_slots) {
|
||||
h_contents << ", "
|
||||
<< (i == slots.size() ? "object_size"
|
||||
: std::to_string(end_offset));
|
||||
}
|
||||
h_contents << ", v);\n";
|
||||
}
|
||||
start_offset = end_offset;
|
||||
}
|
||||
if (i < slots.size()) section_kind = *next_section_kind;
|
||||
end_offset += TargetArchitecture::TaggedSize();
|
||||
}
|
||||
}
|
||||
|
||||
h_contents << " }\n\n";
|
||||
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";
|
||||
if (type->size().SingleValue()) {
|
||||
h_contents << " return " << *type->size().SingleValue() << ";\n";
|
||||
} else {
|
||||
h_contents << " return " << name
|
||||
<< "::cast(raw_object).AllocatedSize();\n";
|
||||
}
|
||||
h_contents << " }\n\n";
|
||||
|
||||
h_contents << "};\n";
|
||||
}
|
||||
}
|
||||
|
||||
WriteFile(output_directory + "/" + file_name + ".h", h_contents.str());
|
||||
WriteFile(output_directory + "/" + file_name, h_contents.str());
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -4330,9 +4370,8 @@ void GenerateFieldValueVerifier(const std::string& class_name,
|
||||
|
||||
// Read the field.
|
||||
cc_contents << " " << object_type << " " << value << " = TaggedField<"
|
||||
<< object_type << ", " << class_name << "::k"
|
||||
<< CamelifyString(class_field.name_and_type.name)
|
||||
<< "Offset>::load(o, " << index_offset << ");\n";
|
||||
<< object_type << ", " << *class_field.offset << ">::load(o, "
|
||||
<< index_offset << ");\n";
|
||||
|
||||
// Call VerifyPointer or VerifyMaybeObjectPointer on it.
|
||||
cc_contents << " " << object_type << "::" << verify_fn << "(isolate, "
|
||||
|
@ -256,6 +256,9 @@ int SolveInstanceTypeConstraints(
|
||||
root->start = root->value;
|
||||
}
|
||||
root->num_values = root->end - root->start + 1;
|
||||
root->type->InitializeInstanceTypes(
|
||||
root->value == -1 ? base::Optional<int>{} : root->value,
|
||||
std::make_pair(root->start, root->end));
|
||||
|
||||
if (root->num_values > 0) {
|
||||
destination->push_back(std::move(root));
|
||||
@ -485,6 +488,8 @@ void ImplementationVisitor::GenerateInstanceTypes(
|
||||
}
|
||||
std::string output_header_path = output_directory + "/" + file_name;
|
||||
WriteFile(output_header_path, header.str());
|
||||
|
||||
GlobalContext::SetInstanceTypesInitialized();
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
|
@ -73,6 +73,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
|
||||
ImplementationVisitor implementation_visitor;
|
||||
implementation_visitor.SetDryRun(output_directory.length() == 0);
|
||||
|
||||
implementation_visitor.GenerateInstanceTypes(output_directory);
|
||||
implementation_visitor.BeginCSAFiles();
|
||||
|
||||
implementation_visitor.VisitAllDeclarables();
|
||||
@ -91,7 +92,6 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
|
||||
implementation_visitor.GenerateBodyDescriptors(output_directory);
|
||||
implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
|
||||
implementation_visitor.GenerateCSATypes(output_directory);
|
||||
implementation_visitor.GenerateInstanceTypes(output_directory);
|
||||
|
||||
implementation_visitor.EndCSAFiles();
|
||||
implementation_visitor.GenerateImplementation(output_directory);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "src/base/optional.h"
|
||||
#include "src/torque/types.h"
|
||||
|
||||
#include "src/base/bits.h"
|
||||
@ -528,6 +529,121 @@ std::vector<Field> ClassType::ComputeAllFields() const {
|
||||
return all_fields;
|
||||
}
|
||||
|
||||
std::vector<Field> ClassType::ComputeHeaderFields() const {
|
||||
std::vector<Field> result;
|
||||
for (Field& field : ComputeAllFields()) {
|
||||
if (field.index) break;
|
||||
DCHECK(*field.offset < header_size());
|
||||
result.push_back(std::move(field));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Field> ClassType::ComputeArrayFields() const {
|
||||
std::vector<Field> result;
|
||||
for (Field& field : ComputeAllFields()) {
|
||||
if (!field.index) {
|
||||
DCHECK(*field.offset < header_size());
|
||||
continue;
|
||||
}
|
||||
result.push_back(std::move(field));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ClassType::InitializeInstanceTypes(
|
||||
base::Optional<int> own, base::Optional<std::pair<int, int>> range) const {
|
||||
DCHECK(!own_instance_type_.has_value());
|
||||
DCHECK(!instance_type_range_.has_value());
|
||||
own_instance_type_ = own;
|
||||
instance_type_range_ = range;
|
||||
}
|
||||
|
||||
base::Optional<int> ClassType::OwnInstanceType() const {
|
||||
DCHECK(GlobalContext::IsInstanceTypesInitialized());
|
||||
return own_instance_type_;
|
||||
}
|
||||
|
||||
base::Optional<std::pair<int, int>> ClassType::InstanceTypeRange() const {
|
||||
DCHECK(GlobalContext::IsInstanceTypesInitialized());
|
||||
return instance_type_range_;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void ComputeSlotKindsHelper(std::vector<ObjectSlotKind>* slots,
|
||||
size_t start_offset,
|
||||
const std::vector<Field>& fields) {
|
||||
size_t offset = start_offset;
|
||||
for (const Field& field : fields) {
|
||||
size_t field_size = std::get<0>(field.GetFieldSizeInformation());
|
||||
size_t slot_index = offset / TargetArchitecture::TaggedSize();
|
||||
// Rounding-up division to find the number of slots occupied by all the
|
||||
// fields up to and including the current one.
|
||||
size_t used_slots =
|
||||
(offset + field_size + TargetArchitecture::TaggedSize() - 1) /
|
||||
TargetArchitecture::TaggedSize();
|
||||
while (used_slots > slots->size()) {
|
||||
slots->push_back(ObjectSlotKind::kNoPointer);
|
||||
}
|
||||
const Type* type = field.name_and_type.type;
|
||||
if (auto struct_type = type->StructSupertype()) {
|
||||
ComputeSlotKindsHelper(slots, offset, (*struct_type)->fields());
|
||||
} else {
|
||||
ObjectSlotKind kind;
|
||||
if (type->IsSubtypeOf(TypeOracle::GetObjectType())) {
|
||||
if (field.is_weak) {
|
||||
kind = ObjectSlotKind::kCustomWeakPointer;
|
||||
} else {
|
||||
kind = ObjectSlotKind::kStrongPointer;
|
||||
}
|
||||
} else if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
|
||||
DCHECK(!field.is_weak);
|
||||
kind = ObjectSlotKind::kMaybeObjectPointer;
|
||||
} else {
|
||||
kind = ObjectSlotKind::kNoPointer;
|
||||
}
|
||||
DCHECK(slots->at(slot_index) == ObjectSlotKind::kNoPointer);
|
||||
slots->at(slot_index) = kind;
|
||||
}
|
||||
|
||||
offset += field_size;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::vector<ObjectSlotKind> ClassType::ComputeHeaderSlotKinds() const {
|
||||
std::vector<ObjectSlotKind> result;
|
||||
std::vector<Field> header_fields = ComputeHeaderFields();
|
||||
ComputeSlotKindsHelper(&result, 0, header_fields);
|
||||
DCHECK_EQ(std::ceil(double{header_size()} / TargetArchitecture::TaggedSize()),
|
||||
result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
base::Optional<ObjectSlotKind> ClassType::ComputeArraySlotKind() const {
|
||||
std::vector<ObjectSlotKind> kinds;
|
||||
ComputeSlotKindsHelper(&kinds, 0, ComputeArrayFields());
|
||||
if (kinds.empty()) return base::nullopt;
|
||||
std::sort(kinds.begin(), kinds.end());
|
||||
if (kinds.front() == kinds.back()) return {kinds.front()};
|
||||
if (kinds.front() == ObjectSlotKind::kStrongPointer &&
|
||||
kinds.back() == ObjectSlotKind::kMaybeObjectPointer) {
|
||||
return ObjectSlotKind::kMaybeObjectPointer;
|
||||
}
|
||||
Error("Array fields mix types with different GC visitation requirements.")
|
||||
.Throw();
|
||||
}
|
||||
|
||||
bool ClassType::HasNoPointerSlots() const {
|
||||
for (ObjectSlotKind slot : ComputeHeaderSlotKinds()) {
|
||||
if (slot != ObjectSlotKind::kNoPointer) return false;
|
||||
}
|
||||
if (auto slot = ComputeArraySlotKind()) {
|
||||
if (*slot != ObjectSlotKind::kNoPointer) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClassType::GenerateAccessors() {
|
||||
// For each field, construct AST snippets that implement a CSA accessor
|
||||
// function. The implementation iterator will turn the snippets into code.
|
||||
|
@ -611,6 +611,23 @@ class StructType final : public AggregateType {
|
||||
|
||||
class TypeAlias;
|
||||
|
||||
enum class ObjectSlotKind : uint8_t {
|
||||
kNoPointer,
|
||||
kStrongPointer,
|
||||
kMaybeObjectPointer,
|
||||
kCustomWeakPointer
|
||||
};
|
||||
|
||||
inline base::Optional<ObjectSlotKind> Combine(ObjectSlotKind a,
|
||||
ObjectSlotKind b) {
|
||||
if (a == b) return {a};
|
||||
if (std::min(a, b) == ObjectSlotKind::kStrongPointer &&
|
||||
std::max(a, b) == ObjectSlotKind::kMaybeObjectPointer) {
|
||||
return {ObjectSlotKind::kMaybeObjectPointer};
|
||||
}
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
class ClassType final : public AggregateType {
|
||||
public:
|
||||
DECLARE_TYPE_BOILERPLATE(ClassType)
|
||||
@ -627,6 +644,7 @@ class ClassType final : public AggregateType {
|
||||
(!HasUndefinedLayout() && !IsShape()));
|
||||
}
|
||||
bool ShouldGenerateBodyDescriptor() const {
|
||||
if (IsAbstract()) return false;
|
||||
return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern();
|
||||
}
|
||||
bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
|
||||
@ -661,6 +679,14 @@ class ClassType final : public AggregateType {
|
||||
void Finalize() const override;
|
||||
|
||||
std::vector<Field> ComputeAllFields() const;
|
||||
std::vector<Field> ComputeHeaderFields() const;
|
||||
std::vector<Field> ComputeArrayFields() const;
|
||||
// The slots of an object are the tagged pointer sized offsets in an object
|
||||
// that may or may not require GC visiting. These helper functions determine
|
||||
// what kind of GC visiting the individual slots require.
|
||||
std::vector<ObjectSlotKind> ComputeHeaderSlotKinds() const;
|
||||
base::Optional<ObjectSlotKind> ComputeArraySlotKind() const;
|
||||
bool HasNoPointerSlots() const;
|
||||
|
||||
const InstanceTypeConstraints& GetInstanceTypeConstraints() const {
|
||||
return decl_->instance_type_constraints;
|
||||
@ -676,6 +702,14 @@ class ClassType final : public AggregateType {
|
||||
}
|
||||
SourcePosition GetPosition() const { return decl_->pos; }
|
||||
|
||||
// TODO(tebbi): We should no longer pass around types as const pointers, so
|
||||
// that we can avoid mutable fields and const initializers for
|
||||
// late-initialized portions of types like this one.
|
||||
void InitializeInstanceTypes(base::Optional<int> own,
|
||||
base::Optional<std::pair<int, int>> range) const;
|
||||
base::Optional<int> OwnInstanceType() const;
|
||||
base::Optional<std::pair<int, int>> InstanceTypeRange() const;
|
||||
|
||||
private:
|
||||
friend class TypeOracle;
|
||||
friend class TypeVisitor;
|
||||
@ -689,6 +723,8 @@ class ClassType final : public AggregateType {
|
||||
const std::string generates_;
|
||||
const ClassDeclaration* decl_;
|
||||
const TypeAlias* alias_;
|
||||
mutable base::Optional<int> own_instance_type_;
|
||||
mutable base::Optional<std::pair<int, int>> instance_type_range_;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const Type& t) {
|
||||
|
@ -1144,6 +1144,14 @@ namespace test {
|
||||
b: HeapObject;
|
||||
}
|
||||
|
||||
@abstract
|
||||
class AbstractInternalClass extends HeapObject {
|
||||
}
|
||||
|
||||
class AbstractInternalClassSubclass1 extends AbstractInternalClass {}
|
||||
|
||||
class AbstractInternalClassSubclass2 extends AbstractInternalClass {}
|
||||
|
||||
class InternalClassWithSmiElements extends FixedArrayBase {
|
||||
data: Smi;
|
||||
object: Oddball;
|
||||
|
@ -29,8 +29,8 @@ INSTANCE_TYPES = {
|
||||
65: "BIG_INT_BASE_TYPE",
|
||||
66: "HEAP_NUMBER_TYPE",
|
||||
67: "ODDBALL_TYPE",
|
||||
68: "EXPORTED_SUB_CLASS_BASE_TYPE",
|
||||
69: "EXPORTED_SUB_CLASS_TYPE",
|
||||
68: "ABSTRACT_INTERNAL_CLASS_SUBCLASS1_TYPE",
|
||||
69: "ABSTRACT_INTERNAL_CLASS_SUBCLASS2_TYPE",
|
||||
70: "FOREIGN_TYPE",
|
||||
71: "PROMISE_FULFILL_REACTION_JOB_TASK_TYPE",
|
||||
72: "PROMISE_REJECT_REACTION_JOB_TASK_TYPE",
|
||||
@ -110,40 +110,42 @@ INSTANCE_TYPES = {
|
||||
146: "SMALL_ORDERED_HASH_MAP_TYPE",
|
||||
147: "SMALL_ORDERED_HASH_SET_TYPE",
|
||||
148: "SMALL_ORDERED_NAME_DICTIONARY_TYPE",
|
||||
149: "SOURCE_TEXT_MODULE_TYPE",
|
||||
150: "SYNTHETIC_MODULE_TYPE",
|
||||
151: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
|
||||
152: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
|
||||
153: "WEAK_FIXED_ARRAY_TYPE",
|
||||
154: "TRANSITION_ARRAY_TYPE",
|
||||
155: "CELL_TYPE",
|
||||
156: "CODE_TYPE",
|
||||
157: "CODE_DATA_CONTAINER_TYPE",
|
||||
158: "COVERAGE_INFO_TYPE",
|
||||
159: "DESCRIPTOR_ARRAY_TYPE",
|
||||
160: "EMBEDDER_DATA_ARRAY_TYPE",
|
||||
161: "FEEDBACK_METADATA_TYPE",
|
||||
162: "FEEDBACK_VECTOR_TYPE",
|
||||
163: "FILLER_TYPE",
|
||||
164: "FREE_SPACE_TYPE",
|
||||
165: "INTERNAL_CLASS_TYPE",
|
||||
166: "INTERNAL_CLASS_WITH_STRUCT_ELEMENTS_TYPE",
|
||||
167: "MAP_TYPE",
|
||||
168: "PREPARSE_DATA_TYPE",
|
||||
169: "PROPERTY_ARRAY_TYPE",
|
||||
170: "PROPERTY_CELL_TYPE",
|
||||
171: "SHARED_FUNCTION_INFO_TYPE",
|
||||
172: "SMI_BOX_TYPE",
|
||||
173: "SMI_PAIR_TYPE",
|
||||
174: "SORT_STATE_TYPE",
|
||||
175: "WASM_STRUCT_TYPE",
|
||||
176: "WEAK_ARRAY_LIST_TYPE",
|
||||
177: "WEAK_CELL_TYPE",
|
||||
178: "JS_PROXY_TYPE",
|
||||
149: "EXPORTED_SUB_CLASS_BASE_TYPE",
|
||||
150: "EXPORTED_SUB_CLASS_TYPE",
|
||||
151: "SOURCE_TEXT_MODULE_TYPE",
|
||||
152: "SYNTHETIC_MODULE_TYPE",
|
||||
153: "UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE",
|
||||
154: "UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE",
|
||||
155: "WEAK_FIXED_ARRAY_TYPE",
|
||||
156: "TRANSITION_ARRAY_TYPE",
|
||||
157: "CELL_TYPE",
|
||||
158: "CODE_TYPE",
|
||||
159: "CODE_DATA_CONTAINER_TYPE",
|
||||
160: "COVERAGE_INFO_TYPE",
|
||||
161: "DESCRIPTOR_ARRAY_TYPE",
|
||||
162: "EMBEDDER_DATA_ARRAY_TYPE",
|
||||
163: "FEEDBACK_METADATA_TYPE",
|
||||
164: "FEEDBACK_VECTOR_TYPE",
|
||||
165: "FILLER_TYPE",
|
||||
166: "FREE_SPACE_TYPE",
|
||||
167: "INTERNAL_CLASS_TYPE",
|
||||
168: "INTERNAL_CLASS_WITH_STRUCT_ELEMENTS_TYPE",
|
||||
169: "MAP_TYPE",
|
||||
170: "PREPARSE_DATA_TYPE",
|
||||
171: "PROPERTY_ARRAY_TYPE",
|
||||
172: "PROPERTY_CELL_TYPE",
|
||||
173: "SHARED_FUNCTION_INFO_TYPE",
|
||||
174: "SMI_BOX_TYPE",
|
||||
175: "SMI_PAIR_TYPE",
|
||||
176: "SORT_STATE_TYPE",
|
||||
177: "WASM_STRUCT_TYPE",
|
||||
178: "WEAK_ARRAY_LIST_TYPE",
|
||||
179: "WEAK_CELL_TYPE",
|
||||
180: "JS_PROXY_TYPE",
|
||||
1057: "JS_OBJECT_TYPE",
|
||||
179: "JS_GLOBAL_OBJECT_TYPE",
|
||||
180: "JS_GLOBAL_PROXY_TYPE",
|
||||
181: "JS_MODULE_NAMESPACE_TYPE",
|
||||
181: "JS_GLOBAL_OBJECT_TYPE",
|
||||
182: "JS_GLOBAL_PROXY_TYPE",
|
||||
183: "JS_MODULE_NAMESPACE_TYPE",
|
||||
1040: "JS_SPECIAL_API_OBJECT_TYPE",
|
||||
1041: "JS_PRIMITIVE_WRAPPER_TYPE",
|
||||
1042: "JS_MAP_KEY_ITERATOR_TYPE",
|
||||
@ -200,13 +202,13 @@ INSTANCE_TYPES = {
|
||||
|
||||
# List of known V8 maps.
|
||||
KNOWN_MAPS = {
|
||||
("read_only_space", 0x00121): (164, "FreeSpaceMap"),
|
||||
("read_only_space", 0x00149): (167, "MetaMap"),
|
||||
("read_only_space", 0x00121): (166, "FreeSpaceMap"),
|
||||
("read_only_space", 0x00149): (169, "MetaMap"),
|
||||
("read_only_space", 0x0018d): (67, "NullMap"),
|
||||
("read_only_space", 0x001c5): (159, "DescriptorArrayMap"),
|
||||
("read_only_space", 0x001f5): (153, "WeakFixedArrayMap"),
|
||||
("read_only_space", 0x0021d): (163, "OnePointerFillerMap"),
|
||||
("read_only_space", 0x00245): (163, "TwoPointerFillerMap"),
|
||||
("read_only_space", 0x001c5): (161, "DescriptorArrayMap"),
|
||||
("read_only_space", 0x001f5): (155, "WeakFixedArrayMap"),
|
||||
("read_only_space", 0x0021d): (165, "OnePointerFillerMap"),
|
||||
("read_only_space", 0x00245): (165, "TwoPointerFillerMap"),
|
||||
("read_only_space", 0x00289): (67, "UninitializedMap"),
|
||||
("read_only_space", 0x002cd): (8, "OneByteInternalizedStringMap"),
|
||||
("read_only_space", 0x00329): (67, "UndefinedMap"),
|
||||
@ -220,14 +222,14 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x00529): (64, "SymbolMap"),
|
||||
("read_only_space", 0x00551): (40, "OneByteStringMap"),
|
||||
("read_only_space", 0x00579): (130, "ScopeInfoMap"),
|
||||
("read_only_space", 0x005a1): (171, "SharedFunctionInfoMap"),
|
||||
("read_only_space", 0x005c9): (156, "CodeMap"),
|
||||
("read_only_space", 0x005f1): (155, "CellMap"),
|
||||
("read_only_space", 0x00619): (170, "GlobalPropertyCellMap"),
|
||||
("read_only_space", 0x005a1): (173, "SharedFunctionInfoMap"),
|
||||
("read_only_space", 0x005c9): (158, "CodeMap"),
|
||||
("read_only_space", 0x005f1): (157, "CellMap"),
|
||||
("read_only_space", 0x00619): (172, "GlobalPropertyCellMap"),
|
||||
("read_only_space", 0x00641): (70, "ForeignMap"),
|
||||
("read_only_space", 0x00669): (154, "TransitionArrayMap"),
|
||||
("read_only_space", 0x00669): (156, "TransitionArrayMap"),
|
||||
("read_only_space", 0x00691): (45, "ThinOneByteStringMap"),
|
||||
("read_only_space", 0x006b9): (162, "FeedbackVectorMap"),
|
||||
("read_only_space", 0x006b9): (164, "FeedbackVectorMap"),
|
||||
("read_only_space", 0x0070d): (67, "ArgumentsMarkerMap"),
|
||||
("read_only_space", 0x0076d): (67, "ExceptionMap"),
|
||||
("read_only_space", 0x007c9): (67, "TerminationExceptionMap"),
|
||||
@ -235,13 +237,13 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x00891): (67, "StaleRegisterMap"),
|
||||
("read_only_space", 0x008d5): (131, "ScriptContextTableMap"),
|
||||
("read_only_space", 0x008fd): (128, "ClosureFeedbackCellArrayMap"),
|
||||
("read_only_space", 0x00925): (161, "FeedbackMetadataArrayMap"),
|
||||
("read_only_space", 0x00925): (163, "FeedbackMetadataArrayMap"),
|
||||
("read_only_space", 0x0094d): (117, "ArrayListMap"),
|
||||
("read_only_space", 0x00975): (65, "BigIntMap"),
|
||||
("read_only_space", 0x0099d): (129, "ObjectBoilerplateDescriptionMap"),
|
||||
("read_only_space", 0x009c5): (133, "BytecodeArrayMap"),
|
||||
("read_only_space", 0x009ed): (157, "CodeDataContainerMap"),
|
||||
("read_only_space", 0x00a15): (158, "CoverageInfoMap"),
|
||||
("read_only_space", 0x009ed): (159, "CodeDataContainerMap"),
|
||||
("read_only_space", 0x00a15): (160, "CoverageInfoMap"),
|
||||
("read_only_space", 0x00a3d): (134, "FixedDoubleArrayMap"),
|
||||
("read_only_space", 0x00a65): (120, "GlobalDictionaryMap"),
|
||||
("read_only_space", 0x00a8d): (96, "ManyClosuresCellMap"),
|
||||
@ -253,8 +255,8 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x00b7d): (123, "OrderedHashMapMap"),
|
||||
("read_only_space", 0x00ba5): (124, "OrderedHashSetMap"),
|
||||
("read_only_space", 0x00bcd): (125, "OrderedNameDictionaryMap"),
|
||||
("read_only_space", 0x00bf5): (168, "PreparseDataMap"),
|
||||
("read_only_space", 0x00c1d): (169, "PropertyArrayMap"),
|
||||
("read_only_space", 0x00bf5): (170, "PreparseDataMap"),
|
||||
("read_only_space", 0x00c1d): (171, "PropertyArrayMap"),
|
||||
("read_only_space", 0x00c45): (92, "SideEffectCallHandlerInfoMap"),
|
||||
("read_only_space", 0x00c6d): (92, "SideEffectFreeCallHandlerInfoMap"),
|
||||
("read_only_space", 0x00c95): (92, "NextCallSideEffectFreeCallHandlerInfoMap"),
|
||||
@ -263,15 +265,15 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x00d0d): (146, "SmallOrderedHashMapMap"),
|
||||
("read_only_space", 0x00d35): (147, "SmallOrderedHashSetMap"),
|
||||
("read_only_space", 0x00d5d): (148, "SmallOrderedNameDictionaryMap"),
|
||||
("read_only_space", 0x00d85): (149, "SourceTextModuleMap"),
|
||||
("read_only_space", 0x00d85): (151, "SourceTextModuleMap"),
|
||||
("read_only_space", 0x00dad): (127, "StringTableMap"),
|
||||
("read_only_space", 0x00dd5): (150, "SyntheticModuleMap"),
|
||||
("read_only_space", 0x00dfd): (152, "UncompiledDataWithoutPreparseDataMap"),
|
||||
("read_only_space", 0x00e25): (151, "UncompiledDataWithPreparseDataMap"),
|
||||
("read_only_space", 0x00e4d): (176, "WeakArrayListMap"),
|
||||
("read_only_space", 0x00dd5): (152, "SyntheticModuleMap"),
|
||||
("read_only_space", 0x00dfd): (154, "UncompiledDataWithoutPreparseDataMap"),
|
||||
("read_only_space", 0x00e25): (153, "UncompiledDataWithPreparseDataMap"),
|
||||
("read_only_space", 0x00e4d): (178, "WeakArrayListMap"),
|
||||
("read_only_space", 0x00e75): (119, "EphemeronHashTableMap"),
|
||||
("read_only_space", 0x00e9d): (160, "EmbedderDataArrayMap"),
|
||||
("read_only_space", 0x00ec5): (177, "WeakCellMap"),
|
||||
("read_only_space", 0x00e9d): (162, "EmbedderDataArrayMap"),
|
||||
("read_only_space", 0x00ec5): (179, "WeakCellMap"),
|
||||
("read_only_space", 0x00eed): (32, "StringMap"),
|
||||
("read_only_space", 0x00f15): (41, "ConsOneByteStringMap"),
|
||||
("read_only_space", 0x00f3d): (33, "ConsStringMap"),
|
||||
@ -329,23 +331,25 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x038ad): (114, "WasmIndirectFunctionTableMap"),
|
||||
("read_only_space", 0x038d5): (115, "WasmJSFunctionDataMap"),
|
||||
("read_only_space", 0x038fd): (116, "WasmValueMap"),
|
||||
("read_only_space", 0x03925): (165, "InternalClassMap"),
|
||||
("read_only_space", 0x0394d): (173, "SmiPairMap"),
|
||||
("read_only_space", 0x03975): (172, "SmiBoxMap"),
|
||||
("read_only_space", 0x0399d): (68, "ExportedSubClassBaseMap"),
|
||||
("read_only_space", 0x039c5): (69, "ExportedSubClassMap"),
|
||||
("read_only_space", 0x039ed): (135, "InternalClassWithSmiElementsMap"),
|
||||
("read_only_space", 0x03a15): (166, "InternalClassWithStructElementsMap"),
|
||||
("read_only_space", 0x03a3d): (174, "SortStateMap"),
|
||||
("read_only_space", 0x03a65): (85, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x03a8d): (85, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x03ab5): (76, "LoadHandler1Map"),
|
||||
("read_only_space", 0x03add): (76, "LoadHandler2Map"),
|
||||
("read_only_space", 0x03b05): (76, "LoadHandler3Map"),
|
||||
("read_only_space", 0x03b2d): (77, "StoreHandler0Map"),
|
||||
("read_only_space", 0x03b55): (77, "StoreHandler1Map"),
|
||||
("read_only_space", 0x03b7d): (77, "StoreHandler2Map"),
|
||||
("read_only_space", 0x03ba5): (77, "StoreHandler3Map"),
|
||||
("read_only_space", 0x03925): (167, "InternalClassMap"),
|
||||
("read_only_space", 0x0394d): (175, "SmiPairMap"),
|
||||
("read_only_space", 0x03975): (174, "SmiBoxMap"),
|
||||
("read_only_space", 0x0399d): (149, "ExportedSubClassBaseMap"),
|
||||
("read_only_space", 0x039c5): (150, "ExportedSubClassMap"),
|
||||
("read_only_space", 0x039ed): (68, "AbstractInternalClassSubclass1Map"),
|
||||
("read_only_space", 0x03a15): (69, "AbstractInternalClassSubclass2Map"),
|
||||
("read_only_space", 0x03a3d): (135, "InternalClassWithSmiElementsMap"),
|
||||
("read_only_space", 0x03a65): (168, "InternalClassWithStructElementsMap"),
|
||||
("read_only_space", 0x03a8d): (176, "SortStateMap"),
|
||||
("read_only_space", 0x03ab5): (85, "AllocationSiteWithWeakNextMap"),
|
||||
("read_only_space", 0x03add): (85, "AllocationSiteWithoutWeakNextMap"),
|
||||
("read_only_space", 0x03b05): (76, "LoadHandler1Map"),
|
||||
("read_only_space", 0x03b2d): (76, "LoadHandler2Map"),
|
||||
("read_only_space", 0x03b55): (76, "LoadHandler3Map"),
|
||||
("read_only_space", 0x03b7d): (77, "StoreHandler0Map"),
|
||||
("read_only_space", 0x03ba5): (77, "StoreHandler1Map"),
|
||||
("read_only_space", 0x03bcd): (77, "StoreHandler2Map"),
|
||||
("read_only_space", 0x03bf5): (77, "StoreHandler3Map"),
|
||||
("map_space", 0x00121): (1057, "ExternalMap"),
|
||||
("map_space", 0x00149): (1073, "JSMessageObjectMap"),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user