aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2016-09-08 11:07:26 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2016-09-30 14:14:31 +0000
commitb80fa8e7d59c2824de067ab4d488d865a6e69d94 (patch)
treedfbab030756f9c5a0f76aba8a558f429311724a2 /src/qml
parentc2e28350a6ea866b9e68059f232aaeccd47f743b (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/qml')
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp4
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h2
-rw-r--r--src/qml/jsruntime/qv4context.cpp31
-rw-r--r--src/qml/jsruntime/qv4context_p.h70
-rw-r--r--src/qml/jsruntime/qv4engine.cpp7
-rw-r--r--src/qml/jsruntime/qv4function.cpp4
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp16
-rw-r--r--src/qml/jsruntime/qv4managed_p.h7
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp4
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h1
-rw-r--r--src/qml/jsruntime/qv4object_p.h16
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp2
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp6
-rw-r--r--src/qml/jsruntime/qv4string.cpp6
-rw-r--r--src/qml/jsruntime/qv4string_p.h2
-rw-r--r--src/qml/jsruntime/qv4value_p.h5
-rw-r--r--src/qml/memory/qv4heap_p.h14
-rw-r--r--src/qml/memory/qv4mm_p.h4
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();
}