aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/memory/qv4mm_p.h
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_p.h
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_p.h')
-rw-r--r--src/qml/memory/qv4mm_p.h52
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;