aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/memory/qv4heap_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/memory/qv4heap_p.h')
-rw-r--r--src/qml/memory/qv4heap_p.h50
1 files changed, 43 insertions, 7 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
}