diff options
Diffstat (limited to 'src/qml/memory')
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 50 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 17 | ||||
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 44 |
3 files changed, 75 insertions, 36 deletions
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index d15d14e463..5a3797f397 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -58,6 +58,12 @@ // parent's init all up the inheritance chain), define QML_CHECK_INIT_DESTROY_CALLS below. #undef QML_CHECK_INIT_DESTROY_CALLS +#if defined(_MSC_VER) && (_MSC_VER < 1900) // broken compilers: +# define V4_ASSERT_IS_TRIVIAL(x) +#else // working compilers: +# define V4_ASSERT_IS_TRIVIAL(x) Q_STATIC_ASSERT(std::is_trivial< x >::value); +#endif + QT_BEGIN_NAMESPACE namespace QV4 { @@ -82,6 +88,8 @@ struct VTable namespace Heap { struct Q_QML_EXPORT Base { + void *operator new(size_t) = delete; + quintptr mm_data; // vtable and markbit inline ReturnedValue asReturnedValue() const; @@ -125,16 +133,44 @@ struct Q_QML_EXPORT Base { void *operator new(size_t, Heap::Base *m) { return m; } void operator delete(void *, Heap::Base *) {} - void init() { setInitialized(); } + void init() { _setInitialized(); } + void destroy() { _setDestroyed(); } #ifdef QML_CHECK_INIT_DESTROY_CALLS - bool _isInitialized; - void _checkIsInitialized() { Q_ASSERT(_isInitialized); } - void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; } + enum { Uninitialized = 0, Initialized, Destroyed } _livenessStatus; + void _checkIsInitialized() { + if (_livenessStatus == Uninitialized) + fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n", + vtable()->className); + else if (_livenessStatus == Destroyed) + fprintf(stderr, "ERROR: use of object '%s' after call to destroy() !!\n", + vtable()->className); + Q_ASSERT(_livenessStatus = Initialized); + } + void _checkIsDestroyed() { + if (_livenessStatus == Initialized) + fprintf(stderr, "ERROR: object '%s' was never destroyed completely !!\n", + vtable()->className); + Q_ASSERT(_livenessStatus == Destroyed); + } + void _setInitialized() { Q_ASSERT(_livenessStatus == Uninitialized); _livenessStatus = Initialized; } + void _setDestroyed() { + if (_livenessStatus == Uninitialized) + fprintf(stderr, "ERROR: attempting to destroy an uninitialized object '%s' !!\n", + vtable()->className); + else if (_livenessStatus == Destroyed) + fprintf(stderr, "ERROR: attempting to destroy repeatedly object '%s' !!\n", + vtable()->className); + Q_ASSERT(_livenessStatus == Initialized); + _livenessStatus = Destroyed; + } #else Q_ALWAYS_INLINE void _checkIsInitialized() {} - Q_ALWAYS_INLINE void setInitialized() {} + Q_ALWAYS_INLINE void _checkIsDestroyed() {} + Q_ALWAYS_INLINE void _setInitialized() {} + Q_ALWAYS_INLINE void _setDestroyed() {} #endif }; +V4_ASSERT_IS_TRIVIAL(Base) template <typename T> struct Pointer { @@ -148,7 +184,7 @@ struct Pointer { T *ptr; }; -Q_STATIC_ASSERT(std::is_trivial<Pointer<void>>::value); +V4_ASSERT_IS_TRIVIAL(Pointer<void>) } @@ -204,7 +240,7 @@ private: QtSharedPointer::ExternalRefCountData *d; QObject *qObject; }; -Q_STATIC_ASSERT(std::is_trivial<QQmlQPointer<QObject>>::value); +V4_ASSERT_IS_TRIVIAL(QQmlQPointer<QObject>) #endif } diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp index 3d25bd1639..6ef2380561 100644 --- a/src/qml/memory/qv4mm.cpp +++ b/src/qml/memory/qv4mm.cpp @@ -46,7 +46,7 @@ #include "PageAllocation.h" #include "StdLibExtras.h" -#include <QTime> +#include <QElapsedTimer> #include <QMap> #include <QScopedValueRollback> @@ -229,10 +229,12 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec *unmanagedHeapSize -= heapBytes; } - if (m->vtable()->destroy) + if (m->vtable()->destroy) { m->vtable()->destroy(m); + m->_checkIsDestroyed(); + } - memset(m, 0, header->itemSize); + memset(m, 0, sizeof(Heap::Base)); #ifdef V4_USE_VALGRIND VALGRIND_DISABLE_ERROR_REPORTING; VALGRIND_MEMPOOL_FREE(engine->memoryManager, m); @@ -482,7 +484,7 @@ void MemoryManager::sweep(bool lastSweep) remainingWeakQObjectWrappers.reserve(pendingCount); for (int i = 0; i < pendingCount; ++i) { Value *v = m_pendingFreedObjectWrapperValue.at(i); - if (v->tag() == Value::Undefined_Type) + if (v->isUndefined() || v->isEmpty()) PersistentValueStorage::free(v); else remainingWeakQObjectWrappers.append(v); @@ -594,18 +596,17 @@ void MemoryManager::runGC() } else { const size_t totalMem = getAllocatedMem(); - QTime t; + QElapsedTimer t; t.start(); mark(); - int markTime = t.elapsed(); - t.restart(); + qint64 markTime = t.restart(); const size_t usedBefore = getUsedMem(); const size_t largeItemsBefore = getLargeItemsMem(); size_t chunksBefore = m_d->heapChunks.size(); sweep(); const size_t usedAfter = getUsedMem(); const size_t largeItemsAfter = getLargeItemsMem(); - int sweepTime = t.elapsed(); + qint64 sweepTime = t.elapsed(); qDebug() << "========== GC =========="; qDebug() << "Marked object in" << markTime << "ms."; diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 6db5b54760..dfa0d85dff 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -108,8 +108,10 @@ public: template<typename ManagedType> inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0) { + V4_ASSERT_IS_TRIVIAL(typename ManagedType::Data) size = align(size); Heap::Base *o = allocData(size, unmanagedSize); + memset(o, 0, size); o->setVtable(ManagedType::staticVTable()); return static_cast<typename ManagedType::Data *>(o); } @@ -144,7 +146,7 @@ public: { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize)); - (void)new (t->d()) typename ManagedType::Data(this, arg1); + t->d_unchecked()->init(this, arg1); return t->d(); } @@ -153,7 +155,7 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - (void)new (t->d()) typename ObjectType::Data(); + t->d_unchecked()->init(); return t->d(); } @@ -162,8 +164,8 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(); return t->d(); } @@ -172,8 +174,8 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1); return t->d(); } @@ -182,8 +184,8 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1, arg2); return t->d(); } @@ -192,8 +194,8 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1, arg2, arg3); return t->d(); } @@ -202,8 +204,8 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>(ic)); - t->d()->prototype = prototype->d(); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4); + t->d_unchecked()->prototype = prototype->d(); + t->d_unchecked()->init(arg1, arg2, arg3, arg4); return t->d(); } @@ -212,7 +214,7 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - (void)new (t->d()) typename ObjectType::Data(); + t->d_unchecked()->init(); return t->d(); } @@ -221,7 +223,7 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - (void)new (t->d()) typename ObjectType::Data(arg1); + t->d_unchecked()->init(arg1); return t->d(); } @@ -230,7 +232,7 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2); + t->d_unchecked()->init(arg1, arg2); return t->d(); } @@ -239,7 +241,7 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3); + t->d_unchecked()->init(arg1, arg2, arg3); return t->d(); } @@ -248,7 +250,7 @@ public: { Scope scope(engine); Scoped<ObjectType> t(scope, allocateObject<ObjectType>()); - (void)new (t->d()) typename ObjectType::Data(arg1, arg2, arg3, arg4); + t->d_unchecked()->init(arg1, arg2, arg3, arg4); return t->d(); } @@ -258,7 +260,7 @@ public: { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(); + t->d_unchecked()->init(); return t->d(); } @@ -267,7 +269,7 @@ public: { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1); + t->d_unchecked()->init(arg1); return t->d(); } @@ -294,7 +296,7 @@ public: { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4); + t->d_unchecked()->init(arg1, arg2, arg3, arg4); return t->d(); } @@ -303,7 +305,7 @@ public: { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5); + t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5); return t->d(); } |