aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-07 08:48:57 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2018-03-08 09:02:02 +0000
commitc99abf1851bbbfcec11eb77173df620746940ab0 (patch)
treea8f4b9c1ebe9cb78d7ac585aa8b299a2a820fdca
parent73e8321255d9f0e70529a58c10dbaf4790a9a659 (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.cpp25
-rw-r--r--src/qml/memory/qv4mm_p.h2
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;
};