Fix ObjectIterator API to be GC safe
authorLars Knoll <lars.knoll@digia.com>
Mon, 30 Sep 2013 11:48:05 +0000 (13:48 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 2 Oct 2013 14:07:33 +0000 (16:07 +0200)
Change-Id: I3a9c48d53d8dbadcb9b32c00fcef1f89447c4b8c
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
29 files changed:
src/imports/localstorage/plugin.cpp
src/qml/jsapi/qjsvalueiterator.cpp
src/qml/jsapi/qjsvalueiterator_p.h
src/qml/jsruntime/qv4debugging.cpp
src/qml/jsruntime/qv4engine.cpp
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4jsonobject.cpp
src/qml/jsruntime/qv4managed.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h
src/qml/jsruntime/qv4objectiterator.cpp
src/qml/jsruntime/qv4objectiterator_p.h
src/qml/jsruntime/qv4objectproto.cpp
src/qml/jsruntime/qv4qobjectwrapper.cpp
src/qml/jsruntime/qv4qobjectwrapper_p.h
src/qml/jsruntime/qv4regexp.cpp
src/qml/jsruntime/qv4regexp_p.h
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4scopedvalue_p.h
src/qml/jsruntime/qv4sequenceobject.cpp
src/qml/jsruntime/qv4stringobject.cpp
src/qml/jsruntime/qv4stringobject_p.h
src/qml/jsruntime/qv4value_def_p.h
src/qml/qml/qqmllistwrapper.cpp
src/qml/qml/qqmllistwrapper_p.h
src/qml/qml/v8/qv8engine.cpp
src/qml/types/qqmldelegatemodel.cpp
src/qml/types/qqmllistmodel.cpp

index 267b2b6..ca69499 100644 (file)
@@ -276,14 +276,13 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx)
                     query.bindValue(ii, engine->toVariant((v = array->getIndexed(ii)), -1));
             } else if (values->asObject()) {
                 ScopedObject object(scope, values);
-                ObjectIterator it(object.getPointer(), ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
+                ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
                 ScopedValue key(scope);
+                QV4::ScopedValue val(scope);
                 while (1) {
-                    Value value;
-                    key = it.nextPropertyName(&value);
+                    key = it.nextPropertyName(val);
                     if (key->isNull())
                         break;
-                    QV4::ScopedValue val(scope, value);
                     QVariant v = engine->toVariant(val, -1);
                     if (key->isString()) {
                         query.bindValue(key->stringValue()->toQString(), v);
index b4156dc..e1786f0 100644 (file)
@@ -50,12 +50,20 @@ QT_BEGIN_NAMESPACE
 
 QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
     : value(v)
-    , iterator(QJSValuePrivate::get(v)->value.asObject(), QV4::ObjectIterator::NoFlags)
-    , currentName(0)
     , currentIndex(UINT_MAX)
-    , nextName(0)
     , nextIndex(UINT_MAX)
 {
+    QJSValuePrivate *jsp = QJSValuePrivate::get(value);
+    QV4::ExecutionEngine *e = jsp->engine;
+    if (!e)
+        return;
+
+    QV4::Scope scope(e);
+    QV4::ScopedObject o(scope, jsp->value);
+    iterator = e->newForEachIteratorObject(e->current, o)->asReturnedValue();
+
+    currentName = (QV4::String *)0;
+    nextName = (QV4::String *)0;
 }
 
 
@@ -96,7 +104,13 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
 QJSValueIterator::QJSValueIterator(const QJSValue& object)
     : d_ptr(new QJSValueIteratorPrivate(object))
 {
-    d_ptr->iterator.next(&d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
+    QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
+    if (!v4)
+        return;
+    QV4::Scope scope(v4);
+    QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+    it->it.flags =  QV4::ObjectIterator::NoFlags;
+    it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
 }
 
 /*!
@@ -117,7 +131,7 @@ bool QJSValueIterator::hasNext() const
 {
     if (!QJSValuePrivate::get(d_ptr->value)->value.isObject())
         return false;
-    return d_ptr->nextName != 0 || d_ptr->nextIndex != UINT_MAX;
+    return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
 }
 
 /*!
@@ -139,8 +153,13 @@ bool QJSValueIterator::next()
     d_ptr->currentIndex = d_ptr->nextIndex;
     d_ptr->currentAttributes = d_ptr->nextAttributes;
 
-    d_ptr->iterator.next(&d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
-    return d_ptr->nextName != 0 || d_ptr->nextIndex != UINT_MAX;
+    QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
+    if (!v4)
+        return false;
+    QV4::Scope scope(v4);
+    QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+    it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
+    return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
 }
 
 /*!
@@ -153,7 +172,7 @@ QString QJSValueIterator::name() const
 {
     if (!QJSValuePrivate::get(d_ptr->value)->value.isObject())
         return QString();
-    if (d_ptr->currentName)
+    if (!!d_ptr->currentName)
         return d_ptr->currentName->toQString();
     if (d_ptr->currentIndex < UINT_MAX)
         return QString::number(d_ptr->currentIndex);
@@ -172,14 +191,18 @@ QJSValue QJSValueIterator::value() const
     if (!QJSValuePrivate::get(d_ptr->value)->value.isObject())
         return QJSValue();
 
-    QV4::Object *o = d_ptr->iterator.object;
-    QV4::ExecutionEngine *engine = o->internalClass->engine;
+    QV4::ExecutionEngine *engine = d_ptr->iterator.engine();
+    if (!engine)
+        return QJSValue();
+
     QV4::Scope scope(engine);
+    QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+    QV4::ScopedObject o(scope, it->it.object);
 
     QV4::ExecutionContext *ctx = engine->current;
     try {
         QV4::ScopedValue v(scope);
-        if (d_ptr->currentName) {
+        if (!!d_ptr->currentName) {
             QV4::ScopedString n(scope, d_ptr->currentName);
             v = o->get(n);
         } else if (d_ptr->currentIndex != UINT_MAX) {
@@ -202,8 +225,24 @@ QJSValue QJSValueIterator::value() const
 */
 QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
 {
-    d_ptr->iterator = QV4::ObjectIterator(QJSValuePrivate::get(object)->value.asObject(), QV4::ObjectIterator::NoFlags);
-    d_ptr->iterator.next(&d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
+    d_ptr->value = object;
+    d_ptr->currentIndex = UINT_MAX;
+    d_ptr->nextIndex = UINT_MAX;
+    d_ptr->currentName = (QV4::String *)0;
+    d_ptr->nextName = (QV4::String *)0;
+    QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
+    if (!v4) {
+        d_ptr->iterator = QV4::Encode::undefined();
+        return *this;
+    }
+
+    QJSValuePrivate *jsp = QJSValuePrivate::get(object);
+    QV4::Scope scope(v4);
+    QV4::ScopedObject o(scope, jsp->value);
+    d_ptr->iterator = v4->newForEachIteratorObject(v4->current, o)->asReturnedValue();
+    QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
+    it->it.flags =  QV4::ObjectIterator::NoFlags;
+    it->it.next(d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes);
     return *this;
 }
 
index 7687f89..b7a9b4a 100644 (file)
@@ -55,12 +55,12 @@ public:
     QJSValueIteratorPrivate(const QJSValue &v);
 
     QJSValue value;
-    QV4::ObjectIterator iterator;
+    QV4::PersistentValue iterator;
     QV4::PropertyAttributes currentAttributes;
-    QV4::String *currentName;
+    QV4::SafeString currentName;
     uint currentIndex;
     QV4::PropertyAttributes nextAttributes;
-    QV4::String *nextName;
+    QV4::SafeString nextName;
     uint nextIndex;
 };
 
index b4da4bb..f95178c 100644 (file)
@@ -245,7 +245,7 @@ static void realDumpValue(QV4::Value v, QV4::ExecutionContext *ctx, std::string
         return;
     }
 
-    Object *o = v.objectValue();
+    ScopedObject o(scope, v);
     if (!o)
         return;
 
index 8808678..7b9071e 100644 (file)
@@ -42,6 +42,7 @@
 #include <qv4value_p.h>
 #include <qv4object_p.h>
 #include <qv4objectproto_p.h>
+#include <qv4objectiterator_p.h>
 #include <qv4arrayobject_p.h>
 #include <qv4booleanobject_p.h>
 #include <qv4globalobject_p.h>
@@ -535,7 +536,7 @@ Returned<Object> *ExecutionEngine::newVariantObject(const QVariant &v)
     return o->asReturned<Object>();
 }
 
-Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
+Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o)
 {
     Object *obj = new (memoryManager) ForEachIteratorObject(ctx, o);
     return obj->asReturned<Object>();
index 32dcac4..d93202d 100644 (file)
@@ -301,7 +301,7 @@ struct Q_QML_EXPORT ExecutionEngine
 
     Returned<Object> *newVariantObject(const QVariant &v);
 
-    Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, Object *o);
+    Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o);
 
     Returned<Object> *qmlContextObject() const;
 
index 3649163..10d3075 100644 (file)
@@ -791,16 +791,14 @@ QString Stringify::JO(ObjectRef o)
 
     QStringList partial;
     if (propertyList.isEmpty()) {
-        ObjectIterator it(o.getPointer(), ObjectIterator::EnumerableOnly);
+        ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
         ScopedValue name(scope);
 
         ScopedValue val(scope);
         while (1) {
-            Value v;
-            name = it.nextPropertyNameAsString(&v);
+            name = it.nextPropertyNameAsString(val);
             if (name->isNull())
                 break;
-            val = v;
             QString key = name->toQStringNoThrow();
             QString member = makeMember(key, val);
             if (!member.isEmpty())
@@ -1024,16 +1022,14 @@ QJsonObject JsonObject::toJsonObject(ObjectRef o, V4ObjectSet &visitedObjects)
 
     visitedObjects.insert(o);
 
-    ObjectIterator it(o, ObjectIterator::EnumerableOnly);
+    ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
     ScopedValue name(scope);
+    QV4::ScopedValue val(scope);
     while (1) {
-        Value v;
-        name = it.nextPropertyNameAsString(&v);
+        name = it.nextPropertyNameAsString(val);
         if (name->isNull())
             break;
 
-        QV4::ScopedValue val(scope, v);
-
         QString key = name->toQStringNoThrow();
         if (!val->asFunctionObject())
             result.insert(key, toJsonValue(val, visitedObjects));
index f5715d5..03608d2 100644 (file)
@@ -241,3 +241,8 @@ bool Managed::deleteProperty(const StringRef name)
 {
     return vtbl->deleteProperty(this, name);
 }
+
+Property *Managed::advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
+{
+    return vtbl->advanceIterator(this, it, name, index, attributes);
+}
index c369353..aca41be 100644 (file)
@@ -108,7 +108,7 @@ struct ManagedVTable
     ReturnedValue (*getLookup)(Managed *m, Lookup *l);
     void (*setLookup)(Managed *m, Lookup *l, const ValueRef v);
     bool (*isEqualTo)(Managed *m, Managed *other);
-    Property *(*advanceIterator)(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
+    Property *(*advanceIterator)(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
     const char *className;
 };
 
@@ -278,8 +278,7 @@ public:
 
     bool isEqualTo(Managed *other)
     { return vtbl->isEqualTo(this, other); }
-    Property *advanceIterator(ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes)
-    { return vtbl->advanceIterator(this, it, name, index, attributes); }
+    Property *advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
 
     static void destroy(Managed *that) { that->_data = 0; }
     static bool hasInstance(Managed *that, const ValueRef value);
index ed2bf09..399cd2e 100644 (file)
@@ -544,10 +544,10 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
         l->setter = Lookup::setterInsert2;
 }
 
-Property *Object::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+Property *Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
 {
     Object *o = static_cast<Object *>(m);
-    *name = 0;
+    name = (String *)0;
     *index = UINT_MAX;
 
     if (!it->arrayIndex)
@@ -595,7 +595,7 @@ Property *Object::advanceIterator(Managed *m, ObjectIterator *it, String **name,
         PropertyAttributes a = o->internalClass->propertyData[it->memberIndex];
         ++it->memberIndex;
         if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
-            *name = n;
+            name = n;
             if (attrs)
                 *attrs = a;
             return p;
@@ -1435,14 +1435,3 @@ QStringList ArrayObject::toQStringList() const
     }
     return result;
 }
-
-
-DEFINE_MANAGED_VTABLE(ForEachIteratorObject);
-
-void ForEachIteratorObject::markObjects(Managed *that)
-{
-    ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
-    Object::markObjects(that);
-    if (o->it.object)
-        o->it.object->mark();
-}
index c28edca..77f8d11 100644 (file)
@@ -49,7 +49,6 @@
 #include "qv4managed_p.h"
 #include "qv4property_p.h"
 #include "qv4internalclass_p.h"
-#include "qv4objectiterator_p.h"
 #include "qv4sparsearray_p.h"
 
 #include <QtCore/QString>
@@ -314,7 +313,7 @@ protected:
     static bool deleteIndexedProperty(Managed *m, uint index);
     static ReturnedValue getLookup(Managed *m, Lookup *l);
     static void setLookup(Managed *m, Lookup *l, const ValueRef v);
-    static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
+    static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
 
 
 private:
@@ -329,21 +328,6 @@ private:
     friend struct ObjectPrototype;
 };
 
-struct ForEachIteratorObject: Object {
-    Q_MANAGED
-    ObjectIterator it;
-    ForEachIteratorObject(ExecutionContext *ctx, Object *o)
-        : Object(ctx->engine), it(o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
-        vtbl = &static_vtbl;
-        type = Type_ForeachIteratorObject;
-    }
-
-    ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); }
-
-protected:
-    static void markObjects(Managed *that);
-};
-
 struct BooleanObject: Object {
     SafeValue value;
     BooleanObject(ExecutionEngine *engine, const ValueRef val)
index fc85a3f..2030489 100644 (file)
 
 using namespace QV4;
 
-ObjectIterator::ObjectIterator(Object *o, uint flags)
-    : object(o)
-    , current(o)
+ObjectIterator::ObjectIterator(SafeObject *scratch1, SafeObject *scratch2, const ObjectRef o, uint flags)
+    : object(*scratch1)
+    , current(*scratch2)
     , arrayNode(0)
     , arrayIndex(0)
     , memberIndex(0)
     , flags(flags)
 {
+    object = o;
+    current = o;
     tmpDynamicProperty.value = Primitive::undefinedValue();
 }
 
-Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *attrs)
+ObjectIterator::ObjectIterator(Scope &scope, const ObjectRef o, uint flags)
+    : object(*static_cast<SafeObject *>(scope.alloc(1)))
+    , current(*static_cast<SafeObject *>(scope.alloc(1)))
+    , arrayNode(0)
+    , arrayIndex(0)
+    , memberIndex(0)
+    , flags(flags)
 {
-    Property *p = 0;
-    *name = 0;
+    object = o;
+    current = o;
+    tmpDynamicProperty.value = Primitive::undefinedValue();
+}
+
+Property *ObjectIterator::next(StringRef name, uint *index, PropertyAttributes *attrs)
+{
+    name = (String *)0;
     *index = UINT_MAX;
+    if (!object)
+        return 0;
+
+    Property *p = 0;
     while (1) {
         if (!current)
             break;
@@ -69,10 +87,8 @@ Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *a
             // check the property is not already defined earlier in the proto chain
             if (current != object) {
                 Property *pp;
-                if (*name) {
-                    Scope scope(object->engine());
-                    ScopedString n(scope, *name);
-                    pp = object->__getPropertyDescriptor__(n);
+                if (name) {
+                    pp = object->__getPropertyDescriptor__(name);
                 } else {
                     assert (*index != UINT_MAX);
                     pp = object->__getPropertyDescriptor__(*index);
@@ -86,7 +102,7 @@ Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *a
         if (flags & WithProtoChain)
             current = current->prototype();
         else
-            current = 0;
+            current = (Object *)0;
 
         arrayIndex = 0;
         memberIndex = 0;
@@ -94,38 +110,74 @@ Property *ObjectIterator::next(String **name, uint *index, PropertyAttributes *a
     return 0;
 }
 
-ReturnedValue ObjectIterator::nextPropertyName(Value *value)
+ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
 {
+    if (!object)
+        return Encode::null();
+
     PropertyAttributes attrs;
     uint index;
-    String *name;
-    Property *p = next(&name, &index, &attrs);
+    Scope scope(object->engine());
+    ScopedString name(scope);
+    Property *p = next(name, &index, &attrs);
     if (!p)
         return Encode::null();
 
-    if (value)
-        *value = Value::fromReturnedValue(object->getValue(p, attrs));
+    value = Value::fromReturnedValue(object->getValue(p, attrs));
 
-    if (name)
+    if (!!name)
         return name->asReturnedValue();
     assert(index < UINT_MAX);
     return Encode(index);
 }
 
-ReturnedValue ObjectIterator::nextPropertyNameAsString(Value *value)
+ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
 {
+    if (!object)
+        return Encode::null();
+
     PropertyAttributes attrs;
     uint index;
-    String *name;
-    Property *p = next(&name, &index, &attrs);
+    Scope scope(object->engine());
+    ScopedString name(scope);
+    Property *p = next(name, &index, &attrs);
     if (!p)
         return Encode::null();
 
-    if (value)
-        *value = Value::fromReturnedValue(object->getValue(p, attrs));
+    value = Value::fromReturnedValue(object->getValue(p, attrs));
 
-    if (name)
+    if (!!name)
         return name->asReturnedValue();
     assert(index < UINT_MAX);
     return Encode(object->engine()->newString(QString::number(index)));
 }
+
+ReturnedValue ObjectIterator::nextPropertyNameAsString()
+{
+    if (!object)
+        return Encode::null();
+
+    PropertyAttributes attrs;
+    uint index;
+    Scope scope(object->engine());
+    ScopedString name(scope);
+    Property *p = next(name, &index, &attrs);
+    if (!p)
+        return Encode::null();
+
+    if (!!name)
+        return name->asReturnedValue();
+    assert(index < UINT_MAX);
+    return Encode(object->engine()->newString(QString::number(index)));
+}
+
+
+DEFINE_MANAGED_VTABLE(ForEachIteratorObject);
+
+void ForEachIteratorObject::markObjects(Managed *that)
+{
+    ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
+    o->workArea[0].mark();
+    o->workArea[1].mark();
+    Object::markObjects(that);
+}
index d546489..e38fa8d 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "qv4global_p.h"
 #include "qv4property_p.h"
+#include "qv4scopedvalue_p.h"
+#include "qv4object_p.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -65,8 +67,8 @@ struct Q_QML_EXPORT ObjectIterator
         WithProtoChain = 0x2,
     };
 
-    Object *object;
-    Object *current;
+    ObjectRef object;
+    ObjectRef current;
     SparseArrayNode *arrayNode;
     uint arrayIndex;
     uint memberIndex;
@@ -74,12 +76,32 @@ struct Q_QML_EXPORT ObjectIterator
 
     Property tmpDynamicProperty;
 
-    ObjectIterator(Object *o, uint flags);
-    Property *next(String **name, uint *index, PropertyAttributes *attributes = 0);
-    ReturnedValue nextPropertyName(Value *value = 0);
-    ReturnedValue nextPropertyNameAsString(Value *value = 0);
+    ObjectIterator(SafeObject *scratch1, SafeObject *scratch2, const ObjectRef o, uint flags);
+    ObjectIterator(Scope &scope, const ObjectRef o, uint flags);
+    Property *next(StringRef name, uint *index, PropertyAttributes *attributes = 0);
+    ReturnedValue nextPropertyName(ValueRef value);
+    ReturnedValue nextPropertyNameAsString(ValueRef value);
+    ReturnedValue nextPropertyNameAsString();
 };
 
+struct ForEachIteratorObject: Object {
+    Q_MANAGED
+    ObjectIterator it;
+    ForEachIteratorObject(ExecutionContext *ctx, const ObjectRef o)
+        : Object(ctx->engine), it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
+        vtbl = &static_vtbl;
+        type = Type_ForeachIteratorObject;
+    }
+
+    ReturnedValue nextPropertyName() { return it.nextPropertyNameAsString(); }
+
+protected:
+    static void markObjects(Managed *that);
+
+    SafeObject workArea[2];
+};
+
+
 }
 
 QT_END_NAMESPACE
index 65fd218..20a5c51 100644 (file)
@@ -222,14 +222,12 @@ ReturnedValue ObjectPrototype::method_defineProperties(SimpleCallContext *ctx)
     Scoped<Object> o(scope, ctx->argument(1), Scoped<Object>::Convert);
     ScopedValue val(scope);
 
-    ObjectIterator it(o.getPointer(), ObjectIterator::EnumerableOnly);
+    ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
+    ScopedString name(scope);
     while (1) {
         uint index;
-        ScopedString name(scope);
         PropertyAttributes attrs;
-        String *tmp = 0;
-        Property *pd = it.next(&tmp, &index, &attrs);
-        name = tmp;
+        Property *pd = it.next(name, &index, &attrs);
         if (!pd)
             break;
         Property n;
@@ -375,7 +373,7 @@ ReturnedValue ObjectPrototype::method_keys(SimpleCallContext *ctx)
 
     Scoped<ArrayObject> a(scope, ctx->engine->newArrayObject());
 
-    ObjectIterator it(o.getPointer(), ObjectIterator::EnumerableOnly);
+    ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
     ScopedValue name(scope);
     while (1) {
         name = it.nextPropertyNameAsString();
@@ -652,7 +650,7 @@ Returned<ArrayObject> *ObjectPrototype::getOwnPropertyNames(ExecutionEngine *v4,
     Scoped<ArrayObject> array(scope, v4->newArrayObject());
     ScopedObject O(scope, o);
     if (O) {
-        ObjectIterator it(O.getPointer(), ObjectIterator::NoFlags);
+        ObjectIterator it(scope, O, ObjectIterator::NoFlags);
         ScopedValue name(scope);
         while (1) {
             name = it.nextPropertyNameAsString();
index 53e915c..90a1950 100644 (file)
@@ -646,13 +646,11 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, StringRef name)
         return QV4::Object::query(m, name);
 }
 
-Property *QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes)
+Property *QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
 {
-    *name = 0;
+    name = (String *)0;
     *index = UINT_MAX;
 
-    QV4::Scope scope(m->engine());
-
     QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
 
     if (!that->m_object)
@@ -661,22 +659,20 @@ Property *QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String
     const QMetaObject *mo = that->m_object->metaObject();
     const int propertyCount = mo->propertyCount();
     if (it->arrayIndex < propertyCount) {
-        ScopedString n(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
-        *name = n.getPointer();
+        name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()));
         ++it->arrayIndex;
         if (attributes)
             *attributes = QV4::Attr_Data;
-        it->tmpDynamicProperty.value = that->get(n);
+        it->tmpDynamicProperty.value = that->get(name);
         return &it->tmpDynamicProperty;
     }
     const int methodCount = mo->methodCount();
     if (it->arrayIndex < propertyCount + methodCount) {
-        ScopedString n(scope, that->engine()->newString(QString::fromUtf8(mo->method(it->arrayIndex - propertyCount).name())));
-        *name = n.getPointer();
+        name = that->engine()->newString(QString::fromUtf8(mo->method(it->arrayIndex - propertyCount).name()));
         ++it->arrayIndex;
         if (attributes)
             *attributes = QV4::Attr_Data;
-        it->tmpDynamicProperty.value = that->get(n);
+        it->tmpDynamicProperty.value = that->get(name);
         return &it->tmpDynamicProperty;
     }
     return QV4::Object::advanceIterator(m, it, name, index, attributes);
index 74c436c..7b9e985 100644 (file)
@@ -108,7 +108,7 @@ private:
     static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
     static void put(Managed *m, const StringRef name, const ValueRef value);
     static PropertyAttributes query(const Managed *, StringRef name);
-    static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
+    static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
     static void markObjects(Managed *that);
     static void collectDeletables(Managed *m, GCDeletable **deletable);
     static void destroy(Managed *that)
index bc0955f..103605e 100644 (file)
@@ -174,7 +174,7 @@ bool RegExp::deleteIndexedProperty(Managed *m, uint index)
     return false;
 }
 
-Property *RegExp::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes)
+Property *RegExp::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes)
 {
     return 0;
 }
index 8aa173c..f674bea 100644 (file)
@@ -119,7 +119,7 @@ protected:
     static PropertyAttributes queryIndexed(const Managed *m, uint index);
     static bool deleteProperty(Managed *, const StringRef);
     static bool deleteIndexedProperty(Managed *m, uint index);
-    static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
+    static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
 
 private:
     friend class RegExpCache;
index 8187da6..1dd35fc 100644 (file)
@@ -544,7 +544,7 @@ ReturnedValue __qmljs_foreach_iterator_object(ExecutionContext *ctx, const Value
     Scoped<Object> o(scope, (Object *)0);
     if (!in->isNullOrUndefined())
         o = in;
-    Scoped<Object> it(scope, ctx->engine->newForEachIteratorObject(ctx, o.getPointer()));
+    Scoped<Object> it(scope, ctx->engine->newForEachIteratorObject(ctx, o));
     return it.asReturnedValue();
 }
 
index 3a75261..a1f6f4b 100644 (file)
@@ -463,9 +463,18 @@ struct Referenced {
     Referenced &operator=(const Referenced &o)
     { *ptr = *o.ptr; return *this; }
     Referenced &operator=(T *t)
-    { ptr->val = t->asReturnedValue(); return *this; }
-    Referenced &operator=(const Returned<T> *t) {
-        ptr->val = t->getPointer()->asReturnedValue();
+    {
+#if QT_POINTER_SIZE == 4
+        ptr->tag = Value::Managed_Type;
+#endif
+        ptr->m = t;
+        return *this;
+    }
+    Referenced &operator=(Returned<T> *t) {
+#if QT_POINTER_SIZE == 4
+        ptr->tag = Value::Managed_Type;
+#endif
+        ptr->m = t->getPointer();
         return *this;
     }
 
index 6b55a09..10293a7 100644 (file)
@@ -277,9 +277,9 @@ public:
         return (signedIdx < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
     }
 
-    Property *containerAdvanceIterator(ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+    Property *containerAdvanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
     {
-        *name = 0;
+        name = (String *)0;
         *index = UINT_MAX;
 
         if (m_isReference) {
@@ -500,7 +500,7 @@ private:
     { return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
     static bool isEqualTo(Managed *that, Managed *other)
     { return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
-    static Property *advanceIterator(Managed *that, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+    static Property *advanceIterator(Managed *that, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
     { return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, attrs); }
 
     static void destroy(Managed *that)
index fd15d7e..7e503e4 100644 (file)
@@ -127,8 +127,9 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
     return true;
 }
 
-Property *StringObject::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+Property *StringObject::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
 {
+    name = (String *)0;
     StringObject *s = static_cast<StringObject *>(m);
     uint slen = s->value.stringValue()->toQString().length();
     if (it->arrayIndex < slen) {
index e02a6a7..08892d1 100644 (file)
@@ -62,7 +62,7 @@ struct StringObject: Object {
 
 protected:
     StringObject(InternalClass *ic);
-    static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs);
+    static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs);
     static void markObjects(Managed *that);
 };
 
index 4ee277c..76f41dc 100644 (file)
@@ -386,6 +386,8 @@ struct Safe : public SafeValue
 
     Safe &operator =(const Safe<T> &t);
 
+    bool operator!() const { return !managed(); }
+
     // ### GC: remove me
     operator T*() { return static_cast<T *>(managed()); }
     Value *operator->() { return this; }
index 523b7cc..de4fbbb 100644 (file)
@@ -147,9 +147,9 @@ void QmlListWrapper::destroy(Managed *that)
     w->~QmlListWrapper();
 }
 
-Property *QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attrs)
+Property *QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attrs)
 {
-    *name = 0;
+    name = (String *)0;
     *index = UINT_MAX;
     QmlListWrapper *w = m->as<QmlListWrapper>();
     quint32 count = w->property.count ? w->property.count(&w->property) : 0;
index ea35ad0..9ece585 100644 (file)
@@ -84,7 +84,7 @@ public:
     static ReturnedValue get(Managed *m, const StringRef name, bool *hasProperty);
     static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
     static void put(Managed *m, const StringRef name, const ValueRef value);
-    static Property *advanceIterator(Managed *m, ObjectIterator *it, String **name, uint *index, PropertyAttributes *attributes);
+    static Property *advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
     static void destroy(Managed *that);
 
 private:
index 9211ffd..7cf769a 100644 (file)
@@ -613,16 +613,15 @@ QVariantMap QV8Engine::variantMapFromJS(QV4::ObjectRef o,
 
     visitedObjects.insert(o);
 
-    QV4::ObjectIterator it(o, QV4::ObjectIterator::EnumerableOnly);
+    QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
     QV4::ScopedValue name(scope);
+    QV4::ScopedValue val(scope);
     while (1) {
-        QV4::Value v;
-        name = it.nextPropertyNameAsString(&v);
+        name = it.nextPropertyNameAsString(val);
         if (name->isNull())
             break;
 
         QString key = name->toQStringNoThrow();
-        QV4::ScopedValue val(scope, v);
         result.insert(key, variantFromJS(val, visitedObjects));
     }
 
index f929880..b87ed63 100644 (file)
@@ -1557,14 +1557,13 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
     if (!o)
         return false;
 
-    QV4::ObjectIterator it(o.getPointer(), QV4::ObjectIterator::EnumerableOnly|QV4::ObjectIterator::WithProtoChain);
+    QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly|QV4::ObjectIterator::WithProtoChain);
     QV4::ScopedValue propertyName(scope);
+    QV4::ScopedValue v(scope);
     while (1) {
-        QV4::Value value;
-        propertyName = it.nextPropertyNameAsString(&value);
+        propertyName = it.nextPropertyNameAsString(v);
         if (propertyName->isNull())
             break;
-        QV4::ScopedValue v(scope, value);
         cacheItem->setValue(propertyName->toQStringNoThrow(), m_cacheMetaType->v8Engine->toVariant(v, QVariant::Invalid));
     }
 
index f5e0e70..0ff3487 100644 (file)
@@ -415,13 +415,13 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
 
     QV4::ExecutionEngine *v4 = object->engine();
     QV4::Scope scope(v4);
-    QV4::Scoped<QV4::Object> o(scope);
+    QV4::ScopedObject o(scope);
 
-    QV4::ObjectIterator it(object, QV4::ObjectIterator::WithProtoChain|QV4::ObjectIterator::EnumerableOnly);
+    QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::WithProtoChain|QV4::ObjectIterator::EnumerableOnly);
     QV4::Scoped<QV4::String> propertyName(scope);
+    QV4::ScopedValue propertyValue(scope);
     while (1) {
-        QV4::Value propertyValue;
-        propertyName = it.nextPropertyNameAsString(&propertyValue);
+        propertyName = it.nextPropertyNameAsString(propertyValue);
         if (!propertyName)
             break;
 
@@ -429,13 +429,13 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
         int roleIndex = -1;
 
         // Add the value now
-        if (QV4::String *s = propertyValue.asString()) {
+        if (QV4::String *s = propertyValue->asString()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::String);
             roleIndex = e->setStringProperty(r, s->toQString());
-        } else if (propertyValue.isNumber()) {
+        } else if (propertyValue->isNumber()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Number);
-            roleIndex = e->setDoubleProperty(r, propertyValue.asDouble());
-        } else if (QV4::ArrayObject *a = propertyValue.asArrayObject()) {
+            roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
+        } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::List);
             ListModel *subModel = new ListModel(r.subLayout, 0, -1);
 
@@ -446,14 +446,14 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
             }
 
             roleIndex = e->setListProperty(r, subModel);
-        } else if (propertyValue.isBoolean()) {
+        } else if (propertyValue->isBoolean()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Bool);
-            roleIndex = e->setBoolProperty(r, propertyValue.booleanValue());
-        } else if (QV4::DateObject *dd = propertyValue.asDateObject()) {
+            roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
+        } else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::DateTime);
             QDateTime dt = dd->toQDateTime();
             roleIndex = e->setDateTimeProperty(r, dt);
-        } else if (QV4::Object *o = propertyValue.asObject()) {
+        } else if (QV4::Object *o = propertyValue->asObject()) {
             if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
                 QObject *o = wrapper->object();
                 const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::QObject);
