aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-04-27 19:37:35 +0200
committerRobin Burchell <robin.burchell@crimson.no>2017-04-28 19:48:26 +0000
commit6a2febc680e163e56eb61d322d156dbf6fb07e0e (patch)
tree889a118a0410dff1312696f3841156f416c3833e
parent4a4a8e911cfafcff069de0c1acb2462974166938 (diff)
Fix memory leak in the memory manager
There was a bug in Chunk::sweep() that would lead to parts of the memory not being freed as it should have been. This happened when an object 'overflowed' into the next index of the estendBitmap, where we then would not correctly clear the extends bits. Fixes performance degradation in qmlbench's delegates_item_empty_jscreation.qml over multiple runs. Change-Id: Ia2cecd2ff218e4258a067a74631b5479589b7a7e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Robin Burchell <robin.burchell@crimson.no>
-rw-r--r--src/qml/memory/qv4mm.cpp34
1 files changed, 32 insertions, 2 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 88912a6678..7aa8f91503 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -262,17 +262,36 @@ void ChunkAllocator::free(Chunk *chunk, size_t size)
Q_ASSERT(false);
}
+#ifdef DUMP_SWEEP
+QString binary(quintptr n) {
+ QString s = QString::number(n, 2);
+ while (s.length() < 64)
+ s.prepend(QChar::fromLatin1('0'));
+ return s;
+}
+#define SDUMP qDebug
+#else
+QString binary(quintptr) { return QString(); }
+#define SDUMP if (1) ; else qDebug
+#endif
void Chunk::sweep()
{
- // DEBUG << "sweeping chunk" << this << (*freeList);
+ SDUMP() << "sweeping chunk" << this;
HeapItem *o = realBase();
+ bool lastSlotFree = false;
for (uint i = 0; i < Chunk::EntriesInBitmap; ++i) {
Q_ASSERT((grayBitmap[i] | blackBitmap[i]) == blackBitmap[i]); // check that we don't have gray only objects
quintptr toFree = objectBitmap[i] ^ blackBitmap[i];
Q_ASSERT((toFree & objectBitmap[i]) == toFree); // check all black objects are marked as being used
quintptr e = extendsBitmap[i];
- // DEBUG << hex << " index=" << i << toFree;
+ SDUMP() << " index=" << i;
+ SDUMP() << " toFree =" << binary(toFree);
+ SDUMP() << " black =" << binary(blackBitmap[i]);
+ SDUMP() << " object =" << binary(objectBitmap[i]);
+ SDUMP() << " extends =" << binary(e);
+ if (lastSlotFree)
+ e &= (e + 1); // clear all lowest extent bits
while (toFree) {
uint index = qCountTrailingZeroBits(toFree);
quintptr bit = (static_cast<quintptr>(1) << index);
@@ -299,6 +318,10 @@ void Chunk::sweep()
objectBitmap[i] = blackBitmap[i];
blackBitmap[i] = 0;
extendsBitmap[i] = e;
+ lastSlotFree = !((objectBitmap[i]|extendsBitmap[i]) >> (sizeof(quintptr)*8 - 1));
+ SDUMP() << " new extends =" << binary(e);
+ SDUMP() << " lastSlotFree" << lastSlotFree;
+ Q_ASSERT((objectBitmap[i] & extendsBitmap[i]) == 0);
o += Chunk::Bits;
}
// DEBUG << "swept chunk" << this << "freed" << slotsFreed << "slots.";
@@ -887,6 +910,13 @@ size_t dumpBins(BlockAllocator *b, bool printOutput = true)
if (printOutput)
qDebug() << " number of entries in slot" << i << ":" << nEntries;
}
+ SDUMP() << " large slot map";
+ HeapItem *h = b->freeBins[BlockAllocator::NumBins - 1];
+ while (h) {
+ SDUMP() << " " << hex << (quintptr(h)/32) << h->freeData.availableSlots;
+ h = h->freeData.next;
+ }
+
if (printOutput)
qDebug() << " total mem in bins" << totalFragmentedSlots*Chunk::SlotSize;
return totalFragmentedSlots*Chunk::SlotSize;