diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-03-07 08:48:57 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-03-08 09:02:02 +0000 |
commit | c99abf1851bbbfcec11eb77173df620746940ab0 (patch) | |
tree | a8f4b9c1ebe9cb78d7ac585aa8b299a2a820fdca | |
parent | 73e8321255d9f0e70529a58c10dbaf4790a9a659 (diff) |
Fix issue with allocating huge objects in the memory manager
We shouldn't allocate objects that are larger than the size of
a standard memory segment through the chunk allocator, as this
can lead to problems when freeing the segment and then re-using
it again.
Instead allocate a private MemorySegment for these objects, and
free it when the object gets garbage collected.
Task-number: QTBUG-66732
Change-Id: Ic24ff65d204977f313ab0adaf7a8132883e525f0
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 25 | ||||
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 2 |
2 files changed, 24 insertions, 3 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index cdda0bf7ef..4e83abebdf 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -664,8 +664,21 @@ void BlockAllocator::collectGrayItems(MarkStack *markStack) } HeapItem *HugeItemAllocator::allocate(size_t size) { - Chunk *c = chunkAllocator->allocate(size); - chunks.push_back(HugeChunk{c, size}); + MemorySegment *m = nullptr; + Chunk *c = nullptr; + if (size >= MemorySegment::SegmentSize/2) { + // too large to handle through the ChunkAllocator, let's get our own memory segement + size_t segmentSize = size + Chunk::HeaderSize; // space required for the Chunk header + size_t pageSize = WTF::pageSize(); + segmentSize = (segmentSize + pageSize - 1) & ~(pageSize - 1); // align to page sizes + m = new MemorySegment(segmentSize); + size = (size + pageSize - 1) & ~(pageSize - 1); // align to page sizes + c = m->allocate(size); + } else { + c = chunkAllocator->allocate(size); + } + Q_ASSERT(c); + chunks.push_back(HugeChunk{m, c, size}); Chunk::setBit(c->objectBitmap, c->first() - c->realBase()); Q_V4_PROFILE_ALLOC(engine, size, Profiling::LargeItem); #ifdef V4_USE_HEAPTRACK @@ -686,7 +699,13 @@ static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocato v->destroy(b); b->_checkIsDestroyed(); } - chunkAllocator->free(c.chunk, c.size); + if (c.segment) { + // own memory segment + c.segment->free(c.chunk, c.size); + delete c.segment; + } else { + chunkAllocator->free(c.chunk, c.size); + } #ifdef V4_USE_HEAPTRACK heaptrack_report_free(c.chunk); #endif diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 1ef54ffcc6..40670bcdc7 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -69,6 +69,7 @@ QT_BEGIN_NAMESPACE namespace QV4 { struct ChunkAllocator; +struct MemorySegment; struct BlockAllocator { BlockAllocator(ChunkAllocator *chunkAllocator, ExecutionEngine *engine) @@ -136,6 +137,7 @@ struct HugeItemAllocator { ChunkAllocator *chunkAllocator; ExecutionEngine *engine; struct HugeChunk { + MemorySegment *segment; Chunk *chunk; size_t size; }; |