diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-09-09 15:37:57 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-10-06 11:44:08 +0000 |
commit | 3b14e2ffdd8eb4b7f7f4508768b75f2acc399370 (patch) | |
tree | 7943f293bf2d0d376d5dc620448bab1a2b58027d /src/qml/memory | |
parent | 1b90dc4482d001512f09a5785d4cbd8030879d82 (diff) |
QML: Make Heap::Object and all subclasses trivial
GCC6 might dead-store-eliminate out our secret write to Base::mmdata,
because it expects all memory content to be "undefined" before
constructor calls. Clang might take the same approach if the constructor
of Heap::Object is removed.
By making these structs trivial, it also makes them memcpy-able.
Change-Id: I055b2ad28311b997fbe059849ebda4d5894eaa9b
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/memory')
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 20 | ||||
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 40 |
2 files changed, 34 insertions, 26 deletions
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index d15d14e463..abbe85c04e 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; @@ -128,13 +136,19 @@ struct Q_QML_EXPORT Base { void init() { setInitialized(); } #ifdef QML_CHECK_INIT_DESTROY_CALLS bool _isInitialized; - void _checkIsInitialized() { Q_ASSERT(_isInitialized); } + void _checkIsInitialized() { + if (!_isInitialized) + fprintf(stderr, "ERROR: use of object '%s' before call to init() !!\n", + vtable()->className); + Q_ASSERT(_isInitialized); + } void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; } #else Q_ALWAYS_INLINE void _checkIsInitialized() {} Q_ALWAYS_INLINE void setInitialized() {} #endif }; +V4_ASSERT_IS_TRIVIAL(Base) template <typename T> struct Pointer { @@ -148,7 +162,7 @@ struct Pointer { T *ptr; }; -Q_STATIC_ASSERT(std::is_trivial<Pointer<void>>::value); +V4_ASSERT_IS_TRIVIAL(Pointer<void>) } @@ -204,7 +218,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_p.h b/src/qml/memory/qv4mm_p.h index cfd348e14a..e68fc07a46 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -108,6 +108,7 @@ 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); o->setVtable(ManagedType::staticVTable()); @@ -142,7 +143,6 @@ public: template <typename ManagedType, typename Arg1> typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1) { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize)); t->d_unchecked()->init(this, arg1); @@ -154,7 +154,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(); } @@ -163,8 +163,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(); } @@ -173,8 +173,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(); } @@ -183,8 +183,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(); } @@ -193,8 +193,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(); } @@ -203,8 +203,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(); } @@ -213,7 +213,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(); } @@ -222,7 +222,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(); } @@ -231,7 +231,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(); } @@ -240,7 +240,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(); } @@ -249,7 +249,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(); } @@ -257,7 +257,6 @@ public: template <typename ManagedType> typename ManagedType::Data *alloc() { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(); @@ -267,7 +266,6 @@ public: template <typename ManagedType, typename Arg1> typename ManagedType::Data *alloc(Arg1 arg1) { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1); @@ -277,7 +275,6 @@ public: template <typename ManagedType, typename Arg1, typename Arg2> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2) { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2); @@ -287,7 +284,6 @@ public: template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3); @@ -297,7 +293,6 @@ public: template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3, arg4); @@ -307,7 +302,6 @@ public: template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { - Q_STATIC_ASSERT(std::is_trivial<typename ManagedType::Data>::value); // TODO: move down to allocManaged Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); t->d_unchecked()->init(arg1, arg2, arg3, arg4, arg5); |