Changed Value to store Managed::Data pointers directly
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 23 Jul 2014 11:56:43 +0000 (13:56 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 4 Nov 2014 13:58:30 +0000 (14:58 +0100)
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 <simon.hausmann@digia.com>
27 files changed:
src/imports/localstorage/plugin.cpp
src/qml/compiler/qv4compileddata.cpp
src/qml/compiler/qv4compileddata_p.h
src/qml/jit/qv4assembler.cpp
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4function.cpp
src/qml/jsruntime/qv4function_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4functionobject_p.h
src/qml/jsruntime/qv4identifiertable.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4memberdata.cpp
src/qml/jsruntime/qv4mm.cpp
src/qml/jsruntime/qv4mm_p.h
src/qml/jsruntime/qv4objectiterator.cpp
src/qml/jsruntime/qv4regexp.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4scopedvalue_p.h
src/qml/jsruntime/qv4script.cpp
src/qml/jsruntime/qv4value_p.h
src/qml/jsruntime/qv4vme_moth.cpp
src/qml/qml/qqmlvaluetypewrapper.cpp
src/qml/types/qqmldelegatemodel.cpp
src/quick/items/qquickview.cpp
src/quick/items/qquickview_p.h

index 8b90f5a..78c1905 100644 (file)
@@ -116,7 +116,7 @@ public:
     };
     V4_OBJECT(Object)
 
-    static QQmlSqlDatabaseWrapper *create(QV8Engine *engine)
+    static QV4::Returned<QQmlSqlDatabaseWrapper> *create(QV8Engine *engine)
     {
         QV4::ExecutionEngine *e = QV8Engine::getV4(engine);
         return e->memoryManager->alloc<QQmlSqlDatabaseWrapper>(e);
index d242fb7..fbef8b8 100644 (file)
@@ -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);
     }
 }
 
index 6791970..6ab7191 100644 (file)
@@ -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;
index ed34274..300f4b0 100644 (file)
@@ -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)
index 5ca47a8..8f9f8cc 100644 (file)
@@ -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> *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<ExecutionContext>::create(c);
 }
 
-WithContext *ExecutionContext::newWithContext(Object *with)
+Returned<WithContext> *ExecutionContext::newWithContext(Object *with)
 {
     return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with);
 }
 
-CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue)
+Returned<CatchContext> *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue)
 {
     return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
 }
 
-CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
+Returned<CallContext> *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
 {
-    CallContext *c = reinterpret_cast<CallContext*>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0)));
+    Scope scope(this);
+    Scoped<CallContext> c(scope, static_cast<CallContext*>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0))));
     new (c->d()) CallContext::Data(d()->engine, qml, f);
-    return c;
+    return c.asReturned();
 }
 
 
index 74530e7..4f7cdd8 100644 (file)
@@ -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<ExecutionContext> *newCallContext(FunctionObject *f, CallData *callData);
+    Returned<WithContext> *newWithContext(Object *with);
+    Returned<CatchContext> *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue);
+    Returned<CallContext> *newQmlContext(FunctionObject *f, Object *qml);
 
     void createMutableBinding(String *name, bool deletable);
 
index 99050b0..ec1ea80 100644 (file)
@@ -508,11 +508,12 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
 
 ExecutionContext *ExecutionEngine::pushGlobalContext()
 {
-    GlobalContext *g = memoryManager->alloc<GlobalContext>(this);
+    Scope scope(this);
+    Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
     g->d()->callData = rootContext->d()->callData;
 
-    Q_ASSERT(currentContext() == g);
-    return g;
+    Q_ASSERT(currentContext() == g.getPointer());
+    return g.getPointer();
 }
 
 
index c7fe212..6bc4815 100644 (file)
@@ -58,7 +58,7 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
     Scope scope(engine);
     ScopedString s(scope);
     for (int i = static_cast<int>(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);
     }
 }
index 465489b..b2c4d2e 100644 (file)
@@ -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(); }
 
index f3ad8ef..ea87ff1 100644 (file)
@@ -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> *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<ScriptFunction>(scope, function);
-    return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
+        return scope->d()->engine->memoryManager->alloc<ScriptFunction>(scope, function)->as<FunctionObject>();
+    return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto)->as<FunctionObject>();
 }
 
 DEFINE_OBJECT_VTABLE(FunctionCtor);
index c8edb76..2d57f6c 100644 (file)
@@ -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<FunctionObject> *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<BuiltinFunction> *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
     {
         return scope->engine()->memoryManager->alloc<BuiltinFunction>(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<BoundFunction> *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs)
     {
         return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
     }
index d7ed7a8..5554b68 100644 (file)
@@ -121,7 +121,8 @@ String *IdentifierTable::insertString(const QString &s)
         idx %= alloc;
     }
 
