From d8110b53ed9ee4d69b92e602e812c6311c1b863b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 20 Mar 2019 17:15:29 +0100 Subject: Trigger the garbage collector when allocating InternalClass objects As we check the icAllocator's slots on shouldRunGC() we should also check shouldRunGC() when adding slots. Otherwise we might never run the GC when only allocating InternalClasses. In addition, account for the "unmanaged" size of the PropertyAttributes that are part of the InternalClass objects. Those can be large. In cases where an excessive number of large InternalClass objects is created the garbage collector is now invoked frequently, which costs a significant number of CPU cycles, but prevents the memory usage from growing indefinitely. Task-number: QTBUG-58559 Change-Id: Icf102cb6100f6dba212b8bffe1c178897880eda0 Reviewed-by: Lars Knoll --- tests/auto/qml/qv4mm/tst_qv4mm.cpp | 54 ++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'tests') diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp index b57b716ed6..1e34b79954 100644 --- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp +++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp @@ -112,26 +112,40 @@ void tst_qv4mm::accessParentOnDestruction() void tst_qv4mm::clearICParent() { - QJSEngine engine; - QJSValue value = engine.evaluate( - "(function() {\n" - " var test = Object.create(null);\n" - " for (var i = 0; i < 100; i++)\n" - " test[(\"key_\"+i)] = true;\n" - " for (var i = 0; i < 100; i++)\n" - " delete test[\"key_\" + i];\n" - " return test;\n" - "})();" - ); - engine.collectGarbage(); - QV4::Value *v4Value = QJSValuePrivate::getValue(&value); - QVERIFY(v4Value); - QV4::Heap::Object *v4Object = v4Value->toObject(engine.handle()); - QVERIFY(v4Object); - - // It should garbage collect the parents of the internalClass, - // as those aren't used anywhere else. - QCOMPARE(v4Object->internalClass->parent, nullptr); + QV4::ExecutionEngine engine; + QV4::Scope scope(engine.rootContext()); + QV4::ScopedObject object(scope, engine.newObject()); + + // Keep identifiers in a separate array so that we don't have to allocate them in the loop that + // should test the GC on InternalClass allocations. + QV4::ScopedArrayObject identifiers(scope, engine.newArrayObject()); + for (uint i = 0; i < 16 * 1024; ++i) { + QV4::Scope scope(&engine); + QV4::ScopedString s(scope); + s = engine.newIdentifier(QString::fromLatin1("key%1").arg(i)); + identifiers->push_back(s); + + QV4::ScopedValue v(scope); + v->setDouble(i); + object->insertMember(s, v); + } + + // When allocating the InternalClass objects required for deleting properties, the GC should + // eventually run and remove all but the last two. + // If we ever manage to avoid allocating the InternalClasses in the first place we will need + // to change this test. + for (uint i = 0; i < 16 * 1024; ++i) { + QV4::Scope scope(&engine); + QV4::ScopedString s(scope, identifiers->getIndexed(i)); + QV4::Scoped ic(scope, object->internalClass()); + QVERIFY(ic->d()->parent != nullptr); + object->deleteProperty(s->toPropertyKey()); + QVERIFY(object->internalClass() != ic->d()); + QCOMPARE(object->internalClass()->parent, ic->d()); + if (ic->d()->parent == nullptr) + return; + } + QFAIL("Garbage collector was not triggered by large amount of InternalClasses"); } QTEST_MAIN(tst_qv4mm) -- cgit v1.2.3 From 82247946b2733bcd5bb3740a31c7d38fb90f6ddd Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 22 Mar 2019 14:30:15 +0100 Subject: Fix text wrap: do not break on last line if right elide is enabled For multiline texts with word wrapping, it is not so meaningful to add breaks in the last line if it is anyway going to be elided. Fix by using the WrapAnywhere strategy for the last line for such situations. Fixes: QTBUG-72736 Change-Id: I1263c81277b6ca89ba461529fced1094263c026f Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../data/text/text_wrap_elide_maxlines.qml | 133 +++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tests/manual/scenegraph_lancelot/data/text/text_wrap_elide_maxlines.qml (limited to 'tests') diff --git a/tests/manual/scenegraph_lancelot/data/text/text_wrap_elide_maxlines.qml b/tests/manual/scenegraph_lancelot/data/text/text_wrap_elide_maxlines.qml new file mode 100644 index 0000000000..927f2b3148 --- /dev/null +++ b/tests/manual/scenegraph_lancelot/data/text/text_wrap_elide_maxlines.qml @@ -0,0 +1,133 @@ +import QtQuick 2.0 + +//test wrapping and elision when maximumLineCount is set + +Item { + width: 320 + height: 480 + Rectangle { + id: text_area + color: "light yellow" + x: 50 + y: 0 + height: parent.height + width: 150 + } + Text { + id: text_0000 + wrapMode: Text.WrapAnywhere + text: "The quick brown fox jumps over the lazy dog." + x: text_area.x + y: text_area.y + width: text_area.width + maximumLineCount: 2 + elide: Text.ElideRight + color: "red" + font.family: "Arial" + font.pixelSize: 22 + } + Text { + id: text_0001 + wrapMode: Text.Wrap + text: text_0000.text + anchors.top: text_0000.bottom + anchors.left: text_0000.left + width: text_0000.width + maximumLineCount: text_0000.maximumLineCount + elide: Text.ElideRight + color: "blue" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0002 + wrapMode: Text.WordWrap + text: text_0000.text + anchors.top: text_0001.bottom + anchors.left: text_0000.left + width: text_0000.width + maximumLineCount: text_0000.maximumLineCount + elide: Text.ElideRight + color: "green" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0003 + wrapMode: Text.WrapAnywhere + text: "ABCDEFGHIJKL 1234567890123" + anchors.top: text_0002.bottom + anchors.left: text_0000.left + width: 150 + maximumLineCount: 2 + elide: Text.ElideRight + color: "red" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0004 + wrapMode: Text.Wrap + text: text_0003.text + anchors.top: text_0003.bottom + anchors.left: text_0000.left + width: text_0000.width + maximumLineCount: text_0000.maximumLineCount + elide: Text.ElideRight + color: "blue" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0005 + wrapMode: Text.WordWrap + text: text_0003.text + anchors.top: text_0004.bottom + anchors.left: text_0000.left + width: text_0000.width + maximumLineCount: text_0000.maximumLineCount + elide: Text.ElideRight + color: "green" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0006 + wrapMode: Text.WrapAnywhere + text: "The quick brown 1234567890123" + anchors.top: text_0005.bottom + anchors.left: text_0000.left + width: 150 + maximumLineCount: 2 + elide: Text.ElideRight + color: "red" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0007 + wrapMode: Text.Wrap + text: text_0006.text + anchors.top: text_0006.bottom + anchors.left: text_0000.left + width: text_0000.width + maximumLineCount: text_0000.maximumLineCount + elide: Text.ElideRight + color: "blue" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } + Text { + id: text_0008 + wrapMode: Text.WordWrap + text: text_0006.text + anchors.top: text_0007.bottom + anchors.left: text_0000.left + width: text_0000.width + maximumLineCount: text_0000.maximumLineCount + elide: Text.ElideRight + color: "green" + font.family: text_0000.font.family + font.pixelSize: text_0000.font.pixelSize + } +} -- cgit v1.2.3 From 1b43149decdf42e47405a9e43840b7382076cb0d Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 21 Mar 2019 14:36:57 +0100 Subject: Fix incorrect PathView.currentIndex assignment with StrictlyEnforceRange If currentIndex is quickly assigned a different index and then the previous current index again, it should not move. Fixes: QTBUG-74508 Change-Id: I8d610e3fe452c8631e082c648e77d2cb70ae57c5 Reviewed-by: Richard Moe Gustavsen --- tests/auto/quick/qquickpathview/data/pathview5.qml | 65 ++++++++++++++++++++++ .../quick/qquickpathview/tst_qquickpathview.cpp | 23 ++++++++ 2 files changed, 88 insertions(+) create mode 100644 tests/auto/quick/qquickpathview/data/pathview5.qml (limited to 'tests') diff --git a/tests/auto/quick/qquickpathview/data/pathview5.qml b/tests/auto/quick/qquickpathview/data/pathview5.qml new file mode 100644 index 0000000000..479c5dc500 --- /dev/null +++ b/tests/auto/quick/qquickpathview/data/pathview5.qml @@ -0,0 +1,65 @@ +import QtQuick 2.0 + +PathView { + property int countclick: 0 + id: pathview + y: 0 + width: 348 + height: 480 + + interactive: false + + cacheItemCount: 10 + currentIndex: 2 + pathItemCount: 4 + highlightMoveDuration: 1000 + highlightRangeMode : PathView.StrictlyEnforceRange + preferredHighlightBegin: 0.5 + preferredHighlightEnd: 0.5 + snapMode : PathView.SnapOneItem + + path: Path { + id: leftPath + startX: pathview.width / 2 - 800 + startY: pathview.height / 2 - 800 + + PathArc { + x: pathview.width / 2 - 800 + y: pathview.height / 2 + 800 + radiusX: 800 + radiusY: 800 + direction: PathArc.Clockwise + } + } + + model: ListModel { + id: model + ListElement { objectName:"aqua"; name: "aqua" ;mycolor:"aqua"} + ListElement { objectName:"blue"; name: "blue" ;mycolor:"blue"} + ListElement { objectName:"blueviolet"; name: "blueviolet" ;mycolor:"blueviolet"} + ListElement { objectName:"brown"; name: "brown" ;mycolor:"brown"} + ListElement { objectName:"chartreuse"; name: "chartreuse" ;mycolor:"chartreuse"} + } + + delegate: Item { + id: revolveritem + objectName: model.objectName + + width: pathview.width + height: pathview.height + + Rectangle + { + id:myRectangle + color: mycolor + width: pathview.width -20 + height: pathview.height -20 + + Text { + anchors.centerIn: parent + text: "index:"+index + color: "white" + } + } + } +} diff --git a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp index 6267a3771e..7491df5087 100644 --- a/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp +++ b/tests/auto/quick/qquickpathview/tst_qquickpathview.cpp @@ -103,6 +103,7 @@ private slots: void offset_data(); void offset(); void setCurrentIndex(); + void setCurrentIndexWrap(); void resetModel(); void propertyChanges(); void pathChanges(); @@ -1137,6 +1138,28 @@ void tst_QQuickPathView::setCurrentIndex() QCOMPARE(currentIndexSpy.count(), 1); } +void tst_QQuickPathView::setCurrentIndexWrap() +{ + QScopedPointer window(createView()); + window->setSource(testFileUrl("pathview5.qml")); + window->show(); + qApp->processEvents(); + + QQuickPathView *pathview = qobject_cast(window->rootObject()); + QVERIFY(pathview); + + // set current index to last item + pathview->setCurrentIndex(4); + // set currentIndex to first item, then quickly set it back (QTBUG-74508) + QSignalSpy currentIndexSpy(pathview, SIGNAL(currentIndexChanged())); + QSignalSpy movementStartedSpy(pathview, SIGNAL(movementStarted())); + pathview->setCurrentIndex(0); + pathview->setCurrentIndex(4); + QCOMPARE(pathview->currentIndex(), 4); + QCOMPARE(currentIndexSpy.count(), 2); + QCOMPARE(movementStartedSpy.count(), 0); +} + void tst_QQuickPathView::resetModel() { QScopedPointer window(createView()); -- cgit v1.2.3 From b6d0ed435d2d57359b6eafb2728c024eab0b1ece Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 25 Mar 2019 15:43:13 +0100 Subject: Scope intermediate values when allocating objects Otherwise the garbage collector might interfere and we might end up with dangling pointers in random places. Task-number: QTBUG-74190 Change-Id: I253c526ef930b8f0be14e96a42af8b66fda3b22d Reviewed-by: Lars Knoll --- tests/auto/qml/qjsengine/tst_qjsengine.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tests') diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index 0491ccd473..0b1f1e0bca 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -236,6 +236,7 @@ private slots: void importExportErrors(); void equality(); + void aggressiveGc(); public: Q_INVOKABLE QJSValue throwingCppMethod1(); @@ -4632,6 +4633,18 @@ void tst_QJSEngine::equality() QCOMPARE(ok.toString(), QString("ok")); } +void tst_QJSEngine::aggressiveGc() +{ + const QByteArray origAggressiveGc = qgetenv("QV4_MM_AGGRESSIVE_GC"); + qputenv("QV4_MM_AGGRESSIVE_GC", "true"); + { + QJSEngine engine; // ctor crashes if core allocation methods don't properly scope things. + QJSValue obj = engine.newObject(); + QVERIFY(obj.isObject()); + } + qputenv("QV4_MM_AGGRESSIVE_GC", origAggressiveGc); +} + QTEST_MAIN(tst_QJSEngine) #include "tst_qjsengine.moc" -- cgit v1.2.3 From 60f766f5c68fc33322c6d095d81b1856828b2b0b Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 26 Mar 2019 13:57:33 +0100 Subject: Re-use existing IC when freezing properties There is no reason to start from the empty class in that case. Furthermore, if the properties are already frozen, starting from the empty class will walk the IC hierarchy to the current IC. However, if the garbage collector has removed the intermediate classes in the mean time, we end up at a new IC which is equivalent but not the same. Therefore, the freezing never terminates. Task-number: QTBUG-74190 Change-Id: Id544bd00d3b4b563fb06dfce0edd0385e1d32a6c Reviewed-by: Lars Knoll --- tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'tests') diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index f58ae38264..b9cb6b70d2 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -80,6 +80,7 @@ private slots: void qrcUrls(); void cppSignalAndEval(); void singletonInstance(); + void aggressiveGc(); public slots: QObject *createAQObjectForOwnershipTest () @@ -1043,6 +1044,18 @@ void tst_qqmlengine::singletonInstance() } } +void tst_qqmlengine::aggressiveGc() +{ + const QByteArray origAggressiveGc = qgetenv("QV4_MM_AGGRESSIVE_GC"); + qputenv("QV4_MM_AGGRESSIVE_GC", "true"); + { + QQmlEngine engine; // freezing should not run into infinite recursion + QJSValue obj = engine.newObject(); + QVERIFY(obj.isObject()); + } + qputenv("QV4_MM_AGGRESSIVE_GC", origAggressiveGc); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" -- cgit v1.2.3 From 3507c29e8d9ea42e63fd0c01e27ee9263d939256 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 27 Mar 2019 10:20:38 +0100 Subject: Blacklist tst_qquickfolderlistmodel::nameFilters() on msvc2015/17 Task-number: QTBUG-74739 Change-Id: Ib0f1d39cb5bc9864195b3c62d254fa38370faf0d Reviewed-by: Shawn Rutledge --- tests/auto/qml/qquickfolderlistmodel/BLACKLIST | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/auto/qml/qquickfolderlistmodel/BLACKLIST (limited to 'tests') diff --git a/tests/auto/qml/qquickfolderlistmodel/BLACKLIST b/tests/auto/qml/qquickfolderlistmodel/BLACKLIST new file mode 100644 index 0000000000..642fdea741 --- /dev/null +++ b/tests/auto/qml/qquickfolderlistmodel/BLACKLIST @@ -0,0 +1,3 @@ +[nameFilters] +msvc-2015 +msvc-2017 -- cgit v1.2.3