aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-03-07 08:48:57 +0100
committerLars Knoll <lars.knoll@qt.io>2018-03-08 12:32:38 +0000
commitdfd5cc04a6745cd90e6459ffd99d59ed14471f15 (patch)
treec54a995d54c83a5102d78c79d51d1d95814c3143
parentded165b94b9dd5eb01b1b879cfef5035efc418d0 (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> (cherry picked from commit c99abf1851bbbfcec11eb77173df620746940ab0) Reviewed-by: Erik Verbruggen <erik.verbruggen@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 418c3444a4..0f46429c5d 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -633,8 +633,21 @@ void BlockAllocator::freeAll()
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
@@ -651,7 +664,13 @@ static void freeHugeChunk(ChunkAllocator *chunkAllocator, const HugeItemAllocato
b->vtable()->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 aa8d13de8c..2721795aea 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;
template<typename T>
struct StackAllocator {
@@ -176,6 +177,7 @@ struct HugeItemAllocator {
ChunkAllocator *chunkAllocator;
ExecutionEngine *engine;
struct HugeChunk {
+ MemorySegment *segment;
Chunk *chunk;
size_t size;
};