diff options
Diffstat (limited to 'src/qml/memory/qv4mmdefs_p.h')
-rw-r--r-- | src/qml/memory/qv4mmdefs_p.h | 108 |
1 files changed, 101 insertions, 7 deletions
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h index ef93971ab8..328797fb5e 100644 --- a/src/qml/memory/qv4mmdefs_p.h +++ b/src/qml/memory/qv4mmdefs_p.h @@ -116,22 +116,29 @@ struct Chunk { HeapItem *realBase(); HeapItem *first(); + static Q_ALWAYS_INLINE size_t bitmapIndex(size_t index) { + return index >> BitShift; + } + static Q_ALWAYS_INLINE quintptr bitForIndex(size_t index) { + return static_cast<quintptr>(1) << (index & (Bits - 1)); + } + static void setBit(quintptr *bitmap, size_t index) { // Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize); - bitmap += index >> BitShift; - quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1)); + bitmap += bitmapIndex(index); + quintptr bit = bitForIndex(index); *bitmap |= bit; } static void clearBit(quintptr *bitmap, size_t index) { // Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize); - bitmap += index >> BitShift; - quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1)); + bitmap += bitmapIndex(index); + quintptr bit = bitForIndex(index); *bitmap &= ~bit; } static bool testBit(quintptr *bitmap, size_t index) { // Q_ASSERT(index >= HeaderSize/SlotSize && index < ChunkSize/SlotSize); - bitmap += index >> BitShift; - quintptr bit = static_cast<quintptr>(1) << (index & (Bits - 1)); + bitmap += bitmapIndex(index); + quintptr bit = bitForIndex(index); return (*bitmap & bit); } static void setBits(quintptr *bitmap, size_t index, size_t nBits) { @@ -179,8 +186,10 @@ struct Chunk { return usedSlots; } - bool sweep(); + bool sweep(ClassDestroyStatsCallback classCountPtr); void freeAll(); + void resetBlackBits(); + void collectGrayItems(QV4::MarkStack *markStack); void sortIntoBins(HeapItem **bins, uint nBins); }; @@ -260,6 +269,91 @@ Q_STATIC_ASSERT(sizeof(HeapItem) == Chunk::SlotSize); Q_STATIC_ASSERT(QT_POINTER_SIZE*8 == Chunk::Bits); Q_STATIC_ASSERT((1 << Chunk::BitShift) == Chunk::Bits); +struct MarkStack { + MarkStack(ExecutionEngine *engine); + Heap::Base **top = 0; + Heap::Base **base = 0; + Heap::Base **limit = 0; + ExecutionEngine *engine; + void push(Heap::Base *m) { + *top = m; + ++top; + } + Heap::Base *pop() { + --top; + return *top; + } + void drain(); + +}; + +// Some helper classes and macros to automate the generation of our +// tables used for marking objects + +enum MarkFlags { + Mark_NoMark = 0, + Mark_Value = 1, + Mark_Pointer = 2, + Mark_ValueArray = 3 +}; + +template <typename T> +struct MarkFlagEvaluator { + static Q_CONSTEXPR quint64 value = 0; +}; +template <typename T, size_t o> +struct MarkFlagEvaluator<Heap::Pointer<T, o>> { + static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Pointer) << (2*o / sizeof(quintptr)); +}; +template <size_t o> +struct MarkFlagEvaluator<ValueArray<o>> { + static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_ValueArray) << (2*o / sizeof(quintptr)); +}; +template <size_t o> +struct MarkFlagEvaluator<HeapValue<o>> { + static Q_CONSTEXPR quint64 value = static_cast<quint64>(Mark_Value) << (2 *o / sizeof(quintptr)); +}; + +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION(c, gcType, type, name) \ + HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_##gcType(c, type, name) + +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_Pointer(c, type, name) Pointer<type, 0> name; +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_NoMark(c, type, name) type name; +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_HeapValue(c, type, name) HeapValue<0> name; +#define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_ValueArray(c, type, name) type<0> name; + +#define HEAP_OBJECT_MEMBER_EXPANSION(c, gcType, type, name) \ + HEAP_OBJECT_MEMBER_EXPANSION_##gcType(c, type, name) + +#define HEAP_OBJECT_MEMBER_EXPANSION_Pointer(c, type, name) \ + Pointer<type, offsetof(c##OffsetStruct, name) + baseOffset> name; +#define HEAP_OBJECT_MEMBER_EXPANSION_NoMark(c, type, name) \ + type name; +#define HEAP_OBJECT_MEMBER_EXPANSION_HeapValue(c, type, name) \ + HeapValue<offsetof(c##OffsetStruct, name) + baseOffset> name; +#define HEAP_OBJECT_MEMBER_EXPANSION_ValueArray(c, type, name) \ + type<offsetof(c##OffsetStruct, name) + baseOffset> name; + +#define HEAP_OBJECT_MARK_EXPANSION(class, gcType, type, name) \ + MarkFlagEvaluator<decltype(class::name)>::value | + +#define DECLARE_HEAP_OBJECT(name, base) \ +struct name##OffsetStruct { \ + name##Members(name, HEAP_OBJECT_OFFSET_MEMBER_EXPANSION) \ +}; \ +struct name##SizeStruct : base, name##OffsetStruct {}; \ +struct name##Data { \ + static Q_CONSTEXPR size_t baseOffset = sizeof(name##SizeStruct) - sizeof(name##OffsetStruct); \ + name##Members(name, HEAP_OBJECT_MEMBER_EXPANSION) \ +}; \ +Q_STATIC_ASSERT(sizeof(name##SizeStruct) == sizeof(name##Data) + name##Data::baseOffset); \ +static Q_CONSTEXPR quint64 name##_markTable = \ + (name##Members(name##Data, HEAP_OBJECT_MARK_EXPANSION) 0) | QV4::Heap::base::markTable; \ + \ +struct name : base, name##Data + +#define DECLARE_MARK_TABLE(class) static Q_CONSTEXPR quint64 markTable = class##_markTable + } QT_END_NAMESPACE |