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_p.h | |
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_p.h')
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index f15b0fb62c..52d95aca0c 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -64,12 +64,58 @@ #define QV4_MM_MAX_CHUNK_SIZE "QV4_MM_MAX_CHUNK_SIZE" #define QV4_MM_STATS "QV4_MM_STATS" +#define MM_DEBUG 0 + QT_BEGIN_NAMESPACE namespace QV4 { struct ChunkAllocator; +template<typename T> +struct StackAllocator { + Q_STATIC_ASSERT(sizeof(T) < Chunk::DataSize); + static const uint requiredSlots = (sizeof(T) + sizeof(HeapItem) - 1)/sizeof(HeapItem); + + StackAllocator(ChunkAllocator *chunkAlloc); + + T *allocate() { + T *m = nextFree->as<T>(); + if (Q_UNLIKELY(nextFree == lastInChunk)) { + nextChunk(); + } else { + nextFree += requiredSlots; + } +#if MM_DEBUG + Chunk *c = m->chunk(); + Chunk::setBit(c->objectBitmap, m - c->realBase()); +#endif + return m; + } + void free() { +#if MM_DEBUG + Chunk::clearBit(item->chunk()->objectBitmap, item - item->chunk()->realBase()); +#endif + if (Q_UNLIKELY(nextFree == firstInChunk)) { + prevChunk(); + } else { + nextFree -= requiredSlots; + } + } + + void nextChunk(); + void prevChunk(); + + void freeAll(); + + ChunkAllocator *chunkAllocator; + HeapItem *nextFree = 0; + HeapItem *firstInChunk = 0; + HeapItem *lastInChunk = 0; + std::vector<Chunk *> chunks; + uint currentChunk = 0; +}; + class Q_QML_EXPORT MemoryManager { Q_DISABLE_COPY(MemoryManager); @@ -86,6 +132,11 @@ public: static inline std::size_t align(std::size_t size) { return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); } + QV4::Heap::CallContext *allocSimpleCallContext() + { return stackAllocator.allocate(); } + void freeSimpleCallContext() + { stackAllocator.free(); } + template<typename ManagedType> inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) { @@ -317,6 +368,7 @@ private: public: QV4::ExecutionEngine *engine; ChunkAllocator *chunkAllocator; + StackAllocator<Heap::CallContext> stackAllocator; QScopedPointer<Data> m_d; PersistentValueStorage *m_persistentValues; PersistentValueStorage *m_weakValues; |