From 351870317388ac7479b39015263f1db440cc6587 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 24 Aug 2009 09:54:07 +0200 Subject: QScriptValue: No need to create the activation object for call or construct It is uneeded and add useless overhead --- src/script/api/qscriptvalue.cpp | 4 ---- tests/auto/qscriptengine/tst_qscriptengine.cpp | 32 ++++++++++++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 73c8d1b..93d6be8 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -1936,7 +1936,6 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, "a different engine"); return QScriptValue(); } - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; @@ -2011,7 +2010,6 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, "a different engine"); return QScriptValue(); } - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; @@ -2077,7 +2075,6 @@ QScriptValue QScriptValue::construct(const QScriptValueList &args) Q_D(const QScriptValue); if (!isFunction()) return QScriptValue(); - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; QVector argsVector; @@ -2125,7 +2122,6 @@ QScriptValue QScriptValue::construct(const QScriptValue &arguments) Q_D(QScriptValue); if (!isFunction()) return QScriptValue(); - engine()->currentContext()->activationObject(); //force the creation of a context for native function; JSC::ExecState *exec = d->engine->currentFrame; JSC::JSValue array = d->engine->scriptValueToJSCValue(arguments); diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index 85cee28..0c67987 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -1518,15 +1518,29 @@ static QScriptValue eval_nested(QScriptContext *ctx, QScriptEngine *eng) void tst_QScriptEngine::nestedEvaluate() { QScriptEngine eng; - eng.globalObject().setProperty("fun", eng.newFunction(eval_nested)); - QScriptValue result = eng.evaluate("o = { id:'foo'}; o.fun = fun; o.fun()"); - QCOMPARE(result.property("local_bar").toString(), QString("local")); - QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); - QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); - QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); - QScriptValue bar = eng.evaluate("bar"); - QVERIFY(bar.isError()); - QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + QScriptValue fun = eng.newFunction(eval_nested); + eng.globalObject().setProperty("fun", fun); + { + QScriptValue result = eng.evaluate("o = { id:'foo'}; o.fun = fun; o.fun()"); + QCOMPARE(result.property("local_bar").toString(), QString("local")); + QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); + QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); + QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); + QScriptValue bar = eng.evaluate("bar"); + QVERIFY(bar.isError()); + QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + } + + { + QScriptValue result = fun.call(eng.evaluate("p = { id:'foo' }") , QScriptValueList() ); + QCOMPARE(result.property("local_bar").toString(), QString("local")); + QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo")); + QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo")); + QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo")); + QScriptValue bar = eng.evaluate("bar"); + QVERIFY(bar.isError()); + QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar")); + } } void tst_QScriptEngine::uncaughtException() -- cgit v0.12 From 648498dd839d88ea6ce9889eb71e16ac9a42e988 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 24 Aug 2009 10:34:57 +0200 Subject: Fix QScriptContext::argumentObjects for function called with QScriptValue::call They have the hostCallFrameFlag, but are function context, not context --- src/script/api/qscriptcontext.cpp | 9 ++++-- tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 35 ++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 0b1ca33..6a85ede 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -305,8 +305,8 @@ QScriptValue QScriptContext::argumentsObject() const { JSC::CallFrame *frame = const_cast(QScriptEnginePrivate::frameForContext(this)); - if (frame == frame->lexicalGlobalObject()->globalExec() || frame->callerFrame()->hasHostCallFrameFlag()) { - // or context doesn't have arguments. return an empty object + if (frame == frame->lexicalGlobalObject()->globalExec()) { + // context doesn't have arguments. return an empty object return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); } @@ -316,6 +316,11 @@ QScriptValue QScriptContext::argumentsObject() const return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); } + if (frame->callerFrame()->hasHostCallFrameFlag()) { + // context doesn't have arguments. return an empty object + return QScriptEnginePrivate::get(QScript::scriptEngineFromExec(frame))->newObject(); + } + //for a native function if (!frame->optionalCalleeArguments()) { Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index a0c56ed..ef609e0 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -559,6 +559,11 @@ static QScriptValue custom_eval(QScriptContext *ctx, QScriptEngine *eng) return eng->evaluate(ctx->argumentsObject().property(0).toString(), ctx->argumentsObject().property(1).toString()); } +static QScriptValue custom_call(QScriptContext *ctx, QScriptEngine *) +{ + return ctx->argumentsObject().property(0).call(QScriptValue(), QScriptValueList() << ctx->argumentsObject().property(1)); +} + void tst_QScriptContext::backtrace_data() { QTest::addColumn("code"); @@ -681,7 +686,36 @@ void tst_QScriptContext::backtrace_data() QTest::newRow("two function") << source << expected; } + { + QString func("function foo(a, b) {\n" + " return bt(a);\n" + "}"); + + QString source = func + QString::fromLatin1("\n" + "custom_call(foo, 'hello');\n" + "var a = 1\n"); + + QStringList expected; + expected << "('hello') at -1" + << "foo(a = 'hello') at testfile:2" + << QString("(%1, 'hello') at -1").arg(func) + << "() at testfile:4"; + QTest::newRow("call") << source << expected; + } + + { + QString source = QString::fromLatin1("\n" + "custom_call(bt, 'hello_world');\n" + "var a = 1\n"); + + QStringList expected; + expected << "('hello_world') at -1" + << "(function () {\n [native code]\n}, 'hello_world') at -1" + << "() at testfile:2"; + + QTest::newRow("call native") << source << expected; + } } @@ -693,6 +727,7 @@ void tst_QScriptContext::backtrace() QScriptEngine eng; eng.globalObject().setProperty("bt", eng.newFunction(getBacktrace)); eng.globalObject().setProperty("custom_eval", eng.newFunction(custom_eval)); + eng.globalObject().setProperty("custom_call", eng.newFunction(custom_call)); QString fileName = "testfile"; QScriptValue ret = eng.evaluate(code, fileName); -- cgit v0.12 From 8528417ec1c064a3b8fd7fa24b1f3b193e668765 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Mon, 24 Aug 2009 10:20:02 +0200 Subject: Revert "Fix trivial QList detaching: QListData::detach2() *must* memcpy." This reverts commit 7a7ea0219f6ebb9f7833649ec76e077796be1843. --- src/corelib/tools/qlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 58406b9..d954160 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -94,6 +94,7 @@ QListData::Data *QListData::detach() /*! * Detaches the QListData by reallocating new memory. * Returns the old (shared) data, it is up to the caller to deref() and free() + * For the new data node_copy needs to be called. * * \internal */ @@ -103,7 +104,6 @@ QListData::Data *QListData::detach2() Data* t = static_cast(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); Q_CHECK_PTR(t); - ::memcpy(t, x, DataHeaderSize + x->alloc * sizeof(void *)); t->ref = 1; t->sharable = true; t->alloc = x->alloc; -- cgit v0.12 From a7d8ba4fb8ed918205815e6d8cd52c5c04365cbe Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Mon, 24 Aug 2009 10:20:29 +0200 Subject: Revert "Remove the unnecessary double memcpy now too." This reverts commit 10a0ed3f2e6a71eced5f470f1c3e09d7be58bbc9. --- src/corelib/tools/qlist.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 5fa0f6c..ab6f7bd 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -381,6 +381,9 @@ Q_INLINE_TEMPLATE void QList::node_copy(Node *from, Node *to, Node *src) (reinterpret_cast(current--))->~T(); QT_RETHROW; } + } else { + if (src != from && to - from > 0) + memcpy(from, src, (to - from) * sizeof(Node *)); } } -- cgit v0.12 From 94c444e71e6a36cfbd3782416200ff20bdd1cea9 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Mon, 24 Aug 2009 10:26:04 +0200 Subject: Restore QList backward compatibility Add detach3 and append2, leaving the old functions as they were. This ensures that new code will use the optimized version of QList, and old code will just continue calling the old functions. Reviewed-by: Thiago --- src/corelib/tools/qlist.cpp | 51 +++++++++++++++++++++++++++++++++++++++++++++ src/corelib/tools/qlist.h | 8 ++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index d954160..868bed1 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -98,12 +98,45 @@ QListData::Data *QListData::detach() * * \internal */ +#if QT_VERSION >= 0x050000 +# error "Remove QListData::detach2(), it is only required for binary compatibility for 4.3.x to 4.5.x" +#endif QListData::Data *QListData::detach2() { Data *x = d; Data* t = static_cast(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); Q_CHECK_PTR(t); + ::memcpy(x, d, DataHeaderSize + d->alloc * sizeof(void *)); + + t->ref = 1; + t->sharable = true; + t->alloc = x->alloc; + if (!t->alloc) { + t->begin = 0; + t->end = 0; + } else { + t->begin = x->begin; + t->end = x->end; + } + d = t; + + return x; +} + +/*! + * Detaches the QListData by reallocating new memory. + * Returns the old (shared) data, it is up to the caller to deref() and free() + * For the new data node_copy needs to be called. + * + * \internal + */ +QListData::Data *QListData::detach3() +{ + Data *x = d; + Data* t = static_cast(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); + Q_CHECK_PTR(t); + t->ref = 1; t->sharable = true; t->alloc = x->alloc; @@ -150,6 +183,9 @@ void **QListData::append() } // ensures that enough space is available to append the list +#if QT_VERSION >= 0x050000 +# error "Remove QListData::append(), it is only required for binary compatibility up to 4.5.x" +#endif void **QListData::append(const QListData& l) { Q_ASSERT(d->ref == 1); @@ -158,6 +194,21 @@ void **QListData::append(const QListData& l) if (n) { if (e + n > d->alloc) realloc(grow(e + l.d->end - l.d->begin)); + ::memcpy(d->array + d->end, l.d->array + l.d->begin, n*sizeof(void*)); + d->end += n; + } + return d->array + e; +} + +// ensures that enough space is available to append the list +void **QListData::append2(const QListData& l) +{ + Q_ASSERT(d->ref == 1); + int e = d->end; + int n = l.d->end - l.d->begin; + if (n) { + if (e + n > d->alloc) + realloc(grow(e + l.d->end - l.d->begin)); d->end += n; } return d->array + e; diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index ab6f7bd..331f448 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -72,13 +72,15 @@ struct Q_CORE_EXPORT QListData { enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; Data *detach(); // remove in 5.0 - Data *detach2(); + Data *detach2(); // remove in 5.0 + Data *detach3(); void realloc(int alloc); static Data shared_null; Data *d; void **erase(void **xi); void **append(); void **append(const QListData &l); + void **append2(const QListData &l); // remove in 5.0 void **prepend(); void **insert(int i); void remove(int i); @@ -593,7 +595,7 @@ template Q_OUTOFLINE_TEMPLATE void QList::detach_helper() { Node *n = reinterpret_cast(p.begin()); - QListData::Data *x = p.detach2(); + QListData::Data *x = p.detach3(); QT_TRY { node_copy(reinterpret_cast(p.begin()), reinterpret_cast(p.end()), n); } QT_CATCH(...) { @@ -693,7 +695,7 @@ template Q_OUTOFLINE_TEMPLATE QList &QList::operator+=(const QList &l) { detach(); - Node *n = reinterpret_cast(p.append(l.p)); + Node *n = reinterpret_cast(p.append2(l.p)); QT_TRY{ node_copy(n, reinterpret_cast(p.end()), reinterpret_cast(l.p.begin())); } QT_CATCH(...) { -- cgit v0.12 From 84081ce91c56168edd686a404b405dcad5f74106 Mon Sep 17 00:00:00 2001 From: Harald Fernengel Date: Mon, 24 Aug 2009 10:29:45 +0200 Subject: Remove QScopedCustomPointer Use QScopedPointer with a custom deleter instead, so we can remove the awful QScopedCustomPointer once and for all :) Reviewed-by: Thiago --- src/corelib/tools/qscopedpointer.h | 9 +++++++++ src/gui/painting/qbrush.cpp | 14 +++++++------- src/gui/painting/qbrush.h | 6 +++--- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h index 7a3ee14..f801366 100644 --- a/src/corelib/tools/qscopedpointer.h +++ b/src/corelib/tools/qscopedpointer.h @@ -166,6 +166,11 @@ public: return oldD; } + inline void swap(QScopedPointer &other) + { + qSwap(d, other.d); + } + typedef T *pointer; protected: @@ -175,6 +180,10 @@ private: Q_DISABLE_COPY(QScopedPointer) }; +template +Q_INLINE_TEMPLATE void qSwap(QScopedPointer &p1, QScopedPointer &p2) +{ p1.swap(p2); } + template > class QScopedArrayPointer : public QScopedPointer { diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index b005842..a52a270 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -389,20 +389,20 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style) { switch(style) { case Qt::NoBrush: - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); if (d->color != color) setColor(color); return; case Qt::TexturePattern: - d.data_ptr() = new QTexturedBrushData; + d.reset(new QTexturedBrushData); break; case Qt::LinearGradientPattern: case Qt::RadialGradientPattern: case Qt::ConicalGradientPattern: - d.data_ptr() = new QGradientBrushData; + d.reset(new QGradientBrushData); break; default: - d.data_ptr() = new QBrushData; + d.reset(new QBrushData); break; } d->ref = 1; @@ -460,7 +460,7 @@ QBrush::QBrush(Qt::BrushStyle style) if (qbrush_check_type(style)) init(Qt::black, style); else { - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -476,7 +476,7 @@ QBrush::QBrush(const QColor &color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } @@ -493,7 +493,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style) if (qbrush_check_type(style)) init(color, style); else { - d.data_ptr() = nullBrushInstance(); + d.reset(nullBrushInstance()); d->ref.ref(); } } diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 51b108e..9f9819c 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -137,13 +137,13 @@ private: friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush); void detach(Qt::BrushStyle newStyle); void init(const QColor &color, Qt::BrushStyle bs); - QCustomScopedPointer d; + QScopedPointer d; void cleanUp(QBrushData *x); public: inline bool isDetached() const; - typedef QBrushData * DataPtr; - inline DataPtr &data_ptr() { return d.data_ptr(); } + typedef QScopedPointer DataPtr; + inline DataPtr &data_ptr() { return d; } }; inline void QBrush::setColor(Qt::GlobalColor acolor) -- cgit v0.12