Skip to content

Commit

Permalink
Fix issue with allocating huge objects in the memory manager
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
laknoll committed Mar 8, 2018
1 parent ded165b commit dfd5cc0
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
25 changes: 22 additions & 3 deletions src/qml/memory/qv4mm.cpp
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/qml/memory/qv4mm_p.h
Expand Up @@ -69,6 +69,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {

struct ChunkAllocator;
struct MemorySegment;

template<typename T>
struct StackAllocator {
Expand Down Expand Up @@ -176,6 +177,7 @@ struct HugeItemAllocator {
ChunkAllocator *chunkAllocator;
ExecutionEngine *engine;
struct HugeChunk {
MemorySegment *segment;
Chunk *chunk;
size_t size;
};
Expand Down

0 comments on commit dfd5cc0

Please sign in to comment.