aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2016-05-12 11:17:52 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2016-05-12 11:17:52 +0200
commitc49baa34d710b94d451d3f1165a442d3cb080ad8 (patch)
treed51a38beee14615e22c98e2277f793c9908412fa
parent2b9693bfa5241c96a0b20861d9700fc5e0b826df (diff)
parent6bed1d55b38effa5ccee69423c104dfad374b484 (diff)
Merge 5.6 into 5.6.1
-rw-r--r--src/qml/jsruntime/qv4engine.cpp109
-rw-r--r--src/qml/jsruntime/qv4engine_p.h33
-rw-r--r--src/qml/jsruntime/qv4value_p.h6
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp7
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp5
-rw-r--r--src/quick/accessible/qaccessiblequickitem_p.h2
-rw-r--r--src/quick/items/qquickflickable.cpp8
-rw-r--r--tests/benchmarks/qml/creation/tst_creation.cpp6
-rw-r--r--tests/benchmarks/qml/librarymetrics_performance/librarymetrics_performance.pro2
-rw-r--r--tests/benchmarks/qml/librarymetrics_performance/tst_librarymetrics_performance.cpp2
-rw-r--r--tests/benchmarks/qml/qml.pro1
11 files changed, 62 insertions, 119 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 2560f065cf..49b6dce697 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -105,84 +105,6 @@ static ReturnedValue throwTypeError(CallContext *ctx)
return ctx->engine()->throwTypeError();
}
-const int MinimumStackSize = 256; // in kbytes
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_MSVC(4172) // MSVC 2015: warning C4172: returning address of local variable or temporary: dummy
-
-quintptr getStackLimit()
-{
- quintptr stackLimit;
-#if USE(PTHREADS) && !OS(QNX)
-# if OS(DARWIN)
- pthread_t thread_self = pthread_self();
- void *stackTop = pthread_get_stackaddr_np(thread_self);
- stackLimit = reinterpret_cast<quintptr>(stackTop);
- quintptr size = 0;
- if (pthread_main_np()) {
- rlimit limit;
- getrlimit(RLIMIT_STACK, &limit);
- size = limit.rlim_cur;
- } else
- size = pthread_get_stacksize_np(thread_self);
- stackLimit -= size;
-# elif defined(__hppa)
- // On some architectures the stack grows upwards. All of these are rather exotic, so simply assume
- // everything is fine there.
- // Known examples:
- // -HP PA-RISC
- stackLimit = 0;
-
-# else
- pthread_attr_t attr;
-#if HAVE(PTHREAD_NP_H) && OS(FREEBSD)
- // on FreeBSD pthread_attr_init() must be called otherwise getting the attrs crashes
- if (pthread_attr_init(&attr) == 0 && pthread_attr_get_np(pthread_self(), &attr) == 0) {
-#else
- if (pthread_getattr_np(pthread_self(), &attr) == 0) {
-#endif
- void *stackBottom = Q_NULLPTR;
- size_t stackSize = 0;
-
- pthread_attr_getstack(&attr, &stackBottom, &stackSize);
- pthread_attr_destroy(&attr);
-
-# if defined(Q_OS_ANDROID)
- // Bionic pretends that the main thread has a tiny stack; work around it
- if (gettid() == getpid()) {
- rlimit limit;
- getrlimit(RLIMIT_STACK, &limit);
- stackBottom = reinterpret_cast<void*>(reinterpret_cast<quintptr>(stackBottom) + stackSize - limit.rlim_cur);
- }
-# endif
-
- stackLimit = reinterpret_cast<quintptr>(stackBottom);
- } else {
- int dummy;
- // this is inexact, as part of the stack is used when being called here,
- // but let's simply default to 1MB from where the stack is right now
- stackLimit = reinterpret_cast<qintptr>(&dummy) - 1024*1024;
- }
-
-# endif
-// This is wrong. StackLimit is the currently committed stack size, not the real end.
-// only way to get that limit is apparently by using VirtualQuery (Yuck)
-//#elif OS(WINDOWS)
-// PNT_TIB tib = (PNT_TIB)NtCurrentTeb();
-// stackLimit = static_cast<quintptr>(tib->StackLimit);
-#else
- int dummy;
- // this is inexact, as part of the stack is used when being called here,
- // but let's simply default to 1MB from where the stack is right now
- // (Note: triggers warning C4172 as of MSVC 2015, returning address of local variable)
- stackLimit = reinterpret_cast<qintptr>(&dummy) - 1024*1024;
-#endif
-
- // 256k slack
- return stackLimit + MinimumStackSize*1024;
-}
-
-QT_WARNING_POP
QJSEngine *ExecutionEngine::jsEngine() const
{
@@ -194,9 +116,12 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
return v8Engine->engine();
}
+qint32 ExecutionEngine::maxCallDepth = -1;
+
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: current(0)
, hasException(false)
+ , callDepth(0)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
@@ -213,6 +138,15 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
{
+ if (maxCallDepth == -1) {
+ bool ok = false;
+ maxCallDepth = qEnvironmentVariableIntValue("QV4_MAX_CALL_DEPTH", &ok);
+ if (!ok || maxCallDepth <= 0) {
+ maxCallDepth = 1234;
+ }
+ }
+ Q_ASSERT(maxCallDepth > 0);
+
MemoryManager::GCBlocker gcBlocker(memoryManager);
if (!factory) {
@@ -251,9 +185,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
// set up stack limits
jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);
- cStackLimit = getStackLimit();
- if (!recheckCStackLimits())
- qFatal("Fatal: Not enough stack space available for QML. Please increase the process stack size to more than %d KBytes.", MinimumStackSize);
identifierTable = new IdentifierTable(this);
@@ -1117,22 +1048,6 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
return error;
}
-bool ExecutionEngine::recheckCStackLimits()
-{
- int dummy;
-#ifdef Q_OS_WIN
- // ### this is only required on windows, where we currently use heuristics to get the stack limit
- if (cStackLimit - reinterpret_cast<quintptr>(&dummy) > 128*1024)
- // we're more then 128k away from our stack limit, assume the thread has changed, and
- // call getStackLimit
-#endif
- // this can happen after a thread change
- cStackLimit = getStackLimit();
-
- return (reinterpret_cast<quintptr>(&dummy) >= cStackLimit);
-}
-
-
// Variant conversion code
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 4640f3f4cc..7fc880023f 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -75,15 +75,11 @@ namespace CompiledData {
struct CompilationUnit;
}
-#define CHECK_STACK_LIMITS(v4) \
- if ((v4->jsStackTop <= v4->jsStackLimit) && (reinterpret_cast<quintptr>(&v4) >= v4->cStackLimit || v4->recheckCStackLimits())) {} \
- else \
- return v4->throwRangeError(QStringLiteral("Maximum call stack size exceeded."))
-
-
struct Q_QML_EXPORT ExecutionEngine
{
private:
+ static qint32 maxCallDepth;
+
friend struct ExecutionContextSaver;
friend struct ExecutionContext;
friend struct Heap::ExecutionContext;
@@ -92,6 +88,7 @@ public:
Value *jsStackTop;
quint32 hasException;
+ qint32 callDepth;
MemoryManager *memoryManager;
ExecutableAllocator *executableAllocator;
@@ -101,7 +98,6 @@ public:
ExecutionContext *currentContext;
Value *jsStackLimit;
- quintptr cStackLimit;
WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine.
@@ -431,8 +427,6 @@ public:
InternalClass *newClass(const InternalClass &other);
- bool recheckCStackLimits();
-
// Exception handling
Value *exceptionValue;
StackTrace exceptionStackTrace;
@@ -465,6 +459,8 @@ public:
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
void assertObjectBelongsToEngine(const Heap::Base &baseObject);
+
+ bool checkStackLimits(ReturnedValue &exception);
};
inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
@@ -517,7 +513,26 @@ inline void Value::mark(ExecutionEngine *e)
o->mark(e);
}
+#define CHECK_STACK_LIMITS(v4) { ReturnedValue e; if ((v4)->checkStackLimits(e)) return e; } \
+ ExecutionEngineCallDepthRecorder _executionEngineCallDepthRecorder(v4);
+
+struct ExecutionEngineCallDepthRecorder
+{
+ ExecutionEngine *ee;
+ ExecutionEngineCallDepthRecorder(ExecutionEngine *e): ee(e) { ++ee->callDepth; }
+ ~ExecutionEngineCallDepthRecorder() { --ee->callDepth; }
+};
+
+inline bool ExecutionEngine::checkStackLimits(ReturnedValue &exception)
+{
+ if (Q_UNLIKELY((jsStackTop > jsStackLimit) || (callDepth >= maxCallDepth))) {
+ exception = throwRangeError(QStringLiteral("Maximum call stack size exceeded."));
+ return true;
+ }
+
+ return false;
+}
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 723afcab54..6bd39355c5 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -50,11 +50,7 @@
#include "qv4global_p.h"
#include <private/qv4heap_p.h>
-/* We cannot rely on QT_POINTER_SIZE to be set correctly on host builds. In qmldevtools the Value objects
- are only used to store primitives, never object pointers. So we can use the 64-bit encoding. */
-#ifdef V4_BOOTSTRAP
-#define QV4_USE_64_BIT_VALUE_ENCODING
-#elif QT_POINTER_SIZE == 8
+#if QT_POINTER_SIZE == 8
#define QV4_USE_64_BIT_VALUE_ENCODING
#endif
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index e85b3dc82c..aed5f5af35 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -665,9 +665,10 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
} else {
QV4::MemberData *md = propertiesAsMemberData();
if (md) {
- QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>();
- if (v)
- QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
+ QVariant propertyAsVariant;
+ if (QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>())
+ propertyAsVariant = v->d()->data;
+ QQml_valueTypeProvider()->readValueType(propertyAsVariant, a[0], t);
}
}
break;
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index 44a2caecec..2ce914c0b6 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -48,6 +48,11 @@ QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
{
}
+QWindow *QAccessibleQuickItem::window() const
+{
+ return item()->window();
+}
+
int QAccessibleQuickItem::childCount() const
{
return childItems().count();
diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h
index 1ec569731e..af9f8db249 100644
--- a/src/quick/accessible/qaccessiblequickitem_p.h
+++ b/src/quick/accessible/qaccessiblequickitem_p.h
@@ -60,6 +60,8 @@ class QAccessibleQuickItem : public QAccessibleObject, public QAccessibleActionI
public:
QAccessibleQuickItem(QQuickItem *item);
+ QWindow *window() const Q_DECL_OVERRIDE;
+
QRect rect() const;
QRect viewRect() const;
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 26c4e66dd4..7d602db57e 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -1392,15 +1392,15 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event)
break;
case Qt::NoScrollPhase: // default phase with an ordinary wheel mouse
case Qt::ScrollUpdate:
- if (d->scrollingPhase) {
+ if (d->scrollingPhase)
d->pressed = true;
- d->movementEndingTimer.start(MovementEndingTimerInterval, this);
- }
+#ifdef Q_OS_OSX
+ d->movementEndingTimer.start(MovementEndingTimerInterval, this);
+#endif
break;
case Qt::ScrollEnd:
d->pressed = false;
d->scrollingPhase = false;
- d->movementEndingTimer.start(MovementEndingTimerInterval, this);
d->draggingEnding();
event->accept();
returnToBounds();
diff --git a/tests/benchmarks/qml/creation/tst_creation.cpp b/tests/benchmarks/qml/creation/tst_creation.cpp
index 4b985d00f1..38ab577120 100644
--- a/tests/benchmarks/qml/creation/tst_creation.cpp
+++ b/tests/benchmarks/qml/creation/tst_creation.cpp
@@ -100,6 +100,12 @@ public:
tst_creation::tst_creation()
{
qmlRegisterType<TestType>("Qt.test", 1, 0, "TestType");
+
+ // Ensure QtQuick is loaded and imported. Some benchmark like elements() rely on QQmlMetaType::qmlTypeNames() to
+ // be populated.
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nItem{}", QUrl());
+ QScopedPointer<QObject> obj(component.create());
}
inline QUrl TEST_FILE(const QString &filename)
diff --git a/tests/benchmarks/qml/librarymetrics_performance/librarymetrics_performance.pro b/tests/benchmarks/qml/librarymetrics_performance/librarymetrics_performance.pro
index 3bedc0ea18..67f9d3b395 100644
--- a/tests/benchmarks/qml/librarymetrics_performance/librarymetrics_performance.pro
+++ b/tests/benchmarks/qml/librarymetrics_performance/librarymetrics_performance.pro
@@ -7,3 +7,5 @@ macx:CONFIG -= app_bundle
CONFIG += release
SOURCES += tst_librarymetrics_performance.cpp
+
+RESOURCES += data
diff --git a/tests/benchmarks/qml/librarymetrics_performance/tst_librarymetrics_performance.cpp b/tests/benchmarks/qml/librarymetrics_performance/tst_librarymetrics_performance.cpp
index a83c1479f2..ad72ebc6f0 100644
--- a/tests/benchmarks/qml/librarymetrics_performance/tst_librarymetrics_performance.cpp
+++ b/tests/benchmarks/qml/librarymetrics_performance/tst_librarymetrics_performance.cpp
@@ -119,7 +119,7 @@ tst_librarymetrics_performance::~tst_librarymetrics_performance()
static QUrl testFileUrl(const char * filename)
{
- return QUrl::fromLocalFile(QString(QLatin1String(filename)));
+ return QUrl(QLatin1String("qrc:///") + QLatin1String(filename));
}
void tst_librarymetrics_performance::metrics_data()
diff --git a/tests/benchmarks/qml/qml.pro b/tests/benchmarks/qml/qml.pro
index 7969866673..d3ce69c713 100644
--- a/tests/benchmarks/qml/qml.pro
+++ b/tests/benchmarks/qml/qml.pro
@@ -8,6 +8,7 @@ SUBDIRS += \
qqmlcomponent \
qqmlimage \
qqmlmetaproperty \
+ librarymetrics_performance \
# script \ ### FIXME: doesn't build
js