diff options
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4identifiertable_p.h | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mm.cpp | 33 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 34 |
6 files changed, 57 insertions, 32 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 6dd33d3f47..4f8f329e2b 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -914,9 +914,9 @@ void ExecutionEngine::markObjects() Heap::ExecutionContext *c = currentContext(); while (c) { Q_ASSERT(c->inUse()); - if (!c->markBit) { - c->markBit = 1; - c->internalClass->vtable->markObjects(c, this); + if (!c->isMarked()) { + c->setMarkBit(); + c->gcGetInternalClass()->vtable->markObjects(c, this); } c = c->parent; } diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 017b2a8c52..8b813ea598 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -403,7 +403,7 @@ void Managed::mark(QV4::ExecutionEngine *engine) Q_ASSERT(inUse()); if (markBit()) return; - d()->markBit = 1; + d()->setMarkBit(); engine->pushForGC(d()); } @@ -412,9 +412,9 @@ inline void Heap::Base::mark(QV4::ExecutionEngine *engine) { Q_ASSERT(inUse()); - if (markBit) + if (isMarked()) return; - markBit = 1; + setMarkBit(); engine->pushForGC(this); } diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h index fe88584c2e..5d29d44dc0 100644 --- a/src/qml/jsruntime/qv4identifiertable_p.h +++ b/src/qml/jsruntime/qv4identifiertable_p.h @@ -77,11 +77,11 @@ public: void mark(ExecutionEngine *e) { for (int i = 0; i < alloc; ++i) { Heap::String *entry = entries[i]; - if (!entry || entry->markBit) + if (!entry || entry->isMarked()) continue; - entry->markBit = 1; - Q_ASSERT(entry->internalClass->vtable->markObjects); - entry->internalClass->vtable->markObjects(entry, e); + entry->setMarkBit(); + Q_ASSERT(entry->gcGetInternalClass()->vtable->markObjects); + entry->gcGetInternalClass()->vtable->markObjects(entry, e); } } }; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 27a601ee13..fad3b85b2e 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -291,7 +291,7 @@ public: void setInternalClass(InternalClass *ic) { d()->internalClass = ic; } bool inUse() const { return d()->inUse(); } - bool markBit() const { return d()->markBit; } + bool markBit() const { return d()->isMarked(); } static void destroy(Heap::Base *) {} private: diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index ff84e47ef9..4ddb544cba 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -188,9 +188,9 @@ void sweepChunk(const MemoryManager::Data::Chunk &chunk, ChunkSweepData *sweepDa Q_ASSERT((qintptr) item % 16 == 0); - if (m->markBit) { + if (m->isMarked()) { Q_ASSERT(m->inUse()); - m->markBit = 0; + m->clearMarkBit(); sweepData->isEmpty = false; ++(*itemsInUse); } else { @@ -199,8 +199,8 @@ void sweepChunk(const MemoryManager::Data::Chunk &chunk, ChunkSweepData *sweepDa #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif - if (m->internalClass->vtable->destroy) - m->internalClass->vtable->destroy(m); + if (m->gcGetInternalClass()->vtable->destroy) + m->gcGetInternalClass()->vtable->destroy(m); memset(m, 0, itemSize); #ifdef V4_USE_VALGRIND @@ -326,8 +326,8 @@ static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) { while (engine->jsStackTop > markBase) { Heap::Base *h = engine->popForGC(); - Q_ASSERT (h->internalClass->vtable->markObjects); - h->internalClass->vtable->markObjects(h, engine); + Q_ASSERT (h->gcGetInternalClass()->vtable->markObjects); + h->gcGetInternalClass()->vtable->markObjects(h, engine); } } @@ -364,7 +364,9 @@ void MemoryManager::mark() for (PersistentValuePrivate *weak = m_weakValues; weak; weak = weak->next) { if (!weak->refcount || !weak->value.isManaged()) continue; - QObjectWrapper *qobjectWrapper = weak->value.managed()->as<QObjectWrapper>(); + if (weak->value.asManaged()->d()->gcGetInternalClass()->vtable != QObjectWrapper::staticVTable()) + continue; + QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>(weak->value.managed()); if (!qobjectWrapper) continue; QObject *qobject = qobjectWrapper->object(); @@ -481,14 +483,14 @@ void MemoryManager::sweep(bool lastSweep) while (i) { Heap::Base *m = i->heapObject(); Q_ASSERT(m->inUse()); - if (m->markBit) { - m->markBit = 0; + if (m->isMarked()) { + m->clearMarkBit(); last = &i->next; i = i->next; continue; } - if (m->internalClass->vtable->destroy) - m->internalClass->vtable->destroy(m); + if (m->gcGetInternalClass()->vtable->destroy) + m->gcGetInternalClass()->vtable->destroy(m); *last = i->next; free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem), @@ -504,6 +506,15 @@ void MemoryManager::sweep(bool lastSweep) delete deletable; deletable = next; } + + // some execution contexts are allocated on the stack, make sure we clear their markBit as well + if (!lastSweep) { + Heap::ExecutionContext *ctx = engine()->current; + while (ctx) { + ctx->clearMarkBit(); + ctx = ctx->parent; + } + } } bool MemoryManager::isGCBlocked() const diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 12e81d4f30..31db8a21c5 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -50,15 +50,18 @@ struct Q_QML_EXPORT Base { Base() {} Base(InternalClass *internal) : internalClass(internal) - , markBit(0) , extensible(1) { + Q_ASSERT(inUse() && !isMarked()); // #### // Q_ASSERT(internal && internal->vtable); } - InternalClass *internalClass; + union { + InternalClass *internalClass; + quintptr mm_data; + }; struct { - uchar markBit : 1; + uchar _markBit : 1; uchar _inUse : 1; uchar extensible : 1; // used by Object uchar _needsActivation : 1; // used by FunctionObject @@ -76,23 +79,34 @@ struct Q_QML_EXPORT Base { inline ReturnedValue asReturnedValue() const; inline void mark(QV4::ExecutionEngine *engine); - inline bool isMarked() const { - return markBit; - } - enum { + MarkBit = 0x1, NotInUse = 0x2, PointerMask = ~0x3 }; + + InternalClass *gcGetInternalClass() const { + return reinterpret_cast<InternalClass *>(mm_data & PointerMask); + } + inline bool isMarked() const { + return mm_data & MarkBit; + } + inline void setMarkBit() { + mm_data |= MarkBit; + } + inline void clearMarkBit() { + mm_data &= ~MarkBit; + } + inline bool inUse() const { - return !((quintptr)internalClass & NotInUse); + return !(mm_data & NotInUse); } Base *nextFree() { - return reinterpret_cast<Base *>(reinterpret_cast<quintptr>(internalClass) & PointerMask); + return reinterpret_cast<Base *>(mm_data & PointerMask); } void setNextFree(Base *m) { - internalClass = reinterpret_cast<InternalClass *>(reinterpret_cast<quintptr>(m) | NotInUse); + mm_data = (reinterpret_cast<quintptr>(m) | NotInUse); } void *operator new(size_t, Managed *m) { return m; } |