-    String *str = engine->newString(s)->getPointer();
+    Returned<String> *_s = engine->newString(s);
+    String *str = _s->getPointer();
     addEntry(str);
     return str;
 }
index c062ec4..c73ad10 100644 (file)
@@ -207,7 +207,7 @@ struct Q_QML_PRIVATE_EXPORT Managed
 
         void setVTable(const ManagedVTable *vt);
         ReturnedValue asReturnedValue() const {
-            return reinterpret_cast<Managed *>(const_cast<Data *>(this))->asReturnedValue();
+            return Value::fromHeapObject(const_cast<Data *>(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;
+}
+
 }
 
 
index 405594c..4183234 100644 (file)
@@ -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;
     }
 }
index b9a4a55..3877dde 100644 (file)
@@ -535,6 +535,11 @@ MemoryManager::~MemoryManager()
 #endif
 }
 
+ExecutionEngine *MemoryManager::engine() const
+{
+    return m_d->engine;
+}
+
 void MemoryManager::setExecutionEngine(ExecutionEngine *engine)
 {
     m_d->engine = engine;
index d5e28f7..cf9a148 100644 (file)
@@ -96,57 +96,64 @@ public:
     }
 
     template <typename ManagedType>
-    ManagedType *alloc()
+    Returned<ManagedType> *alloc()
     {
-        ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+        Scope scope(engine());
+        Scoped<ManagedType> t(scope, static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))));
         (void)new (t->d()) typename ManagedType::Data();
-        return t;
+        return t.asReturned();
     }
 
     template <typename ManagedType, typename Arg1>
-    ManagedType *alloc(Arg1 arg1)
+    Returned<ManagedType> *alloc(Arg1 arg1)
     {
-        ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+        Scope scope(engine());
+        Scoped<ManagedType> t(scope, static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))));
         (void)new (t->d()) typename ManagedType::Data(arg1);
-        return t;
+        return t.asReturned();
     }
 
     template <typename ManagedType, typename Arg1, typename Arg2>
-    ManagedType *alloc(Arg1 arg1, Arg2 arg2)
+    Returned<ManagedType> *alloc(Arg1 arg1, Arg2 arg2)
     {
-        ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+        Scope scope(engine());
+        Scoped<ManagedType> t(scope, static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))));
         (void)new (t->d()) typename ManagedType::Data(arg1, arg2);
-        return t;
+        return t.asReturned();
     }
 
     template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
-    ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+    Returned<ManagedType> *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
     {
-        ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+        Scope scope(engine());
+        Scoped<ManagedType> t(scope, static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))));
         (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
-        return t;
+        return t.asReturned();
     }
 
     template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-    ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+    Returned<ManagedType> *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
     {
-        ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+        Scope scope(engine());
+        Scoped<ManagedType> t(scope, static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data))));
         (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
-        return t;
+        return t.asReturned();
     }
 
     template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
-    ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+    Returned<ManagedType> *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
     {
-        ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+        Scope scope(engine());
+        Scoped<ManagedType> t(scope, static_cast<ManagedType*>(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;
index f9ccb8f..b2875a1 100644 (file)
@@ -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;
index e84c96f..ed67289 100644 (file)
@@ -73,7 +73,8 @@ RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ign
             return result;
     }
 
-    RegExp *result = engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline);
+    Scope scope(engine);
+    Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline));
 
     if (!cache)
         cache = engine->regExpCache = new RegExpCache;
index cb7e219..957f8cd 100644 (file)
@@ -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<ExecutionContext *>(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<ExecutionContext *>(ctx->newCatchContext(exceptionVarName, v));
+    return ctx->newCatchContext(exceptionVarName, v)->getPointer();
 }
 
 ExecutionContext *Runtime::popScope(ExecutionContext *ctx)
