diff options
author | Lars Knoll <lars.knoll@theqtcompany.com> | 2015-01-12 21:55:51 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2015-01-16 21:12:49 +0100 |
commit | 8ffb79bbd214c239e414dc4e9cf4569b3219bdab (patch) | |
tree | c9cc7e596be2616f8c1211f4fb7623c9153cd7d6 /src/qml/jsruntime | |
parent | 9fe1588915b935298917a0c29593eeed70da682f (diff) |
Refactor persistent values
Use a page wise allocation mechanism for persistent
values. This significantly reduces memory consumption
of persistent values and also improves their performance
a lot.
Change-Id: I8499d2ca5bdd871e029f643ae605a94544558bb5
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mm.cpp | 70 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mm_p.h | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4persistent.cpp | 386 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4persistent_p.h | 120 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 1 |
8 files changed, 328 insertions, 273 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index a51ea36351..3d3423b03a 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -183,7 +183,7 @@ QQmlEngine *ExecutionEngine::qmlEngine() const ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) : current(0) - , memoryManager(new QV4::MemoryManager) + , memoryManager(new QV4::MemoryManager(this)) , executableAllocator(new QV4::ExecutableAllocator) , regExpAllocator(new QV4::ExecutableAllocator) , bumperPointerAllocator(new WTF::BumpPointerAllocator) @@ -218,8 +218,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) } iselFactory.reset(factory); - memoryManager->setExecutionEngine(this); - // reserve space for the JS stack // we allow it to grow to 2 times JSStackLimit, as we can overshoot due to garbage collection // and ScopedValues allocated outside of JIT'ed methods. @@ -1291,7 +1289,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::ValueRef value, in return re->toQRegExp(); if (createJSValueForObjects) - return QVariant::fromValue(QJSValue(new QJSValuePrivate(o->asReturnedValue()))); + return QVariant::fromValue(QJSValue(new QJSValuePrivate(scope.engine, o->asReturnedValue()))); return objectToVariant(e, o, visitedObjects); } diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 687ff19be4..5378cc92df 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -198,7 +198,7 @@ typedef Scoped<ArrayObject> ScopedArrayObject; typedef Scoped<FunctionObject> ScopedFunctionObject; typedef Scoped<ExecutionContext> ScopedContext; -struct PersistentValuePrivate; +struct PersistentValueStorage; class PersistentValue; class WeakValue; diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index c5538a8c7f..f4c3d930ac 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -208,14 +208,15 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec } // namespace -MemoryManager::MemoryManager() +MemoryManager::MemoryManager(ExecutionEngine *engine) : m_d(new Data) - , m_persistentValues(0) - , m_weakValues(0) + , m_persistentValues(new PersistentValueStorage(engine)) + , m_weakValues(new PersistentValueStorage(engine)) { #ifdef V4_USE_VALGRIND VALGRIND_CREATE_MEMPOOL(this, 0, true); #endif + m_d->engine = engine; } Heap::Base *MemoryManager::allocData(std::size_t size) @@ -334,21 +335,7 @@ void MemoryManager::mark() m_d->engine->markObjects(); - PersistentValuePrivate *persistent = m_persistentValues; - while (persistent) { - if (!persistent->refcount) { - PersistentValuePrivate *n = persistent->next; - persistent->removeFromList(); - delete persistent; - persistent = n; - continue; - } - persistent->value.mark(m_d->engine); - persistent = persistent->next; - - if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit) - drainMarkStack(m_d->engine, markBase); - } + m_persistentValues->mark(m_d->engine); collectFromJSStack(); @@ -358,12 +345,12 @@ void MemoryManager::mark() // Do this _after_ collectFromStack to ensure that processing the weak // managed objects in the loop down there doesn't make then end up as leftovers // on the stack and thus always get collected. - for (PersistentValuePrivate *weak = m_weakValues; weak; weak = weak->next) { - if (!weak->refcount || !weak->value.isManaged()) + for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) { + if (!(*it).isManaged()) continue; - if (weak->value.asManaged()->d()->gcGetInternalClass()->vtable != QObjectWrapper::staticVTable()) + if ((*it).managed()->d()->gcGetInternalClass()->vtable != QObjectWrapper::staticVTable()) continue; - QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>(weak->value.managed()); + QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>((*it).managed()); if (!qobjectWrapper) continue; QObject *qobject = qobjectWrapper->object(); @@ -392,25 +379,13 @@ void MemoryManager::mark() void MemoryManager::sweep(bool lastSweep) { - PersistentValuePrivate *weak = m_weakValues; - while (weak) { - if (!weak->refcount) { - PersistentValuePrivate *n = weak->next; - weak->removeFromList(); - delete weak; - weak = n; - continue; - } - if (Managed *m = weak->value.asManaged()) { - if (!m->markBit()) { - weak->value = Primitive::undefinedValue(); - PersistentValuePrivate *n = weak->next; - weak->removeFromList(); - weak = n; - continue; + if (m_weakValues) { + for (PersistentValueStorage::Iterator it = m_weakValues->begin(); it != m_weakValues->end(); ++it) { + if (Managed *m = (*it).asManaged()) { + if (!m->markBit()) + (*it) = Primitive::undefinedValue(); } } - weak = weak->next; } if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) { @@ -580,15 +555,9 @@ size_t MemoryManager::getLargeItemsMem() const MemoryManager::~MemoryManager() { - PersistentValuePrivate *persistent = m_persistentValues; - while (persistent) { - PersistentValuePrivate *n = persistent->next; - persistent->value = Primitive::undefinedValue(); - persistent->engine = 0; - persistent->prev = 0; - persistent->next = 0; - persistent = n; - } + delete m_persistentValues; + delete m_weakValues; + m_weakValues = 0; sweep(/*lastSweep*/true); #ifdef V4_USE_VALGRIND @@ -601,11 +570,6 @@ ExecutionEngine *MemoryManager::engine() const return m_d->engine; } -void MemoryManager::setExecutionEngine(ExecutionEngine *engine) -{ - m_d->engine = engine; -} - void MemoryManager::dumpStats() const { #ifdef DETAILED_MM_STATS diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h index 5c21294ad0..6049eb2d8a 100644 --- a/src/qml/jsruntime/qv4mm_p.h +++ b/src/qml/jsruntime/qv4mm_p.h @@ -48,8 +48,7 @@ struct GCDeletable; class Q_QML_EXPORT MemoryManager { - MemoryManager(const MemoryManager &); - MemoryManager &operator=(const MemoryManager&); + Q_DISABLE_COPY(MemoryManager); public: struct Data; @@ -75,7 +74,7 @@ public: }; public: - MemoryManager(); + MemoryManager(ExecutionEngine *engine); ~MemoryManager(); // TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries). @@ -149,7 +148,6 @@ public: void runGC(); ExecutionEngine *engine() const; - void setExecutionEngine(ExecutionEngine *engine); void dumpStats() const; @@ -176,8 +174,8 @@ private: protected: QScopedPointer<Data> m_d; public: - PersistentValuePrivate *m_persistentValues; - PersistentValuePrivate *m_weakValues; + PersistentValueStorage *m_persistentValues; + PersistentValueStorage *m_weakValues; }; } diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp index 1236d2a469..ff5061d968 100644 --- a/src/qml/jsruntime/qv4persistent.cpp +++ b/src/qml/jsruntime/qv4persistent.cpp @@ -34,232 +34,320 @@ #include "qv4persistent_p.h" #include "qv4mm_p.h" #include "qv4object_p.h" +#include "PageAllocation.h" using namespace QV4; -PersistentValue::PersistentValue(ExecutionEngine *engine, const ValueRef val) - : d(new PersistentValuePrivate(val.asReturnedValue(), engine)) +namespace { + +struct Page; +struct Header { + WTF::PageAllocation alloc; + ExecutionEngine *engine; + Page **prev; + Page *next; + int refCount; + int freeList; +}; + +enum { + PageSize = 4096, + NEntries = (PageSize - sizeof(Header))/sizeof(Value) +}; +struct Page { + Header header; + Value values[NEntries]; +}; + +Page *getPage(Value *val) { + return reinterpret_cast<Page *>(reinterpret_cast<quintptr>(val) & ~((quintptr)(PageSize - 1))); +} + + +Page *allocatePage(PersistentValueStorage *storage) { + PageAllocation page = WTF::PageAllocation::allocate(PageSize); + Page *p = reinterpret_cast<Page *>(page.base()); + + Q_ASSERT(!((quintptr)p & (PageSize - 1))); + + p->header.engine = storage->engine; + p->header.alloc = page; + p->header.next = reinterpret_cast<Page *>(storage->firstPage); + p->header.prev = reinterpret_cast<Page **>(&storage->firstPage); + p->header.refCount = 0; + p->header.freeList = 0; + if (p->header.next) + p->header.next->header.prev = &p->header.next; + for (int i = 0; i < NEntries - 1; ++i) { + p->values[i].tag = QV4::Value::Empty_Type; + p->values[i].int_32 = i + 1; + } + p->values[NEntries - 1].tag = QV4::Value::Empty_Type; + p->values[NEntries - 1].int_32 = -1; + + storage->firstPage = p; + + return p; +} + + +} + + +PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++() { + while (p) { + while (index < NEntries - 1) { + ++index; + if (static_cast<Page *>(p)->values[index].tag != QV4::Value::Empty_Type) + return *this; + } + index = -1; + p = static_cast<Page *>(p)->header.next; + } + index = 0; + return *this; } -PersistentValue::PersistentValue(ExecutionEngine *engine, ReturnedValue val) - : d(new PersistentValuePrivate(val, engine)) +Value &PersistentValueStorage::Iterator::operator *() { + return static_cast<Page *>(p)->values[index]; } -PersistentValue::PersistentValue(const PersistentValue &other) - : d(other.d) +PersistentValueStorage::PersistentValueStorage(ExecutionEngine *engine) + : engine(engine), + firstPage(0) { - if (d) - d->ref(); } -PersistentValue::~PersistentValue() +PersistentValueStorage::~PersistentValueStorage() { - if (d) - d->deref(); + Page *p = static_cast<Page *>(firstPage); + while (p) { + for (int i = 0; i < NEntries; ++i) { + if (!p->values[i].isEmpty()) + p->values[i] = Encode::undefined(); + } + Page *n = p->header.next; + p->header.engine = 0; + p->header.prev = 0; + p->header.next = 0; + Q_ASSERT(p->header.refCount); + p = n; + } } -PersistentValue &PersistentValue::operator=(const PersistentValue &other) +Value *PersistentValueStorage::allocate() { - if (d == other.d) - return *this; + Page *p = static_cast<Page *>(firstPage); + while (p) { + if (p->header.freeList != -1) + break; + p = p->header.next; + } + if (!p) + p = allocatePage(this); - // the memory manager cleans up those with a refcount of 0 + Value *v = p->values + p->header.freeList; + p->header.freeList = v->int_32; + ++p->header.refCount; - if (d) - d->deref(); - d = other.d; - if (d) - d->ref(); + v->val = Encode::undefined(); - return *this; + return v; } -PersistentValue &PersistentValue::operator=(const WeakValue &other) +void PersistentValueStorage::free(Value *v) { - QV4::ExecutionEngine *engine = other.engine(); - if (!d) - d = new PersistentValuePrivate(other.value(), engine); - else - d = d->detach(other.value()); - return *this; + if (!v) + return; + + Page *p = getPage(v); + + v->tag = QV4::Value::Empty_Type; + v->int_32 = p->header.freeList; + p->header.freeList = v - p->values; + if (!--p->header.refCount) { + if (p->header.prev) + *p->header.prev = p->header.next; + if (p->header.next) + p->header.next->header.prev = p->header.prev; + p->header.alloc.deallocate(); + } } -PersistentValue &PersistentValue::operator=(Object *object) +static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase) { - QV4::ExecutionEngine *engine = object->engine(); - if (!d) - d = new PersistentValuePrivate(object->asReturnedValue(), engine); - else - d = d->detach(object->asReturnedValue()); - return *this; + while (engine->jsStackTop > markBase) { + Heap::Base *h = engine->popForGC(); + Q_ASSERT (h->gcGetInternalClass()->vtable->markObjects); + h->gcGetInternalClass()->vtable->markObjects(h, engine); + } } -void PersistentValue::set(ExecutionEngine *engine, const ValueRef val) +void PersistentValueStorage::mark(ExecutionEngine *e) { - if (!d) - d = new PersistentValuePrivate(val.asReturnedValue(), engine); - else - d = d->detach(val.asReturnedValue()); + Value *markBase = e->jsStackTop; + + Page *p = static_cast<Page *>(firstPage); + while (p) { + for (int i = 0; i < NEntries; ++i) { + if (Managed *m = p->values[i].asManaged()) + m->mark(e); + } + drainMarkStack(e, markBase); + + p = p->header.next; + } } -void PersistentValue::set(ExecutionEngine *engine, ReturnedValue val) +ExecutionEngine *PersistentValueStorage::getEngine(Value *v) { - if (!d) - d = new PersistentValuePrivate(val, engine); - else - d = d->detach(val); + return getPage(v)->header.engine; } -void PersistentValue::set(ExecutionEngine *engine, Heap::Base *obj) + +PersistentValue::PersistentValue(const PersistentValue &other) + : val(0) { - if (!d) - d = new PersistentValuePrivate(obj->asReturnedValue(), engine); - else - d = d->detach(obj->asReturnedValue()); + if (other.val) { + val = other.engine()->memoryManager->m_persistentValues->allocate(); + *val = *other.val; + } } -WeakValue::WeakValue(const WeakValue &other) - : d(other.d) +PersistentValue::PersistentValue(ExecutionEngine *engine, const ValueRef value) { - if (d) - d->ref(); + val = engine->memoryManager->m_persistentValues->allocate(); + *val = value; } -WeakValue &WeakValue::operator=(const WeakValue &other) +PersistentValue::PersistentValue(ExecutionEngine *engine, ReturnedValue value) { - if (d == other.d) - return *this; + val = engine->memoryManager->m_persistentValues->allocate(); + *val = value; +} + +PersistentValue::~PersistentValue() +{ + PersistentValueStorage::free(val); +} - // the memory manager cleans up those with a refcount of 0 +PersistentValue &PersistentValue::operator=(const PersistentValue &other) +{ + if (!val) { + if (!other.val) + return *this; + val = other.engine()->memoryManager->m_persistentValues->allocate(); + } - if (d) - d->deref(); - d = other.d; - if (d) - d->ref(); + Q_ASSERT(engine() == other.engine()); + *val = *other.val; return *this; } -WeakValue::~WeakValue() +PersistentValue &PersistentValue::operator=(const WeakValue &other) { - if (d) - d->deref(); + if (!val) { + if (!other.valueRef()) + return *this; + val = other.engine()->memoryManager->m_persistentValues->allocate(); + } + + Q_ASSERT(engine() == other.engine()); + + *val = *other.valueRef(); + return *this; } -void WeakValue::set(ExecutionEngine *e, const ValueRef val) +PersistentValue &PersistentValue::operator=(Object *object) { - if (!d) - d = new PersistentValuePrivate(val.asReturnedValue(), e, /*weak*/true); - else - d = d->detach(val.asReturnedValue(), /*weak*/true); + if (!object) { + PersistentValueStorage::free(val); + return *this; + } + if (!val) + val = object->engine()->memoryManager->m_persistentValues->allocate(); + + *val = object; + return *this; } -void WeakValue::set(ExecutionEngine *e, ReturnedValue val) +void PersistentValue::set(ExecutionEngine *engine, const ValueRef value) { - if (!d) - d = new PersistentValuePrivate(val, e, /*weak*/true); - else - d = d->detach(val, /*weak*/true); + if (!val) + val = engine->memoryManager->m_persistentValues->allocate(); + *val = value; } -void WeakValue::set(ExecutionEngine *e, Heap::Base *obj) +void PersistentValue::set(ExecutionEngine *engine, ReturnedValue value) { - if (!d) - d = new PersistentValuePrivate(obj->asReturnedValue(), e, /*weak*/true); - else - d = d->detach(obj->asReturnedValue(), /*weak*/true); + if (!val) + val = engine->memoryManager->m_persistentValues->allocate(); + *val = value; } -void WeakValue::markOnce(ExecutionEngine *e) +void PersistentValue::set(ExecutionEngine *engine, Heap::Base *obj) { - if (!d) - return; - d->value.mark(e); + if (!val) + val = engine->memoryManager->m_persistentValues->allocate(); + *val = obj; } -PersistentValuePrivate::PersistentValuePrivate(ReturnedValue v, ExecutionEngine *e, bool weak) - : refcount(1) - , weak(weak) - , engine(e) - , prev(0) - , next(0) +WeakValue::WeakValue(const WeakValue &other) + : val(0) { - value.val = v; - init(); + if (other.val) { + val = other.engine()->memoryManager->m_weakValues->allocate(); + *val = *other.val; + } } -void PersistentValuePrivate::init() +WeakValue &WeakValue::operator=(const WeakValue &other) { - if (!engine) { - Managed *m = value.asManaged(); - if (!m) - return; - - engine = m->engine(); - } - if (engine && !prev) { - PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues; - - prev = listRoot; - next = *listRoot; - *prev = this; - if (next) - next->prev = &this->next; + if (!val) { + if (!other.val) + return *this; + val = other.engine()->memoryManager->m_weakValues->allocate(); } + + Q_ASSERT(engine() == other.engine()); + + *val = *other.val; + return *this; } -PersistentValuePrivate::~PersistentValuePrivate() +WeakValue::~WeakValue() { + PersistentValueStorage::free(val); } -void PersistentValuePrivate::removeFromList() +void WeakValue::set(ExecutionEngine *engine, const ValueRef value) { - if (prev) { - if (next) - next->prev = prev; - *prev = next; - next = 0; - prev = 0; - } + if (!val) + val = engine->memoryManager->m_weakValues->allocate(); + *val = value; } -void PersistentValuePrivate::deref() +void WeakValue::set(ExecutionEngine *engine, ReturnedValue value) { - // if engine is not 0, they are registered with the memory manager - // and will get cleaned up in the next gc run - if (!--refcount) { - removeFromList(); - delete this; - } + if (!val) + val = engine->memoryManager->m_weakValues->allocate(); + *val = value; } -PersistentValuePrivate *PersistentValuePrivate::detach(const QV4::ReturnedValue val, bool weak) +void WeakValue::set(ExecutionEngine *engine, Heap::Base *obj) { - if (refcount == 1) { - value.val = val; - - Managed *m = value.asManaged(); - if (!prev) { - if (m) { - ExecutionEngine *engine = m->engine(); - if (engine) { - PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues; - prev = listRoot; - next = *listRoot; - *prev = this; - if (next) - next->prev = &this->next; - } - } - } else if (!m) - removeFromList(); - - return this; - } - --refcount; - return new PersistentValuePrivate(val, engine, weak); + if (!val) + val = engine->memoryManager->m_weakValues->allocate(); + *val = obj; +} + +void WeakValue::markOnce(ExecutionEngine *e) +{ + if (!val) + return; + val->mark(e); } diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h index 41c482fbb7..b71f943f80 100644 --- a/src/qml/jsruntime/qv4persistent_p.h +++ b/src/qml/jsruntime/qv4persistent_p.h @@ -39,114 +39,126 @@ QT_BEGIN_NAMESPACE namespace QV4 { -struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate +struct Q_QML_EXPORT PersistentValueStorage { - PersistentValuePrivate(ReturnedValue v, ExecutionEngine *engine = 0, bool weak = false); - virtual ~PersistentValuePrivate(); - Value value; - uint refcount; - bool weak; - QV4::ExecutionEngine *engine; - PersistentValuePrivate **prev; - PersistentValuePrivate *next; - - void init(); - void removeFromList(); - void ref() { ++refcount; } - void deref(); - PersistentValuePrivate *detach(const ReturnedValue value, bool weak = false); - - bool checkEngine(QV4::ExecutionEngine *otherEngine) { - if (!engine) { - Q_ASSERT(!value.isObject()); - engine = otherEngine; + PersistentValueStorage(ExecutionEngine *engine); + ~PersistentValueStorage(); + + Value *allocate(); + static void free(Value *e); + + void mark(ExecutionEngine *e); + + struct Iterator { + Q_DECL_CONSTEXPR Iterator(void *p, int idx) + : p(p), index(idx) {} + void *p; + int index; + Iterator &operator++(); + bool operator !=(const Iterator &other) { + return p != other.p || index != other.index; } - return (engine == otherEngine); - } + Value &operator *(); + }; + Iterator begin() { return Iterator(firstPage, 0); } + Iterator end() { return Iterator(0, 0); } + + static ExecutionEngine *getEngine(Value *v); + + ExecutionEngine *engine; + void *firstPage; }; class Q_QML_EXPORT PersistentValue { public: - PersistentValue() : d(0) {} + PersistentValue() : val(0) {} PersistentValue(const PersistentValue &other); PersistentValue &operator=(const PersistentValue &other); PersistentValue &operator=(const WeakValue &other); PersistentValue &operator=(Object *object); ~PersistentValue(); - PersistentValue(ExecutionEngine *engine, const ValueRef val); - PersistentValue(ExecutionEngine *engine, ReturnedValue val); + PersistentValue(ExecutionEngine *engine, const ValueRef value); + PersistentValue(ExecutionEngine *engine, ReturnedValue value); - void set(ExecutionEngine *engine, const ValueRef val); - void set(ExecutionEngine *engine, ReturnedValue val); + void set(ExecutionEngine *engine, const ValueRef value); + void set(ExecutionEngine *engine, ReturnedValue value); void set(ExecutionEngine *engine, Heap::Base *obj); ReturnedValue value() const { - return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue()); + return (val ? val->asReturnedValue() : Encode::undefined()); + } + Value *valueRef() const { + return val; } Managed *asManaged() const { - if (!d) + if (!val) return 0; - return d->value.asManaged(); + return val->asManaged(); } ExecutionEngine *engine() const { - if (!d) + if (!val) return 0; - if (d->engine) - return d->engine; - Managed *m = d->value.asManaged(); - return m ? m->engine() : 0; + return PersistentValueStorage::getEngine(val); } - bool isUndefined() const { return !d || d->value.isUndefined(); } - bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); } + bool isUndefined() const { return !val || val->isUndefined(); } + bool isNullOrUndefined() const { return !val || val->isNullOrUndefined(); } void clear() { - *this = PersistentValue(); + PersistentValueStorage::free(val); + val = 0; } + bool isEmpty() { return !val; } private: friend struct ValueRef; - PersistentValuePrivate *d; + + Value *val; }; class Q_QML_EXPORT WeakValue { public: - WeakValue() : d(0) {} + WeakValue() : val(0) {} WeakValue(const WeakValue &other); WeakValue &operator=(const WeakValue &other); ~WeakValue(); - void set(ExecutionEngine *e, const ValueRef val); - void set(ExecutionEngine *e, ReturnedValue val); - void set(ExecutionEngine *e, Heap::Base *obj); + void set(ExecutionEngine *engine, const ValueRef value); + void set(ExecutionEngine *engine, ReturnedValue value); + void set(ExecutionEngine *engine, Heap::Base *obj); ReturnedValue value() const { - return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue()); + return (val ? val->asReturnedValue() : Encode::undefined()); + } + Value *valueRef() const { + return val; + } + Managed *asManaged() const { + if (!val) + return 0; + return val->asManaged(); } ExecutionEngine *engine() const { - if (!d) + if (!val) return 0; - if (d->engine) - return d->engine; - Managed *m = d->value.asManaged(); - return m ? m->engine() : 0; + return PersistentValueStorage::getEngine(val); } - bool isUndefined() const { return !d || d->value.isUndefined(); } - bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); } + bool isUndefined() const { return !val || val->isUndefined(); } + bool isNullOrUndefined() const { return !val || val->isNullOrUndefined(); } void clear() { - *this = WeakValue(); + PersistentValueStorage::free(val); + val = 0; } void markOnce(ExecutionEngine *e); private: - friend struct ValueRef; - PersistentValuePrivate *d; + Value *val; }; } // namespace QV4 diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index e12b91340d..705e5301dc 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -478,11 +478,7 @@ inline ValueRef::ValueRef(const Scoped<T> &v) {} inline ValueRef::ValueRef(const PersistentValue &v) - : ptr(&v.d->value) -{} - -inline ValueRef::ValueRef(PersistentValuePrivate *p) - : ptr(&p->value) + : ptr(v.val) {} inline ValueRef &ValueRef::operator=(const ScopedValue &o) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 8fff22ed86..0a0da27f41 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -534,7 +534,6 @@ struct ValueRef { template <typename T> ValueRef(const Scoped<T> &v); ValueRef(const PersistentValue &v); - ValueRef(PersistentValuePrivate *p); ValueRef(Value &v) { ptr = &v; } // Important: Do NOT add a copy constructor to this class // adding a copy constructor actually changes the calling convention, ie. |