diff options
author | Lars Knoll <lars.knoll@qt.io> | 2017-03-21 14:49:10 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-03-22 11:30:57 +0000 |
commit | 9b7071637415bdad82bf61caf21603963f7fe21a (patch) | |
tree | 3f227343d11b0936798a63f256679d0e3077dcfd /src/qml/memory/qv4mm.cpp | |
parent | db51441a955f63abba41b80198969df38c3d4a10 (diff) |
Fix handling of huge memory segments
Allocating a MemorySegment larger than 4M was not working
correctly. We would in this case reserve the right amount of
memory, but where not able to use it, leading to an assertion
in the HugeItemAllocator.
Fix this by ensuring we can properly allocate the memory that
was reserved in the Segment.
Change-Id: I1e3d2b3beebdde0a509fd123ad2aa8b1bc35a26b
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/memory/qv4mm.cpp')
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index a829e902fb..27adfcb517 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -113,14 +113,16 @@ struct MemorySegment { pageReservation = PageReservation::reserve(size, OSAllocator::JSGCHeapPages); base = reinterpret_cast<Chunk *>((reinterpret_cast<quintptr>(pageReservation.base()) + Chunk::ChunkSize - 1) & ~(Chunk::ChunkSize - 1)); nChunks = NumChunks; - if (base != pageReservation.base()) + availableBytes = size - (reinterpret_cast<quintptr>(base) - reinterpret_cast<quintptr>(pageReservation.base())); + if (availableBytes < SegmentSize) --nChunks; } MemorySegment(MemorySegment &&other) { qSwap(pageReservation, other.pageReservation); qSwap(base, other.base); - qSwap(nChunks, other.nChunks); qSwap(allocatedMap, other.allocatedMap); + qSwap(availableBytes, other.availableBytes); + qSwap(nChunks, other.nChunks); } ~MemorySegment() { @@ -150,7 +152,7 @@ struct MemorySegment { void free(Chunk *chunk, size_t size) { DEBUG << "freeing chunk" << chunk; size_t index = static_cast<size_t>(chunk - base); - size_t end = index + (size - 1)/Chunk::ChunkSize + 1; + size_t end = qMin(static_cast<size_t>(NumChunks), index + (size - 1)/Chunk::ChunkSize + 1); while (index < end) { Q_ASSERT(testBit(index)); clearBit(index); @@ -169,11 +171,19 @@ struct MemorySegment { PageReservation pageReservation; Chunk *base = 0; quint64 allocatedMap = 0; + size_t availableBytes = 0; uint nChunks = 0; }; Chunk *MemorySegment::allocate(size_t size) { + if (!allocatedMap && size >= SegmentSize) { + // chunk allocated for one huge allocation + Q_ASSERT(availableBytes >= size); + pageReservation.commit(base, size); + allocatedMap = ~static_cast<quintptr>(0); + return base; + } size_t requiredChunks = (size + sizeof(Chunk) - 1)/sizeof(Chunk); uint sequence = 0; Chunk *candidate = 0; |