@@ -466,7 +466,7 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QVector<int> *roles
                     roleIndex = e->setVariantMapProperty(role, obj, eng);
                 }
             }
-        } else if (propertyValue.isNullOrUndefined()) {
+        } else if (propertyValue->isNullOrUndefined()) {
             const ListLayout::Role *r = m_layout->getExistingRole(propertyName.getPointer());
             if (r)
                 e->clearProperty(*r);
@@ -489,25 +489,25 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
     QV4::Scope scope(v4);
     QV4::Scoped<QV4::Object> o(scope);
 
-    QV4::ObjectIterator it(object, QV4::ObjectIterator::WithProtoChain|QV4::ObjectIterator::EnumerableOnly);
+    QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::WithProtoChain|QV4::ObjectIterator::EnumerableOnly);
     QV4::Scoped<QV4::String> propertyName(scope);
+    QV4::ScopedValue propertyValue(scope);
     while (1) {
-        QV4::Value propertyValue;
-        propertyName = it.nextPropertyNameAsString(&propertyValue);
+        propertyName = it.nextPropertyNameAsString(propertyValue);
         if (!propertyName)
             break;
 
         // Add the value now
-        if (QV4::String *s = propertyValue.asString()) {
+        if (QV4::String *s = propertyValue->asString()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::String);
             if (r.type == ListLayout::Role::String)
                 e->setStringPropertyFast(r, s->toQString());
-        } else if (propertyValue.isNumber()) {
+        } else if (propertyValue->isNumber()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Number);
             if (r.type == ListLayout::Role::Number) {
-                e->setDoublePropertyFast(r, propertyValue.asDouble());
+                e->setDoublePropertyFast(r, propertyValue->asDouble());
             }
-        } else if (QV4::ArrayObject *a = propertyValue.asArrayObject()) {
+        } else if (QV4::ArrayObject *a = propertyValue->asArrayObject()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::List);
             if (r.type == ListLayout::Role::List) {
                 ListModel *subModel = new ListModel(r.subLayout, 0, -1);
@@ -520,18 +520,18 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
 
                 e->setListPropertyFast(r, subModel);
             }
