From 3f1d0b27a11a1d560c11057d2a801224d1613d60 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 23 Jul 2014 13:56:43 +0200 Subject: [PATCH] Changed Value to store Managed::Data pointers directly This is a step towards storing direct heap object pointers for the values on the JS stack, to avoid the costly indirection for data access. Change-Id: Ibb57ed6cf52a7088bbc95ee04ae3a4cb25b8c045 Reviewed-by: Simon Hausmann --- src/imports/localstorage/plugin.cpp | 2 +- src/qml/compiler/qv4compileddata.cpp | 14 +++++---- src/qml/compiler/qv4compileddata_p.h | 2 +- src/qml/jit/qv4assembler.cpp | 4 +-- src/qml/jsruntime/qv4context.cpp | 15 ++++----- src/qml/jsruntime/qv4context_p.h | 8 ++--- src/qml/jsruntime/qv4engine.cpp | 7 +++-- src/qml/jsruntime/qv4function.cpp | 4 +-- src/qml/jsruntime/qv4function_p.h | 2 +- src/qml/jsruntime/qv4functionobject.cpp | 6 ++-- src/qml/jsruntime/qv4functionobject_p.h | 6 ++-- src/qml/jsruntime/qv4identifiertable.cpp | 3 +- src/qml/jsruntime/qv4managed_p.h | 16 +++++++++- src/qml/jsruntime/qv4memberdata.cpp | 2 +- src/qml/jsruntime/qv4mm.cpp | 5 +++ src/qml/jsruntime/qv4mm_p.h | 43 ++++++++++++++----------- src/qml/jsruntime/qv4objectiterator.cpp | 17 +++++----- src/qml/jsruntime/qv4regexp.cpp | 3 +- src/qml/jsruntime/qv4runtime.cpp | 8 ++--- src/qml/jsruntime/qv4scopedvalue_p.h | 22 +++++++------ src/qml/jsruntime/qv4script.cpp | 4 +-- src/qml/jsruntime/qv4value_p.h | 54 +++++++++++++++++--------------- src/qml/jsruntime/qv4vme_moth.cpp | 4 +-- src/qml/qml/qqmlvaluetypewrapper.cpp | 4 +-- src/qml/types/qqmldelegatemodel.cpp | 6 ++-- src/quick/items/qquickview.cpp | 2 +- src/quick/items/qquickview_p.h | 2 +- 27 files changed, 151 insertions(+), 114 deletions(-) diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 8b90f5a..78c1905 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -116,7 +116,7 @@ public: }; V4_OBJECT(Object) - static QQmlSqlDatabaseWrapper *create(QV8Engine *engine) + static QV4::Returned *create(QV8Engine *engine) { QV4::ExecutionEngine *e = QV8Engine::getV4(engine); return e->memoryManager->alloc(e); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index d242fb7..fbef8b8 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -65,9 +65,9 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) Q_ASSERT(!runtimeStrings); Q_ASSERT(data); - runtimeStrings = (QV4::StringValue *)malloc(data->stringTableSize * sizeof(QV4::StringValue)); + runtimeStrings = (QV4::String **)malloc(data->stringTableSize * sizeof(QV4::String*)); // memset the strings to 0 in case a GC run happens while we're within the loop below - memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::StringValue)); + memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::String*)); for (uint i = 0; i < data->stringTableSize; ++i) runtimeStrings[i] = engine->newIdentifier(data->stringAt(i)); @@ -109,7 +109,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) l->classList[j] = 0; l->level = -1; l->index = UINT_MAX; - l->name = runtimeStrings[compiledLookups[i].nameIndex].asString(); + l->name = runtimeStrings[compiledLookups[i].nameIndex]; if (type == CompiledData::Lookup::Type_IndexedGetter || type == CompiledData::Lookup::Type_IndexedSetter) l->engine = engine; } @@ -123,7 +123,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount); QV4::InternalClass *klass = engine->objectClass; for (int j = 0; j < memberCount; ++j, ++member) - klass = klass->addMember(runtimeStrings[member->nameOffset].asString(), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); + klass = klass->addMember(runtimeStrings[member->nameOffset], member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); runtimeClasses[i] = klass; } @@ -166,14 +166,16 @@ void CompilationUnit::unlink() void CompilationUnit::markObjects(QV4::ExecutionEngine *e) { for (uint i = 0; i < data->stringTableSize; ++i) - runtimeStrings[i].mark(e); + if (runtimeStrings[i]) + runtimeStrings[i]->mark(e); if (runtimeRegularExpressions) { for (uint i = 0; i < data->regexpTableSize; ++i) runtimeRegularExpressions[i].mark(e); } if (runtimeLookups) { for (uint i = 0; i < data->lookupTableSize; ++i) - runtimeLookups[i].name->mark(e); + if (runtimeLookups[i].name) + runtimeLookups[i].name->mark(e); } } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 6791970..6ab7191 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -588,7 +588,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount ExecutionEngine *engine; QString fileName() const { return data->stringAt(data->sourceFileIndex); } - QV4::StringValue *runtimeStrings; // Array + QV4::String **runtimeStrings; // Array QV4::Lookup *runtimeLookups; QV4::Value *runtimeRegularExpressions; QV4::InternalClass **runtimeClasses; diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index ed34274..300f4b0 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -214,7 +214,7 @@ Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &s loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, compilationUnit)), Assembler::ScratchRegister); loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg); const int id = _isel->registerString(string); - return Pointer(reg, id * sizeof(QV4::StringValue)); + return Pointer(reg, id * sizeof(QV4::String*)); } void Assembler::loadStringRef(RegisterID reg, const QString &string) @@ -222,7 +222,7 @@ void Assembler::loadStringRef(RegisterID reg, const QString &string) loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, compilationUnit)), reg); loadPtr(Address(reg, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg); const int id = _isel->registerString(string); - loadPtr(Address(reg, id * sizeof(QV4::StringValue)), reg); + loadPtr(Address(reg, id * sizeof(QV4::String*)), reg); } void Assembler::storeValue(QV4::Primitive value, IR::Expr *destination) diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 5ca47a8..8f9f8cc 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -48,7 +48,7 @@ DEFINE_MANAGED_VTABLE(CallContext); DEFINE_MANAGED_VTABLE(WithContext); DEFINE_MANAGED_VTABLE(GlobalContext); -HeapObject *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData) +Returned *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData) { Q_ASSERT(function->function()); @@ -78,24 +78,25 @@ HeapObject *ExecutionContext::newCallContext(FunctionObject *function, CallData std::fill(c->callData->args + c->callData->argc, c->callData->args + compiledFunction->nFormals, Primitive::undefinedValue()); c->callData->argc = qMax((uint)callData->argc, compiledFunction->nFormals); - return c; + return Returned::create(c); } -WithContext *ExecutionContext::newWithContext(Object *with) +Returned *ExecutionContext::newWithContext(Object *with) { return d()->engine->memoryManager->alloc(d()->engine, with); } -CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue) +Returned *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue) { return d()->engine->memoryManager->alloc(d()->engine, exceptionVarName, exceptionValue); } -CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml) +Returned *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml) { - CallContext *c = reinterpret_cast(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0))); + Scope scope(this); + Scoped c(scope, static_cast(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0)))); new (c->d()) CallContext::Data(d()->engine, qml, f); - return c; + return c.asReturned(); } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index 74530e7..4f7cdd8 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -127,10 +127,10 @@ struct Q_QML_EXPORT ExecutionContext : public Managed engine->current = this; } - HeapObject *newCallContext(FunctionObject *f, CallData *callData); - WithContext *newWithContext(Object *with); - CatchContext *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue); - CallContext *newQmlContext(FunctionObject *f, Object *qml); + Returned *newCallContext(FunctionObject *f, CallData *callData); + Returned *newWithContext(Object *with); + Returned *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue); + Returned *newQmlContext(FunctionObject *f, Object *qml); void createMutableBinding(String *name, bool deletable); diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 99050b0..ec1ea80 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -508,11 +508,12 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other) ExecutionContext *ExecutionEngine::pushGlobalContext() { - GlobalContext *g = memoryManager->alloc(this); + Scope scope(this); + Scoped g(scope, memoryManager->alloc(this)); g->d()->callData = rootContext->d()->callData; - Q_ASSERT(currentContext() == g); - return g; + Q_ASSERT(currentContext() == g.getPointer()); + return g.getPointer(); } diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index c7fe212..6bc4815 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -58,7 +58,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, Scope scope(engine); ScopedString s(scope); for (int i = static_cast(compiledFunction->nFormals - 1); i >= 0; --i) { - String *arg = compilationUnit->runtimeStrings[formalsIndices[i]].asString(); + String *arg = compilationUnit->runtimeStrings[formalsIndices[i]]; while (1) { InternalClass *newClass = internalClass->addMember(arg, Attr_NotConfigurable); if (newClass != internalClass) { @@ -72,7 +72,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const quint32 *localsIndices = compiledFunction->localsTable(); for (quint32 i = 0; i < compiledFunction->nLocals; ++i) { - String *local = compilationUnit->runtimeStrings[localsIndices[i]].asString(); + String *local = compilationUnit->runtimeStrings[localsIndices[i]]; internalClass = internalClass->addMember(local, Attr_NotConfigurable); } } diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 465489b..b2c4d2e 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -87,7 +87,7 @@ struct Q_QML_EXPORT Function { ~Function(); inline String *name() { - return compilationUnit->runtimeStrings[compiledFunction->nameIndex].getPointer(); + return compilationUnit->runtimeStrings[compiledFunction->nameIndex]; } inline QString sourceFile() const { return compilationUnit->fileName(); } diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index f3ad8ef..ea87ff1 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -165,14 +165,14 @@ void FunctionObject::markObjects(Managed *that, ExecutionEngine *e) Object::markObjects(that, e); } -FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto) +Returned *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto) { if (function->needsActivation() || function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith || function->compiledFunction->nFormals > QV4::Global::ReservedArgumentCount || function->isNamedExpression()) - return scope->d()->engine->memoryManager->alloc(scope, function); - return scope->d()->engine->memoryManager->alloc(scope, function, createProto); + return scope->d()->engine->memoryManager->alloc(scope, function)->as(); + return scope->d()->engine->memoryManager->alloc(scope, function, createProto)->as(); } DEFINE_OBJECT_VTABLE(FunctionCtor); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index c8edb76..2d57f6c 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -138,7 +138,7 @@ struct Q_QML_EXPORT FunctionObject: Object { return v.asFunctionObject(); } - static FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true); + static Returned *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true); ReturnedValue protoProperty() { return memberData()[Index_Prototype].asReturnedValue(); } @@ -188,7 +188,7 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject { }; V4_OBJECT(FunctionObject) - static BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) + static Returned *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *)) { return scope->engine()->memoryManager->alloc(scope, name, code); } @@ -253,7 +253,7 @@ struct BoundFunction: FunctionObject { }; V4_OBJECT(FunctionObject) - static BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs) + static Returned *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs) { return scope->engine()->memoryManager->alloc(scope, target, boundThis, boundArgs); } diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp index d7ed7a8..5554b68 100644 --- a/src/qml/jsruntime/qv4identifiertable.cpp +++ b/src/qml/jsruntime/qv4identifiertable.cpp @@ -121,7 +121,8 @@ String *IdentifierTable::insertString(const QString &s) idx %= alloc; } - String *str = engine->newString(s)->getPointer(); + Returned *_s = engine->newString(s); + String *str = _s->getPointer(); addEntry(str); return str; } diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h index c062ec4..c73ad10 100644 --- a/src/qml/jsruntime/qv4managed_p.h +++ b/src/qml/jsruntime/qv4managed_p.h @@ -207,7 +207,7 @@ struct Q_QML_PRIVATE_EXPORT Managed void setVTable(const ManagedVTable *vt); ReturnedValue asReturnedValue() const { - return reinterpret_cast(const_cast(this))->asReturnedValue(); + return Value::fromHeapObject(const_cast(this)).asReturnedValue(); } void *operator new(size_t, Managed *m) { return m; } @@ -377,6 +377,20 @@ inline FunctionObject *managed_cast(Managed *m) return m ? m->asFunctionObject() : 0; } +inline Value Value::fromManaged(Managed *m) +{ + if (!m) + return QV4::Primitive::undefinedValue(); + Value v; +#if QT_POINTER_SIZE == 8 + v.m = &m->data; +#else + v.tag = Managed_Type; + v.m = &m->data; +#endif + return v; +} + } diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index 405594c..4183234 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -57,6 +57,6 @@ void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx) else new (newMemberData) MemberData(e->memberDataClass); newMemberData->d()->size = newAlloc; - m = newMemberData; + m = &newMemberData->data; } } diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index b9a4a55..3877dde 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -535,6 +535,11 @@ MemoryManager::~MemoryManager() #endif } +ExecutionEngine *MemoryManager::engine() const +{ + return m_d->engine; +} + void MemoryManager::setExecutionEngine(ExecutionEngine *engine) { m_d->engine = engine; diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h index d5e28f7..cf9a148 100644 --- a/src/qml/jsruntime/qv4mm_p.h +++ b/src/qml/jsruntime/qv4mm_p.h @@ -96,57 +96,64 @@ public: } template - ManagedType *alloc() + Returned *alloc() { - ManagedType *t = static_cast(allocManaged(sizeof(typename ManagedType::Data))); + Scope scope(engine()); + Scoped t(scope, static_cast(allocManaged(sizeof(typename ManagedType::Data)))); (void)new (t->d()) typename ManagedType::Data(); - return t; + return t.asReturned(); } template - ManagedType *alloc(Arg1 arg1) + Returned *alloc(Arg1 arg1) { - ManagedType *t = static_cast(allocManaged(sizeof(typename ManagedType::Data))); + Scope scope(engine()); + Scoped t(scope, static_cast(allocManaged(sizeof(typename ManagedType::Data)))); (void)new (t->d()) typename ManagedType::Data(arg1); - return t; + return t.asReturned(); } template - ManagedType *alloc(Arg1 arg1, Arg2 arg2) + Returned *alloc(Arg1 arg1, Arg2 arg2) { - ManagedType *t = static_cast(allocManaged(sizeof(typename ManagedType::Data))); + Scope scope(engine()); + Scoped t(scope, static_cast(allocManaged(sizeof(typename ManagedType::Data)))); (void)new (t->d()) typename ManagedType::Data(arg1, arg2); - return t; + return t.asReturned(); } template - ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) + Returned *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3) { - ManagedType *t = static_cast(allocManaged(sizeof(typename ManagedType::Data))); + Scope scope(engine()); + Scoped t(scope, static_cast(allocManaged(sizeof(typename ManagedType::Data)))); (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3); - return t; + return t.asReturned(); } template - ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + Returned *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { - ManagedType *t = static_cast(allocManaged(sizeof(typename ManagedType::Data))); + Scope scope(engine()); + Scoped t(scope, static_cast(allocManaged(sizeof(typename ManagedType::Data)))); (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4); - return t; + return t.asReturned(); } template - ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) + Returned *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) { - ManagedType *t = static_cast(allocManaged(sizeof(typename ManagedType::Data))); + Scope scope(engine()); + Scoped t(scope, static_cast(allocManaged(sizeof(typename ManagedType::Data)))); (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5); - return t; + return t.asReturned(); } bool isGCBlocked() const; void setGCBlocked(bool blockGC); void runGC(); + ExecutionEngine *engine() const; void setExecutionEngine(ExecutionEngine *engine); void dumpStats() const; diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp index f9ccb8f..b2875a1 100644 --- a/src/qml/jsruntime/qv4objectiterator.cpp +++ b/src/qml/jsruntime/qv4objectiterator.cpp @@ -68,15 +68,15 @@ ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, uint flags) , memberIndex(0) , flags(flags) { - object->m = (Object*)0; - current->m = (Object*)0; + object->m = 0; + current->m = 0; // Caller needs to call init! } void ObjectIterator::init(Object *o) { - object->m = o; - current->m = o; + object->m = o ? &o->data : 0; + current->m = o ? &o->data : 0; #if QT_POINTER_SIZE == 4 object->tag = QV4::Value::Managed_Type; @@ -125,10 +125,11 @@ void ObjectIterator::next(String *&name, uint *index, Property *pd, PropertyAttr return; } - if (flags & WithProtoChain) - current->m = current->objectValue()->prototype(); - else - current->m = (Object *)0; + if (flags & WithProtoChain) { + Object *proto = current->objectValue()->prototype(); + current->m = proto ? &proto->data : 0; + } else + current->m = (HeapObject *)0; arrayIndex = 0; memberIndex = 0; diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp index e84c96f..ed67289 100644 --- a/src/qml/jsruntime/qv4regexp.cpp +++ b/src/qml/jsruntime/qv4regexp.cpp @@ -73,7 +73,8 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign return result; } - RegExp *result = engine->memoryManager->alloc(engine, pattern, ignoreCase, multiline); + Scope scope(engine); + Scoped result(scope, engine->memoryManager->alloc(engine, pattern, ignoreCase, multiline)); if (!cache) cache = engine->regExpCache = new RegExpCache; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index cb7e219..957f8cd 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -881,9 +881,9 @@ ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, String Scope scope(context); ScopedObject base(scope); - Object *baseObj = base.ptr->objectValue(); + Object *baseObj = 0; ScopedValue func(scope, context->getPropertyAndBase(name, baseObj)); - base.ptr->m = baseObj; + base.ptr->m = baseObj ? &baseObj->data : 0; if (scope.engine->hasException) return Encode::undefined(); @@ -1101,7 +1101,7 @@ ExecutionContext *Runtime::pushWithScope(const ValueRef o, ExecutionContext *ctx { Scope scope(ctx); ScopedObject obj(scope, o->toObject(ctx)); - return reinterpret_cast(ctx->newWithContext(obj)); + return ctx->newWithContext(obj)->getPointer(); } ReturnedValue Runtime::unwindException(ExecutionContext *ctx) @@ -1115,7 +1115,7 @@ ExecutionContext *Runtime::pushCatchScope(ExecutionContext *ctx, String *excepti { Scope scope(ctx); ScopedValue v(scope, ctx->engine()->catchException(ctx, 0)); - return reinterpret_cast(ctx->newCatchContext(exceptionVarName, v)); + return ctx->newCatchContext(exceptionVarName, v)->getPointer(); } ExecutionContext *Runtime::popScope(ExecutionContext *ctx) diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index b1b4d5d..5cc8495 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -112,7 +112,7 @@ struct ScopedValue ScopedValue(const Scope &scope, HeapObject *o) { ptr = scope.engine->jsStackTop++; - ptr->m = reinterpret_cast(o); + ptr->m = o; #if QT_POINTER_SIZE == 4 ptr->tag = QV4::Value::Managed_Type; #endif @@ -155,7 +155,7 @@ struct ScopedValue } ScopedValue &operator=(HeapObject *o) { - ptr->m = reinterpret_cast(o); + ptr->m = o; #if QT_POINTER_SIZE == 4 ptr->tag = QV4::Value::Managed_Type; #endif @@ -204,7 +204,7 @@ struct Scoped inline void setPointer(Managed *p) { #if QT_POINTER_SIZE == 8 - ptr->val = (quint64)p; + ptr->val = (quint64)(p ? &p->data : 0); #else *ptr = p ? QV4::Value::fromManaged(p) : QV4::Primitive::undefinedValue(); #endif @@ -230,7 +230,7 @@ struct Scoped Scoped(const Scope &scope, HeapObject *o) { Value v; - v.m = reinterpret_cast(o); + v.m = o; #if QT_POINTER_SIZE == 4 v.tag = QV4::Value::Managed_Type; #endif @@ -317,7 +317,7 @@ struct Scoped Scoped &operator=(HeapObject *o) { Value v; - v.m = reinterpret_cast(o); + v.m = o; #if QT_POINTER_SIZE == 4 v.tag = QV4::Value::Managed_Type; #endif @@ -361,10 +361,10 @@ struct Scoped } bool operator!() const { - return !ptr->managed(); + return !ptr->m; } operator void *() const { - return ptr->managed(); + return ptr->m; } T *getPointer() { @@ -379,6 +379,8 @@ struct Scoped #endif } + Returned *asReturned() const { return Returned::create(static_cast(ptr->heapObject())); } + Value *ptr; }; @@ -478,7 +480,7 @@ inline Returned *Value::as() template inline TypedValue &TypedValue::operator =(T *t) { - m = t; + m = t ? &t->data : 0; #if QT_POINTER_SIZE == 4 tag = Managed_Type; #endif @@ -488,7 +490,7 @@ inline TypedValue &TypedValue::operator =(T *t) template inline TypedValue &TypedValue::operator =(const Scoped &v) { - m = v.ptr->managed(); + m = v.ptr->m; #if QT_POINTER_SIZE == 4 tag = Managed_Type; #endif @@ -519,7 +521,7 @@ inline TypedValue &TypedValue::operator=(const TypedValue &t) template inline Returned * TypedValue::ret() const { - return Returned::create(static_cast(managed())); + return Returned::create(static_cast(heapObject())); } inline Primitive::operator ValueRef() diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index fa4b4b1..20b0832 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -70,7 +70,7 @@ QmlBindingWrapper::Data::Data(ExecutionContext *scope, Function *f, Object *qml) o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1)); - o->d()->qmlContext = reinterpret_cast(s.engine->currentContext()->newQmlContext(o, qml)); + o->d()->qmlContext = s.engine->currentContext()->newQmlContext(o, qml)->getPointer(); s.engine->popContext(); } @@ -88,7 +88,7 @@ QmlBindingWrapper::Data::Data(ExecutionContext *scope, Object *qml) o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1)); - o->d()->qmlContext = reinterpret_cast(s.engine->currentContext()->newQmlContext(o, qml)); + o->d()->qmlContext = s.engine->currentContext()->newQmlContext(o, qml)->getPointer(); s.engine->popContext(); } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index f215162..9c6bd60 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -44,19 +44,21 @@ namespace QV4 { typedef uint Bool; +struct HeapObject {}; + template -struct Returned : private T +struct Returned : private HeapObject { - static Returned *create(T *t) { return static_cast *>(t); } - T *getPointer() { return this; } + static Returned *create(T *t) { Q_ASSERT((void *)&t->data == (void *)t); return static_cast *>(static_cast(t ? &t->data : 0)); } + static Returned *create(typename T::Data *t) { return static_cast *>(static_cast(t)); } + T *getPointer() { return reinterpret_cast(this); } template static T *getPointer(Returned *x) { return x->getPointer(); } template Returned *as() { return Returned::create(Returned::getPointer(this)); } - using T::asReturnedValue; -}; -struct HeapObject {}; + inline ReturnedValue asReturnedValue(); +}; struct Q_QML_PRIVATE_EXPORT Value { @@ -86,7 +88,7 @@ struct Q_QML_PRIVATE_EXPORT Value union { quint64 val; #if QT_POINTER_SIZE == 8 - Managed *m; + HeapObject *m; #else double dbl; #endif @@ -98,7 +100,7 @@ struct Q_QML_PRIVATE_EXPORT Value uint uint_32; int int_32; #if QT_POINTER_SIZE == 4 - Managed *m; + HeapObject *m; #endif }; #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN @@ -266,12 +268,15 @@ struct Q_QML_PRIVATE_EXPORT Value } String *stringValue() const { - return reinterpret_cast(m); + return m ? reinterpret_cast(m) : 0; } Object *objectValue() const { - return reinterpret_cast(m); + return m ? reinterpret_cast(m) : 0; } Managed *managed() const { + return m ? reinterpret_cast(m) : 0; + } + HeapObject *heapObject() const { return m; } @@ -279,6 +284,16 @@ struct Q_QML_PRIVATE_EXPORT Value return val; } + static inline Value fromHeapObject(HeapObject *m) + { + Value v; + v.m = m; +#if QT_POINTER_SIZE == 4 + v.tag = Managed_Type; +#endif + return v; + } + static inline Value fromManaged(Managed *m); int toUInt16() const; @@ -338,7 +353,7 @@ struct Q_QML_PRIVATE_EXPORT Value return *this; } Value &operator=(HeapObject *o) { - m = reinterpret_cast(o); + m = o; return *this; } @@ -405,20 +420,6 @@ inline Primitive Primitive::emptyValue() return v; } -inline Value Value::fromManaged(Managed *m) -{ - if (!m) - return QV4::Primitive::undefinedValue(); - Value v; -#if QT_POINTER_SIZE == 8 - v.m = m; -#else - v.tag = Managed_Type; - v.m = m; -#endif - return v; -} - template struct TypedValue : public Value { @@ -557,7 +558,8 @@ T *value_cast(const Value &v) template ReturnedValue value_convert(ExecutionEngine *e, const Value &v); - +template +ReturnedValue Returned::asReturnedValue() { return Value::fromHeapObject(this).asReturnedValue(); } } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index cd73314..35ac5ea 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -184,7 +184,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code qDebug("Starting VME with context=%p and code=%p", context, code); #endif // DO_TRACE_INSTR - QV4::StringValue * const runtimeStrings = context->d()->compilationUnit->runtimeStrings; + QV4::String ** const runtimeStrings = context->d()->compilationUnit->runtimeStrings; // setup lookup scopes int scopeDepth = 0; @@ -240,7 +240,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code MOTH_BEGIN_INSTR(LoadRuntimeString) // TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData()); - VALUE(instr.result) = runtimeStrings[instr.stringId].asReturnedValue(); + VALUE(instr.result) = runtimeStrings[instr.stringId]->asReturnedValue(); MOTH_END_INSTR(LoadRuntimeString) MOTH_BEGIN_INSTR(LoadRegExp) diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index b0125b4..8123a29 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -144,7 +144,7 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int pr Scope scope(v4); initProto(v4); - QmlValueTypeReference *r = v4->memoryManager->alloc(v8); + Scoped r(scope, v4->memoryManager->alloc(v8)); r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype); r->d()->type = type; r->d()->object = object; r->d()->property = property; return r->asReturnedValue(); @@ -156,7 +156,7 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, Scope scope(v4); initProto(v4); - QmlValueTypeCopy *r = v4->memoryManager->alloc(v8); + Scoped r(scope, v4->memoryManager->alloc(v8)); r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype); r->d()->type = type; r->d()->value = value; return r->asReturnedValue(); diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 639df4f..b26557e 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -67,7 +67,7 @@ struct DelegateModelGroupFunction: QV4::FunctionObject }; V4_OBJECT(QV4::FunctionObject) - static DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg)) + static QV4::Returned *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg)) { return scope->engine()->memoryManager->alloc(scope, flag, code); } @@ -3220,7 +3220,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object }; V4_OBJECT(QV4::Object) - static QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) { + static QV4::Returned *create(QV4::ExecutionEngine *e) { return e->memoryManager->alloc(e); } @@ -3267,7 +3267,7 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object }; V4_OBJECT(QV4::Object) public: - static QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector &changes) + static QV4::Returned *create(QV4::ExecutionEngine *engine, const QVector &changes) { return engine->memoryManager->alloc(engine, changes); } diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp index a55d056..d00fd10 100644 --- a/src/quick/items/qquickview.cpp +++ b/src/quick/items/qquickview.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE DEFINE_OBJECT_VTABLE(QQuickRootItemMarker); -QQuickRootItemMarker *QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window) +QV4::Returned *QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window) { QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine); return e->memoryManager->alloc(e, window); diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h index 54f60c8..50d6375 100644 --- a/src/quick/items/qquickview_p.h +++ b/src/quick/items/qquickview_p.h @@ -108,7 +108,7 @@ struct QQuickRootItemMarker : public QV4::Object }; V4_OBJECT(QV4::Object) - static QQuickRootItemMarker *create(QQmlEngine *engine, QQuickWindow *window); + static QV4::Returned *create(QQmlEngine *engine, QQuickWindow *window); static void markObjects(Managed *that, QV4::ExecutionEngine *e); -- 2.7.4