From 9e8b3f2e789e24c561d2f583927ee15b38808941 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 24 Aug 2009 15:54:09 +0200 Subject: handle memory management of QScriptValuePrivate in engine if possible Avoid calling malloc() and free() so often. The premise is that QScriptValue is usually a short-lived type, and only a few QScriptValues exist at a time, so if we cache privates in the engine, QScriptValues will be much faster to create and destroy. Reviewed-by: Olivier Goffart --- src/script/api/qscriptengine.cpp | 25 ++++++++++++++++++++-- src/script/api/qscriptengine_p.h | 4 ++++ src/script/api/qscriptvalue.cpp | 46 +++++++++++++++++++++++++++------------- src/script/api/qscriptvalue_p.h | 3 +++ 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index afbe6bb..b4b4f91 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -791,7 +791,7 @@ static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng) } // namespace QScript QScriptEnginePrivate::QScriptEnginePrivate() - : registeredScriptValues(0), inEval(false) + : registeredScriptValues(0), freeScriptValues(0), inEval(false) { qMetaTypeId(); @@ -836,6 +836,11 @@ QScriptEnginePrivate::QScriptEnginePrivate() QScriptEnginePrivate::~QScriptEnginePrivate() { + while (freeScriptValues) { + QScriptValuePrivate *p = freeScriptValues; + freeScriptValues = p->next; + qFree(p); + } while (!ownedAgents.isEmpty()) delete ownedAgents.takeFirst(); detachAllRegisteredScriptValues(); @@ -851,7 +856,7 @@ QScriptValue QScriptEnginePrivate::scriptValueFromJSCValue(JSC::JSValue value) if (!value) return QScriptValue(); - QScriptValuePrivate *p_value = new QScriptValuePrivate(); + QScriptValuePrivate *p_value = new (this)QScriptValuePrivate(); p_value->engine = this; p_value->initFrom(value); return QScriptValuePrivate::toPublic(p_value); @@ -1362,6 +1367,22 @@ bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue re #endif +QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size) +{ + if (freeScriptValues) { + QScriptValuePrivate *p = freeScriptValues; + freeScriptValues = p->next; + return p; + } + return reinterpret_cast(qMalloc(size)); +} + +void QScriptEnginePrivate::freeScriptValuePrivate(QScriptValuePrivate *p) +{ + p->next = freeScriptValues; + freeScriptValues = p; +} + void QScriptEnginePrivate::registerScriptValue(QScriptValuePrivate *value) { value->prev = 0; diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index eb660e2..1142fcb 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -210,6 +210,9 @@ public: bool scriptDisconnect(JSC::JSValue signal, JSC::JSValue receiver, JSC::JSValue function); + QScriptValuePrivate *allocateScriptValuePrivate(size_t); + void freeScriptValuePrivate(QScriptValuePrivate *p); + void registerScriptValue(QScriptValuePrivate *value); void unregisterScriptValue(QScriptValuePrivate *value); void detachAllRegisteredScriptValues(); @@ -237,6 +240,7 @@ public: QScriptEngineAgent *activeAgent; int agentLineNumber; QScriptValuePrivate *registeredScriptValues; + QScriptValuePrivate *freeScriptValues; QHash m_typeInfos; int processEventsInterval; QScriptValue abortResult; diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index a9c07a7..4b92049 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -406,6 +406,22 @@ void QScriptValuePrivate::detachFromEngine() engine = 0; } +void* QScriptValuePrivate::operator new(size_t size, QScriptEnginePrivate *engine) +{ + if (engine) + return engine->allocateScriptValuePrivate(size); + return qMalloc(size); +} + +void QScriptValuePrivate::operator delete(void *ptr) +{ + QScriptValuePrivate *d = reinterpret_cast(ptr); + if (d->engine) + d->engine->freeScriptValuePrivate(d); + else + qFree(d); +} + /*! Constructs an invalid QScriptValue. */ @@ -440,7 +456,7 @@ QScriptValue::QScriptValue(const QScriptValue &other) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); switch (value) { @@ -462,7 +478,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, QScriptValue::SpecialValue val registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine *engine, bool val) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); d_ptr->initFrom(JSC::jsBoolean(val)); @@ -476,7 +492,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, bool val) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine *engine, int val) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); if (engine) { @@ -499,7 +515,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, int val) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine *engine, uint val) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); if (engine) { @@ -522,7 +538,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, uint val) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); if (engine) { @@ -545,7 +561,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, qsreal val) registers it with the script \a engine. */ QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); if (engine) { @@ -566,7 +582,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, const QString &val) #ifndef QT_NO_CAST_FROM_ASCII QScriptValue::QScriptValue(QScriptEngine *engine, const char *val) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (QScriptEnginePrivate::get(engine))QScriptValuePrivate) { d_ptr->engine = QScriptEnginePrivate::get(engine); if (engine) { @@ -584,7 +600,7 @@ QScriptValue::QScriptValue(QScriptEngine *engine, const char *val) Constructs a new QScriptValue with a special \a value. */ QScriptValue::QScriptValue(SpecialValue value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; switch (value) { @@ -603,7 +619,7 @@ QScriptValue::QScriptValue(SpecialValue value) Constructs a new QScriptValue with a boolean \a value. */ QScriptValue::QScriptValue(bool value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; d_ptr->initFrom(JSC::jsBoolean(value)); @@ -615,7 +631,7 @@ QScriptValue::QScriptValue(bool value) Constructs a new QScriptValue with a number \a value. */ QScriptValue::QScriptValue(int value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; JSC::JSValue immediate = JSC::JSImmediate::from(value); @@ -631,7 +647,7 @@ QScriptValue::QScriptValue(int value) Constructs a new QScriptValue with a number \a value. */ QScriptValue::QScriptValue(uint value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; JSC::JSValue immediate = JSC::JSImmediate::from(value); @@ -647,7 +663,7 @@ QScriptValue::QScriptValue(uint value) Constructs a new QScriptValue with a number \a value. */ QScriptValue::QScriptValue(qsreal value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; JSC::JSValue immediate = JSC::JSImmediate::from(value); @@ -663,7 +679,7 @@ QScriptValue::QScriptValue(qsreal value) Constructs a new QScriptValue with a string \a value. */ QScriptValue::QScriptValue(const QString &value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; d_ptr->initFrom(value); @@ -675,7 +691,7 @@ QScriptValue::QScriptValue(const QString &value) Constructs a new QScriptValue with a string \a value. */ QScriptValue::QScriptValue(const QLatin1String &value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; d_ptr->initFrom(value); @@ -689,7 +705,7 @@ QScriptValue::QScriptValue(const QLatin1String &value) #ifndef QT_NO_CAST_FROM_ASCII QScriptValue::QScriptValue(const char *value) - : d_ptr(new QScriptValuePrivate) + : d_ptr(new (/*engine=*/0)QScriptValuePrivate) { d_ptr->engine = 0; d_ptr->initFrom(QString::fromAscii(value)); diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index cb4f1ba..115c755 100644 --- a/src/script/api/qscriptvalue_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -68,6 +68,9 @@ class QScriptValuePrivate { Q_DISABLE_COPY(QScriptValuePrivate); public: + void* operator new(size_t, QScriptEnginePrivate*); + void operator delete(void*); + enum Type { JSC, Number, -- cgit v0.12