-        } else if (propertyValue.isBoolean()) {
+        } else if (propertyValue->isBoolean()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Bool);
             if (r.type == ListLayout::Role::Bool) {
-                e->setBoolPropertyFast(r, propertyValue.booleanValue());
+                e->setBoolPropertyFast(r, propertyValue->booleanValue());
             }
-        } else if (QV4::DateObject *dd = propertyValue.asDateObject()) {
+        } else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
             const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::DateTime);
             if (r.type == ListLayout::Role::DateTime) {
                 QDateTime dt = dd->toQDateTime();;
                 e->setDateTimePropertyFast(r, dt);
             }
-        } else if (propertyValue.isObject()) {
+        } else if (propertyValue->isObject()) {
             QV4::ScopedObject o(scope, propertyValue);
             if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
                 QObject *o = wrapper->object();
@@ -543,7 +543,7 @@ void ListModel::set(int elementIndex, QV4::ObjectRef object, QV8Engine *eng)
                 if (role.type == ListLayout::Role::VariantMap)
                     e->setVariantMapFast(role, o, eng);
             }
-        } else if (propertyValue.isUndefined() || propertyValue.isNull()) {
+        } else if (propertyValue->isNullOrUndefined()) {
             const ListLayout::Role *r = m_layout->getExistingRole(propertyName.getPointer());
             if (r)
                 e->clearProperty(*r);