Commit f1400e43 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[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: 's avatarNico Hartmann <nicohartmann@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67542}
parent 0d449054
...@@ -1211,7 +1211,7 @@ template("run_torque") { ...@@ -1211,7 +1211,7 @@ template("run_torque") {
"class-verifiers-tq.h", "class-verifiers-tq.h",
"enum-verifiers-tq.cc", "enum-verifiers-tq.cc",
"objects-printer-tq.cc", "objects-printer-tq.cc",
"objects-body-descriptors-tq-inl.h", "objects-body-descriptors-tq-inl.inc",
"class-definitions-tq.cc", "class-definitions-tq.cc",
"class-definitions-tq-inl.h", "class-definitions-tq-inl.h",
"class-definitions-tq.h", "class-definitions-tq.h",
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "src/objects/oddball.h" #include "src/objects/oddball.h"
#include "src/objects/ordered-hash-table.h" #include "src/objects/ordered-hash-table.h"
#include "src/wasm/wasm-objects.h" #include "src/wasm/wasm-objects.h"
#include "torque-generated/objects-body-descriptors-tq-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -61,8 +60,6 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map map, ...@@ -61,8 +60,6 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map map,
return visitor->VisitStruct(map, object); return visitor->VisitStruct(map, object);
case kVisitFreeSpace: case kVisitFreeSpace:
return visitor->VisitFreeSpace(map, FreeSpace::cast(object)); return visitor->VisitFreeSpace(map, FreeSpace::cast(object));
case kVisitWeakArray:
return visitor->VisitWeakArray(map, object);
case kDataOnlyVisitorIdCount: case kDataOnlyVisitorIdCount:
case kVisitorIdCount: case kVisitorIdCount:
UNREACHABLE(); UNREACHABLE();
...@@ -169,19 +166,6 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace( ...@@ -169,19 +166,6 @@ ResultType HeapVisitor<ResultType, ConcreteVisitor>::VisitFreeSpace(
return static_cast<ResultType>(object.size()); 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> template <typename ConcreteVisitor>
int NewSpaceVisitor<ConcreteVisitor>::VisitNativeContext(Map map, int NewSpaceVisitor<ConcreteVisitor>::VisitNativeContext(Map map,
NativeContext object) { NativeContext object) {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "src/objects/map.h" #include "src/objects/map.h"
#include "src/objects/objects.h" #include "src/objects/objects.h"
#include "src/objects/visitors.h" #include "src/objects/visitors.h"
#include "torque-generated/field-offsets-tq.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -21,7 +22,6 @@ namespace internal { ...@@ -21,7 +22,6 @@ namespace internal {
V(Cell) \ V(Cell) \
V(Code) \ V(Code) \
V(CodeDataContainer) \ V(CodeDataContainer) \
V(ConsString) \
V(Context) \ V(Context) \
V(CoverageInfo) \ V(CoverageInfo) \
V(DataHandler) \ V(DataHandler) \
...@@ -31,7 +31,6 @@ namespace internal { ...@@ -31,7 +31,6 @@ namespace internal {
V(FeedbackCell) \ V(FeedbackCell) \
V(FeedbackMetadata) \ V(FeedbackMetadata) \
V(FeedbackVector) \ V(FeedbackVector) \
V(FixedArray) \
V(FixedDoubleArray) \ V(FixedDoubleArray) \
V(JSArrayBuffer) \ V(JSArrayBuffer) \
V(JSDataView) \ V(JSDataView) \
...@@ -48,17 +47,13 @@ namespace internal { ...@@ -48,17 +47,13 @@ namespace internal {
V(PropertyArray) \ V(PropertyArray) \
V(PropertyCell) \ V(PropertyCell) \
V(PrototypeInfo) \ V(PrototypeInfo) \
V(SeqOneByteString) \
V(SeqTwoByteString) \
V(SharedFunctionInfo) \ V(SharedFunctionInfo) \
V(SlicedString) \
V(SmallOrderedHashMap) \ V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \ V(SmallOrderedHashSet) \
V(SmallOrderedNameDictionary) \ V(SmallOrderedNameDictionary) \
V(SourceTextModule) \ V(SourceTextModule) \
V(Symbol) \ V(Symbol) \
V(SyntheticModule) \ V(SyntheticModule) \
V(ThinString) \
V(TransitionArray) \ V(TransitionArray) \
V(UncompiledDataWithoutPreparseData) \ V(UncompiledDataWithoutPreparseData) \
V(UncompiledDataWithPreparseData) \ V(UncompiledDataWithPreparseData) \
...@@ -113,7 +108,6 @@ class HeapVisitor : public ObjectVisitor { ...@@ -113,7 +108,6 @@ class HeapVisitor : public ObjectVisitor {
V8_INLINE ResultType VisitJSApiObject(Map map, JSObject object); V8_INLINE ResultType VisitJSApiObject(Map map, JSObject object);
V8_INLINE ResultType VisitStruct(Map map, HeapObject object); V8_INLINE ResultType VisitStruct(Map map, HeapObject object);
V8_INLINE ResultType VisitFreeSpace(Map map, FreeSpace object); V8_INLINE ResultType VisitFreeSpace(Map map, FreeSpace object);
V8_INLINE ResultType VisitWeakArray(Map map, HeapObject object);
template <typename T> template <typename T>
static V8_INLINE T Cast(HeapObject object); static V8_INLINE T Cast(HeapObject object);
......
...@@ -195,6 +195,19 @@ void FixedArray::CopyElements(Isolate* isolate, int dst_index, FixedArray src, ...@@ -195,6 +195,19 @@ void FixedArray::CopyElements(Isolate* isolate, int dst_index, FixedArray src,
isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode); 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. // Perform a binary search in a fixed array.
template <SearchMode search_mode, typename T> template <SearchMode search_mode, typename T>
int BinarySearch(T* array, Name name, int valid_entries, int BinarySearch(T* array, Name name, int valid_entries,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/handles/maybe-handles.h" #include "src/handles/maybe-handles.h"
#include "src/objects/instance-type.h" #include "src/objects/instance-type.h"
#include "src/objects/objects.h"
#include "src/objects/smi.h" #include "src/objects/smi.h"
#include "torque-generated/class-definitions-tq.h" #include "torque-generated/class-definitions-tq.h"
...@@ -15,8 +16,6 @@ ...@@ -15,8 +16,6 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
using WeakArrayBodyDescriptor =
FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>;
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \ #define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \ V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
...@@ -182,7 +181,9 @@ class FixedArray ...@@ -182,7 +181,9 @@ class FixedArray
// Dispatched behavior. // Dispatched behavior.
DECL_PRINTER(FixedArray) DECL_PRINTER(FixedArray)
using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>; int AllocatedSize();
class BodyDescriptor;
static constexpr int kObjectsOffset = kHeaderSize; static constexpr int kObjectsOffset = kHeaderSize;
...@@ -280,16 +281,19 @@ class WeakFixedArray ...@@ -280,16 +281,19 @@ class WeakFixedArray
DECL_PRINTER(WeakFixedArray) DECL_PRINTER(WeakFixedArray)
DECL_VERIFIER(WeakFixedArray) DECL_VERIFIER(WeakFixedArray)
using BodyDescriptor = WeakArrayBodyDescriptor; class BodyDescriptor;
static const int kMaxLength = static const int kMaxLength =
(FixedArray::kMaxSize - kHeaderSize) / kTaggedSize; (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
static_assert(Internals::IsValidSmi(kMaxLength), static_assert(Internals::IsValidSmi(kMaxLength),
"WeakFixedArray maxLength not a Smi"); "WeakFixedArray maxLength not a Smi");
int AllocatedSize();
protected: protected:
static int OffsetOfElementAt(int index) { static int OffsetOfElementAt(int index) {
return kHeaderSize + index * kTaggedSize; STATIC_ASSERT(kObjectsOffset == SizeFor(0));
return SizeFor(index);
} }
private: private:
...@@ -360,8 +364,9 @@ class WeakArrayList ...@@ -360,8 +364,9 @@ class WeakArrayList
// Get and set the capacity using acquire loads and release stores. // Get and set the capacity using acquire loads and release stores.
DECL_SYNCHRONIZED_INT_ACCESSORS(capacity) DECL_SYNCHRONIZED_INT_ACCESSORS(capacity)
int AllocatedSize();
using BodyDescriptor = WeakArrayBodyDescriptor; class BodyDescriptor;
static const int kMaxCapacity = static const int kMaxCapacity =
(FixedArray::kMaxSize - kHeaderSize) / kTaggedSize; (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
......
...@@ -9,6 +9,7 @@ extern class FixedArrayBase extends HeapObject { ...@@ -9,6 +9,7 @@ extern class FixedArrayBase extends HeapObject {
const length: Smi; const length: Smi;
} }
@generateBodyDescriptor
@generateCppClass @generateCppClass
extern class FixedArray extends FixedArrayBase { extern class FixedArray extends FixedArrayBase {
objects[length]: Object; objects[length]: Object;
...@@ -21,6 +22,7 @@ extern class FixedDoubleArray extends FixedArrayBase { ...@@ -21,6 +22,7 @@ extern class FixedDoubleArray extends FixedArrayBase {
floats[length]: float64_or_hole; floats[length]: float64_or_hole;
} }
@generateBodyDescriptor
@generateCppClass @generateCppClass
extern class WeakFixedArray extends HeapObject { extern class WeakFixedArray extends HeapObject {
const length: Smi; const length: Smi;
...@@ -41,6 +43,7 @@ extern class ArrayList extends FixedArray { ...@@ -41,6 +43,7 @@ extern class ArrayList extends FixedArray {
extern class TemplateList extends FixedArray { extern class TemplateList extends FixedArray {
} }
@generateBodyDescriptor
@generateCppClass @generateCppClass
extern class WeakArrayList extends HeapObject { extern class WeakArrayList extends HeapObject {
const capacity: Smi; const capacity: Smi;
......
...@@ -142,7 +142,6 @@ VisitorId Map::GetVisitorId(Map map) { ...@@ -142,7 +142,6 @@ VisitorId Map::GetVisitorId(Map map) {
case EMBEDDER_DATA_ARRAY_TYPE: case EMBEDDER_DATA_ARRAY_TYPE:
return kVisitEmbedderDataArray; return kVisitEmbedderDataArray;
case FIXED_ARRAY_TYPE:
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE: case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE: case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case HASH_TABLE_TYPE: case HASH_TABLE_TYPE:
...@@ -175,10 +174,6 @@ VisitorId Map::GetVisitorId(Map map) { ...@@ -175,10 +174,6 @@ VisitorId Map::GetVisitorId(Map map) {
case EPHEMERON_HASH_TABLE_TYPE: case EPHEMERON_HASH_TABLE_TYPE:
return kVisitEphemeronHashTable; return kVisitEphemeronHashTable;
case WEAK_FIXED_ARRAY_TYPE:
case WEAK_ARRAY_LIST_TYPE:
return kVisitWeakArray;
case FIXED_DOUBLE_ARRAY_TYPE: case FIXED_DOUBLE_ARRAY_TYPE:
return kVisitFixedDoubleArray; return kVisitFixedDoubleArray;
...@@ -373,7 +368,7 @@ VisitorId Map::GetVisitorId(Map map) { ...@@ -373,7 +368,7 @@ VisitorId Map::GetVisitorId(Map map) {
#define MAKE_TQ_CASE(TYPE, Name) \ #define MAKE_TQ_CASE(TYPE, Name) \
case TYPE: \ case TYPE: \
return kVisit##Name; return kVisit##Name;
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TQ_CASE) TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(MAKE_TQ_CASE)
#undef MAKE_TQ_CASE #undef MAKE_TQ_CASE
default: default:
......
...@@ -28,9 +28,7 @@ enum InstanceType : uint16_t; ...@@ -28,9 +28,7 @@ enum InstanceType : uint16_t;
V(CoverageInfo) \ V(CoverageInfo) \
V(DataObject) \ V(DataObject) \
V(FeedbackMetadata) \ V(FeedbackMetadata) \
V(FixedDoubleArray) \ V(FixedDoubleArray)
V(SeqOneByteString) \
V(SeqTwoByteString)
#define POINTER_VISITOR_ID_LIST(V) \ #define POINTER_VISITOR_ID_LIST(V) \
V(AllocationSite) \ V(AllocationSite) \
...@@ -38,7 +36,6 @@ enum InstanceType : uint16_t; ...@@ -38,7 +36,6 @@ enum InstanceType : uint16_t;
V(Cell) \ V(Cell) \
V(Code) \ V(Code) \
V(CodeDataContainer) \ V(CodeDataContainer) \
V(ConsString) \
V(Context) \ V(Context) \
V(DataHandler) \ V(DataHandler) \
V(DescriptorArray) \ V(DescriptorArray) \
...@@ -46,7 +43,6 @@ enum InstanceType : uint16_t; ...@@ -46,7 +43,6 @@ enum InstanceType : uint16_t;
V(EphemeronHashTable) \ V(EphemeronHashTable) \
V(FeedbackCell) \ V(FeedbackCell) \
V(FeedbackVector) \ V(FeedbackVector) \
V(FixedArray) \
V(FreeSpace) \ V(FreeSpace) \
V(JSApiObject) \ V(JSApiObject) \
V(JSArrayBuffer) \ V(JSArrayBuffer) \
...@@ -66,7 +62,6 @@ enum InstanceType : uint16_t; ...@@ -66,7 +62,6 @@ enum InstanceType : uint16_t;
V(PrototypeInfo) \ V(PrototypeInfo) \
V(SharedFunctionInfo) \ V(SharedFunctionInfo) \
V(ShortcutCandidate) \ V(ShortcutCandidate) \
V(SlicedString) \
V(SmallOrderedHashMap) \ V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \ V(SmallOrderedHashSet) \
V(SmallOrderedNameDictionary) \ V(SmallOrderedNameDictionary) \
...@@ -74,7 +69,6 @@ enum InstanceType : uint16_t; ...@@ -74,7 +69,6 @@ enum InstanceType : uint16_t;
V(Struct) \ V(Struct) \
V(Symbol) \ V(Symbol) \
V(SyntheticModule) \ V(SyntheticModule) \
V(ThinString) \
V(TransitionArray) \ V(TransitionArray) \
V(UncompiledDataWithoutPreparseData) \ V(UncompiledDataWithoutPreparseData) \
V(UncompiledDataWithPreparseData) \ V(UncompiledDataWithPreparseData) \
...@@ -82,15 +76,11 @@ enum InstanceType : uint16_t; ...@@ -82,15 +76,11 @@ enum InstanceType : uint16_t;
V(WasmIndirectFunctionTable) \ V(WasmIndirectFunctionTable) \
V(WasmInstanceObject) \ V(WasmInstanceObject) \
V(WasmStruct) \ V(WasmStruct) \
V(WeakArray) \
V(WeakCell) V(WeakCell)
#define TORQUE_OBJECT_BODY_TO_VISITOR_ID_LIST_ADAPTER(V, TYPE, TypeName) \ #define TORQUE_VISITOR_ID_LIST(V) \
V(TypeName) TORQUE_DATA_ONLY_VISITOR_ID_LIST(V) \
TORQUE_POINTER_VISITOR_ID_LIST(V)
#define TORQUE_VISITOR_ID_LIST(V) \
TORQUE_BODY_DESCRIPTOR_LIST_GENERATOR( \
TORQUE_OBJECT_BODY_TO_VISITOR_ID_LIST_ADAPTER, V)
// Objects with the same visitor id are processed in the same way by // Objects with the same visitor id are processed in the same way by
// the heap visitors. The visitor ids for data only objects must precede // the heap visitors. The visitor ids for data only objects must precede
...@@ -98,9 +88,11 @@ enum InstanceType : uint16_t; ...@@ -98,9 +88,11 @@ enum InstanceType : uint16_t;
// of whether an object contains only data or may contain pointers. // of whether an object contains only data or may contain pointers.
enum VisitorId { enum VisitorId {
#define VISITOR_ID_ENUM_DECL(id) kVisit##id, #define VISITOR_ID_ENUM_DECL(id) kVisit##id,
DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) kDataOnlyVisitorIdCount, DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
TORQUE_DATA_ONLY_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
kDataOnlyVisitorIdCount,
POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
TORQUE_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL) TORQUE_POINTER_VISITOR_ID_LIST(VISITOR_ID_ENUM_DECL)
#undef VISITOR_ID_ENUM_DECL #undef VISITOR_ID_ENUM_DECL
kVisitorIdCount kVisitorIdCount
}; };
......
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
#include "src/objects/transitions.h" #include "src/objects/transitions.h"
#include "src/wasm/wasm-objects-inl.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 v8 {
namespace internal { namespace internal {
...@@ -681,34 +684,6 @@ class Code::BodyDescriptor final : public BodyDescriptorBase { ...@@ -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 { class WasmInstanceObject::BodyDescriptor final : public BodyDescriptorBase {
public: public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) { 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) { ...@@ -923,7 +898,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case EMBEDDER_DATA_ARRAY_TYPE: case EMBEDDER_DATA_ARRAY_TYPE:
return Op::template apply<EmbedderDataArray::BodyDescriptor>(p1, p2, p3, return Op::template apply<EmbedderDataArray::BodyDescriptor>(p1, p2, p3,
p4); p4);
case FIXED_ARRAY_TYPE:
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE: case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE: case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case HASH_TABLE_TYPE: case HASH_TABLE_TYPE:
...@@ -953,10 +927,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { ...@@ -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); return Op::template apply<Context::BodyDescriptor>(p1, p2, p3, p4);
case NATIVE_CONTEXT_TYPE: case NATIVE_CONTEXT_TYPE:
return Op::template apply<NativeContext::BodyDescriptor>(p1, p2, p3, p4); 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: case FIXED_DOUBLE_ARRAY_TYPE:
return ReturnType(); return ReturnType();
case FEEDBACK_METADATA_TYPE: case FEEDBACK_METADATA_TYPE:
...@@ -1129,10 +1099,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { ...@@ -1129,10 +1099,12 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case SYNTHETIC_MODULE_TYPE: case SYNTHETIC_MODULE_TYPE:
return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3, return Op::template apply<SyntheticModule::BodyDescriptor>(p1, p2, p3,
p4); p4);
// TODO(tebbi): Avoid duplicated cases when the body descriptors are identical.
#define MAKE_TORQUE_BODY_DESCRIPTOR_APPLY(TYPE, TypeName) \ #define MAKE_TORQUE_BODY_DESCRIPTOR_APPLY(TYPE, TypeName) \
case TYPE: \ case TYPE: \
return Op::template apply<TypeName::BodyDescriptor>(p1, p2, p3, p4); 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 #undef MAKE_TORQUE_BODY_DESCRIPTOR_APPLY
default: default:
...@@ -1193,6 +1165,8 @@ class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase { ...@@ -1193,6 +1165,8 @@ class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase {
} }
}; };
#include "torque-generated/objects-body-descriptors-tq-inl.inc"
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -74,15 +74,14 @@ class BodyDescriptorBase { ...@@ -74,15 +74,14 @@ class BodyDescriptorBase {
ObjectVisitor* v); ObjectVisitor* v);
}; };
// This class describes a body of an object of a fixed size // This class describes a body of an object in which all pointer fields are
// in which all pointer fields are located in the [start_offset, end_offset) // located in the [start_offset, end_offset) interval.
// interval. // All pointers have to be strong.
template <int start_offset, int end_offset, int size> template <int start_offset, int end_offset>
class FixedBodyDescriptor final : public BodyDescriptorBase { class FixedRangeBodyDescriptor : public BodyDescriptorBase {
public: public:
static const int kStartOffset = start_offset; static const int kStartOffset = start_offset;
static const int kEndOffset = end_offset; static const int kEndOffset = end_offset;
static const int kSize = size;
static bool IsValidSlot(Map map, HeapObject obj, int offset) { static bool IsValidSlot(Map map, HeapObject obj, int offset) {
return offset >= kStartOffset && offset < kEndOffset; return offset >= kStartOffset && offset < kEndOffset;
...@@ -99,14 +98,30 @@ class FixedBodyDescriptor final : public BodyDescriptorBase { ...@@ -99,14 +98,30 @@ class FixedBodyDescriptor final : public BodyDescriptorBase {
IterateBody(map, obj, v); IterateBody(map, obj, v);
} }
static inline int SizeOf(Map map, HeapObject object) { return kSize; } 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 // This class describes a body of an object of a fixed size
// in which all pointer fields are located in the [start_offset, object_size) // in which all pointer fields are located in the [start_offset, end_offset)
// interval. // 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 in which all pointer fields are
// located in the [start_offset, object_size) interval.
// All pointers have to be strong.
template <int start_offset> template <int start_offset>
class FlexibleBodyDescriptor final : public BodyDescriptorBase { class SuffixRangeBodyDescriptor : public BodyDescriptorBase {
public: public:
static const int kStartOffset = start_offset; static const int kStartOffset = start_offset;
...@@ -120,13 +135,30 @@ class FlexibleBodyDescriptor final : public BodyDescriptorBase { ...@@ -120,13 +135,30 @@ class FlexibleBodyDescriptor final : public BodyDescriptorBase {
IteratePointers(obj, start_offset, object_size, v); 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); static inline int SizeOf(Map map, HeapObject object);
}; };
using StructBodyDescriptor = FlexibleBodyDescriptor<HeapObject::kHeaderSize>; 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> template <int start_offset>
class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase { class SuffixRangeWeakBodyDescriptor : public BodyDescriptorBase {
public: public:
static const int kStartOffset = start_offset; static const int kStartOffset = start_offset;
...@@ -140,9 +172,40 @@ class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase { ...@@ -140,9 +172,40 @@ class FlexibleWeakBodyDescriptor final : public BodyDescriptorBase {
IterateMaybeWeakPointers(obj, start_offset, object_size, v); 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); 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 // 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 // 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 // descriptor, and a new descriptor for the child -- so, both parent and child's
...@@ -180,10 +243,6 @@ class SubclassBodyDescriptor final : public BodyDescriptorBase { ...@@ -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 internal
} // namespace v8 } // namespace v8
......
...@@ -126,7 +126,6 @@ ...@@ -126,7 +126,6 @@
#include "torque-generated/class-definitions-tq-inl.h" #include "torque-generated/class-definitions-tq-inl.h"
#include "torque-generated/internal-class-definitions-tq-inl.h" #include "torque-generated/internal-class-definitions-tq-inl.h"
#include "torque-generated/objects-body-descriptors-tq-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -2278,12 +2277,11 @@ int HeapObject::SizeFromMap(Map map) const { ...@@ -2278,12 +2277,11 @@ int HeapObject::SizeFromMap(Map map) const {
PreparseData data = PreparseData::unchecked_cast(*this); PreparseData data = PreparseData::unchecked_cast(*this);
return PreparseData::SizeFor(data.data_length(), data.children_length()); return PreparseData::SizeFor(data.data_length(), data.children_length());
} }
#define MAKE_TORQUE_SIZE_FOR(TYPE, TypeName) \ #define MAKE_TORQUE_SIZE_FOR(TYPE, TypeName) \
if (instance_type == TYPE) { \ if (instance_type == TYPE) { \
TypeName instance = TypeName::unchecked_cast(*this); \ return TypeName::unchecked_cast(*this).AllocatedSize(); \
return TypeName::SizeFor(instance); \
} }
TORQUE_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_SIZE_FOR) TORQUE_INSTANCE_TYPE_TO_BODY_DESCRIPTOR_LIST(MAKE_TORQUE_SIZE_FOR)
#undef MAKE_TORQUE_SIZE_FOR #undef MAKE_TORQUE_SIZE_FOR
if (instance_type == CODE_TYPE) { if (instance_type == CODE_TYPE) {
......
...@@ -569,12 +569,13 @@ void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) { ...@@ -569,12 +569,13 @@ void SeqTwoByteString::SeqTwoByteStringSet(int index, uint16_t value) {
WriteField<uint16_t>(kHeaderSize + index * kShortSize, value); WriteField<uint16_t>(kHeaderSize + index * kShortSize, value);
} }
int SeqTwoByteString::SeqTwoByteStringSize(InstanceType instance_type) { // Due to ThinString rewriting, concurrent visitors need to read the length with
return SizeFor(length()); // acquire semantics.
inline int SeqOneByteString::AllocatedSize() {
return SizeFor(synchronized_length());
} }
inline int SeqTwoByteString::AllocatedSize() {
int SeqOneByteString::SeqOneByteStringSize(InstanceType instance_type) { return SizeFor(synchronized_length());
return SizeFor(length());
} }
void SlicedString::set_parent(String parent, WriteBarrierMode mode) { void SlicedString::set_parent(String parent, WriteBarrierMode mode) {
......
...@@ -558,16 +558,13 @@ class SeqOneByteString ...@@ -558,16 +558,13 @@ class SeqOneByteString
// instance. // instance.
inline int SeqOneByteStringSize(InstanceType instance_type); 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. // Maximal memory usage for a single sequential one-byte string.
static const int kMaxCharsSize = kMaxLength; static const int kMaxCharsSize = kMaxLength;
static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxCharsSize + kHeaderSize); static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxCharsSize + kHeaderSize);
STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength); STATIC_ASSERT((kMaxSize - kHeaderSize) >= String::kMaxLength);
int AllocatedSize();
class BodyDescriptor; class BodyDescriptor;
TQ_OBJECT_CONSTRUCTORS(SeqOneByteString) TQ_OBJECT_CONSTRUCTORS(SeqOneByteString)
...@@ -599,17 +596,14 @@ class SeqTwoByteString ...@@ -599,17 +596,14 @@ class SeqTwoByteString
// instance. // instance.
inline int SeqTwoByteStringSize(InstanceType instance_type); 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. // Maximal memory usage for a single sequential two-byte string.
static const int kMaxCharsSize = kMaxLength * 2; static const int kMaxCharsSize = kMaxLength * 2;
static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxCharsSize + kHeaderSize); static const int kMaxSize = OBJECT_POINTER_ALIGN(kMaxCharsSize + kHeaderSize);
STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize) / sizeof(uint16_t)) >= STATIC_ASSERT(static_cast<int>((kMaxSize - kHeaderSize) / sizeof(uint16_t)) >=
String::kMaxLength); String::kMaxLength);
int AllocatedSize();
class BodyDescriptor; class BodyDescriptor;
TQ_OBJECT_CONSTRUCTORS(SeqTwoByteString) TQ_OBJECT_CONSTRUCTORS(SeqTwoByteString)
...@@ -639,7 +633,7 @@ class ConsString : public TorqueGeneratedConsString<ConsString, String> { ...@@ -639,7 +633,7 @@ class ConsString : public TorqueGeneratedConsString<ConsString, String> {
// Minimum length for a cons string. // Minimum length for a cons string.
static const int kMinLength = 13; static const int kMinLength = 13;
using BodyDescriptor = FixedBodyDescriptor<kFirstOffset, kSize, kSize>; class BodyDescriptor;
DECL_VERIFIER(ConsString) DECL_VERIFIER(ConsString)
...@@ -661,7 +655,7 @@ class ThinString : public TorqueGeneratedThinString<ThinString, String> { ...@@ -661,7 +655,7 @@ class ThinString : public TorqueGeneratedThinString<ThinString, String> {
DECL_VERIFIER(ThinString) DECL_VERIFIER(ThinString)
using BodyDescriptor = FixedBodyDescriptor<kActualOffset, kSize, kSize>; class BodyDescriptor;
TQ_OBJECT_CONSTRUCTORS(ThinString) TQ_OBJECT_CONSTRUCTORS(ThinString)
}; };
...@@ -688,7 +682,7 @@ class SlicedString : public TorqueGeneratedSlicedString<SlicedString, String> { ...@@ -688,7 +682,7 @@ class SlicedString : public TorqueGeneratedSlicedString<SlicedString, String> {
// Minimum length for a sliced string. // Minimum length for a sliced string.
static const int kMinLength = 13; static const int kMinLength = 13;
using BodyDescriptor = FixedBodyDescriptor<kParentOffset, kSize, kSize>; class BodyDescriptor;
DECL_VERIFIER(SlicedString) DECL_VERIFIER(SlicedString)
......
...@@ -10,12 +10,14 @@ extern class String extends Name { ...@@ -10,12 +10,14 @@ extern class String extends Name {
} }
@generateCppClass @generateCppClass
@generateBodyDescriptor
extern class ConsString extends String { extern class ConsString extends String {
first: String; first: String;
second: String; second: String;
} }
@abstract @abstract
@generateBodyDescriptor
extern class ExternalString extends String { extern class ExternalString extends String {
resource: RawPtr; resource: RawPtr;
resource_data: RawPtr; resource_data: RawPtr;
...@@ -28,27 +30,30 @@ extern class ExternalTwoByteString extends ExternalString {} ...@@ -28,27 +30,30 @@ extern class ExternalTwoByteString extends ExternalString {}
extern class InternalizedString extends String { extern class InternalizedString extends String {
} }
// TODO(v8:8983): Add declaration for variable-sized region.
@abstract @abstract
@generateCppClass @generateCppClass
extern class SeqString extends String { extern class SeqString extends String {
} }
@generateCppClass @generateCppClass
@generateBodyDescriptor
extern class SeqOneByteString extends SeqString { extern class SeqOneByteString extends SeqString {
chars[length]: char8; chars[length]: char8;
} }
@generateCppClass @generateCppClass
@generateBodyDescriptor
extern class SeqTwoByteString extends SeqString { extern class SeqTwoByteString extends SeqString {
chars[length]: char16; chars[length]: char16;
} }
@generateCppClass @generateCppClass
@generateBodyDescriptor
extern class SlicedString extends String { extern class SlicedString extends String {
parent: String; parent: String;
offset: Smi; offset: Smi;
} }
@generateCppClass @generateCppClass
@generateBodyDescriptor
extern class ThinString extends String { extern class ThinString extends String {
actual: String; actual: String;
} }
......
...@@ -127,7 +127,6 @@ enum class ClassFlag { ...@@ -127,7 +127,6 @@ enum class ClassFlag {
kIsShape = 1 << 5, kIsShape = 1 << 5,
kHasSameInstanceTypeAsParent = 1 << 6, kHasSameInstanceTypeAsParent = 1 << 6,
kGenerateCppClassDefinitions = 1 << 7, kGenerateCppClassDefinitions = 1 << 7,
kHasIndexedField = 1 << 8,
kHighestInstanceTypeWithinParent = 1 << 9, kHighestInstanceTypeWithinParent = 1 << 9,
kLowestInstanceTypeWithinParent = 1 << 10, kLowestInstanceTypeWithinParent = 1 << 10,
kUndefinedLayout = 1 << 11, kUndefinedLayout = 1 << 11,
......
...@@ -67,6 +67,14 @@ class GlobalContext : public ContextualClass<GlobalContext> { ...@@ -67,6 +67,14 @@ class GlobalContext : public ContextualClass<GlobalContext> {
return Get().generated_per_file_[file]; 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: private:
bool collect_language_server_data_; bool collect_language_server_data_;
bool force_assert_statements_; bool force_assert_statements_;
...@@ -76,6 +84,7 @@ class GlobalContext : public ContextualClass<GlobalContext> { ...@@ -76,6 +84,7 @@ class GlobalContext : public ContextualClass<GlobalContext> {
std::set<std::string> cpp_includes_; std::set<std::string> cpp_includes_;
std::map<SourceId, PerFileStreams> generated_per_file_; std::map<SourceId, PerFileStreams> generated_per_file_;
std::map<std::string, size_t> fresh_ids_; std::map<std::string, size_t> fresh_ids_;
bool instance_types_initialized_ = false;
friend class LanguageServerData; friend class LanguageServerData;
}; };
......
This diff is collapsed.
...@@ -256,6 +256,9 @@ int SolveInstanceTypeConstraints( ...@@ -256,6 +256,9 @@ int SolveInstanceTypeConstraints(
root->start = root->value; root->start = root->value;
} }
root->num_values = root->end - root->start + 1; 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) { if (root->num_values > 0) {
destination->push_back(std::move(root)); destination->push_back(std::move(root));
...@@ -485,6 +488,8 @@ void ImplementationVisitor::GenerateInstanceTypes( ...@@ -485,6 +488,8 @@ void ImplementationVisitor::GenerateInstanceTypes(
} }
std::string output_header_path = output_directory + "/" + file_name; std::string output_header_path = output_directory + "/" + file_name;
WriteFile(output_header_path, header.str()); WriteFile(output_header_path, header.str());
GlobalContext::SetInstanceTypesInitialized();
} }
} // namespace torque } // namespace torque
......
...@@ -73,6 +73,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) { ...@@ -73,6 +73,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
ImplementationVisitor implementation_visitor; ImplementationVisitor implementation_visitor;
implementation_visitor.SetDryRun(output_directory.length() == 0); implementation_visitor.SetDryRun(output_directory.length() == 0);
implementation_visitor.GenerateInstanceTypes(output_directory);
implementation_visitor.BeginCSAFiles(); implementation_visitor.BeginCSAFiles();
implementation_visitor.VisitAllDeclarables(); implementation_visitor.VisitAllDeclarables();
...@@ -91,7 +92,6 @@ void CompileCurrentAst(TorqueCompilerOptions options) { ...@@ -91,7 +92,6 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
implementation_visitor.GenerateBodyDescriptors(output_directory); implementation_visitor.GenerateBodyDescriptors(output_directory);
implementation_visitor.GenerateExportedMacrosAssembler(output_directory); implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
implementation_visitor.GenerateCSATypes(output_directory); implementation_visitor.GenerateCSATypes(output_directory);
implementation_visitor.GenerateInstanceTypes(output_directory);
implementation_visitor.EndCSAFiles(); implementation_visitor.EndCSAFiles();
implementation_visitor.GenerateImplementation(output_directory); implementation_visitor.GenerateImplementation(output_directory);
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <iostream> #include <iostream>
#include "src/base/optional.h"
#include "src/torque/types.h" #include "src/torque/types.h"
#include "src/base/bits.h" #include "src/base/bits.h"
...@@ -528,6 +529,121 @@ std::vector<Field> ClassType::ComputeAllFields() const { ...@@ -528,6 +529,121 @@ std::vector<Field> ClassType::ComputeAllFields() const {
return all_fields; 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() { void ClassType::GenerateAccessors() {
// For each field, construct AST snippets that implement a CSA accessor // For each field, construct AST snippets that implement a CSA accessor
// function. The implementation iterator will turn the snippets into code. // function. The implementation iterator will turn the snippets into code.
......
...@@ -611,6 +611,23 @@ class StructType final : public AggregateType { ...@@ -611,6 +611,23 @@ class StructType final : public AggregateType {
class TypeAlias; 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 { class ClassType final : public AggregateType {
public: public:
DECLARE_TYPE_BOILERPLATE(ClassType) DECLARE_TYPE_BOILERPLATE(ClassType)
...@@ -627,6 +644,7 @@ class ClassType final : public AggregateType { ...@@ -627,6 +644,7 @@ class ClassType final : public AggregateType {
(!HasUndefinedLayout() && !IsShape())); (!HasUndefinedLayout() && !IsShape()));
} }
bool ShouldGenerateBodyDescriptor() const { bool ShouldGenerateBodyDescriptor() const {
if (IsAbstract()) return false;
return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern(); return flags_ & ClassFlag::kGenerateBodyDescriptor || !IsExtern();
} }
bool IsTransient() const override { return flags_ & ClassFlag::kTransient; } bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
...@@ -661,6 +679,14 @@ class ClassType final : public AggregateType { ...@@ -661,6 +679,14 @@ class ClassType final : public AggregateType {
void Finalize() const override; void Finalize() const override;
std::vector<Field> ComputeAllFields() const; 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 { const InstanceTypeConstraints& GetInstanceTypeConstraints() const {
return decl_->instance_type_constraints; return decl_->instance_type_constraints;
...@@ -676,6 +702,14 @@ class ClassType final : public AggregateType { ...@@ -676,6 +702,14 @@ class ClassType final : public AggregateType {
} }
SourcePosition GetPosition() const { return decl_->pos; } 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: private:
friend class TypeOracle; friend class TypeOracle;
friend class TypeVisitor; friend class TypeVisitor;
...@@ -689,6 +723,8 @@ class ClassType final : public AggregateType { ...@@ -689,6 +723,8 @@ class ClassType final : public AggregateType {
const std::string generates_; const std::string generates_;
const ClassDeclaration* decl_; const ClassDeclaration* decl_;
const TypeAlias* alias_; 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) { inline std::ostream& operator<<(std::ostream& os, const Type& t) {
......
...@@ -1144,6 +1144,14 @@ namespace test { ...@@ -1144,6 +1144,14 @@ namespace test {
b: HeapObject; b: HeapObject;
} }
@abstract
class AbstractInternalClass extends HeapObject {
}
class AbstractInternalClassSubclass1 extends AbstractInternalClass {}
class AbstractInternalClassSubclass2 extends AbstractInternalClass {}
class InternalClassWithSmiElements extends FixedArrayBase { class InternalClassWithSmiElements extends FixedArrayBase {
data: Smi; data: Smi;
object: Oddball; object: Oddball;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment