aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/memory/qv4mm.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2016-12-22 21:24:27 +0100
committerLars Knoll <lars.knoll@qt.io>2017-01-25 08:30:36 +0000
commita325b21e1bd51263551829089e9f31e2156bc641 (patch)
tree9df265b8821254a01e66abef31e4009b18a37c4c /src/qml/memory/qv4mm.cpp
parent90f055dbb44846b9ed37be8b9114573fcf2cd8ff (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.cpp45
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