From a267b590d17d1e7088acf44a8ba7e307f898ccb1 Mon Sep 17 00:00:00 2001 From: Kent Hansen <khansen@trolltech.com> Date: Mon, 13 Jul 2009 11:18:22 +0200 Subject: add GC marking guards Caller is responsible for calling marked() before mark(), otherwise you might get infinite recursion. --- src/script/api/qscriptengine.cpp | 20 +++++++++++++------- src/script/bridge/qscriptobject.cpp | 6 ++++-- src/script/bridge/qscriptqobject.cpp | 21 +++++++++++++++------ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index bf76cd4..4800286 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -563,17 +563,19 @@ void GlobalObject::mark() if (engine->uncaughtException) engine->uncaughtException.mark(); - if (engine->qobjectPrototype) + if (engine->qobjectPrototype && !engine->qobjectPrototype->marked()) engine->qobjectPrototype->mark(); - if (engine->qmetaobjectPrototype) + if (engine->qmetaobjectPrototype && !engine->qmetaobjectPrototype->marked()) engine->qmetaobjectPrototype->mark(); - if (engine->variantPrototype) + if (engine->variantPrototype && !engine->variantPrototype->marked()) engine->variantPrototype->mark(); { QHash<JSC::JSCell*,QBasicAtomicInt>::const_iterator it; for (it = engine->keepAliveValues.constBegin(); it != engine->keepAliveValues.constEnd(); ++it) { - it.key()->mark(); + JSC::JSCell *cell = it.key(); + if (!cell->marked()) + cell->mark(); } } @@ -590,7 +592,7 @@ void GlobalObject::mark() { QHash<int, QScriptTypeInfo*>::const_iterator it; for (it = engine->m_typeInfos.constBegin(); it != engine->m_typeInfos.constEnd(); ++it) { - if ((*it)->prototype) + if ((*it)->prototype && !(*it)->prototype.marked()) (*it)->prototype.mark(); } } @@ -1413,8 +1415,10 @@ QScriptValue QScriptEngine::newVariant(const QScriptValue &object, if (!object.isObject()) return newVariant(value); JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(object)->jscValue); - if (!jscObject->isObject(&QScriptObject::info)) + if (!jscObject->isObject(&QScriptObject::info)) { + qWarning("QScriptEngine::newVariant(): changing class of non-QScriptObject not supported"); return QScriptValue(); + } QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); if (!object.isVariant()) { delete jscScriptObject->delegate(); @@ -1489,8 +1493,10 @@ QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject, if (!scriptObject.isObject()) return newQObject(qtObject, ownership, options); JSC::JSObject *jscObject = JSC::asObject(QScriptValuePrivate::get(scriptObject)->jscValue); - if (!jscObject->isObject(&QScriptObject::info)) + if (!jscObject->isObject(&QScriptObject::info)) { + qWarning("QScriptEngine::newQObject(): changing class of non-QScriptObject not supported"); return QScriptValue(); + } QScriptObject *jscScriptObject = static_cast<QScriptObject*>(jscObject); if (!scriptObject.isQObject()) { delete jscScriptObject->delegate(); diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp index b657af7..5cf415a 100644 --- a/src/script/bridge/qscriptobject.cpp +++ b/src/script/bridge/qscriptobject.cpp @@ -113,7 +113,8 @@ void QScriptObject::getPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArra void QScriptObject::mark() { - if (d && d->data) + Q_ASSERT(!marked()); + if (d && d->data && !d->data.marked()) d->data.mark(); if (!d || !d->delegate) { JSC::JSObject::mark(); @@ -203,7 +204,8 @@ void QScriptObjectDelegate::getPropertyNames(QScriptObject* object, JSC::ExecSta void QScriptObjectDelegate::mark(QScriptObject* object) { - object->JSC::JSObject::mark(); + if (!object->marked()) + object->JSC::JSObject::mark(); } JSC::CallType QScriptObjectDelegate::getCallData(QScriptObject* object, JSC::CallData& data) diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index a17daea..ff58102 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -82,9 +82,9 @@ struct QObjectConnection } #endif } - if (receiver) + if (receiver && !receiver.marked()) receiver.mark(); - if (slot) + if (slot && !slot.marked()) slot.mark(); } }; @@ -234,7 +234,13 @@ JSC::CallType QtFunction::getCallData(JSC::CallData &callData) void QtFunction::mark() { - data->object.mark(); + Q_ASSERT(!marked()); + if (data->object && !data->object.marked()) { + // FIXME: Causes infinite recursion because the object will mark this function, + // which will again mark the object, and so on. Need an "is marking" flag. +// data->object.mark(); + } + JSC::InternalFunction::mark(); } QScriptObject *QtFunction::wrapperObject() const @@ -1498,10 +1504,13 @@ void QObjectDelegate::getPropertyNames(QScriptObject *object, JSC::ExecState *ex void QObjectDelegate::mark(QScriptObject *object) { QHash<QByteArray, JSC::JSValue>::const_iterator it; - for (it = data->cachedMembers.constBegin(); it != data->cachedMembers.constEnd(); ++it) - JSC::asObject(it.value())->mark(); + for (it = data->cachedMembers.constBegin(); it != data->cachedMembers.constEnd(); ++it) { + JSC::JSValue val = it.value(); + if (val && !val.marked()) + val.mark(); + } - object->JSC::JSObject::mark(); + QScriptObjectDelegate::mark(object); } static JSC::JSValue JSC_HOST_CALL qobjectProtoFuncFindChild(JSC::ExecState *exec, JSC::JSObject*, -- cgit v0.12