index b1b4d5d..5cc8495 100644 (file)
@@ -112,7 +112,7 @@ struct ScopedValue
     ScopedValue(const Scope &scope, HeapObject *o)
     {
         ptr = scope.engine->jsStackTop++;
-        ptr->m = reinterpret_cast<Managed *>(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<Managed *>(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<Managed *>(o);
+        v.m = o;
 #if QT_POINTER_SIZE == 4
         v.tag = QV4::Value::Managed_Type;
 #endif
@@ -317,7 +317,7 @@ struct Scoped
 
     Scoped<T> &operator=(HeapObject *o) {
         Value v;
-        v.m = reinterpret_cast<Managed *>(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<T> *asReturned() const { return Returned<T>::create(static_cast<typename T::Data*>(ptr->heapObject())); }
+
     Value *ptr;
 };
 
@@ -478,7 +480,7 @@ inline Returned<T> *Value::as()
 template<typename T>
 inline TypedValue<T> &TypedValue<T>::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<T> &TypedValue<T>::operator =(T *t)
 template<typename T>
 inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
 {
-    m = v.ptr->managed();
+    m = v.ptr->m;
 #if QT_POINTER_SIZE == 4
     tag = Managed_Type;
 #endif
@@ -519,7 +521,7 @@ inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
 template<typename T>
 inline Returned<T> * TypedValue<T>::ret() const
 {
-    return Returned<T>::create(static_cast<T *>(managed()));
+    return Returned<T>::create(static_cast<typename T::Data *>(heapObject()));
 }
 
 inline Primitive::operator ValueRef()
index fa4b4b1..20b0832 100644 (file)
@@ -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<CallContext *>(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<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml));
+    o->d()->qmlContext = s.engine->currentContext()->newQmlContext(o, qml)->getPointer();
     s.engine->popContext();
 }
 
index f215162..9c6bd60 100644 (file)
@@ -44,19 +44,21 @@ namespace QV4 {
 
 typedef uint Bool;
 
+struct HeapObject {};
+
 template <typename T>
-struct Returned : private T
+struct Returned : private HeapObject
 {
-    static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
-    T *getPointer() { return this; }
+    static Returned<T> *create(T *t) { Q_ASSERT((void *)&t->data == (void *)t); return static_cast<Returned<T> *>(static_cast<HeapObject*>(t ? &t->data : 0)); }
+    static Returned<T> *create(typename T::Data *t) { return static_cast<Returned<T> *>(static_cast<HeapObject*>(t)); }
+    T *getPointer() { return reinterpret_cast<T *>(this); }
     template<typename X>
     static T *getPointer(Returned<X> *x) { return x->getPointer(); }
     template<typename X>
     Returned<X> *as() { return Returned<X>::create(Returned<X>::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<String*>(m);
+        return m ? reinterpret_cast<String*>(m) : 0;
     }
     Object *objectValue() const {
-        return reinterpret_cast<Object*>(m);
+        return m ? reinterpret_cast<Object*>(m) : 0;
     }
     Managed *managed() const {
+        return m ? reinterpret_cast<Managed*>(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<Managed *>(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 <typename T>
 struct TypedValue : public Value
 {
@@ -557,7 +558,8 @@ T *value_cast(const Value &v)
 template<typename T>
 ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
 
-
+template <typename T>
+ReturnedValue Returned<T>::asReturnedValue() { return Value::fromHeapObject(this).asReturnedValue(); }
 
 }
 
index cd73314..35ac5ea 100644 (file)
@@ -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)
index b0125b4..8123a29 100644 (file)
@@ -144,7 +144,7 @@ ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int pr
     Scope scope(v4);
     initProto(v4);
 
-    QmlValueTypeReference *r = v4->memoryManager->alloc<QmlValueTypeReference>(v8);
+    Scoped<QmlValueTypeReference> r(scope, v4->memoryManager->alloc<QmlValueTypeReference>(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<QmlValueTypeCopy>(v8);
+    Scoped<QmlValueTypeCopy> r(scope, v4->memoryManager->alloc<QmlValueTypeCopy>(v8));
     r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
     r->d()->type = type; r->d()->value = value;
     return r->asReturnedValue();
index 639df4f..b26557e 100644 (file)
@@ -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<DelegateModelGroupFunction> *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
     {
         return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
     }
@@ -3220,7 +3220,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object
     };
     V4_OBJECT(QV4::Object)
 
-    static QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
+    static QV4::Returned<QQmlDelegateModelGroupChange> *create(QV4::ExecutionEngine *e) {
         return e->memoryManager->alloc<QQmlDelegateModelGroupChange>(e);
     }
 
@@ -3267,7 +3267,7 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object
     };
     V4_OBJECT(QV4::Object)
 public:
-    static QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
+    static QV4::Returned<QQmlDelegateModelGroupChangeArray> *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
     {
         return engine->memoryManager->alloc<QQmlDelegateModelGroupChangeArray>(engine, changes);
     }
index a55d056..d00fd10 100644 (file)
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
 
 DEFINE_OBJECT_VTABLE(QQuickRootItemMarker);
 
-QQuickRootItemMarker *QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
+QV4::Returned<QQuickRootItemMarker> *QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
 {
     QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine);
     return e->memoryManager->alloc<QQuickRootItemMarker>(e, window);
index 54f60c8..50d6375 100644 (file)
@@ -108,7 +108,7 @@ struct QQuickRootItemMarker : public QV4::Object
     };
     V4_OBJECT(QV4::Object)
 
-    static QQuickRootItemMarker *create(QQmlEngine *engine, QQuickWindow *window);
+    static QV4::Returned<QQuickRootItemMarker> *create(QQmlEngine *engine, QQuickWindow *window);
 
     static void markObjects(Managed *that, QV4::ExecutionEngine *e);