diff options
author | Lars Knoll <lars.knoll@qt.io> | 2016-12-22 21:24:27 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2017-01-25 08:30:36 +0000 |
commit | a325b21e1bd51263551829089e9f31e2156bc641 (patch) | |
tree | 9df265b8821254a01e66abef31e4009b18a37c4c /src/qml/memory/qv4mm.cpp | |
parent | 90f055dbb44846b9ed37be8b9114573fcf2cd8ff (diff) |
Allocate simple call contexts from a special allocator
We used to allocate those on the C stack, but this doesn't work
anymore with the new GC, as the mark bit is not stored inside the
object anymore.
Instead use a special allocator for these contexts that operates like a
stack.
Change-Id: I381ac3914ca866945312a1e79883aefe72662d2c
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/memory/qv4mm.cpp')
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 92d8170ece..96875c70f6 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -246,6 +246,49 @@ void ChunkAllocator::free(Chunk *chunk, size_t size) } +template<typename T> +StackAllocator<T>::StackAllocator(ChunkAllocator *chunkAlloc) + : chunkAllocator(chunkAlloc) +{ + chunks.push_back(chunkAllocator->allocate()); + firstInChunk = chunks.back()->first(); + nextFree = firstInChunk; + lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots; +} + +template<typename T> +void StackAllocator<T>::freeAll() +{ + for (auto c : chunks) + chunkAllocator->free(c); +} + +template<typename T> +void StackAllocator<T>::nextChunk() { + Q_ASSERT(nextFree == lastInChunk); + ++currentChunk; + if (currentChunk >= chunks.size()) { + Chunk *newChunk = chunkAllocator->allocate(); + chunks.push_back(newChunk); + } + firstInChunk = chunks.at(currentChunk)->first(); + nextFree = firstInChunk; + lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots; +} + +template<typename T> +void QV4::StackAllocator<T>::prevChunk() { + Q_ASSERT(nextFree == firstInChunk); + Q_ASSERT(chunks.at(currentChunk) == nextFree->chunk()); + Q_ASSERT(currentChunk > 0); + --currentChunk; + firstInChunk = chunks.at(currentChunk)->first(); + lastInChunk = firstInChunk + (Chunk::AvailableSlots - 1)/requiredSlots*requiredSlots; + nextFree = lastInChunk; +} + +template struct StackAllocator<Heap::CallContext>; + struct MemoryManager::Data { const size_t pageSize; @@ -384,6 +427,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec MemoryManager::MemoryManager(ExecutionEngine *engine) : engine(engine) , chunkAllocator(new ChunkAllocator) + , stackAllocator(chunkAllocator) , m_d(new Data) , m_persistentValues(new PersistentValueStorage(engine)) , m_weakValues(new PersistentValueStorage(engine)) @@ -770,6 +814,7 @@ MemoryManager::~MemoryManager() delete m_persistentValues; sweep(/*lastSweep*/true); + stackAllocator.freeAll(); delete m_weakValues; #ifdef V4_USE_VALGRIND |