diff options
author | Lars Knoll <lars.knoll@theqtcompany.com> | 2015-01-09 19:48:56 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2015-01-12 11:04:30 +0100 |
commit | 53e144ae8dec84f70870a5e315c3043b16b57d92 (patch) | |
tree | 8ddc93adb025c19d1c45daab39a6c63b1f1b561b /src/qml/jsruntime | |
parent | 7a0d121f9eafee9dfb948dce01de8204c4385e94 (diff) |
Fold the inUse flag into the internalClass pointer
Revert the flag (ie. flag == 0 means the item is used), and fold it
into the second lowest bit of the internalClass/nextFree field.
Change-Id: I7b690fdce00d16aa538fa70a269a755511477c5c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mm.cpp | 54 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 21 |
5 files changed, 46 insertions, 35 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 39528e396a..6dd33d3f47 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -913,7 +913,7 @@ void ExecutionEngine::markObjects() Heap::ExecutionContext *c = currentContext(); while (c) { - Q_ASSERT(c->inUse); + Q_ASSERT(c->inUse()); if (!c->markBit) { c->markBit = 1; c->internalClass->vtable->markObjects(c, this); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 87aa3bb16f..017b2a8c52 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -411,7 +411,7 @@ void Managed::mark(QV4::ExecutionEngine *engine) inline void Heap::Base::mark(QV4::ExecutionEngine *engine) { - Q_ASSERT(inUse); + Q_ASSERT(inUse()); if (markBit) return; markBit = 1; diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 28b7059e4c..27a601ee13 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -290,7 +290,7 @@ public: InternalClass *internalClass() const { return d()->internalClass; } void setInternalClass(InternalClass *ic) { d()->internalClass = ic; } - bool inUse() const { return d()->inUse; } + bool inUse() const { return d()->inUse(); } bool markBit() const { return d()->markBit; } static void destroy(Heap::Base *) {} diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index e2d1d19654..ff84e47ef9 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -77,7 +77,7 @@ struct MemoryManager::Data ExecutionEngine *engine; enum { MaxItemSize = 512 }; - Heap::Base *smallItems[MaxItemSize/16]; + Heap::Base smallItems[MaxItemSize/16]; uint nChunks[MaxItemSize/16]; uint availableItems[MaxItemSize/16]; uint allocCount[MaxItemSize/16]; @@ -124,7 +124,8 @@ struct MemoryManager::Data , totalLargeItemsAllocated(0) , deletable(0) { - memset(smallItems, 0, sizeof(smallItems)); + for (int i = 0; i < MaxItemSize/16; ++i) + smallItems[i].setNextFree(0); memset(nChunks, 0, sizeof(nChunks)); memset(availableItems, 0, sizeof(availableItems)); memset(allocCount, 0, sizeof(allocCount)); @@ -165,9 +166,9 @@ bool operator<(const MemoryManager::Data::Chunk &a, const MemoryManager::Data::C namespace { struct ChunkSweepData { - ChunkSweepData() : tail(&head), head(0), isEmpty(true) { } - Heap::Base **tail; - Heap::Base *head; + ChunkSweepData() : tail(&head), isEmpty(true) { head.setNextFree(0); } + Heap::Base *tail; + Heap::Base head; bool isEmpty; }; @@ -188,12 +189,12 @@ void sweepChunk(const MemoryManager::Data::Chunk &chunk, ChunkSweepData *sweepDa Q_ASSERT((qintptr) item % 16 == 0); if (m->markBit) { - Q_ASSERT(m->inUse); + Q_ASSERT(m->inUse()); m->markBit = 0; sweepData->isEmpty = false; ++(*itemsInUse); } else { - if (m->inUse) { + if (m->inUse()) { // qDebug() << "-- collecting it." << m << sweepData->tail << m->nextFree(); #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; @@ -210,11 +211,11 @@ void sweepChunk(const MemoryManager::Data::Chunk &chunk, ChunkSweepData *sweepDa ++(*itemsInUse); } // Relink all free blocks to rewrite references to any released chunk. - *sweepData->tail = m; - sweepData->tail = m->nextFreeRef(); + sweepData->tail->setNextFree(m); + sweepData->tail = m; } } - *sweepData->tail = 0; + sweepData->tail->setNextFree(0); #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif @@ -262,14 +263,14 @@ Heap::Base *MemoryManager::allocData(std::size_t size) return item->heapObject(); } - Heap::Base *m = m_d->smallItems[pos]; + Heap::Base *m = m_d->smallItems[pos].nextFree(); if (m) goto found; // try to free up space, otherwise allocate if (m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) { runGC(); - m = m_d->smallItems[pos]; + m = m_d->smallItems[pos].nextFree(); if (m) goto found; } @@ -292,15 +293,15 @@ Heap::Base *MemoryManager::allocData(std::size_t size) char *chunk = (char *)allocation.memory.base(); char *end = chunk + allocation.memory.size() - size; - Heap::Base **last = &m_d->smallItems[pos]; + Heap::Base *last = &m_d->smallItems[pos]; while (chunk <= end) { Heap::Base *o = reinterpret_cast<Heap::Base *>(chunk); - *last = o; - last = o->nextFreeRef(); + last->setNextFree(o); + last = o; chunk += size; } - *last = 0; - m = m_d->smallItems[pos]; + last->setNextFree(0); + m = m_d->smallItems[pos].nextFree(); const size_t increase = allocation.memory.size()/size - 1; m_d->availableItems[pos] += uint(increase); m_d->totalItems += int(increase); @@ -317,7 +318,7 @@ Heap::Base *MemoryManager::allocData(std::size_t size) ++m_d->allocCount[pos]; ++m_d->totalAlloc; - m_d->smallItems[pos] = m->nextFree(); + m_d->smallItems[pos].setNextFree(m->nextFree()); return m; } @@ -431,10 +432,11 @@ void MemoryManager::sweep(bool lastSweep) sweepChunk(chunk, &chunkSweepData[i], &itemsInUse[chunk.chunkSize >> 4], m_d->engine); } - Heap::Base **tails[MemoryManager::Data::MaxItemSize/16]; - memset(m_d->smallItems, 0, sizeof(m_d->smallItems)); - for (int pos = 0; pos < MemoryManager::Data::MaxItemSize/16; ++pos) + Heap::Base *tails[MemoryManager::Data::MaxItemSize/16]; + for (int pos = 0; pos < MemoryManager::Data::MaxItemSize/16; ++pos) { + m_d->smallItems[pos].setNextFree(0); tails[pos] = &m_d->smallItems[pos]; + } #ifdef V4_USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; @@ -454,11 +456,11 @@ void MemoryManager::sweep(bool lastSweep) chunkIter->memory.deallocate(); chunkIter = m_d->heapChunks.erase(chunkIter); continue; - } else if (chunkSweepData[i].head) { + } else if (chunkSweepData[i].head.nextFree()) { #ifdef V4_USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; #endif - *tails[pos] = chunkSweepData[i].head; + tails[pos]->setNextFree(chunkSweepData[i].head.nextFree()); #ifdef V4_USE_VALGRIND VALGRIND_ENABLE_ERROR_REPORTING; #endif @@ -470,7 +472,7 @@ void MemoryManager::sweep(bool lastSweep) #ifdef V4_USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; for (int pos = 0; pos < MemoryManager::Data::MaxItemSize/16; ++pos) - Q_ASSERT(*tails[pos] == 0); + Q_ASSERT(tails[pos]->nextFree() == 0); VALGRIND_ENABLE_ERROR_REPORTING; #endif @@ -478,7 +480,7 @@ void MemoryManager::sweep(bool lastSweep) Data::LargeItem **last = &m_d->largeItems; while (i) { Heap::Base *m = i->heapObject(); - Q_ASSERT(m->inUse); + Q_ASSERT(m->inUse()); if (m->markBit) { m->markBit = 0; last = &i->next; @@ -563,7 +565,7 @@ size_t MemoryManager::getUsedMem() const for (char *chunk = chunkStart; chunk <= chunkEnd; chunk += i->chunkSize) { Heap::Base *m = reinterpret_cast<Heap::Base *>(chunk); Q_ASSERT((qintptr) chunk % 16 == 0); - if (m->inUse) + if (m->inUse()) usedMem += i->chunkSize; } } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 02a4fcf6e0..12e81d4f30 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -47,10 +47,10 @@ typedef uint Bool; namespace Heap { struct Q_QML_EXPORT Base { + Base() {} Base(InternalClass *internal) : internalClass(internal) , markBit(0) - , inUse(1) , extensible(1) { // #### @@ -59,7 +59,7 @@ struct Q_QML_EXPORT Base { InternalClass *internalClass; struct { uchar markBit : 1; - uchar inUse : 1; + uchar _inUse : 1; uchar extensible : 1; // used by Object uchar _needsActivation : 1; // used by FunctionObject uchar _strictMode : 1; // used by FunctionObject @@ -76,14 +76,23 @@ struct Q_QML_EXPORT Base { inline ReturnedValue asReturnedValue() const; inline void mark(QV4::ExecutionEngine *engine); - Base **nextFreeRef() { - return reinterpret_cast<Base **>(this); + inline bool isMarked() const { + return markBit; } + + enum { + NotInUse = 0x2, + PointerMask = ~0x3 + }; + inline bool inUse() const { + return !((quintptr)internalClass & NotInUse); + } + Base *nextFree() { - return *reinterpret_cast<Base **>(this); + return reinterpret_cast<Base *>(reinterpret_cast<quintptr>(internalClass) & PointerMask); } void setNextFree(Base *m) { - *reinterpret_cast<Base **>(this) = m; + internalClass = reinterpret_cast<InternalClass *>(reinterpret_cast<quintptr>(m) | NotInUse); } void *operator new(size_t, Managed *m) { return m; } |