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.h110
1 files changed, 107 insertions, 3 deletions
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index ed7a531766..5a3797f397 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -52,6 +52,17 @@
#include <QtCore/QString>
#include <private/qv4global_p.h>
+#include <QSharedPointer>
+
+// To check if Heap::Base::init is called (meaning, all subclasses did their init and called their
+// 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
@@ -77,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;
@@ -119,13 +132,48 @@ struct Q_QML_EXPORT Base {
void *operator new(size_t, Managed *m) { return m; }
void *operator new(size_t, Heap::Base *m) { return m; }
void operator delete(void *, Heap::Base *) {}
+
+ void init() { _setInitialized(); }
+ void destroy() { _setDestroyed(); }
+#ifdef QML_CHECK_INIT_DESTROY_CALLS
+ 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 _checkIsDestroyed() {}
+ Q_ALWAYS_INLINE void _setInitialized() {}
+ Q_ALWAYS_INLINE void _setDestroyed() {}
+#endif
};
+V4_ASSERT_IS_TRIVIAL(Base)
template <typename T>
struct Pointer {
- Pointer() {}
- Pointer(T *t) : ptr(t) {}
-
T *operator->() const { return ptr; }
operator T *() const { return ptr; }
@@ -136,9 +184,65 @@ struct Pointer {
T *ptr;
};
+V4_ASSERT_IS_TRIVIAL(Pointer<void>)
}
+#ifdef QT_NO_QOBJECT
+template <class T>
+struct QQmlQPointer {
+};
+#else
+template <class T>
+struct QQmlQPointer {
+ void init()
+ {
+ d = nullptr;
+ qObject = nullptr;
+ }
+
+ void init(T *o)
+ {
+ Q_ASSERT(d == nullptr);
+ Q_ASSERT(qObject == nullptr);
+ if (o) {
+ d = QtSharedPointer::ExternalRefCountData::getAndRef(o);
+ qObject = o;
+ }
+ }
+
+ void destroy()
+ {
+ if (d && !d->weakref.deref())
+ delete d;
+ d = nullptr;
+ qObject = nullptr;
+ }
+
+ T *data() const {
+ return d == nullptr || d->strongref.load() == 0 ? nullptr : qObject;
+ }
+ operator T*() const { return data(); }
+ inline T* operator->() const { return data(); }
+ QQmlQPointer &operator=(T *o)
+ {
+ if (d)
+ destroy();
+ init(o);
+ return *this;
+ }
+ bool isNull() const Q_DECL_NOTHROW
+ {
+ return d == nullptr || qObject == nullptr || d->strongref.load() == 0;
+ }
+
+private:
+ QtSharedPointer::ExternalRefCountData *d;
+ QObject *qObject;
+};
+V4_ASSERT_IS_TRIVIAL(QQmlQPointer<QObject>)
+#endif
+
}
QT_END_NAMESPACE