diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-11-02 16:02:10 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-11-14 21:45:42 +0000 |
commit | 002fdc48d43e4fd67921e0cd46c28d28aee06848 (patch) | |
tree | 08fdc81dc91153649d8b6c6514ed3b49ad970064 /src/qml/memory | |
parent | 010197a42150ee73a17cb53fbe397a6c55b2d342 (diff) |
Bring back markObjects(), this time generated
Doing the marking of objects in a function instead of
using the table seems to be somewhat faster.
Change-Id: I9ec00cc0264f9a15c69b285db493bee31d99bf96
Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/memory')
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 23 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 58 | ||||
-rw-r--r-- | src/qml/memory/qv4mmdefs_p.h | 61 | ||||
-rw-r--r-- | src/qml/memory/qv4writebarrier_p.h | 36 |
4 files changed, 78 insertions, 100 deletions
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index f00ce4283c..363e891d5c 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -75,7 +75,6 @@ struct InternalClass; struct VTable { const VTable * const parent; - const quint64 markTable; uint inlinePropertyOffset : 16; uint nInlineProperties : 16; uint isExecutionContext : 1; @@ -97,7 +96,7 @@ namespace Heap { struct Q_QML_EXPORT Base { void *operator new(size_t) = delete; - static Q_CONSTEXPR quint64 markTable = 0; + static void markObjects(Heap::Base *, MarkStack *) {} InternalClass *internalClass; @@ -131,7 +130,9 @@ struct Q_QML_EXPORT Base { return Chunk::testBit(c->objectBitmap, h - c->realBase()); } - inline void markChildren(MarkStack *markStack); + inline void markChildren(MarkStack *markStack) { + vtable()->markObjects(this, markStack); + } void *operator new(size_t, Managed *m) { return m; } void *operator new(size_t, Heap::Base *m) { return m; } @@ -184,6 +185,22 @@ Q_STATIC_ASSERT(sizeof(Base) == QT_POINTER_SIZE); } +inline +void Heap::Base::mark(QV4::MarkStack *markStack) +{ + Q_ASSERT(inUse()); + const HeapItem *h = reinterpret_cast<const HeapItem *>(this); + Chunk *c = h->chunk(); + size_t index = h - c->realBase(); + Q_ASSERT(!Chunk::testBit(c->extendsBitmap, index)); + quintptr *bitmap = c->blackBitmap + Chunk::bitmapIndex(index); + quintptr bit = Chunk::bitForIndex(index); + if (!(*bitmap & bit)) { + *bitmap |= bit; + markStack->push(this); + } +} + #ifdef QT_NO_QOBJECT template <class T> struct QQmlQPointer { diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 21c95bbe6e..3ea7908e9d 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -279,64 +279,6 @@ QString binary(quintptr) { return QString(); } #define SDUMP if (1) ; else qDebug #endif -void Heap::Base::markChildren(MarkStack *markStack) -{ - if (vtable()->markObjects) - vtable()->markObjects(this, markStack); - if (quint64 m = vtable()->markTable) { -// qDebug() << "using mark table:" << hex << m << "for" << h; - void **mem = reinterpret_cast<void **>(this); - while (m) { - MarkFlags mark = static_cast<MarkFlags>(m & 3); - switch (mark) { - case Mark_NoMark: - break; - case Mark_Value: -// qDebug() << "marking value at " << mem; - reinterpret_cast<Value *>(mem)->mark(markStack); - break; - case Mark_Pointer: { -// qDebug() << "marking pointer at " << mem; - Heap::Base *p = *reinterpret_cast<Heap::Base **>(mem); - if (p) - p->mark(markStack); - break; - } - case Mark_ValueArray: { - Q_ASSERT(m == Mark_ValueArray); -// qDebug() << "marking Value Array at offset" << hex << (mem - reinterpret_cast<void **>(h)); - ValueArray<0> *a = reinterpret_cast<ValueArray<0> *>(mem); - Value *v = a->values; - const Value *end = v + a->alloc; - if (a->alloc > 32*1024) { - // drain from time to time to avoid overflows in the js stack - Heap::Base **currentBase = markStack->top; - while (v < end) { - v->mark(markStack); - ++v; - if (markStack->top >= currentBase + 32*1024) { - Heap::Base **oldBase = markStack->base; - markStack->base = currentBase; - markStack->drain(); - markStack->base = oldBase; - } - } - } else { - while (v < end) { - v->mark(markStack); - ++v; - } - } - break; - } - } - - m >>= 2; - ++mem; - } - } -} - // Stores a classname -> freed count mapping. typedef QHash<const char*, int> MMStatsHash; Q_GLOBAL_STATIC(MMStatsHash, freedObjectStatsGlobal) diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h index 328797fb5e..6d911e69f6 100644 --- a/src/qml/memory/qv4mmdefs_p.h +++ b/src/qml/memory/qv4mmdefs_p.h @@ -287,32 +287,8 @@ struct MarkStack { }; -// 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)); -}; +// Some helper to automate the generation of our +// functions used for marking objects #define HEAP_OBJECT_OFFSET_MEMBER_EXPANSION(c, gcType, type, name) \ HEAP_OBJECT_OFFSET_MEMBER_EXPANSION_##gcType(c, type, name) @@ -334,25 +310,42 @@ struct MarkFlagEvaluator<HeapValue<o>> { #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 HEAP_OBJECT_MARKOBJECTS_EXPANSION(c, gcType, type, name) \ + HEAP_OBJECT_MARKOBJECTS_EXPANSION_##gcType(c, type, name) +#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_Pointer(c, type, name) \ + if (o->name) o->name.heapObject()->mark(stack); +#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_NoMark(c, type, name) +#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_HeapValue(c, type, name) \ + o->name.mark(stack); +#define HEAP_OBJECT_MARKOBJECTS_EXPANSION_ValueArray(c, type, name) \ + o->name.mark(stack); -#define DECLARE_HEAP_OBJECT(name, base) \ + +#define DECLARE_HEAP_OBJECT_BASE(name, base) \ struct name##OffsetStruct { \ name##Members(name, HEAP_OBJECT_OFFSET_MEMBER_EXPANSION) \ }; \ struct name##SizeStruct : base, name##OffsetStruct {}; \ struct name##Data { \ + typedef base SuperClass; \ 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 +#define DECLARE_HEAP_OBJECT(name, base) \ +DECLARE_HEAP_OBJECT_BASE(name, base) \ +struct name : base, name##Data +#define DECLARE_EXPORTED_HEAP_OBJECT(name, base) \ +DECLARE_HEAP_OBJECT_BASE(name, base) \ +struct Q_QML_EXPORT name : base, name##Data + +#define DECLARE_MARKOBJECTS(class) \ + static void markObjects(Heap::Base *b, MarkStack *stack) { \ + class *o = static_cast<class *>(b); \ + class##Data::SuperClass::markObjects(o, stack); \ + class##Members(class, HEAP_OBJECT_MARKOBJECTS_EXPANSION) \ + } } diff --git a/src/qml/memory/qv4writebarrier_p.h b/src/qml/memory/qv4writebarrier_p.h index f55c724c12..4ec224cc36 100644 --- a/src/qml/memory/qv4writebarrier_p.h +++ b/src/qml/memory/qv4writebarrier_p.h @@ -114,8 +114,8 @@ namespace Heap { template <typename T, size_t o> struct Pointer { static Q_CONSTEXPR size_t offset = o; - T operator->() const { return ptr; } - operator T () const { return ptr; } + T operator->() const { return get(); } + operator T () const { return get(); } Heap::Base *base() { Heap::Base *base = reinterpret_cast<Heap::Base *>(this) - (offset/sizeof(Heap::Base)); @@ -124,16 +124,18 @@ struct Pointer { } void set(EngineBase *e, T newVal) { - WriteBarrier::write(e, base(), reinterpret_cast<Heap::Base **>(&ptr), reinterpret_cast<Heap::Base *>(newVal)); + WriteBarrier::write(e, base(), &ptr, reinterpret_cast<Heap::Base *>(newVal)); } - T get() { return ptr; } + T get() const { return reinterpret_cast<T>(ptr); } template <typename Type> Type *cast() { return static_cast<Type *>(ptr); } + Heap::Base *heapObject() const { return ptr; } + private: - T ptr; + Heap::Base *ptr; }; typedef Pointer<char *, 0> V4PointerCheck; V4_ASSERT_IS_TRIVIAL(V4PointerCheck) @@ -194,6 +196,30 @@ struct ValueArray { values[i] = values[i + n]; } } + + void mark(MarkStack *markStack) { + Value *v = values; + const Value *end = v + alloc; + if (alloc > 32*1024) { + // drain from time to time to avoid overflows in the js stack + Heap::Base **currentBase = markStack->top; + while (v < end) { + v->mark(markStack); + ++v; + if (markStack->top >= currentBase + 32*1024) { + Heap::Base **oldBase = markStack->base; + markStack->base = currentBase; + markStack->drain(); + markStack->base = oldBase; + } + } + } else { + while (v < end) { + v->mark(markStack); + ++v; + } + } + } }; // It's really important that the offset of values in this structure is |