From c320a2c42820a5b31f6611463330c46ea644d8dc Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 2 Jul 2009 13:04:38 +0200 Subject: implement caching of slot wrapper functions --- src/script/bridge/qscriptqobject.cpp | 40 +++++++++++++++++++++++- src/script/bridge/qscriptqobject_p.h | 3 ++ tests/auto/qscriptqobject/tst_qscriptqobject.cpp | 3 -- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index a33f001..188ded9 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -980,6 +980,14 @@ bool QObjectWrapperObject::getOwnPropertySlot(JSC::ExecState *exec, return false; } + { + QHash::const_iterator it = data->cachedMembers.constFind(name); + if (it != data->cachedMembers.constEnd()) { + slot.setValue(it.value()); + return true; + } + } + const QScriptEngine::QObjectWrapOptions &opt = data->options; const QMetaObject *meta = qobject->metaObject(); QScriptEnginePrivate *eng = static_cast(exec->dynamicGlobalObject())->engine; @@ -996,6 +1004,7 @@ bool QObjectWrapperObject::getOwnPropertySlot(JSC::ExecState *exec, &exec->globalData(), exec->dynamicGlobalObject()->functionStructure(), propertyName); slot.setValue(fun); + data->cachedMembers.insert(name, fun); return true; } } @@ -1038,6 +1047,7 @@ bool QObjectWrapperObject::getOwnPropertySlot(JSC::ExecState *exec, &exec->globalData(), exec->dynamicGlobalObject()->functionStructure(), propertyName); slot.setValue(fun); + data->cachedMembers.insert(name, fun); return true; } } @@ -1081,7 +1091,7 @@ void QObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& prop if (hasMethodAccess(method, index, opt)) { if (!(opt & QScriptEngine::ExcludeSuperClassMethods) || (index >= meta->methodOffset())) { - Q_ASSERT(0); + data->cachedMembers.insert(name, value); return; } } @@ -1108,6 +1118,17 @@ void QObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& prop return; } + const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods) + ? meta->methodOffset() : 0; + for (index = meta->methodCount() - 1; index >= offset; --index) { + QMetaMethod method = meta->method(index); + if (hasMethodAccess(method, index, opt) + && (methodName(method) == name)) { + data->cachedMembers.insert(name, value); + return; + } + } + JSC::JSObject::put(exec, propertyName, value, slot); } @@ -1123,6 +1144,14 @@ bool QObjectWrapperObject::deleteProperty(JSC::ExecState *exec, return false; } + { + QHash::iterator it = data->cachedMembers.find(name); + if (it != data->cachedMembers.end()) { + data->cachedMembers.erase(it); + return true; + } + } + int index = qobject->dynamicPropertyNames().indexOf(name); if (index != -1) { (void)qobject->setProperty(name, QVariant()); @@ -1256,6 +1285,15 @@ void QObjectWrapperObject::getPropertyNames(JSC::ExecState *exec, JSC::PropertyN JSC::JSObject::getPropertyNames(exec, propertyNames); } +void QObjectWrapperObject::mark() +{ + QHash::const_iterator it; + for (it = data->cachedMembers.constBegin(); it != data->cachedMembers.constEnd(); ++it) + JSC::asObject(it.value())->mark(); + + JSC::JSObject::mark(); +} + static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*, JSC::JSValue thisValue, const JSC::ArgList &args) { diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h index 2e508ba..b35b6ba 100644 --- a/src/script/bridge/qscriptqobject_p.h +++ b/src/script/bridge/qscriptqobject_p.h @@ -53,6 +53,8 @@ public: QScriptEngine::ValueOwnership ownership; QScriptEngine::QObjectWrapOptions options; + QHash cachedMembers; + Data(QObject *o, QScriptEngine::ValueOwnership own, QScriptEngine::QObjectWrapOptions opt) : value(o), ownership(own), options(opt) {} @@ -74,6 +76,7 @@ public: virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&); + virtual void mark(); virtual const JSC::ClassInfo* classInfo() const { return &info; } static const JSC::ClassInfo info; diff --git a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp index f1fec9f..89dbd3d 100644 --- a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp +++ b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp @@ -859,7 +859,6 @@ void tst_QScriptExtQObject::getSetStaticProperty() QScriptValue slot = m_engine->evaluate("myObject.mySlot"); QVERIFY(slot.isFunction()); QScriptValue sameSlot = m_engine->evaluate("myObject.mySlot"); - QEXPECT_FAIL("", "Slot wrappers aren't persistent yet", Continue); QVERIFY(sameSlot.strictlyEquals(slot)); sameSlot = m_engine->evaluate("myObject[mySlot()]"); QEXPECT_FAIL("", "Slot wrappers aren't persistent yet", Continue); @@ -1673,7 +1672,6 @@ void tst_QScriptExtQObject::connectAndDisconnect() QVERIFY(m_engine->evaluate("myObject.mySignal.connect(yetAnotherObject, 'func')").isUndefined()); QVERIFY(m_engine->evaluate("myObject.mySignal.connect(myObject, 'mySlot')").isUndefined()); QVERIFY(m_engine->evaluate("myObject.mySignal.disconnect(yetAnotherObject, 'func')").isUndefined()); - QEXPECT_FAIL("", "Slot wrappers aren't persistent yet", Continue); QVERIFY(m_engine->evaluate("myObject.mySignal.disconnect(myObject, 'mySlot')").isUndefined()); // check that emitting signals from script works @@ -1683,7 +1681,6 @@ void tst_QScriptExtQObject::connectAndDisconnect() m_myObject->resetQtFunctionInvoked(); QCOMPARE(m_engine->evaluate("myObject.mySignal()").isUndefined(), true); QCOMPARE(m_myObject->qtFunctionInvoked(), 20); - QEXPECT_FAIL("", "Slot wrappers aren't persistent yet", Continue); QVERIFY(m_engine->evaluate("myObject.mySignal.disconnect(myObject.mySlot)").isUndefined()); // one argument -- cgit v0.12