Reduce memory usage for object literals with integral keys
authorSimon Hausmann <simon.hausmann@digia.com>
Fri, 14 Feb 2014 15:35:12 +0000 (16:35 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sun, 16 Feb 2014 16:57:02 +0000 (17:57 +0100)
Be more aggressive about using sparse arrays for object literals than for
regular array handling, to reduce the memory usage in this use case. The
current heuristic is that indices over 0x1000 switch to sparse, which means a
simple { "3000" : "test" } creates a long vector instead of a sparse array.

Task-number: QTBUG-36803
Change-Id: Id05c76f0f597cd016114cd27ec54effbebe26e48
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/jsruntime/qv4runtime.cpp
src/qml/qml/v8/qv8engine.cpp

index a3cae33..38d46f3 100644 (file)
@@ -1095,6 +1095,8 @@ void __qmljs_builtin_define_property(ExecutionContext *ctx, const ValueRef objec
 
     uint idx = name->asArrayIndex();
     if (idx != UINT_MAX) {
+        if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
+            o->initSparseArray();
         o->arraySet(idx, val);
     } else {
         ScopedValue v(scope, val ? *val : Primitive::undefinedValue());
index 76327e3..f448cca 100644 (file)
@@ -226,8 +226,13 @@ static QV4::ReturnedValue objectFromVariantMap(QV8Engine *engine, const QVariant
     QV4::ScopedObject o(scope, e->newObject());
     QV4::ScopedString s(scope);
     QV4::ScopedValue v(scope);
-    for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter)
-        o->put((s = e->newString(iter.key())), (v = engine->fromVariant(iter.value())));
+    for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) {
+        s = e->newString(iter.key());
+        uint idx = s->asArrayIndex();
+        if (idx > 16 && (!o->arrayData || idx > o->arrayData->length() * 2))
+            o->initSparseArray();
+        o->put(s, (v = engine->fromVariant(iter.value())));
+    }
     return o.asReturnedValue();
 }