[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:
Tobias Tebbi 2020-05-04 14:50:30 +02:00 committed by Commit Bot
parent 0d44905481
commit f1400e43f1
23 changed files with 563 additions and 330 deletions

View File

@ -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",

View File

@ -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) {

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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
};

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -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)

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
};

View File

@ -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, "

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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) {

View File

@ -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;

View File

@ -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"),
}