diff options
author | Erik Verbruggen <erik.verbruggen@digia.com> | 2016-09-08 11:07:26 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-09-30 14:14:31 +0000 |
commit | b80fa8e7d59c2824de067ab4d488d865a6e69d94 (patch) | |
tree | dfbab030756f9c5a0f76aba8a558f429311724a2 /src | |
parent | c2e28350a6ea866b9e68059f232aaeccd47f743b (diff) |
QML: Make all context objects trivial
This change also adds a check to the d() calls for Managed, verifies
that the object has been initialized. This is only done for debug
builds.
To prevent other code from tripping the check, a number of other classes
are either marked as trivial, or do initialization in the constructors.
Because of template function changes in them memory manager (those now
call init() instead of in-place new), String has an extra parameter
to force it to temporarily use an old/unmodified template function.
Change-Id: I8c35161ce7680835d830638b6d21498c5129b02b
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4arraydata.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arraydata_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 31 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 70 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata.cpp | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4memberdata_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object_p.h | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexp.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 5 | ||||
-rw-r--r-- | src/qml/memory/qv4heap_p.h | 14 | ||||
-rw-r--r-- | src/qml/memory/qv4mm_p.h | 4 |
18 files changed, 123 insertions, 78 deletions
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index f4afe46fcb..74c83b1940 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -143,13 +143,13 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt Scoped<ArrayData> newData(scope); if (newType < Heap::ArrayData::Sparse) { Heap::SimpleArrayData *n = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size); - new (n) Heap::SimpleArrayData; + n->init(); n->offset = 0; n->len = d ? d->d()->len : 0; newData = n; } else { Heap::SparseArrayData *n = scope.engine->memoryManager->allocManaged<SparseArrayData>(size); - new (n) Heap::SparseArrayData; + n->init(); newData = n; } newData->setAlloc(alloc); diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h index 8ad4704227..d7ee4798b0 100644 --- a/src/qml/jsruntime/qv4arraydata_p.h +++ b/src/qml/jsruntime/qv4arraydata_p.h @@ -133,6 +133,7 @@ struct ArrayData : public Base { } }; +Q_STATIC_ASSERT(std::is_trivial<ArrayData>::value); struct SimpleArrayData : public ArrayData { uint mappedIndex(uint index) const { return (index + offset) % alloc; } @@ -152,6 +153,7 @@ struct SimpleArrayData : public ArrayData { return attrs ? attrs[i] : Attr_Data; } }; +Q_STATIC_ASSERT(std::is_trivial<SimpleArrayData>::value); struct SparseArrayData : public ArrayData { inline ~SparseArrayData(); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 1abaca3dd1..390a5e7d7a 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -61,8 +61,9 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi { Q_ASSERT(function->function()); - Heap::CallContext *c = d()->engine->memoryManager->allocManaged<CallContext>(requiredMemoryForExecutionContect(function, callData->argc)); - new (c) Heap::CallContext(d()->engine, Heap::ExecutionContext::Type_CallContext); + Heap::CallContext *c = d()->engine->memoryManager->allocManaged<CallContext>( + requiredMemoryForExecutionContect(function, callData->argc)); + c->init(d()->engine, Heap::ExecutionContext::Type_CallContext); c->function = function->d(); @@ -160,28 +161,16 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable) activation->__defineOwnProperty__(scope.engine, name, desc, attrs); } - -Heap::GlobalContext::GlobalContext(ExecutionEngine *eng) - : Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext) +void Heap::GlobalContext::init(ExecutionEngine *eng) { + Heap::ExecutionContext::init(eng, Heap::ExecutionContext::Type_GlobalContext); global = eng->globalObject->d(); } -Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with) - : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_WithContext) -{ - outer = outerContext; - callData = outer->callData; - lookups = outer->lookups; - constantTable = outer->constantTable; - compilationUnit = outer->compilationUnit; - - withObject = with; -} - -Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue) - : Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_CatchContext) +void Heap::CatchContext::init(ExecutionContext *outerContext, String *exceptionVarName, + const Value &exceptionValue) { + Heap::ExecutionContext::init(outerContext->engine, Heap::ExecutionContext::Type_CatchContext); outer = outerContext; strictMode = outer->strictMode; callData = outer->callData; @@ -193,9 +182,9 @@ Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *excepti this->exceptionValue = exceptionValue; } -Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml) - : Heap::ExecutionContext(outerContext->engine(), Heap::ExecutionContext::Type_QmlContext) +void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml) { + Heap::ExecutionContext::init(outerContext->engine(), Heap::ExecutionContext::Type_QmlContext); outer = outerContext->d(); strictMode = false; callData = outer->callData; diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 713b2b6412..ffedf737ce 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -101,7 +101,20 @@ struct ExecutionContext : Base { Type_CallContext = 0x6 }; - inline ExecutionContext(ExecutionEngine *engine, ContextType t); + void init(ExecutionEngine *engine, ContextType t) + { + Base::init(); + + callData = nullptr; + this->engine = engine; + outer = nullptr; + lookups = nullptr; + constantTable = nullptr; + compilationUnit = nullptr; + type = t; + strictMode = false; + lineNumber = -1; + } CallData *callData; @@ -115,25 +128,14 @@ struct ExecutionContext : Base { bool strictMode : 8; int lineNumber; }; - -inline -ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t) - : engine(engine) - , lookups(nullptr) - , constantTable(nullptr) - , compilationUnit(nullptr) - , type(t) - , strictMode(false) - , lineNumber(-1) -{ - outer = nullptr; -} - +Q_STATIC_ASSERT(std::is_trivial<ExecutionContext>::value); struct CallContext : ExecutionContext { - CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext) - : ExecutionContext(engine, t) + static CallContext createOnStack(ExecutionEngine *v4); + + void init(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext) { + ExecutionContext::init(engine, t); function = 0; locals = 0; activation = 0; @@ -143,27 +145,43 @@ struct CallContext : ExecutionContext { Value *locals; Pointer<Object> activation; }; +Q_STATIC_ASSERT(std::is_trivial<CallContext>::value); struct GlobalContext : ExecutionContext { - GlobalContext(ExecutionEngine *engine); + void init(ExecutionEngine *engine); Pointer<Object> global; }; +Q_STATIC_ASSERT(std::is_trivial<GlobalContext>::value); struct CatchContext : ExecutionContext { - CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue); + void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue); Pointer<String> exceptionVarName; Value exceptionValue; }; +Q_STATIC_ASSERT(std::is_trivial<CatchContext>::value); struct WithContext : ExecutionContext { - WithContext(ExecutionContext *outerContext, Object *with); + void init(ExecutionContext *outerContext, Object *with) + { + Heap::ExecutionContext::init(outerContext->engine, Heap::ExecutionContext::Type_WithContext); + outer = outerContext; + callData = outer->callData; + lookups = outer->lookups; + constantTable = outer->constantTable; + compilationUnit = outer->compilationUnit; + + withObject = with; + } + Pointer<Object> withObject; }; +Q_STATIC_ASSERT(std::is_trivial<WithContext>::value); struct QmlContextWrapper; struct QmlContext : ExecutionContext { - QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml); + void init(QV4::ExecutionContext *outerContext, QV4::QmlContextWrapper *qml); + Pointer<QmlContextWrapper> qml; }; @@ -280,6 +298,16 @@ inline const WithContext *ExecutionContext::asWithContext() const return d()->type == Heap::ExecutionContext::Type_WithContext ? static_cast<const WithContext *>(this) : 0; } +inline Heap::CallContext Heap::CallContext::createOnStack(ExecutionEngine *v4) +{ + Heap::CallContext ctxt; + memset(&ctxt, 0, sizeof(Heap::CallContext)); + ctxt.mm_data = 0; + ctxt.setVtable(QV4::CallContext::staticVTable()); + ctxt.init(v4); + return ctxt; +} + /* Function *f, int argc */ #define requiredMemoryForExecutionContect(f, argc) \ ((sizeof(CallContext::Data) + 7) & ~7) + sizeof(Value) * (f->varCount() + qMax((uint)argc, f->formalParameterCount())) + sizeof(CallData) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index f8110d29f6..e81292f598 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -488,8 +488,9 @@ void ExecutionEngine::setProfiler(Profiling::Profiler *profiler) void ExecutionEngine::initRootContext() { Scope scope(this); - Scoped<GlobalContext> r(scope, memoryManager->allocManaged<GlobalContext>(sizeof(GlobalContext::Data) + sizeof(CallData))); - new (r->d()) GlobalContext::Data(this); + Scoped<GlobalContext> r(scope, memoryManager->allocManaged<GlobalContext>( + sizeof(GlobalContext::Data) + sizeof(CallData))); + r->d_unchecked()->init(this); r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1); r->d()->callData->tag = QV4::Value::Integer_Type_Internal; r->d()->callData->argc = 0; @@ -572,7 +573,7 @@ Heap::ArrayObject *ExecutionEngine::newArrayObject(const Value *values, int leng if (length) { size_t size = sizeof(Heap::ArrayData) + (length-1)*sizeof(Value); Heap::SimpleArrayData *d = scope.engine->memoryManager->allocManaged<SimpleArrayData>(size); - new (d) Heap::SimpleArrayData; + d->init(); d->alloc = length; d->type = Heap::ArrayData::Simple; d->offset = 0; diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index caabee322a..300e538d3d 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -73,7 +73,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, } // duplicate arguments, need some trick to store them MemoryManager *mm = engine->memoryManager; - arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe))); + arg = mm->alloc<String>(mm, arg->d(), engine->newString(QString(0xfffe)), true); } } nFormals = compiledFunction->nFormals; @@ -105,7 +105,7 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr break; } // duplicate arguments, need some trick to store them - arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe))); + arg = engine->memoryManager->alloc<String>(engine->memoryManager, arg->d(), engine->newString(QString(0xfffe)), true); } } nFormals = parameters.size(); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index df9f92b259..e160dd8a36 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -527,9 +527,7 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData ScopedObject proto(scope, f->protoForConstructor()); callData->thisObject = v4->newObject(ic, proto); - CallContext::Data ctx(v4); - ctx.mm_data = 0; - ctx.setVtable(CallContext::staticVTable()); + CallContext::Data ctx = CallContext::Data::createOnStack(v4); ctx.strictMode = f->strictMode(); ctx.callData = callData; ctx.function = f->d(); @@ -568,9 +566,7 @@ void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *cal Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); - CallContext::Data ctx(v4); - ctx.mm_data = 0; - ctx.setVtable(CallContext::staticVTable()); + CallContext::Data ctx = CallContext::Data::createOnStack(v4); ctx.strictMode = f->strictMode(); ctx.callData = callData; ctx.function = f->d(); @@ -626,9 +622,7 @@ void BuiltinFunction::call(const Managed *that, Scope &scope, CallData *callData ExecutionContextSaver ctxSaver(scope); - CallContext::Data ctx(v4); - ctx.mm_data = 0; - ctx.setVtable(CallContext::staticVTable()); + CallContext::Data ctx = CallContext::Data::createOnStack(v4); ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context? ctx.callData = callData; v4->pushContext(&ctx); @@ -649,9 +643,7 @@ void IndexedBuiltinFunction::call(const Managed *that, Scope &scope, CallData *c ExecutionContextSaver ctxSaver(scope); - CallContext::Data ctx(v4); - ctx.mm_data = 0; - ctx.setVtable(CallContext::staticVTable()); + CallContext::Data ctx = CallContext::Data::createOnStack(v4); ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context? ctx.callData = callData; v4->pushContext(&ctx); diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index 1109760fc0..764a8e7f3f 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -85,7 +85,12 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {} static const QV4::VTable static_vtbl; \ static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \ V4_MANAGED_SIZE_TEST \ - QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); } + QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \ + QV4::Heap::DataClass *d() const { \ + QV4::Heap::DataClass *dptr = d_unchecked(); \ + if (std::is_trivial<QV4::Heap::DataClass>::value) dptr->_checkIsInitialized(); \ + return dptr; \ + } #define V4_MANAGED(DataClass, superClass) \ private: \ diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index 62e4f0a14d..5646a44891 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -58,9 +58,9 @@ static Heap::MemberData *reallocateHelper(ExecutionEngine *e, Heap::MemberData * Scope scope(e); Scoped<MemberData> newMemberData(scope, e->memoryManager->allocManaged<MemberData>(alloc)); if (old) - memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + old->size * sizeof(Value)); + memcpy(newMemberData->d_unchecked(), old, sizeof(Heap::MemberData) + old->size * sizeof(Value)); else - new (newMemberData->d()) Heap::MemberData; + newMemberData->d_unchecked()->init(); newMemberData->d()->size = n; return newMemberData->d(); } diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h index 2742e0b212..41da730428 100644 --- a/src/qml/jsruntime/qv4memberdata_p.h +++ b/src/qml/jsruntime/qv4memberdata_p.h @@ -66,6 +66,7 @@ struct MemberData : Base { }; Value data[1]; }; +Q_STATIC_ASSERT(std::is_trivial<MemberData>::value); } diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h index eda7774f90..54ce2ea60d 100644 --- a/src/qml/jsruntime/qv4object_p.h +++ b/src/qml/jsruntime/qv4object_p.h @@ -68,7 +68,7 @@ namespace QV4 { namespace Heap { struct Object : Base { - inline Object() {} + inline Object() { Base::init(); } const Value *propertyData(uint index) const { if (index < inlineMemberSize) return reinterpret_cast<const Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } Value *propertyData(uint index) { if (index < inlineMemberSize) return reinterpret_cast<Value *>(this) + inlineMemberOffset + index; return memberData->data + index - inlineMemberSize; } @@ -90,7 +90,12 @@ struct Object : Base { static const QV4::ObjectVTable static_vtbl; \ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \ V4_MANAGED_SIZE_TEST \ - Data *d() const { return static_cast<Data *>(m()); } + Data *d_unchecked() const { return static_cast<Data *>(m()); } \ + Data *d() const { \ + Data *dptr = d_unchecked(); \ + if (std::is_trivial<Data>::value) dptr->_checkIsInitialized(); \ + return dptr; \ + } #define V4_OBJECT2(DataClass, superClass) \ private: \ @@ -103,7 +108,12 @@ struct Object : Base { static const QV4::ObjectVTable static_vtbl; \ static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \ V4_MANAGED_SIZE_TEST \ - QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); } + QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \ + QV4::Heap::DataClass *d() const { \ + QV4::Heap::DataClass *dptr = d_unchecked(); \ + if (std::is_trivial<QV4::Heap::DataClass>::value) dptr->_checkIsInitialized(); \ + return dptr; \ + } #define V4_INTERNALCLASS(c) \ static QV4::InternalClass *defaultInternalClass(QV4::ExecutionEngine *e) \ diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index af5355c964..6d6d446ca2 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -95,6 +95,8 @@ Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignor , ignoreCase(ignoreCase) , multiLine(multiline) { + Base::init(); + const char* error = 0; JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error); if (error) diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index b7a4c4f643..88c1286c61 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -555,7 +555,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); + return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue(); } double x = RuntimeHelpers::toNumber(pleft); double y = RuntimeHelpers::toNumber(pright); @@ -572,7 +572,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu if (!right.stringValue()->d()->length()) return left.asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d()))->asReturnedValue(); + return (mm->alloc<String>(mm, left.stringValue()->d(), right.stringValue()->d(), true))->asReturnedValue(); } Scope scope(engine); @@ -590,7 +590,7 @@ QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Valu if (!pright->stringValue()->d()->length()) return pleft->asReturnedValue(); MemoryManager *mm = engine->memoryManager; - return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); + return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d(), true))->asReturnedValue(); } void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp index 3901514326..8bc867e2cd 100644 --- a/src/qml/jsruntime/qv4string.cpp +++ b/src/qml/jsruntime/qv4string.cpp @@ -77,6 +77,8 @@ bool String::isEqualTo(Managed *t, Managed *o) Heap::String::String(MemoryManager *mm, const QString &t) : mm(mm) { + Base::init(); + subtype = String::StringType_Unknown; text = const_cast<QString &>(t).data_ptr(); @@ -87,9 +89,11 @@ Heap::String::String(MemoryManager *mm, const QString &t) len = text->size; } -Heap::String::String(MemoryManager *mm, String *l, String *r) +Heap::String::String(MemoryManager *mm, String *l, String *r, bool) // TODO: remove the dummy bool when String is trivial : mm(mm) { + Base::init(); + subtype = String::StringType_Unknown; left = l; diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h index ff42ab6471..f347ea8897 100644 --- a/src/qml/jsruntime/qv4string_p.h +++ b/src/qml/jsruntime/qv4string_p.h @@ -72,7 +72,7 @@ struct Q_QML_PRIVATE_EXPORT String : Base { #ifndef V4_BOOTSTRAP String(MemoryManager *mm, const QString &text); - String(MemoryManager *mm, String *l, String *n); + String(MemoryManager *mm, String *l, String *n, bool dummy); ~String() { if (!largestSubLength && !text->ref.deref()) QStringData::deallocate(text); diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index d02d08f3e6..78cd4de9fb 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -427,11 +427,8 @@ public: template<typename T> Value &operator=(const Scoped<T> &t); - Value &operator=(const Value &v) { - _val = v._val; - return *this; - } }; +Q_STATIC_ASSERT(std::is_trivial<Value>::value); inline bool Value::isString() const { diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h index f38898b2ea..d15d14e463 100644 --- a/src/qml/memory/qv4heap_p.h +++ b/src/qml/memory/qv4heap_p.h @@ -54,6 +54,10 @@ #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 + QT_BEGIN_NAMESPACE namespace QV4 { @@ -120,6 +124,16 @@ 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(); } +#ifdef QML_CHECK_INIT_DESTROY_CALLS + bool _isInitialized; + void _checkIsInitialized() { Q_ASSERT(_isInitialized); } + void setInitialized() { Q_ASSERT(!_isInitialized); _isInitialized = true; } +#else + Q_ALWAYS_INLINE void _checkIsInitialized() {} + Q_ALWAYS_INLINE void setInitialized() {} +#endif }; template <typename T> diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h index 026cbd8c6b..6db5b54760 100644 --- a/src/qml/memory/qv4mm_p.h +++ b/src/qml/memory/qv4mm_p.h @@ -276,7 +276,7 @@ public: { Scope scope(engine); Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data))); - (void)new (t->d()) typename ManagedType::Data(arg1, arg2); + t->d_unchecked()->init(arg1, arg2); return t->d(); } @@ -285,7 +285,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); + t->d_unchecked()->init(arg1, arg2, arg3); return t->d(); } |