aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/v8/qv8engine.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@theqtcompany.com>2015-09-07 15:47:18 +0200
committerLars Knoll <lars.knoll@theqtcompany.com>2015-09-25 08:38:00 +0000
commit81f8e599112471ee802d7fd7b0b79b7330348be6 (patch)
tree86c79674e79c26a7f25ea1fdca1bc7ff2531d195 /src/qml/qml/v8/qv8engine.cpp
parente255fdf207891765aa550709e084614242aebeec (diff)
Speed up QQmlEngine constructor
Freezing the global object using a script is pretty slow, esp. given that the script needs to be compiled as well. Rather do it programmatically. The old code actually had a bug that would only cause the global object to be frozen, not it's children. The new code fixes this, but doesn't completely freeze the objects. Instead it makes all the existing properties of the global object and it's children readonly, but still allows extending existing objects with new properties. Change-Id: I0d7331cdc89a0ac717b8ed3b1a490b2a3742de02 Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
Diffstat (limited to 'src/qml/qml/v8/qv8engine.cpp')
-rw-r--r--src/qml/qml/v8/qv8engine.cpp62
1 files changed, 34 insertions, 28 deletions
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 6cb316ce9f..effc37a0eb 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -191,41 +191,47 @@ void QV8Engine::initializeGlobal()
m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
}
}
+}
- {
-#define FREEZE_SOURCE "(function freeze_recur(obj) { "\
- " if (Qt.isQtObject(obj)) return;"\
- " if (obj != Function.connect && obj != Function.disconnect && "\
- " obj instanceof Object) {"\
- " var properties = Object.getOwnPropertyNames(obj);"\
- " for (var prop in properties) { "\
- " if (prop == \"connect\" || prop == \"disconnect\") {"\
- " Object.freeze(obj[prop]); "\
- " continue;"\
- " }"\
- " freeze_recur(obj[prop]);"\
- " }"\
- " }"\
- " if (obj instanceof Object) {"\
- " Object.freeze(obj);"\
- " }"\
- "})"
-
- QV4::ScopedFunctionObject result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0));
- Q_ASSERT(!!result);
- m_freezeObject.set(scope.engine, result);
-#undef FREEZE_SOURCE
+static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
+{
+ if (object->as<QV4::QObjectWrapper>())
+ return;
+
+ QV4::Scope scope(v4);
+
+ bool instanceOfObject = false;
+ QV4::ScopedObject p(scope, object->prototype());
+ while (p) {
+ if (p->d() == v4->objectPrototype()->d()) {
+ instanceOfObject = true;
+ break;
+ }
+ p = p->prototype();
+ }
+ if (!instanceOfObject)
+ return;
+
+ QV4::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ if (object->internalClass() == frozen)
+ return;
+ object->setInternalClass(frozen);
+
+ QV4::ScopedObject o(scope);
+ for (uint i = 0; i < frozen->size; ++i) {
+ if (!frozen->nameMap.at(i))
+ continue;
+ o = *object->propertyData(i);
+ if (o)
+ freeze_recursive(v4, o);
}
}
void QV8Engine::freezeObject(const QV4::Value &value)
{
QV4::Scope scope(m_v4Engine);
- QV4::ScopedFunctionObject f(scope, m_freezeObject.value());
- QV4::ScopedCallData callData(scope, 1);
- callData->args[0] = value;
- callData->thisObject = m_v4Engine->globalObject;
- f->call(callData);
+ QV4::ScopedObject o(scope, value);
+ freeze_recursive(m_v4Engine, o);
}
struct QV8EngineRegistrationData