Merge branch 'dev' into wip/pointerhandler

Conflicts:
src/quick/items/qquickwindow.cpp: we need the fix for QTBUG-31861 but
now using QQuickPointerMouseEvent
src/quick/items/qquickwindow_p.h: hover events need timestamps (e4f7ab42)
tests/auto/quick/qquickwindow/tst_qquickwindow.cpp: added test for QTBUG-31861

Change-Id: Ic120513b69b318df3ba62d8174c276cbf6b7b55e
This commit is contained in:
Frederik Gladhorn 2016-08-04 13:12:57 +02:00
commit 175f53860a
197 changed files with 4080 additions and 1193 deletions

View File

@ -41,7 +41,7 @@
#include "pieslice.h"
PieChart::PieChart(QQuickItem *parent)
: QQuickItem(parent)
: QQuickItem(parent), m_pieSlice(0)
{
}

View File

@ -42,7 +42,7 @@
#include <QPainter>
PieSlice::PieSlice(QQuickItem *parent)
: QQuickPaintedItem(parent)
: QQuickPaintedItem(parent), m_fromAngle(0), m_angleSpan(0)
{
}

View File

@ -5,9 +5,8 @@ SUBDIRS = samegame \
tweetsearch \
maroon \
photosurface \
photoviewer \
stocqt
qtHaveModule(xmlpatterns): SUBDIRS += rssnews
EXAMPLE_FILES = \
photoviewer

View File

@ -1,19 +0,0 @@
android {
x86 {
target.path = /libs/x86
} else: armeabi-v7a {
target.path = /libs/armeabi-v7a
} else {
target.path = /libs/armeabi
}
export(target.path)
INSTALLS += target
} else:unix {
isEmpty(target.path) {
target.path = /opt/$${TARGET}/bin
export(target.path)
}
INSTALLS += target
}
export(INSTALLS)

View File

@ -15,8 +15,5 @@ TRANSLATIONS += i18n/qml_fr.ts \
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Default rules for deployment.
include(deployment.pri)
target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/photoviewer
INSTALLS += target

View File

@ -270,4 +270,14 @@ void D3D12RenderNode::render(const RenderState *state)
// No need to reimplement changedStates() because no relevant commands are
// added to the command list in render().
QSGRenderNode::RenderingFlags D3D12RenderNode::flags() const
{
return BoundedRectRendering | DepthAwareRendering;
}
QRectF D3D12RenderNode::rect() const
{
return QRect(0, 0, m_item->width(), m_item->height());
}
#endif // HAS_D3D12

View File

@ -60,6 +60,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
RenderingFlags flags() const override;
QRectF rect() const override;
private:
void init();

View File

@ -151,4 +151,14 @@ QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const
return BlendState;
}
QSGRenderNode::RenderingFlags OpenGLRenderNode::flags() const
{
return BoundedRectRendering | DepthAwareRendering;
}
QRectF OpenGLRenderNode::rect() const
{
return QRect(0, 0, m_item->width(), m_item->height());
}
#endif // QT_NO_OPENGL

View File

@ -45,6 +45,8 @@
#ifndef QT_NO_OPENGL
QT_BEGIN_NAMESPACE
class QQuickItem;
class QOpenGLShaderProgram;
class QOpenGLBuffer;
@ -58,6 +60,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
StateFlags changedStates() const override;
RenderingFlags flags() const override;
QRectF rect() const override;
private:
void init();
@ -69,6 +73,8 @@ private:
QOpenGLBuffer *m_vbo = nullptr;
};
QT_END_NAMESPACE
#endif // QT_NO_OPENGL
#endif

View File

@ -68,7 +68,7 @@ void SoftwareRenderNode::render(const RenderState *renderState)
p->setOpacity(inheritedOpacity());
const QRegion *clipRegion = renderState->clipRegion();
if (clipRegion && !clipRegion->isEmpty())
p->setClipRegion(*clipRegion);
p->setClipRegion(*clipRegion, Qt::IntersectClip);
const QPointF p0(m_item->width() - 1, m_item->height() - 1);
const QPointF p1(0, 0);
@ -89,3 +89,13 @@ QSGRenderNode::StateFlags SoftwareRenderNode::changedStates() const
{
return 0;
}
QSGRenderNode::RenderingFlags SoftwareRenderNode::flags() const
{
return BoundedRectRendering;
}
QRectF SoftwareRenderNode::rect() const
{
return QRect(0, 0, m_item->width(), m_item->height());
}

View File

@ -54,6 +54,8 @@ public:
void render(const RenderState *state) override;
void releaseResources() override;
StateFlags changedStates() const override;
RenderingFlags flags() const override;
QRectF rect() const override;
private:
QQuickItem *m_item;

View File

@ -102,8 +102,8 @@
state and we use it to update the shader program with the current
color. The previous state is passed in as a second parameter so
that the user can update only that which has changed. In our
usecase, where all the colors are different, the updateState will
be called once for every node.
use case, where all the colors are different, the updateState()
function will be called once for every node.
\snippet scenegraph/simplematerial/simplematerial.cpp 7

View File

@ -149,7 +149,12 @@ public:
using namespace QV4;
QT_WARNING_PUSH
#if (Q_CC_GNU >= 600)
QT_WARNING_DISABLE_GCC("-Wtautological-compare")
#endif
DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
QT_WARNING_POP

View File

@ -124,12 +124,9 @@ QPacketProtocol::QPacketProtocol(QIODevice *dev, QObject *parent)
Q_ASSERT(4 == sizeof(qint32));
Q_ASSERT(dev);
QObject::connect(dev, SIGNAL(readyRead()),
this, SLOT(readyToRead()));
QObject::connect(dev, SIGNAL(aboutToClose()),
this, SLOT(aboutToClose()));
QObject::connect(dev, SIGNAL(bytesWritten(qint64)),
this, SLOT(bytesWritten(qint64)));
QObject::connect(dev, &QIODevice::readyRead, this, &QPacketProtocol::readyToRead);
QObject::connect(dev, &QIODevice::aboutToClose, this, &QPacketProtocol::aboutToClose);
QObject::connect(dev, &QIODevice::bytesWritten, this, &QPacketProtocol::bytesWritten);
}
/*!
@ -247,12 +244,9 @@ void QPacketProtocol::readyToRead()
// Check sizing constraints
if (d->inProgressSize > MAX_PACKET_SIZE) {
QObject::disconnect(d->dev, SIGNAL(readyRead()),
this, SLOT(readyToRead()));
QObject::disconnect(d->dev, SIGNAL(aboutToClose()),
this, SLOT(aboutToClose()));
QObject::disconnect(d->dev, SIGNAL(bytesWritten(qint64)),
this, SLOT(bytesWritten(qint64)));
disconnect(d->dev, &QIODevice::readyRead, this, &QPacketProtocol::readyToRead);
disconnect(d->dev, &QIODevice::aboutToClose, this, &QPacketProtocol::aboutToClose);
disconnect(d->dev, &QIODevice::bytesWritten, this, &QPacketProtocol::bytesWritten);
d->dev = 0;
emit invalidPacket();
return;

View File

@ -74,7 +74,7 @@ Q_SIGNALS:
void readyRead();
void invalidPacket();
private Q_SLOTS:
private:
void aboutToClose();
void bytesWritten(qint64 bytes);
void readyToRead();

View File

@ -63,8 +63,12 @@ QT_BEGIN_NAMESPACE
QQmlEngineDebugServiceImpl::QQmlEngineDebugServiceImpl(QObject *parent) :
QQmlEngineDebugService(2, parent), m_watch(new QQmlWatcher(this)), m_statesDelegate(0)
{
QObject::connect(m_watch, SIGNAL(propertyChanged(int,int,QMetaProperty,QVariant)),
this, SLOT(propertyChanged(int,int,QMetaProperty,QVariant)));
connect(m_watch, &QQmlWatcher::propertyChanged,
this, &QQmlEngineDebugServiceImpl::propertyChanged);
// Move the message into the correct thread for processing
connect(this, &QQmlEngineDebugServiceImpl::scheduleMessage,
this, &QQmlEngineDebugServiceImpl::processMessage, Qt::QueuedConnection);
}
QQmlEngineDebugServiceImpl::~QQmlEngineDebugServiceImpl()
@ -420,7 +424,7 @@ QQmlEngineDebugServiceImpl::objectData(QObject *object)
void QQmlEngineDebugServiceImpl::messageReceived(const QByteArray &message)
{
QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection, Q_ARG(QByteArray, message));
emit scheduleMessage(message);
}
/*!

View File

@ -101,16 +101,18 @@ public:
void setStatesDelegate(QQmlDebugStatesDelegate *) Q_DECL_OVERRIDE;
signals:
void scheduleMessage(const QByteArray &);
protected:
virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
private Q_SLOTS:
void processMessage(const QByteArray &msg);
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
private:
friend class QQmlDebuggerServiceFactory;
void processMessage(const QByteArray &msg);
void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value);
void prepareDeferredObjects(QObject *);
void buildObjectList(QDataStream &, QQmlContext *,
const QList<QPointer<QObject> > &instances);

View File

@ -761,7 +761,7 @@ void QQmlNativeDebugServiceImpl::stateAboutToBeChanged(QQmlDebugService::State s
if (state == Enabled) {
foreach (NativeDebugger *debugger, m_debuggers) {
QV4::ExecutionEngine *engine = debugger->engine();
if (!engine->debugger)
if (!engine->debugger())
engine->setDebugger(debugger);
}
}

View File

@ -69,7 +69,7 @@ public:
QQmlWatcher *parent = 0);
public slots:
void notifyValueChanged();
void notifyValueChanged(); // Needs to be a slot because of QQmlPropertyPrivate::connect()
private:
friend class QQmlWatcher;
@ -88,7 +88,8 @@ QQmlWatchProxy::QQmlWatchProxy(int id,
QQmlWatcher *parent)
: QObject(parent), m_id(id), m_watch(parent), m_object(0), m_debugId(debugId), m_expr(exp)
{
QObject::connect(m_expr, SIGNAL(valueChanged()), this, SLOT(notifyValueChanged()));
QObject::connect(m_expr, &QQmlExpression::valueChanged,
this, &QQmlWatchProxy::notifyValueChanged);
}
QQmlWatchProxy::QQmlWatchProxy(int id,

View File

@ -79,6 +79,8 @@ QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine)
static int pauseReasonId = qRegisterMetaType<QV4Debugger::PauseReason>();
Q_UNUSED(debuggerId);
Q_UNUSED(pauseReasonId);
connect(this, &QV4Debugger::scheduleJob,
this, &QV4Debugger::runJobUnpaused, Qt::QueuedConnection);
}
QV4::ExecutionEngine *QV4Debugger::engine() const
@ -320,7 +322,7 @@ void QV4Debugger::runInEngine_havingLock(QV4DebugJob *job)
if (state() == Paused)
m_runningCondition.wakeAll();
else
QMetaObject::invokeMethod(this, "runJobUnpaused", Qt::QueuedConnection);
emit scheduleJob();
m_jobIsRunning.wait(&m_lock);
m_runningJob = 0;
}

View File

@ -140,15 +140,14 @@ public:
signals:
void debuggerPaused(QV4Debugger *self, QV4Debugger::PauseReason reason);
private slots:
void runJobUnpaused();
void scheduleJob();
private:
// requires lock to be held
void pauseAndWait(PauseReason reason);
bool reallyHitTheBreakPoint(const QString &filename, int linenr);
void runInEngine_havingLock(QV4DebugJob *job);
void runJobUnpaused();
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_currentContext;

View File

@ -72,7 +72,6 @@ public:
void setBreakOnThrow(bool onoff);
void clearAllPauseRequests();
public slots:
void debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason);
void handleDebuggerDeleted(QObject *debugger);

View File

@ -706,7 +706,7 @@ void QV4DebugServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
if (engine){
const QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle());
if (ee) {
QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger);
QV4Debugger *debugger = qobject_cast<QV4Debugger *>(ee->debugger());
if (debugger)
debuggerAgent.removeDebugger(debugger);
}
@ -720,7 +720,7 @@ void QV4DebugServiceImpl::stateAboutToBeChanged(State state)
if (state == Enabled) {
foreach (QV4Debugger *debugger, debuggerAgent.debuggers()) {
QV4::ExecutionEngine *ee = debugger->engine();
if (!ee->debugger)
if (!ee->debugger())
ee->setDebugger(debugger);
}
}

View File

@ -148,10 +148,6 @@ public:
m_component.setData(qml, filename);
}
signals:
void result(int requestId, bool success);
public slots:
void tryCreateObject(QQmlComponent::Status status)
{
switch (status) {
@ -171,7 +167,7 @@ public slots:
else
emit result(m_requestId, false);
}
delete this;
deleteLater(); // The component might send more signals
return;
}
default:
@ -179,6 +175,9 @@ public slots:
}
}
signals:
void result(int requestId, bool success);
private:
QQmlComponent m_component;
int m_requestId;

View File

@ -72,10 +72,8 @@ public:
signals:
void messageToClient(const QString &name, const QByteArray &data);
private slots:
void sendResult(int requestId, bool success);
private:
void sendResult(int requestId, bool success);
void sendCurrentObjects(const QList<QObject *> &objects);
void removeFromSelectedItems(QObject *object);
QString titleForItem(QQuickItem *item) const;

View File

@ -72,24 +72,22 @@ void Highlight::setItem(QQuickItem *item)
m_item->disconnect(this);
if (item) {
connect(item, SIGNAL(xChanged()), SLOT(adjust()));
connect(item, SIGNAL(yChanged()), SLOT(adjust()));
connect(item, SIGNAL(widthChanged()), SLOT(adjust()));
connect(item, SIGNAL(heightChanged()), SLOT(adjust()));
connect(item, SIGNAL(rotationChanged()), SLOT(adjust()));
connect(item, SIGNAL(transformOriginChanged(TransformOrigin)),
SLOT(adjust()));
connect(item, &QQuickItem::xChanged, this, &Highlight::adjust);
connect(item, &QQuickItem::yChanged, this, &Highlight::adjust);
connect(item, &QQuickItem::widthChanged, this, &Highlight::adjust);
connect(item, &QQuickItem::heightChanged, this, &Highlight::adjust);
connect(item, &QQuickItem::rotationChanged, this, &Highlight::adjust);
connect(item, &QQuickItem::transformOriginChanged, this, &Highlight::adjust);
}
QQuickWindow *view = item->window();
QQuickItem * contentItem = view->contentItem();
if (contentItem) {
connect(contentItem, SIGNAL(xChanged()), SLOT(adjust()));
connect(contentItem, SIGNAL(yChanged()), SLOT(adjust()));
connect(contentItem, SIGNAL(widthChanged()), SLOT(adjust()));
connect(contentItem, SIGNAL(heightChanged()), SLOT(adjust()));
connect(contentItem, SIGNAL(rotationChanged()), SLOT(adjust()));
connect(contentItem, SIGNAL(transformOriginChanged(TransformOrigin)),
SLOT(adjust()));
connect(contentItem, &QQuickItem::xChanged, this, &Highlight::adjust);
connect(contentItem, &QQuickItem::yChanged, this, &Highlight::adjust);
connect(contentItem, &QQuickItem::widthChanged, this, &Highlight::adjust);
connect(contentItem, &QQuickItem::heightChanged, this, &Highlight::adjust);
connect(contentItem, &QQuickItem::rotationChanged, this, &Highlight::adjust);
connect(contentItem, &QQuickItem::transformOriginChanged, this, &Highlight::adjust);
}
m_item = item;
setContentsSize(view->size());

View File

@ -65,8 +65,6 @@ protected:
private:
void initRenderDetails();
private slots:
void adjust();
private:
@ -86,13 +84,12 @@ public:
void paint(QPainter *painter);
void showName(const QPointF &displayPoint);
private slots:
void disableNameDisplay();
private:
QPointF m_displayPoint;
QString m_name;
bool m_nameDisplayActive;
void disableNameDisplay();
};
/**

View File

@ -55,23 +55,27 @@ public:
void setParentWindow(QQuickWindow *window, QWindow *parent) Q_DECL_OVERRIDE;
void removeWindow(QQuickWindow *window) Q_DECL_OVERRIDE;
signals:
void scheduleMessage(const QByteArray &message);
protected:
virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
private slots:
void messageFromClient(const QByteArray &message);
private:
friend class QQmlInspectorServiceFactory;
QmlJSDebugger::GlobalInspector *checkInspector();
QmlJSDebugger::GlobalInspector *m_globalInspector;
QHash<QQuickWindow *, QWindow *> m_waitingWindows;
void messageFromClient(const QByteArray &message);
};
QQmlInspectorServiceImpl::QQmlInspectorServiceImpl(QObject *parent):
QQmlInspectorService(1, parent), m_globalInspector(0)
{
connect(this, &QQmlInspectorServiceImpl::scheduleMessage,
this, &QQmlInspectorServiceImpl::messageFromClient, Qt::QueuedConnection);
}
QmlJSDebugger::GlobalInspector *QQmlInspectorServiceImpl::checkInspector()
@ -122,8 +126,8 @@ void QQmlInspectorServiceImpl::setParentWindow(QQuickWindow *window, QWindow *pa
void QQmlInspectorServiceImpl::messageReceived(const QByteArray &message)
{
QMetaObject::invokeMethod(this, "messageFromClient", Qt::QueuedConnection,
Q_ARG(QByteArray, message));
// Move the message to the right thread via queued signal
emit scheduleMessage(message);
}
void QQmlInspectorServiceImpl::messageFromClient(const QByteArray &message)

View File

@ -65,10 +65,8 @@ public:
void waitForConnection();
void flush();
private slots:
void connectionEstablished();
private:
void connectionEstablished();
bool connectToServer();
bool m_block;
@ -135,7 +133,8 @@ bool QLocalClientConnection::connectToServer()
{
m_socket = new QLocalSocket;
m_socket->setParent(this);
QObject::connect(m_socket, SIGNAL(connected()), this, SLOT(connectionEstablished()));
QObject::connect(m_socket, &QLocalSocket::connected,
this, &QLocalClientConnection::connectionEstablished);
m_socket->connectToServer(m_filename);
qDebug("QML Debugger: Connecting to socket %s...", m_filename.toLatin1().constData());
return true;

View File

@ -63,11 +63,9 @@ public:
bool open(const QVariantHash &configuration) Q_DECL_OVERRIDE;
static void setDataStreamVersion(int version);
private slots:
private:
void sendMessage(const QString &name, const QByteArray &message);
void sendMessages(const QString &name, const QList<QByteArray> &messages);
private:
void announceObjectAvailability(const QString &objectType, QObject *object, bool available);
QVector<QQmlDebugService *> m_services;

View File

@ -48,20 +48,21 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
next(0)
{
setService(service);
engine->enableProfiler();
connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64)));
connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
connect(engine->profiler,
SIGNAL(dataReady(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)),
this,
SLOT(receiveData(QVector<QQmlProfilerData>,QQmlProfiler::LocationHash)));
engine->profiler = new QQmlProfiler;
connect(this, &QQmlProfilerAdapter::profilingEnabled,
engine->profiler, &QQmlProfiler::startProfiling);
connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
engine->profiler, &QQmlProfiler::startProfiling, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
engine->profiler, &QQmlProfiler::stopProfiling);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
engine->profiler, &QQmlProfiler::stopProfiling, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
engine->profiler, &QQmlProfiler::reportData);
connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
engine->profiler, &QQmlProfiler::setTimer);
connect(engine->profiler, &QQmlProfiler::dataReady,
this, &QQmlProfilerAdapter::receiveData);
}
// convert to QByteArrays that can be sent to the debug client

View File

@ -63,7 +63,6 @@ public:
qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
bool trackLocations) Q_DECL_OVERRIDE;
public slots:
void receiveData(const QVector<QQmlProfilerData> &new_data,
const QQmlProfiler::LocationHash &locations);

View File

@ -409,14 +409,16 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
if (!stream.atEnd()) {
stream >> flushInterval;
m_flushTimer.setInterval(flushInterval);
auto timerStart = static_cast<void(QTimer::*)()>(&QTimer::start);
if (flushInterval > 0) {
connect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush()));
connect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start()));
connect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
connect(&m_flushTimer, &QTimer::timeout, this, &QQmlProfilerServiceImpl::flush);
connect(this, &QQmlProfilerServiceImpl::startFlushTimer, &m_flushTimer, timerStart);
connect(this, &QQmlProfilerServiceImpl::stopFlushTimer, &m_flushTimer, &QTimer::stop);
} else {
disconnect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush()));
disconnect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start()));
disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
disconnect(&m_flushTimer, &QTimer::timeout, this, &QQmlProfilerServiceImpl::flush);
disconnect(this, &QQmlProfilerServiceImpl::startFlushTimer, &m_flushTimer, timerStart);
disconnect(this, &QQmlProfilerServiceImpl::stopFlushTimer,
&m_flushTimer, &QTimer::stop);
}
}
if (!stream.atEnd())

View File

@ -99,9 +99,6 @@ signals:
void startFlushTimer();
void stopFlushTimer();
private slots:
void flush();
protected:
virtual void stateAboutToBeChanged(State state) Q_DECL_OVERRIDE;
virtual void messageReceived(const QByteArray &) Q_DECL_OVERRIDE;
@ -112,6 +109,7 @@ private:
void sendMessages();
void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QJSEngine *engine);
void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler);
void flush();
QElapsedTimer m_timer;
QTimer m_flushTimer;

View File

@ -46,27 +46,26 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
m_functionCallPos(0), m_memoryPos(0)
{
setService(service);
engine->enableProfiler();
connect(this, SIGNAL(profilingEnabled(quint64)),
this, SLOT(forwardEnabled(quint64)));
connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
this, SLOT(forwardEnabledWhileWaiting(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(v4ProfilingEnabled(quint64)),
engine->profiler, SLOT(startProfiling(quint64)));
connect(this, SIGNAL(v4ProfilingEnabledWhileWaiting(quint64)),
engine->profiler, SLOT(startProfiling(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
engine->setProfiler(new QV4::Profiling::Profiler(engine));
connect(this, &QQmlAbstractProfilerAdapter::profilingEnabled,
this, &QV4ProfilerAdapter::forwardEnabled);
connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
this, &QV4ProfilerAdapter::forwardEnabledWhileWaiting, Qt::DirectConnection);
connect(this, &QV4ProfilerAdapter::v4ProfilingEnabled,
engine->profiler(), &QV4::Profiling::Profiler::startProfiling);
connect(this, &QV4ProfilerAdapter::v4ProfilingEnabledWhileWaiting,
engine->profiler(), &QV4::Profiling::Profiler::startProfiling, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
engine->profiler(), &QV4::Profiling::Profiler::stopProfiling);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
engine->profiler(), &QV4::Profiling::Profiler::stopProfiling,
Qt::DirectConnection);
connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
QVector<QV4::Profiling::FunctionCallProperties>,
QVector<QV4::Profiling::MemoryAllocationProperties>)),
this, SLOT(receiveData(QV4::Profiling::FunctionLocationHash,
QVector<QV4::Profiling::FunctionCallProperties>,
QVector<QV4::Profiling::MemoryAllocationProperties>)));
connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
engine->profiler(), &QV4::Profiling::Profiler::reportData);
connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
engine->profiler(), &QV4::Profiling::Profiler::setTimer);
connect(engine->profiler(), &QV4::Profiling::Profiler::dataReady,
this, &QV4ProfilerAdapter::receiveData);
}
qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &messages,

View File

@ -70,18 +70,13 @@ public:
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
bool trackLocations) override;
signals:
void v4ProfilingEnabled(quint64 v4Features);
void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
public slots:
void receiveData(const QV4::Profiling::FunctionLocationHash &,
const QVector<QV4::Profiling::FunctionCallProperties> &,
const QVector<QV4::Profiling::MemoryAllocationProperties> &);
private slots:
void forwardEnabled(quint64 features);
void forwardEnabledWhileWaiting(quint64 features);
signals:
void v4ProfilingEnabled(quint64 v4Features);
void v4ProfilingEnabledWhileWaiting(quint64 v4Features);
private:
QV4::Profiling::FunctionLocationHash m_functionLocations;
@ -93,6 +88,8 @@ private:
qint64 appendMemoryEvents(qint64 until, QList<QByteArray> &messages, QQmlDebugPacket &d);
qint64 finalizeMessages(qint64 until, QList<QByteArray> &messages, qint64 callNext,
QQmlDebugPacket &d);
void forwardEnabled(quint64 features);
void forwardEnabledWhileWaiting(quint64 features);
static quint64 translateFeatures(quint64 qmlFeatures);
};

View File

@ -51,20 +51,20 @@ QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
QQuickProfiler::initialize(this);
// We can always do DirectConnection here as all methods are protected by mutexes
connect(this, SIGNAL(profilingEnabled(quint64)),
QQuickProfiler::s_instance, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)),
QQuickProfiler::s_instance, SLOT(startProfilingImpl(quint64)), Qt::DirectConnection);
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
QQuickProfiler::s_instance, SLOT(setTimer(QElapsedTimer)), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabled()),
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
connect(this, SIGNAL(dataRequested(bool)),
QQuickProfiler::s_instance, SLOT(reportDataImpl(bool)), Qt::DirectConnection);
connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingEnabled,
QQuickProfiler::s_instance, &QQuickProfiler::startProfilingImpl, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
QQuickProfiler::s_instance, &QQuickProfiler::startProfilingImpl, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::referenceTimeKnown,
QQuickProfiler::s_instance, &QQuickProfiler::setTimer, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabled,
QQuickProfiler::s_instance, &QQuickProfiler::stopProfilingImpl, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
QQuickProfiler::s_instance, &QQuickProfiler::stopProfilingImpl, Qt::DirectConnection);
connect(this, &QQmlAbstractProfilerAdapter::dataRequested,
QQuickProfiler::s_instance, &QQuickProfiler::reportDataImpl, Qt::DirectConnection);
connect(QQuickProfiler::s_instance, &QQuickProfiler::dataReady,
this, &QQuickProfilerAdapter::receiveData, Qt::DirectConnection);
}
QQuickProfilerAdapter::~QQuickProfilerAdapter()

View File

@ -62,8 +62,6 @@ public:
QQuickProfilerAdapter(QObject *parent = 0);
~QQuickProfilerAdapter();
qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) override;
public slots:
void receiveData(const QVector<QQuickProfilerData> &new_data);
private:

View File

@ -149,15 +149,6 @@ public:
static void cleanup();
private slots:
void wakeEngine(QJSEngine *engine);
void sendMessage(const QString &name, const QByteArray &message);
void sendMessages(const QString &name, const QList<QByteArray> &messages);
void changeServiceState(const QString &serviceName, QQmlDebugService::State state);
void removeThread();
void receiveMessage();
void invalidPacket();
private:
friend class QQmlDebugServerThread;
friend class QQmlDebugServerFactory;
@ -179,6 +170,13 @@ private:
bool canSendMessage(const QString &name);
void doSendMessage(const QString &name, const QByteArray &message);
void wakeEngine(QJSEngine *engine);
void sendMessage(const QString &name, const QByteArray &message);
void sendMessages(const QString &name, const QList<QByteArray> &messages);
void changeServiceState(const QString &serviceName, QQmlDebugService::State state);
void removeThread();
void receiveMessage();
void invalidPacket();
QQmlDebugServerConnection *m_connection;
QHash<QString, QQmlDebugService *> m_plugins;
@ -203,18 +201,22 @@ void QQmlDebugServerImpl::cleanup()
if (!server)
return;
for (QHash<QString, QQmlDebugService *>::ConstIterator i = server->m_plugins.constBegin();
i != server->m_plugins.constEnd(); ++i) {
server->m_changeServiceStateCalls.ref();
QMetaObject::invokeMethod(server, "changeServiceState", Qt::QueuedConnection,
Q_ARG(QString, i.key()),
Q_ARG(QQmlDebugService::State,
QQmlDebugService::NotConnected));
{
QObject signalSource;
for (QHash<QString, QQmlDebugService *>::ConstIterator i = server->m_plugins.constBegin();
i != server->m_plugins.constEnd(); ++i) {
server->m_changeServiceStateCalls.ref();
QString key = i.key();
// Process this in the server's thread.
connect(&signalSource, &QObject::destroyed, server, [key, server](){
server->changeServiceState(key, QQmlDebugService::NotConnected);
}, Qt::QueuedConnection);
}
}
// Wait for changeServiceState calls to finish
// (while running an event loop because some services
// might again use slots to execute stuff in the GUI thread)
// might again defer execution of stuff in the GUI thread)
QEventLoop loop;
while (!server->m_changeServiceStateCalls.testAndSetOrdered(0, 0))
loop.processEvents();
@ -293,7 +295,7 @@ QQmlDebugServerImpl::QQmlDebugServerImpl() :
// Remove the thread immmediately when it finishes, so that we don't have to wait for the
// event loop to signal that.
QObject::connect(&m_thread, SIGNAL(finished()), this, SLOT(removeThread()),
QObject::connect(&m_thread, &QThread::finished, this, &QQmlDebugServerImpl::removeThread,
Qt::DirectConnection);
m_thread.setObjectName(QStringLiteral("QQmlDebugServerThread"));
parseArguments();
@ -631,15 +633,15 @@ bool QQmlDebugServerImpl::addService(const QString &name, QQmlDebugService *serv
if (!service || m_plugins.contains(name))
return false;
connect(service, SIGNAL(messageToClient(QString,QByteArray)),
this, SLOT(sendMessage(QString,QByteArray)));
connect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
this, SLOT(sendMessages(QString,QList<QByteArray>)));
connect(service, &QQmlDebugService::messageToClient,
this, &QQmlDebugServerImpl::sendMessage);
connect(service, &QQmlDebugService::messagesToClient,
this, &QQmlDebugServerImpl::sendMessages);
connect(service, SIGNAL(attachedToEngine(QJSEngine*)),
this, SLOT(wakeEngine(QJSEngine*)), Qt::QueuedConnection);
connect(service, SIGNAL(detachedFromEngine(QJSEngine*)),
this, SLOT(wakeEngine(QJSEngine*)), Qt::QueuedConnection);
connect(service, &QQmlDebugService::attachedToEngine,
this, &QQmlDebugServerImpl::wakeEngine, Qt::QueuedConnection);
connect(service, &QQmlDebugService::detachedFromEngine,
this, &QQmlDebugServerImpl::wakeEngine, Qt::QueuedConnection);
service->setState(QQmlDebugService::Unavailable);
m_plugins.insert(name, service);
@ -659,15 +661,15 @@ bool QQmlDebugServerImpl::removeService(const QString &name)
m_plugins.remove(name);
service->setState(QQmlDebugService::NotConnected);
disconnect(service, SIGNAL(detachedFromEngine(QJSEngine*)),
this, SLOT(wakeEngine(QJSEngine*)));
disconnect(service, SIGNAL(attachedToEngine(QJSEngine*)),
this, SLOT(wakeEngine(QJSEngine*)));
disconnect(service, &QQmlDebugService::detachedFromEngine,
this, &QQmlDebugServerImpl::wakeEngine);
disconnect(service, &QQmlDebugService::attachedToEngine,
this, &QQmlDebugServerImpl::wakeEngine);
disconnect(service, SIGNAL(messagesToClient(QString,QList<QByteArray>)),
this, SLOT(sendMessages(QString,QList<QByteArray>)));
disconnect(service, SIGNAL(messageToClient(QString,QByteArray)),
this, SLOT(sendMessage(QString,QByteArray)));
disconnect(service, &QQmlDebugService::messagesToClient,
this, &QQmlDebugServerImpl::sendMessages);
disconnect(service, &QQmlDebugService::messageToClient,
this, &QQmlDebugServerImpl::sendMessage);
return true;
}
@ -738,8 +740,10 @@ void QQmlDebugServerImpl::EngineCondition::wake()
void QQmlDebugServerImpl::setDevice(QIODevice *socket)
{
m_protocol = new QPacketProtocol(socket, this);
QObject::connect(m_protocol, SIGNAL(readyRead()), this, SLOT(receiveMessage()));
QObject::connect(m_protocol, SIGNAL(invalidPacket()), this, SLOT(invalidPacket()));
QObject::connect(m_protocol, &QPacketProtocol::readyRead,
this, &QQmlDebugServerImpl::receiveMessage);
QObject::connect(m_protocol, &QPacketProtocol::invalidPacket,
this, &QQmlDebugServerImpl::invalidPacket);
if (blockingMode())
m_protocol->waitForReadyRead(-1);

View File

@ -65,10 +65,8 @@ public:
void waitForConnection();
void flush();
private slots:
void newConnection();
private:
void newConnection();
bool listen();
int m_portFrom;
@ -152,7 +150,8 @@ void QTcpServerConnection::flush()
bool QTcpServerConnection::listen()
{
m_tcpServer = new QTcpServer(this);
QObject::connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
QObject::connect(m_tcpServer, &QTcpServer::newConnection,
this, &QTcpServerConnection::newConnection);
QHostAddress hostaddress;
if (!m_hostaddress.isEmpty()) {
if (!hostaddress.setAddress(m_hostaddress)) {

View File

@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
class QQmlDebugServer : protected QQmlDebugConnector
class QQmlDebugServer : public QQmlDebugConnector
{
Q_OBJECT
public:

View File

@ -682,9 +682,11 @@ void QSGD3D12EnginePrivate::releaseResources()
commandQueue = nullptr;
copyCommandQueue = nullptr;
#ifndef Q_OS_WINRT
dcompTarget = nullptr;
dcompVisual = nullptr;
dcompDevice = nullptr;
#endif
swapChain = nullptr;

View File

@ -435,9 +435,11 @@ private:
DeviceLossTester devLossTest;
#ifndef Q_OS_WINRT
ComPtr<IDCompositionDevice> dcompDevice;
ComPtr<IDCompositionTarget> dcompTarget;
ComPtr<IDCompositionVisual> dcompVisual;
#endif
};
inline uint qHash(const QSGD3D12EnginePrivate::PersistentFrameData::PendingRelease &pr, uint seed = 0)

View File

@ -44,7 +44,6 @@
#include "qsgd3d12shadereffectnode_p.h"
#include <private/qsgrenderer_p.h>
#include <private/qquickwindow_p.h>
#include <private/qquickprofiler_p.h>
#include <private/qquickanimatorcontroller_p.h>
#include <private/qquickprofiler_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>

View File

@ -819,7 +819,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
const QStringRef &name = node->name;
bool typeFound = false;
QV4::CompiledData::Property::Type type;
QV4::CompiledData::Property::Type type = QV4::CompiledData::Property::Var;
for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
const TypeNameToType *t = propTypeNameToTypes + ii;
@ -1359,7 +1359,7 @@ bool IRBuilder::isRedundantNullInitializerForPropertyDeclaration(Property *prope
return QQmlJS::AST::cast<QQmlJS::AST::NullExpression *>(expr);
}
QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output, QQmlEngine *engine, const QV4::CompiledData::ResolvedTypeReferenceMap &dependentTypes)
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit;
QV4::CompiledData::Unit *jsUnit = compilationUnit->createUnitData(&output);
@ -1402,6 +1402,20 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
qmlUnit->offsetToStringTable = totalSize - output.jsGenerator.stringTable.sizeOfTableAndData();
qmlUnit->stringTableSize = output.jsGenerator.stringTable.stringCount();
#ifndef V4_BOOTSTRAP
if (!dependentTypes.isEmpty()) {
QCryptographicHash hash(QCryptographicHash::Md5);
if (dependentTypes.addToHash(&hash, engine)) {
QByteArray checksum = hash.result();
Q_ASSERT(checksum.size() == sizeof(qmlUnit->dependencyMD5Checksum));
memcpy(qmlUnit->dependencyMD5Checksum, checksum.constData(), sizeof(qmlUnit->dependencyMD5Checksum));
}
}
#else
Q_UNUSED(dependentTypes);
Q_UNUSED(engine);
#endif
// write imports
char *importPtr = data + qmlUnit->offsetToImports;
foreach (const QV4::CompiledData::Import *imp, output.imports) {

View File

@ -549,7 +549,7 @@ public:
struct Q_QML_PRIVATE_EXPORT QmlUnitGenerator
{
QV4::CompiledData::Unit *generate(Document &output);
QV4::CompiledData::Unit *generate(Document &output, QQmlEngine *engine, const QV4::CompiledData::ResolvedTypeReferenceMap &dependentTypes);
private:
typedef bool (Binding::*BindingFilter)() const;

View File

@ -492,6 +492,16 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
}
break;
case QVariant::Vector2D: {
struct {
float xp;
float yp;
} vec;
if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: 2D vector expected"));
}
}
break;
case QVariant::Vector3D: {
struct {
float xp;
@ -515,6 +525,18 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
}
}
break;
case QVariant::Quaternion: {
struct {
float wp;
float xp;
float yp;
float zp;
} vec;
if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(qmlUnit), &vec, sizeof(vec))) {
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: quaternion expected"));
}
}
break;
case QVariant::RegExp:
return QQmlCompileError(binding->valueLocation, tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
default: {

View File

@ -76,7 +76,7 @@ private:
QQmlEnginePrivate *enginePrivate;
const QQmlImports &imports;
const QV4::CompiledData::Unit *qmlUnit;
const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QQmlPropertyCacheVector &propertyCaches;
QVector<QV4::CompiledData::BindingPropertyData> * const bindingPropertyDataPerObject;

View File

@ -56,7 +56,9 @@
QT_BEGIN_NAMESPACE
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap &resolvedTypeCache)
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &importCache,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
: resolvedTypes(resolvedTypeCache)
, engine(engine)
, typeData(typeData)
@ -154,7 +156,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
// Generate QML compiled type data structures
QmlIR::QmlUnitGenerator qmlGenerator;
QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document);
QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document, QQmlEnginePrivate::get(engine), resolvedTypes);
Q_ASSERT(document->javaScriptCompilationUnit);
// The js unit owns the data and will free the qml unit.
@ -837,7 +839,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
auto typeRef = new QV4::CompiledData::CompilationUnit::ResolvedTypeReference;
auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
typeRef->type = componentType;
typeRef->majorVersion = componentType->majorVersion();
typeRef->minorVersion = componentType->minorVersion();

View File

@ -89,7 +89,7 @@ struct QQmlTypeCompiler
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeCompiler)
public:
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap &resolvedTypeCache);
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer<QQmlTypeNameCache> &importCache, const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
// --- interface used by QQmlPropertyCacheCreator
typedef QmlIR::Object CompiledObject;
@ -98,7 +98,7 @@ public:
QString stringAt(int idx) const;
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
QV4::CompiledData::CompilationUnit::ResolvedTypeReferenceMap resolvedTypes;
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypes;
// ---
QV4::CompiledData::CompilationUnit *compile();
@ -182,7 +182,7 @@ private:
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlImports *imports;
const QHash<int, QQmlCustomParser*> &customParsers;
const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QSet<QString> &illegalNames;
const QQmlPropertyCacheVector * const propertyCaches;
};
@ -213,7 +213,7 @@ private:
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlPropertyCacheVector * const propertyCaches;
const QQmlImports *imports;
QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference *> *resolvedTypes;
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
};
class QQmlCustomParserScriptIndexer: public QQmlCompilePass
@ -288,7 +288,7 @@ protected:
QHash<int, int> _idToObjectIndex;
QVector<int> _objectsWithAliases;
QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> *resolvedTypes;
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes;
QQmlPropertyCacheVector propertyCaches;
};
@ -321,7 +321,7 @@ private:
bool compileComponent(int componentRoot);
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
const QHash<int, QV4::CompiledData::CompilationUnit::ResolvedTypeReference*> &resolvedTypes;
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypes;
const QHash<int, QQmlCustomParser*> &customParsers;
const QVector<QmlIR::Object*> &qmlObjects;
const QQmlPropertyCacheVector * const propertyCaches;

View File

@ -1058,6 +1058,8 @@ bool Codegen::visit(ArrayLiteral *ast)
current->expr = _block->CONST(IR::MissingType, 0);
}
Result expr = expression(it->expression);
if (hasError)
return false;
IR::ExprList *arg = _function->New<IR::ExprList>();
if (!current) {
@ -1100,6 +1102,8 @@ bool Codegen::visit(ArrayMemberExpression *ast)
Result base = expression(ast->base);
Result index = expression(ast->expression);
if (hasError)
return false;
_expr.code = subscript(*base, *index);
return false;
}
@ -1139,10 +1143,16 @@ bool Codegen::visit(BinaryExpression *ast)
const unsigned r = _block->newTemp();
move(_block->TEMP(r), *expression(ast->left));
Result lhs = expression(ast->left);
if (hasError)
return false;
move(_block->TEMP(r), *lhs);
setLocation(cjump(_block->TEMP(r), iftrue, endif), ast->operatorToken);
_block = iftrue;
move(_block->TEMP(r), *expression(ast->right));
Result rhs = expression(ast->right);
if (hasError)
return false;
move(_block->TEMP(r), *rhs);
_block->JUMP(endif);
_expr.code = _block->TEMP(r);
@ -1160,10 +1170,16 @@ bool Codegen::visit(BinaryExpression *ast)
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
const unsigned r = _block->newTemp();
move(_block->TEMP(r), *expression(ast->left));
Result lhs = expression(ast->left);
if (hasError)
return false;
move(_block->TEMP(r), *lhs);
setLocation(cjump(_block->TEMP(r), endif, iffalse), ast->operatorToken);
_block = iffalse;
move(_block->TEMP(r), *expression(ast->right));
Result rhs = expression(ast->right);
if (hasError)
return false;
move(_block->TEMP(r), *rhs);
_block->JUMP(endif);
_block = endif;
@ -1173,6 +1189,8 @@ bool Codegen::visit(BinaryExpression *ast)
}
IR::Expr* left = *expression(ast->left);
if (hasError)
return false;
switch (ast->op) {
case QSOperator::Or:
@ -1182,17 +1200,19 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::Assign: {
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
IR::Expr* right = *expression(ast->right);
Result right = expression(ast->right);
if (hasError)
return false;
if (!left->isLValue()) {
throwReferenceError(ast->operatorToken, QStringLiteral("left-hand side of assignment operator is not an lvalue"));
return false;
}
if (_expr.accept(nx)) {
move(left, right);
move(left, *right);
} else {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), right);
move(_block->TEMP(t), *right);
move(left, _block->TEMP(t));
_expr.code = _block->TEMP(t);
}
@ -1212,17 +1232,19 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::InplaceXor: {
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(left, ast->left->lastSourceLocation()))
return false;
IR::Expr* right = *expression(ast->right);
Result right = expression(ast->right);
if (hasError)
return false;
if (!left->isLValue()) {
throwSyntaxError(ast->operatorToken, QStringLiteral("left-hand side of inplace operator is not an lvalue"));
return false;
}
if (_expr.accept(nx)) {
move(left, right, baseOp(ast->op));
move(left, *right, baseOp(ast->op));
} else {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), right);
move(_block->TEMP(t), *right);
move(left, _block->TEMP(t), baseOp(ast->op));
_expr.code = left;
}
@ -1245,12 +1267,14 @@ bool Codegen::visit(BinaryExpression *ast)
left = _block->TEMP(t);
}
IR::Expr* right = *expression(ast->right);
Result right = expression(ast->right);
if (hasError)
return false;
if (_expr.accept(cx)) {
setLocation(cjump(binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken);
setLocation(cjump(binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken), _expr.iftrue, _expr.iffalse), ast->operatorToken);
} else {
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken);
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken);
if (e->asConst() || e->asString())
_expr.code = e;
else {
@ -1279,9 +1303,11 @@ bool Codegen::visit(BinaryExpression *ast)
left = _block->TEMP(t);
}
IR::Expr* right = *expression(ast->right);
Result right = expression(ast->right);
if (hasError)
return false;
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, right, ast->operatorToken);
IR::Expr *e = binop(IR::binaryOperator(ast->op), left, *right, ast->operatorToken);
if (e->asConst() || e->asString())
_expr.code = e;
else {
@ -1306,11 +1332,15 @@ bool Codegen::visit(CallExpression *ast)
IR::ExprList *args = 0, **args_it = &args;
for (ArgumentList *it = ast->arguments; it; it = it->next) {
Result arg = expression(it->expression);
if (hasError)
return false;
IR::Expr *actual = argument(*arg);
*args_it = _function->New<IR::ExprList>();
(*args_it)->init(actual);
args_it = &(*args_it)->next;
}
if (hasError)
return false;
_expr.code = call(*base, args);
return false;
}
@ -1329,11 +1359,17 @@ bool Codegen::visit(ConditionalExpression *ast)
condition(ast->expression, iftrue, iffalse);
_block = iftrue;
move(_block->TEMP(t), *expression(ast->ok));
Result ok = expression(ast->ok);
if (hasError)
return false;
move(_block->TEMP(t), *ok);
_block->JUMP(endif);
_block = iffalse;
move(_block->TEMP(t), *expression(ast->ko));
Result ko = expression(ast->ko);
if (hasError)
return false;
move(_block->TEMP(t), *ko);
_block->JUMP(endif);
_block = endif;
@ -1349,6 +1385,8 @@ bool Codegen::visit(DeleteExpression *ast)
return false;
IR::Expr* expr = *expression(ast->expression);
if (hasError)
return false;
// Temporaries cannot be deleted
IR::ArgLocal *al = expr->asArgLocal();
if (al && al->index < static_cast<unsigned>(_env->members.size())) {
@ -1410,7 +1448,8 @@ bool Codegen::visit(FieldMemberExpression *ast)
return false;
Result base = expression(ast->base);
_expr.code = member(*base, _function->newString(ast->name.toString()));
if (!hasError)
_expr.code = member(*base, _function->newString(ast->name.toString()));
return false;
}
@ -1501,6 +1540,8 @@ bool Codegen::visit(NewExpression *ast)
return false;
Result base = expression(ast->expression);
if (hasError)
return false;
IR::Expr *expr = *base;
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
@ -1517,6 +1558,8 @@ bool Codegen::visit(NewMemberExpression *ast)
return false;
Result base = expression(ast->base);
if (hasError)
return false;
IR::Expr *expr = *base;
if (expr && !expr->asTemp() && !expr->asArgLocal() && !expr->asName() && !expr->asMember()) {
const unsigned t = _block->newTemp();
@ -1527,6 +1570,8 @@ bool Codegen::visit(NewMemberExpression *ast)
IR::ExprList *args = 0, **args_it = &args;
for (ArgumentList *it = ast->arguments; it; it = it->next) {
Result arg = expression(it->expression);
if (hasError)
return false;
IR::Expr *actual = argument(*arg);
*args_it = _function->New<IR::ExprList>();
(*args_it)->init(actual);
@ -1544,6 +1589,8 @@ bool Codegen::visit(NotExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
const unsigned r = _block->newTemp();
setLocation(move(_block->TEMP(r), unop(IR::OpNot, *expr, ast->notToken)), ast->notToken);
_expr.code = _block->TEMP(r);
@ -1601,6 +1648,8 @@ bool Codegen::visit(ObjectLiteral *ast)
QString name = it->assignment->name->asString();
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
Result value = expression(nv->value);
if (hasError)
return false;
ObjectPropertyValue &v = valueMap[name];
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value)) {
throwSyntaxError(nv->lastSourceLocation(),
@ -1731,6 +1780,8 @@ bool Codegen::visit(PostDecrementExpression *ast)
return false;
Result expr = expression(ast->base);
if (hasError)
return false;
if (!expr->isLValue()) {
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
return false;
@ -1757,6 +1808,8 @@ bool Codegen::visit(PostIncrementExpression *ast)
return false;
Result expr = expression(ast->base);
if (hasError)
return false;
if (!expr->isLValue()) {
throwReferenceError(ast->base->lastSourceLocation(), QStringLiteral("Invalid left-hand side expression in postfix operation"));
return false;
@ -1783,6 +1836,8 @@ bool Codegen::visit(PreDecrementExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
if (!expr->isLValue()) {
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
return false;
@ -1808,6 +1863,8 @@ bool Codegen::visit(PreIncrementExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
if (!expr->isLValue()) {
throwReferenceError(ast->expression->lastSourceLocation(), QStringLiteral("Prefix ++ operator applied to value that is not a reference."));
return false;
@ -1860,6 +1917,8 @@ bool Codegen::visit(TildeExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpCompl, *expr, ast->tildeToken)), ast->tildeToken);
_expr.code = _block->TEMP(t);
@ -1885,6 +1944,8 @@ bool Codegen::visit(TypeOfExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
IR::ExprList *args = _function->New<IR::ExprList>();
args->init(reference(*expr));
_expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
@ -1897,6 +1958,8 @@ bool Codegen::visit(UnaryMinusExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpUMinus, *expr, ast->minusToken)), ast->minusToken);
_expr.code = _block->TEMP(t);
@ -1909,6 +1972,8 @@ bool Codegen::visit(UnaryPlusExpression *ast)
return false;
Result expr = expression(ast->expression);
if (hasError)
return false;
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpUPlus, *expr, ast->plusToken)), ast->plusToken);
_expr.code = _block->TEMP(t);
@ -2224,7 +2289,10 @@ bool Codegen::visit(ForEachStatement *ast)
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
int objectToIterateOn = _block->newTemp();
move(_block->TEMP(objectToIterateOn), *expression(ast->expression));
Result expr = expression(ast->expression);
if (hasError)
return false;
move(_block->TEMP(objectToIterateOn), *expr);
IR::ExprList *args = _function->New<IR::ExprList>();
args->init(_block->TEMP(objectToIterateOn));
@ -2236,7 +2304,10 @@ bool Codegen::visit(ForEachStatement *ast)
_block = foreachbody;
int temp = _block->newTemp();
move(*expression(ast->initialiser), _block->TEMP(temp));
Result init = expression(ast->initialiser);
if (hasError)
return false;
move(*init, _block->TEMP(temp));
statement(ast->statement);
_block->JUMP(foreachin);
@ -2726,7 +2797,10 @@ bool Codegen::visit(WithStatement *ast)
_function->hasWith = true;
const int withObject = _block->newTemp();
_block->MOVE(_block->TEMP(withObject), *expression(ast->expression));
Result src = expression(ast->expression);
if (hasError)
return false;
_block->MOVE(_block->TEMP(withObject), *src);
// need an exception handler for with to cleanup the with scope
IR::BasicBlock *withExceptionHandler = _function->newBasicBlock(exceptionHandler());

View File

@ -50,6 +50,7 @@
#include <private/qqmltypeloader_p.h>
#include <private/qqmlengine_p.h>
#include <QQmlPropertyMap>
#include <QDateTime>
#include <QSaveFile>
#include <QFile>
#include <QFileInfo>
@ -57,6 +58,7 @@
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
#include <QCryptographicHash>
#include <algorithm>
@ -160,6 +162,16 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
}
}
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
Value *bigEndianConstants = new Value[data->constantTableSize];
const LEUInt64 *littleEndianConstants = data->constants();
for (uint i = 0; i < data->constantTableSize; ++i)
bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]);
constants = bigEndianConstants;
#else
constants = reinterpret_cast<const Value*>(data->constants());
#endif
linkBackendToEngine(engine);
if (data->indexOfRootFunction != -1)
@ -202,6 +214,9 @@ void CompilationUnit::unlink()
runtimeClasses = 0;
qDeleteAll(runtimeFunctions);
runtimeFunctions.clear();
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
delete [] constants;
#endif
}
void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
@ -290,6 +305,11 @@ bool CompilationUnit::saveToDisk(QString *errorString)
{
errorString->clear();
if (data->sourceTimeStamp == 0) {
*errorString = QStringLiteral("Missing time stamp for source file");
return false;
}
const QUrl unitUrl = url();
if (!unitUrl.isLocalFile()) {
*errorString = QStringLiteral("File has to be a local file.");
@ -330,20 +350,56 @@ bool CompilationUnit::saveToDisk(QString *errorString)
return true;
}
bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString)
{
if (!url.isLocalFile()) {
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
QScopedPointer<QFile> cacheFile(new QFile(url.toLocalFile() + QLatin1Char('c')));
const QString sourcePath = url.toLocalFile();
QScopedPointer<QFile> cacheFile(new QFile(sourcePath + QLatin1Char('c')));
if (!cacheFile->open(QIODevice::ReadOnly)) {
*errorString = cacheFile->errorString();
return false;
}
{
CompiledData::Unit header;
qint64 bytesRead = cacheFile->read(reinterpret_cast<char *>(&header), sizeof(header));
if (bytesRead != sizeof(header)) {
*errorString = QStringLiteral("File too small for the header fields");
return false;
}
if (strncmp(header.magic, CompiledData::magic_str, sizeof(header.magic))) {
*errorString = QStringLiteral("Magic bytes in the header do not match");
return false;
}
if (header.version != quint32(QV4_DATA_STRUCTURE_VERSION)) {
*errorString = QString::fromUtf8("V4 data structure version mismatch. Found %1 expected %2").arg(header.version, 0, 16).arg(QV4_DATA_STRUCTURE_VERSION, 0, 16);
return false;
}
if (header.qtVersion != quint32(QT_VERSION)) {
*errorString = QString::fromUtf8("Qt version mismatch. Found %1 expected %2").arg(header.qtVersion, 0, 16).arg(QT_VERSION, 0, 16);
return false;
}
{
QFileInfo sourceCode(sourcePath);
if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != header.sourceTimeStamp) {
*errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
return false;
}
}
}
// Data structure and qt version matched, so now we can access the rest of the file safely.
uchar *cacheData = cacheFile->map(/*offset*/0, cacheFile->size());
if (!cacheData) {
*errorString = cacheFile->errorString();
@ -353,13 +409,22 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, QString *errorString)
QScopedValueRollback<const Unit *> dataPtrChange(data, reinterpret_cast<const Unit *>(cacheData));
{
QFileInfo sourceCode(url.toLocalFile());
if (sourceCode.exists() && sourceCode.lastModified().toMSecsSinceEpoch() != data->sourceTimeStamp) {
*errorString = QStringLiteral("QML source file has a different time stamp than cached file.");
const QString foundArchitecture = stringAt(data->architectureIndex);
const QString expectedArchitecture = QSysInfo::buildAbi();
if (foundArchitecture != expectedArchitecture) {
*errorString = QString::fromUtf8("Architecture mismatch. Found %1 expected %2").arg(foundArchitecture).arg(expectedArchitecture);
return false;
}
}
{
const QString foundCodeGenerator = stringAt(data->codeGeneratorIndex);
const QString expectedCodeGenerator = iselFactory->codeGeneratorName;
if (foundCodeGenerator != expectedCodeGenerator) {
*errorString = QString::fromUtf8("Code generator mismatch. Found code generated by %1 but expected %2").arg(foundCodeGenerator).arg(expectedCodeGenerator);
return false;
}
}
if (!memoryMapCode(errorString))
return false;
@ -489,7 +554,7 @@ QString Binding::valueAsScriptString(const Unit *unit) const
/*!
Returns the property cache, if one alread exists. The cache is not referenced.
*/
QQmlPropertyCache *CompilationUnit::ResolvedTypeReference::propertyCache() const
QQmlPropertyCache *ResolvedTypeReference::propertyCache() const
{
if (type)
return typePropertyCache;
@ -500,7 +565,7 @@ QQmlPropertyCache *CompilationUnit::ResolvedTypeReference::propertyCache() const
/*!
Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
*/
QQmlPropertyCache *CompilationUnit::ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
QQmlPropertyCache *ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
{
if (typePropertyCache) {
return typePropertyCache;
@ -522,7 +587,7 @@ bool qtTypeInherits(const QMetaObject *mo) {
return false;
}
void CompilationUnit::ResolvedTypeReference::doDynamicTypeCheck()
void ResolvedTypeReference::doDynamicTypeCheck()
{
const QMetaObject *mo = 0;
if (typePropertyCache)
@ -533,6 +598,19 @@ void CompilationUnit::ResolvedTypeReference::doDynamicTypeCheck()
mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
{
for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
QQmlPropertyCache *pc = it.value()->createPropertyCache(engine);
bool ok = false;
hash->addData(pc->checksum(&ok));
if (!ok)
return false;
}
return true;
}
#endif
}

View File

@ -70,6 +70,9 @@
QT_BEGIN_NAMESPACE
// Bump this whenever the compiler data structures change in an incompatible way.
#define QV4_DATA_STRUCTURE_VERSION 0x01
class QIODevice;
class QQmlPropertyCache;
class QQmlPropertyData;
@ -88,6 +91,7 @@ struct Function;
}
struct Function;
class EvalISelFactory;
namespace CompiledData {
@ -597,11 +601,17 @@ static const char magic_str[] = "qv4cdata";
struct Unit
{
// DO NOT CHANGE THESE FIELDS EVER
char magic[8];
LEInt16 architecture;
LEInt16 version;
LEUInt32 version;
LEUInt32 qtVersion;
LEInt64 sourceTimeStamp;
LEUInt32 unitSize; // Size of the Unit and any depending data.
// END DO NOT CHANGE THESE FIELDS EVER
LEUInt32 architectureIndex; // string index to QSysInfo::buildAbi()
LEUInt32 codeGeneratorIndex;
char dependencyMD5Checksum[16];
enum : unsigned int {
IsJavascript = 0x1,
@ -681,8 +691,8 @@ struct Unit
const RegExp *regexpAt(int index) const {
return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
}
const QV4::Value *constants() const {
return reinterpret_cast<const QV4::Value*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
const LEUInt64 *constants() const {
return reinterpret_cast<const LEUInt64*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
}
const JSClassMember *jsClassAt(int idx, int *nMembers) const {
@ -753,6 +763,42 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
#ifndef V4_BOOTSTRAP
struct ResolvedTypeReference
{
ResolvedTypeReference()
: type(0)
, majorVersion(0)
, minorVersion(0)
, isFullyDynamicType(false)
{}
QQmlType *type;
QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
int majorVersion;
int minorVersion;
// Types such as QQmlPropertyMap can add properties dynamically at run-time and
// therefore cannot have a property cache installed when instantiated.
bool isFullyDynamicType;
QQmlPropertyCache *propertyCache() const;
QQmlPropertyCache *createPropertyCache(QQmlEngine *);
void doDynamicTypeCheck();
};
// map from name index
// While this could be a hash, a map is chosen here to provide a stable
// order, which is used to calculating a check-sum on dependent meta-objects.
struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
{
bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
};
#else
struct ResolvedTypeReferenceMap {};
#endif
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
@ -807,6 +853,9 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QHash<int, IdentifierHash<int>> namedObjectsPerComponentCache;
IdentifierHash<int> namedObjectsPerComponent(int componentObjectIndex);
// pointers either to data->constants() or little-endian memory copy.
const Value* constants;
void finalize(QQmlEnginePrivate *engine);
int totalBindingsCount; // Number of bindings used in this type
@ -814,33 +863,6 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
int totalObjectCount; // Number of objects explicitly instantiated
QVector<QQmlScriptData *> dependentScripts;
struct ResolvedTypeReference
{
ResolvedTypeReference()
: type(0)
, majorVersion(0)
, minorVersion(0)
, isFullyDynamicType(false)
{}
QQmlType *type;
QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
int majorVersion;
int minorVersion;
// Types such as QQmlPropertyMap can add properties dynamically at run-time and
// therefore cannot have a property cache installed when instantiated.
bool isFullyDynamicType;
QQmlPropertyCache *propertyCache() const;
QQmlPropertyCache *createPropertyCache(QQmlEngine *);
void doDynamicTypeCheck();
};
// map from name index
typedef QHash<int, ResolvedTypeReference*> ResolvedTypeReferenceMap;
ResolvedTypeReferenceMap resolvedTypes;
int metaTypeId;
@ -880,7 +902,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
void destroy() Q_DECL_OVERRIDE;
bool saveToDisk(QString *errorString);
bool loadFromDisk(const QUrl &url, QString *errorString);
bool loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString);
protected:
virtual void linkBackendToEngine(QV4::ExecutionEngine *engine) = 0;

View File

@ -43,6 +43,7 @@
#include <private/qv4string_p.h>
#include <private/qv4value_p.h>
#include <private/qv4alloca_p.h>
#include <wtf/MathExtras.h>
QV4::Compiler::StringTableGenerator::StringTableGenerator()
{
@ -247,8 +248,14 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
CompiledData::RegExp *regexpTable = reinterpret_cast<CompiledData::RegExp *>(dataPtr + unit->offsetToRegexpTable);
memcpy(regexpTable, regexps.constData(), regexps.size() * sizeof(*regexpTable));
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
ReturnedValue *constantTable = reinterpret_cast<ReturnedValue *>(dataPtr + unit->offsetToConstantTable);
memcpy(constantTable, constants.constData(), constants.size() * sizeof(ReturnedValue));
#else
CompiledData::LEUInt64 *constantTable = reinterpret_cast<CompiledData::LEUInt64 *>(dataPtr + unit->offsetToConstantTable);
for (int i = 0; i < constants.count(); ++i)
constantTable[i] = constants.at(i);
#endif
{
memcpy(dataPtr + jsClassDataOffset, jsClassData.constData(), jsClassData.size());
@ -352,17 +359,20 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::IR::Function *i
}
}
QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset) const
QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Compiler::JSUnitGenerator::GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset)
{
CompiledData::Unit unit;
memcpy(unit.magic, CompiledData::magic_str, sizeof(unit.magic));
unit.architecture = 0; // ###
unit.flags = QV4::CompiledData::Unit::IsJavascript;
unit.version = 1;
unit.functionTableSize = irModule->functions.size();
unit.version = QV4_DATA_STRUCTURE_VERSION;
unit.qtVersion = QT_VERSION;
unit.architectureIndex = registerString(QSysInfo::buildAbi());
unit.codeGeneratorIndex = registerString(codeGeneratorName);
memset(unit.dependencyMD5Checksum, 0, sizeof(unit.dependencyMD5Checksum));
quint32 nextOffset = sizeof(CompiledData::Unit);
unit.functionTableSize = irModule->functions.size();
unit.offsetToFunctionTable = nextOffset;
nextOffset += unit.functionTableSize * sizeof(uint);
@ -375,6 +385,9 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
nextOffset += unit.regexpTableSize * sizeof(CompiledData::RegExp);
unit.constantTableSize = constants.size();
// Ensure we load constants from well-aligned addresses into for example SSE registers.
nextOffset = static_cast<quint32>(WTF::roundUpToMultipleOf(16, nextOffset));
unit.offsetToConstantTable = nextOffset;
nextOffset += unit.constantTableSize * sizeof(ReturnedValue);

View File

@ -118,8 +118,9 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
void writeFunction(char *f, IR::Function *irFunction) const;
StringTableGenerator stringTable;
QString codeGeneratorName;
private:
CompiledData::Unit generateHeader(GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset) const;
CompiledData::Unit generateHeader(GeneratorOption option, QJsonPrivate::q_littleendian<quint32> *functionOffsets, uint *jsClassDataOffset);
IR::Module *irModule;

View File

@ -58,10 +58,17 @@
QT_BEGIN_NAMESPACE
#ifdef QT_NO_QML_DEBUGGER
#define MOTH_DEBUG_INSTR(F)
#else
#define MOTH_DEBUG_INSTR(F) \
F(Line, line) \
F(Debug, debug)
#endif
#define FOR_EACH_MOTH_INSTR(F) \
F(Ret, ret) \
F(Line, line) \
F(Debug, debug) \
MOTH_DEBUG_INSTR(F) \
F(LoadRuntimeString, loadRuntimeString) \
F(LoadRegExp, loadRegExp) \
F(LoadClosure, loadClosure) \
@ -174,6 +181,8 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Moth {
// When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h
struct Param {
// Params are looked up as follows:
// Constant: 0
@ -252,6 +261,8 @@ union Instr
MOTH_INSTR_HEADER
Param result;
};
#ifndef QT_NO_QML_DEBUGGING
struct instr_line {
MOTH_INSTR_HEADER
qint32 lineNumber;
@ -260,6 +271,8 @@ union Instr
MOTH_INSTR_HEADER
qint32 lineNumber;
};
#endif // QT_NO_QML_DEBUGGING
struct instr_loadRuntimeString {
MOTH_INSTR_HEADER
int stringId;

View File

@ -313,8 +313,8 @@ protected:
};
} // anonymous namespace
InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
: EvalInstructionSelection(execAllocator, module, jsGenerator)
InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
: EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory)
, qmlEngine(qmlEngine)
, _block(0)
, _codeStart(0)
@ -412,6 +412,7 @@ void InstructionSelection::run(int functionIndex)
if (s->location.startLine != currentLine) {
blockNeedsDebugInstruction = false;
currentLine = s->location.startLine;
#ifndef QT_NO_QML_DEBUGGER
if (irModule->debugMode) {
Instruction::Debug debug;
debug.lineNumber = currentLine;
@ -421,6 +422,7 @@ void InstructionSelection::run(int functionIndex)
line.lineNumber = currentLine;
addInstruction(line);
}
#endif
}
}
@ -1092,6 +1094,17 @@ void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint
}
}
void InstructionSelection::addDebugInstruction()
{
#ifndef QT_NO_QML_DEBUGGER
if (blockNeedsDebugInstruction) {
Instruction::Debug debug;
debug.lineNumber = -int(currentLine);
addInstruction(debug);
}
#endif
}
void InstructionSelection::visitJump(IR::Jump *s)
{
if (s->target == _nextBlock)
@ -1099,11 +1112,7 @@ void InstructionSelection::visitJump(IR::Jump *s)
if (_removableJumps.contains(s))
return;
if (blockNeedsDebugInstruction) {
Instruction::Debug debug;
debug.lineNumber = -int(currentLine);
addInstruction(debug);
}
addDebugInstruction();
Instruction::Jump jump;
jump.offset = 0;
@ -1114,11 +1123,7 @@ void InstructionSelection::visitJump(IR::Jump *s)
void InstructionSelection::visitCJump(IR::CJump *s)
{
if (blockNeedsDebugInstruction) {
Instruction::Debug debug;
debug.lineNumber = -int(currentLine);
addInstruction(debug);
}
addDebugInstruction();
Param condition;
if (IR::Temp *t = s->cond->asTemp()) {
@ -1153,12 +1158,8 @@ void InstructionSelection::visitCJump(IR::CJump *s)
void InstructionSelection::visitRet(IR::Ret *s)
{
if (blockNeedsDebugInstruction) {
// this is required so stepOut will always be guaranteed to stop in every stack frame
Instruction::Debug debug;
debug.lineNumber = -int(currentLine);
addInstruction(debug);
}
// this is required so stepOut will always be guaranteed to stop in every stack frame
addDebugInstruction();
Instruction::Ret ret;
ret.result = getParam(s->expr);

View File

@ -80,7 +80,7 @@ class Q_QML_EXPORT InstructionSelection:
public EvalInstructionSelection
{
public:
InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory);
~InstructionSelection();
virtual void run(int functionIndex);
@ -177,6 +177,8 @@ private:
template <int Instr>
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
inline void addDebugInstruction();
ptrdiff_t addInstructionHelper(Instr::Type type, Instr &instr);
void patchJumpAddresses();
QByteArray squeezeCode() const;
@ -205,10 +207,11 @@ private:
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
ISelFactory() : EvalISelFactory(QStringLiteral("moth")) {}
virtual ~ISelFactory() {}
virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
{ return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
virtual bool jitCompileRegexps() const
EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) Q_DECL_OVERRIDE Q_DECL_FINAL
{ return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); }
bool jitCompileRegexps() const Q_DECL_OVERRIDE Q_DECL_FINAL
{ return false; }
QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading() Q_DECL_OVERRIDE;

View File

@ -52,7 +52,7 @@
using namespace QV4;
using namespace QV4::IR;
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
: useFastLookups(true)
, useTypeInference(true)
, executableAllocator(execAllocator)
@ -67,6 +67,7 @@ EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *exe
Q_ASSERT(execAllocator);
#endif
Q_ASSERT(module);
jsGenerator->codeGeneratorName = iselFactory->codeGeneratorName;
}
EvalInstructionSelection::~EvalInstructionSelection()

View File

@ -65,13 +65,14 @@ class QQmlEnginePrivate;
namespace QV4 {
class EvalISelFactory;
class ExecutableAllocator;
struct Function;
class Q_QML_PRIVATE_EXPORT EvalInstructionSelection
{
public:
EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory);
virtual ~EvalInstructionSelection() = 0;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile(bool generateUnitData = true);
@ -104,10 +105,13 @@ protected:
class Q_QML_PRIVATE_EXPORT EvalISelFactory
{
public:
EvalISelFactory(const QString &codeGeneratorName) : codeGeneratorName(codeGeneratorName) {}
virtual ~EvalISelFactory() = 0;
virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) = 0;
virtual bool jitCompileRegexps() const = 0;
virtual QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading() = 0;
const QString codeGeneratorName;
};
namespace IR {

View File

@ -934,7 +934,11 @@ struct Q_QML_PRIVATE_EXPORT Module {
QString fileName;
qint64 sourceTimeStamp;
bool isQmlModule; // implies rootFunction is always 0
#ifdef QT_NO_QML_DEBUGGER
static const bool debugMode = false;
#else
bool debugMode;
#endif
Function *newFunction(const QString &name, Function *outer);
@ -942,8 +946,12 @@ struct Q_QML_PRIVATE_EXPORT Module {
: rootFunction(0)
, sourceTimeStamp(0)
, isQmlModule(false)
#ifndef QT_NO_QML_DEBUGGER
, debugMode(debugMode)
{}
#else
{ Q_UNUSED(debugMode); }
#endif
~Module();
void setFileName(const QString &name);

View File

@ -1,21 +1,28 @@
contains(QT_CONFIG, no-qml-debug):DEFINES += QT_NO_QML_DEBUGGER
contains(QT_CONFIG, no-qml-debug) {
DEFINES += QT_NO_QML_DEBUGGER
MODULE_DEFINES += QT_NO_QML_DEBUGGER
} else {
HEADERS += \
$$PWD/qqmldebugpluginmanager_p.h \
$$PWD/qqmldebugservicefactory_p.h
SOURCES += \
$$PWD/qqmldebug.cpp \
$$PWD/qqmldebugconnector.cpp \
$$PWD/qqmldebugservice.cpp \
$$PWD/qqmldebugserviceinterfaces.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
$$PWD/qqmlprofiler.cpp
SOURCES += \
$$PWD/qqmldebug.cpp \
$$PWD/qqmldebugconnector.cpp \
$$PWD/qqmldebugservice.cpp \
$$PWD/qqmlabstractprofileradapter.cpp \
$$PWD/qqmlmemoryprofiler.cpp \
$$PWD/qqmlprofiler.cpp \
$$PWD/qqmldebugserviceinterfaces.cpp
}
HEADERS += \
$$PWD/qqmldebugconnector_p.h \
$$PWD/qqmldebugpluginmanager_p.h \
$$PWD/qqmldebugservice_p.h \
$$PWD/qqmldebugservicefactory_p.h \
$$PWD/qqmldebugserviceinterfaces_p.h \
$$PWD/qqmldebugstatesdelegate_p.h \
$$PWD/qqmldebug.h \
$$PWD/qqmlmemoryprofiler_p.h \
$$PWD/qqmlprofilerdefinitions_p.h \
$$PWD/qqmlabstractprofileradapter_p.h \
$$PWD/qqmlprofiler_p.h

View File

@ -59,6 +59,8 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_QML_DEBUGGER
class QQmlProfilerService;
class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
@ -114,6 +116,8 @@ public:
#define QQmlAbstractProfilerAdapterFactory_iid "org.qt-project.Qt.QQmlAbstractProfilerAdapterFactory"
#endif // QT_NO_QML_DEBUGGER
QT_END_NAMESPACE
#endif // QQMLABSTRACTPROFILERADAPTER_P_H

View File

@ -47,15 +47,11 @@ QT_BEGIN_NAMESPACE
QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
{
#ifndef QQML_NO_DEBUG_PROTOCOL
if (!QQmlEnginePrivate::qml_debugging_enabled
&& printWarning) {
qDebug("QML debugging is enabled. Only use this in a safe environment.");
}
QQmlEnginePrivate::qml_debugging_enabled = true;
#else
Q_UNUSED(printWarning);
#endif
}
/*!
@ -105,11 +101,7 @@ QStringList QQmlDebuggingEnabler::profilerServices()
*/
void QQmlDebuggingEnabler::setServices(const QStringList &services)
{
#ifndef QQML_NO_DEBUG_PROTOCOL
QQmlDebugConnector::setServices(services);
#else
Q_UNUSED(services);
#endif
}
/*!
@ -172,16 +164,9 @@ bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName,
bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName,
const QVariantHash &configuration)
{
#ifndef QQML_NO_DEBUG_PROTOCOL
QQmlDebugConnector::setPluginKey(pluginName);
QQmlDebugConnector *connector = QQmlDebugConnector::instance();
if (connector)
return connector->open(configuration);
#else
Q_UNUSED(pluginName);
Q_UNUSED(configuration);
#endif
return false;
return connector ? connector->open(configuration) : false;
}
QT_END_NAMESPACE

View File

@ -46,6 +46,7 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_QML_DEBUGGER
struct Q_QML_EXPORT QQmlDebuggingEnabler
{
@ -77,6 +78,8 @@ static QQmlDebuggingEnabler qQmlEnableDebuggingHelper(false);
static QQmlDebuggingEnabler qQmlEnableDebuggingHelper(true);
#endif
#endif
QT_END_NAMESPACE
#endif // QQMLDEBUG_H

View File

@ -59,6 +59,29 @@
QT_BEGIN_NAMESPACE
#ifdef QT_NO_QML_DEBUGGER
class Q_QML_PRIVATE_EXPORT QQmlDebugConnector
{
public:
static QQmlDebugConnector *instance() { return nullptr; }
template<class Service>
static Service *service() { return nullptr; }
bool hasEngine(QJSEngine *) const { return false; }
void addEngine(QJSEngine *) {}
void removeEngine(QJSEngine *) {}
bool open(const QVariantHash &configuration = QVariantHash())
{
Q_UNUSED(configuration);
return false;
}
};
#else
class QQmlDebugService;
class Q_QML_PRIVATE_EXPORT QQmlDebugConnector : public QObject
{
@ -106,6 +129,8 @@ public:
#define QQmlDebugConnectorFactory_iid "org.qt-project.Qt.QQmlDebugConnectorFactory"
#endif
QT_END_NAMESPACE
#endif // QQMLDEBUGCONNECTOR_H

View File

@ -132,7 +132,6 @@ public:
int nextId;
private slots:
void remove(QObject *obj);
};
}
@ -163,7 +162,7 @@ int QQmlDebugService::idForObject(QObject *object)
int id = hash->nextId++;
hash->ids.insert(id, object);
iter = hash->objects.insert(object, id);
connect(object, SIGNAL(destroyed(QObject*)), hash, SLOT(remove(QObject*)));
connect(object, &QObject::destroyed, hash, &ObjectReferenceHash::remove);
}
return iter.value();
}
@ -176,36 +175,6 @@ const QHash<int, QObject *> &QQmlDebugService::objectsForIds()
return objectReferenceHash()->ids;
}
void QQmlDebugService::stateAboutToBeChanged(State)
{
}
void QQmlDebugService::stateChanged(State)
{
}
void QQmlDebugService::messageReceived(const QByteArray &)
{
}
void QQmlDebugService::engineAboutToBeAdded(QJSEngine *engine)
{
emit attachedToEngine(engine);
}
void QQmlDebugService::engineAboutToBeRemoved(QJSEngine *engine)
{
emit detachedFromEngine(engine);
}
void QQmlDebugService::engineAdded(QJSEngine *)
{
}
void QQmlDebugService::engineRemoved(QJSEngine *)
{
}
QT_END_NAMESPACE
#include "qqmldebugservice.moc"

View File

@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_QML_DEBUGGER
class QJSEngine;
class QQmlDebugServicePrivate;
@ -65,7 +67,6 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQmlDebugService)
Q_DISABLE_COPY(QQmlDebugService)
public:
~QQmlDebugService();
@ -77,14 +78,15 @@ public:
State state() const;
void setState(State newState);
virtual void stateAboutToBeChanged(State);
virtual void stateChanged(State);
virtual void messageReceived(const QByteArray &);
virtual void stateAboutToBeChanged(State) {}
virtual void stateChanged(State) {}
virtual void messageReceived(const QByteArray &) {}
virtual void engineAboutToBeAdded(QJSEngine *);
virtual void engineAboutToBeRemoved(QJSEngine *);
virtual void engineAdded(QJSEngine *);
virtual void engineRemoved(QJSEngine *);
virtual void engineAboutToBeAdded(QJSEngine *engine) { emit attachedToEngine(engine); }
virtual void engineAboutToBeRemoved(QJSEngine *engine) { emit detachedFromEngine(engine); }
virtual void engineAdded(QJSEngine *) {}
virtual void engineRemoved(QJSEngine *) {}
static const QHash<int, QObject *> &objectsForIds();
static int idForObject(QObject *);
@ -101,6 +103,8 @@ signals:
void messagesToClient(const QString &name, const QList<QByteArray> &messages);
};
#endif
QT_END_NAMESPACE
#endif // QQMLDEBUGSERVICE_H

View File

@ -62,7 +62,46 @@
QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService
class QWindow;
class QQuickWindow;
#ifdef QT_NO_QML_DEBUGGER
struct QV4DebugService
{
void signalEmitted(const QString &) {}
};
struct QQmlProfilerService
{
void startProfiling(QJSEngine *engine, quint64 features = std::numeric_limits<quint64>::max())
{
Q_UNUSED(engine);
Q_UNUSED(features);
}
void stopProfiling(QJSEngine *) {}
};
struct QQmlEngineDebugService
{
void objectCreated(QJSEngine *, QObject *) {}
virtual void setStatesDelegate(QQmlDebugStatesDelegate *) {}
};
struct QQmlInspectorService {
void addWindow(QQuickWindow *) {}
void setParentWindow(QQuickWindow *, QWindow *) {}
void removeWindow(QQuickWindow *) {}
};
struct QDebugMessageService {};
struct QQmlEngineControlService {};
struct QQmlNativeDebugService {};
#else
class Q_QML_PRIVATE_EXPORT QV4DebugService : public QQmlDebugService
{
Q_OBJECT
public:
@ -77,7 +116,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService
class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlDebugService
{
Q_OBJECT
public:
@ -99,7 +138,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService
class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : public QQmlDebugService
{
Q_OBJECT
public:
@ -117,9 +156,7 @@ protected:
QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; }
};
class QWindow;
class QQuickWindow;
class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService
class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService
{
Q_OBJECT
public:
@ -136,7 +173,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
class Q_QML_PRIVATE_EXPORT QDebugMessageService : protected QQmlDebugService
class Q_QML_PRIVATE_EXPORT QDebugMessageService : public QQmlDebugService
{
Q_OBJECT
public:
@ -151,7 +188,7 @@ protected:
QQmlDebugService(s_key, version, parent) {}
};
class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : protected QQmlDebugService
class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : public QQmlDebugService
{
Q_OBJECT
public:
@ -165,7 +202,7 @@ protected:
};
class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : protected QQmlDebugService
class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : public QQmlDebugService
{
Q_OBJECT
@ -178,6 +215,8 @@ protected:
static const QString s_key;
};
#endif
QT_END_NAMESPACE
#endif // QQMLDEBUGSERVICEINTERFACES_P_H

View File

@ -57,6 +57,11 @@
QT_BEGIN_NAMESPACE
#ifdef QT_NO_QML_DEBUGGER
class QQmlDebugStatesDelegate {};
#else
class QQmlContext;
class QQmlProperty;
@ -90,6 +95,8 @@ private:
Q_DISABLE_COPY(QQmlDebugStatesDelegate)
};
#endif
QT_END_NAMESPACE
#endif // QQMLDEBUGSTATESDELEGATE_P_H

View File

@ -55,6 +55,13 @@
QT_BEGIN_NAMESPACE
#ifdef QT_NO_QML_DEBUGGER
#define QML_MEMORY_SCOPE_URL(url)
#define QML_MEMORY_SCOPE_STRING(s)
#else
class QUrl;
class Q_QML_PRIVATE_EXPORT QQmlMemoryScope
@ -83,5 +90,7 @@ public:
#define QML_MEMORY_SCOPE_URL(url) QQmlMemoryScope _qml_memory_scope(url)
#define QML_MEMORY_SCOPE_STRING(s) QQmlMemoryScope _qml_memory_scope(s)
#endif
QT_END_NAMESPACE
#endif // QQMLMEMORYPROFILER_H

View File

@ -63,6 +63,54 @@
QT_BEGIN_NAMESPACE
#ifdef QT_NO_QML_DEBUGGER
#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)
#define Q_QML_PROFILE(feature, profiler, Method)
#define Q_QML_OC_PROFILE(member, Code)
struct QQmlProfiler {};
struct QQmlBindingProfiler
{
QQmlBindingProfiler(quintptr, QQmlBinding *, QV4::FunctionObject *) {}
};
struct QQmlHandlingSignalProfiler
{
QQmlHandlingSignalProfiler(quintptr, QQmlBoundSignalExpression *) {}
};
struct QQmlCompilingProfiler
{
QQmlCompilingProfiler(quintptr, QQmlDataBlob *) {}
};
struct QQmlVmeProfiler {
QQmlVmeProfiler() {}
void init(quintptr, int) {}
const QV4::CompiledData::Object *pop() { return nullptr; }
void push(const QV4::CompiledData::Object *) {}
static const quintptr profiler = 0;
};
struct QQmlObjectCreationProfiler
{
QQmlObjectCreationProfiler(quintptr, const QV4::CompiledData::Object *) {}
void update(QV4::CompiledData::CompilationUnit *, const QV4::CompiledData::Object *,
const QString &, const QUrl &) {}
};
struct QQmlObjectCompletionProfiler
{
QQmlObjectCompletionProfiler(QQmlVmeProfiler *) {}
};
#else
#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)\
if (profiler && (profiler->featuresEnabled & (1 << feature))) {\
Code;\
@ -72,6 +120,9 @@ QT_BEGIN_NAMESPACE
#define Q_QML_PROFILE(feature, profiler, Method)\
Q_QML_PROFILE_IF_ENABLED(feature, profiler, profiler->Method)
#define Q_QML_OC_PROFILE(member, Code)\
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
// This struct is somewhat dangerous to use:
// The messageType is a bit field. You can pack multiple messages into
// one object, e.g. RangeStart and RangeLocation. Each one will be read
@ -94,7 +145,7 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions
Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE);
class QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
class Q_QML_PRIVATE_EXPORT QQmlProfiler : public QObject, public QQmlProfilerDefinitions {
Q_OBJECT
public:
@ -250,7 +301,6 @@ public:
return reinterpret_cast<quintptr>(pointer);
}
public slots:
void startProfiling(quint64 features);
void stopProfiling();
void reportData(bool trackLocations);
@ -349,9 +399,6 @@ private:
QFiniteStack<const QV4::CompiledData::Object *> ranges;
};
#define Q_QML_OC_PROFILE(member, Code)\
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code)
class QQmlObjectCreationProfiler {
public:
@ -399,4 +446,6 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(QVector<QQmlProfilerData>)
Q_DECLARE_METATYPE(QQmlProfiler::LocationHash)
#endif // QT_NO_QML_DEBUGGER
#endif // QQMLPROFILER_P_H

View File

@ -56,6 +56,8 @@
QT_BEGIN_NAMESPACE
#ifndef QT_NO_QML_DEBUGGER
struct QQmlProfilerDefinitions {
enum Message {
Event,
@ -161,6 +163,8 @@ struct QQmlProfilerDefinitions {
};
};
#endif // QT_NO_QML_DEBUGGER
QT_END_NAMESPACE
#endif

View File

@ -381,6 +381,8 @@ Message {
}
\endqml
To use an enum as a \l {QFlags}{flags} type in QML, see \l Q_FLAG().
\note The names of enum values must begin with a capital letter in order to
be accessible from QML.

View File

@ -729,7 +729,7 @@ Rectangle {
MouseArea {
anchors.fill: parent
onPressed: root.activated(mouse.x, mouse.y)
onRelased: root.deactivated()
onReleased: root.deactivated()
}
}
\endqml

View File

@ -148,8 +148,7 @@ bool CompilationUnit::memoryMapCode(QString *errorString)
const Assembler::VoidType Assembler::Void;
Assembler::Assembler(InstructionSelection *isel, IR::Function* function, QV4::ExecutableAllocator *executableAllocator)
: _constTable(this)
, _function(function)
: _function(function)
, _nextBlock(0)
, _executableAllocator(executableAllocator)
, _isel(isel)
@ -279,6 +278,19 @@ Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &s
return Pointer(reg, id * sizeof(QV4::String*));
}
Assembler::Address Assembler::loadConstant(IR::Const *c, RegisterID baseReg)
{
return loadConstant(convertToValue(c), baseReg);
}
Assembler::Address Assembler::loadConstant(const Primitive &v, RegisterID baseReg)
{
loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), baseReg);
loadPtr(Address(baseReg, qOffsetOf(QV4::Heap::ExecutionContext, constantTable)), baseReg);
const int index = _isel->jsUnitGenerator()->registerConstant(v.asReturnedValue());
return Address(baseReg, index * sizeof(QV4::Value));
}
void Assembler::loadStringRef(RegisterID reg, const QString &string)
{
const int id = _isel->registerString(string);

View File

@ -89,7 +89,6 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit
// Coderef + execution engine
QVector<JSC::MacroAssemblerCodeRef> codeRefs;
QList<QVector<QV4::Primitive> > constantValues;
};
struct LookupCall {
@ -105,7 +104,7 @@ struct LookupCall {
struct RuntimeCall {
JSC::MacroAssembler::Address addr;
inline RuntimeCall(uint offset = INT_MIN);
inline RuntimeCall(uint offset = uint(INT_MIN));
bool isValid() const { return addr.offset >= 0; }
};
@ -297,22 +296,6 @@ public:
int savedRegCount;
};
class ConstantTable
{
public:
ConstantTable(Assembler *as): _as(as) {}
int add(const QV4::Primitive &v);
Address loadValueAddress(IR::Const *c, RegisterID baseReg);
Address loadValueAddress(const QV4::Primitive &v, RegisterID baseReg);
void finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel);
private:
Assembler *_as;
QVector<QV4::Primitive> _values;
QVector<DataLabelPtr> _toPatch;
};
struct VoidType { VoidType() {} };
static const VoidType Void;
@ -382,6 +365,8 @@ public:
Pointer loadTempAddress(IR::Temp *t);
Pointer loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al);
Pointer loadStringAddress(RegisterID reg, const QString &string);
Address loadConstant(IR::Const *c, RegisterID baseReg);
Address loadConstant(const Primitive &v, RegisterID baseReg);
void loadStringRef(RegisterID reg, const QString &string);
Pointer stackSlotPointer(IR::Temp *t) const
{
@ -1029,7 +1014,7 @@ public:
move(TrustedImm64(i), ReturnValueRegister);
move64ToDouble(ReturnValueRegister, target);
#else
JSC::MacroAssembler::loadDouble(constantTable().loadValueAddress(c, ScratchRegister), target);
JSC::MacroAssembler::loadDouble(loadConstant(c, ScratchRegister), target);
#endif
return target;
}
@ -1093,7 +1078,7 @@ public:
// it's not in signed int range, so load it as a double, and truncate it down
loadDouble(addr, FPGpr0);
Address inversionAddress = constantTable().loadValueAddress(QV4::Primitive::fromDouble(double(INT_MAX) + 1), scratchReg);
Address inversionAddress = loadConstant(QV4::Primitive::fromDouble(double(INT_MAX) + 1), scratchReg);
subDouble(inversionAddress, FPGpr0);
Jump canNeverHappen = branchTruncateDoubleToUint32(FPGpr0, scratchReg);
canNeverHappen.link(this);
@ -1111,14 +1096,12 @@ public:
void setStackLayout(int maxArgCountForBuiltins, int regularRegistersToSave, int fpRegistersToSave);
const StackLayout &stackLayout() const { return *_stackLayout.data(); }
ConstantTable &constantTable() { return _constTable; }
Label exceptionReturnLabel;
IR::BasicBlock * catchBlock;
QVector<Jump> exceptionPropagationJumps;
private:
QScopedPointer<const StackLayout> _stackLayout;
ConstantTable _constTable;
IR::Function *_function;
QHash<IR::BasicBlock *, Label> _addrs;
QHash<IR::BasicBlock *, QVector<Jump> > _patches;

View File

@ -162,7 +162,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X + constant -> Y = X; Y += [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->addDouble(addr, targetReg);
break;
}
@ -184,7 +184,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X * constant -> Y = X; Y *= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->mulDouble(addr, targetReg);
break;
}
@ -203,7 +203,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X - constant -> Y = X; Y -= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->subDouble(addr, targetReg);
break;
}
@ -231,7 +231,7 @@ void Binop::doubleBinop(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
#if CPU(X86)
if (IR::Const *c = rhs->asConst()) { // Y = X / constant -> Y = X; Y /= [constant-address]
as->moveDouble(as->toDoubleRegister(lhs, targetReg), targetReg);
Assembler::Address addr = as->constantTable().loadValueAddress(c, Assembler::ScratchRegister);
Assembler::Address addr = as->loadConstant(c, Assembler::ScratchRegister);
as->divDouble(addr, targetReg);
break;
}

View File

@ -177,7 +177,6 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
linkBuffer.patch(label, linkBuffer.locationOf(target));
}
}
_constTable.finalize(linkBuffer, _isel);
*codeSize = linkBuffer.offsetOf(endOfCode);
@ -258,8 +257,8 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
return codeRef;
}
InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator)
: EvalInstructionSelection(execAllocator, module, jsGenerator)
InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
: EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory)
, _block(0)
, _as(0)
, compilationUnit(new CompilationUnit)
@ -370,16 +369,6 @@ void InstructionSelection::run(int functionIndex)
qSwap(_removableJumps, removableJumps);
}
const void *InstructionSelection::addConstantTable(QVector<Primitive> *values)
{
compilationUnit->constantValues.append(*values);
values->clear();
QVector<QV4::Primitive> &finalValues = compilationUnit->constantValues.last();
finalValues.squeeze();
return finalValues.constData();
}
QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backendCompileStep()
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
@ -1719,38 +1708,6 @@ bool operator==(const Primitive &v1, const Primitive &v2)
} // QV4 namespace
QT_END_NAMESPACE
int Assembler::ConstantTable::add(const Primitive &v)
{
int idx = _values.indexOf(v);
if (idx == -1) {
idx = _values.size();
_values.append(v);
}
return idx;
}
Assembler::Address Assembler::ConstantTable::loadValueAddress(IR::Const *c, RegisterID baseReg)
{
return loadValueAddress(convertToValue(c), baseReg);
}
Assembler::Address Assembler::ConstantTable::loadValueAddress(const Primitive &v, RegisterID baseReg)
{
_toPatch.append(_as->moveWithPatch(TrustedImmPtr(0), baseReg));
Address addr(baseReg);
addr.offset = add(v) * sizeof(QV4::Primitive);
Q_ASSERT(addr.offset >= 0);
return addr;
}
void Assembler::ConstantTable::finalize(JSC::LinkBuffer &linkBuffer, InstructionSelection *isel)
{
const void *tablePtr = isel->addConstantTable(&_values);
foreach (DataLabelPtr label, _toPatch)
linkBuffer.patch(label, const_cast<void *>(tablePtr));
}
bool InstructionSelection::visitCJumpDouble(IR::AluOp op, IR::Expr *left, IR::Expr *right,
IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
{

View File

@ -76,12 +76,11 @@ class Q_QML_EXPORT InstructionSelection:
public EvalInstructionSelection
{
public:
InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory);
~InstructionSelection();
virtual void run(int functionIndex);
const void *addConstantTable(QVector<QV4::Primitive> *values);
protected:
virtual QQmlRefPointer<QV4::CompiledData::CompilationUnit> backendCompileStep();
@ -285,12 +284,13 @@ private:
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
ISelFactory() : EvalISelFactory(QStringLiteral("jit")) {}
virtual ~ISelFactory() {}
virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
{ return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
virtual bool jitCompileRegexps() const
EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) Q_DECL_OVERRIDE Q_DECL_FINAL
{ return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator, this); }
bool jitCompileRegexps() const Q_DECL_OVERRIDE Q_DECL_FINAL
{ return true; }
QQmlRefPointer<CompiledData::CompilationUnit> createUnitForLoading() Q_DECL_OVERRIDE;
QQmlRefPointer<CompiledData::CompilationUnit> createUnitForLoading() Q_DECL_OVERRIDE Q_DECL_FINAL;
};
} // end of namespace JIT

View File

@ -6,7 +6,6 @@ SOURCES += \
$$PWD/qv4engine.cpp \
$$PWD/qv4context.cpp \
$$PWD/qv4persistent.cpp \
$$PWD/qv4debugging.cpp \
$$PWD/qv4lookup.cpp \
$$PWD/qv4identifier.cpp \
$$PWD/qv4identifiertable.cpp \
@ -40,11 +39,12 @@ SOURCES += \
$$PWD/qv4include.cpp \
$$PWD/qv4qobjectwrapper.cpp \
$$PWD/qv4vme_moth.cpp \
$$PWD/qv4profiling.cpp \
$$PWD/qv4arraybuffer.cpp \
$$PWD/qv4typedarray.cpp \
$$PWD/qv4dataview.cpp
!contains(QT_CONFIG, no-qml-debug): SOURCES += $$PWD/qv4profiling.cpp
HEADERS += \
$$PWD/qv4global_p.h \
$$PWD/qv4engine_p.h \

View File

@ -73,6 +73,7 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi
c->compilationUnit = function->function()->compilationUnit;
c->lookups = c->compilationUnit->runtimeLookups;
c->constantTable = c->compilationUnit->constants;
c->locals = (Value *)((quintptr(c + 1) + 7) & ~7);
const CompiledData::Function *compiledFunction = function->function()->compiledFunction;
@ -172,6 +173,7 @@ Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with)
outer = outerContext;
callData = outer->callData;
lookups = outer->lookups;
constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
withObject = with;
@ -184,6 +186,7 @@ Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *excepti
strictMode = outer->strictMode;
callData = outer->callData;
lookups = outer->lookups;
constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
this->exceptionVarName = exceptionVarName;
@ -197,6 +200,7 @@ Heap::QmlContext::QmlContext(QV4::ExecutionContext *outerContext, QV4::QmlContex
strictMode = false;
callData = outer->callData;
lookups = outer->lookups;
constantTable = outer->constantTable;
compilationUnit = outer->compilationUnit;
this->qml = qml->d();

View File

@ -108,6 +108,7 @@ struct ExecutionContext : Base {
ExecutionEngine *engine;
Pointer<ExecutionContext> outer;
Lookup *lookups;
const QV4::Value *constantTable;
CompiledData::CompilationUnit *compilationUnit;
ContextType type : 8;
@ -118,9 +119,10 @@ struct ExecutionContext : Base {
inline
ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
: engine(engine)
, outer(0)
, lookups(0)
, compilationUnit(0)
, outer(nullptr)
, lookups(nullptr)
, constantTable(nullptr)
, compilationUnit(nullptr)
, type(t)
, strictMode(false)
, lineNumber(-1)

View File

@ -1,60 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qv4debugging_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4function_p.h"
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
#include "qv4script_p.h"
#include "qv4identifier_p.h"
#include "qv4string_p.h"
#include "qv4objectiterator_p.h"
#include <iostream>
#include <algorithm>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonValue>
QT_BEGIN_NAMESPACE
QT_END_NAMESPACE

View File

@ -59,6 +59,19 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Debugging {
#ifdef QT_NO_QML_DEBUGGER
struct Debugger
{
bool pauseAtNextOpportunity() const { return false; }
void maybeBreakAtInstruction() {}
void enteringFunction() {}
void leavingFunction(const ReturnedValue &) {}
void aboutToThrow() {}
};
#else
class Q_QML_EXPORT Debugger : public QObject
{
Q_OBJECT
@ -72,6 +85,8 @@ public:
virtual void aboutToThrow() = 0;
};
#endif // QT_NO_QML_DEBUGGING
} // namespace Debugging
} // namespace QV4

View File

@ -136,8 +136,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, currentContext(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, debugger(0)
, profiler(0)
, globalCode(0)
, v8Engine(0)
, argumentsAccessors(0)
@ -145,6 +143,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
#ifndef QT_NO_QML_DEBUGGER
, m_debugger(0)
, m_profiler(0)
#endif
{
if (maxCallDepth == -1) {
bool ok = false;
@ -442,10 +444,12 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
ExecutionEngine::~ExecutionEngine()
{
delete debugger;
debugger = 0;
delete profiler;
profiler = 0;
#ifndef QT_NO_QML_DEBUGGER
delete m_debugger;
m_debugger = 0;
delete m_profiler;
m_profiler = 0;
#endif
delete m_multiplyWrappedQObjects;
m_multiplyWrappedQObjects = 0;
delete identifierTable;
@ -467,17 +471,19 @@ ExecutionEngine::~ExecutionEngine()
delete [] argumentsAccessors;
}
void ExecutionEngine::setDebugger(Debugging::Debugger *debugger_)
#ifndef QT_NO_QML_DEBUGGER
void ExecutionEngine::setDebugger(Debugging::Debugger *debugger)
{
Q_ASSERT(!debugger);
debugger = debugger_;
Q_ASSERT(!m_debugger);
m_debugger = debugger;
}
void ExecutionEngine::enableProfiler()
void ExecutionEngine::setProfiler(Profiling::Profiler *profiler)
{
Q_ASSERT(!profiler);
profiler = new QV4::Profiling::Profiler(this);
Q_ASSERT(!m_profiler);
m_profiler = profiler;
}
#endif // QT_NO_QML_DEBUGGER
void ExecutionEngine::initRootContext()
{
@ -910,8 +916,8 @@ ReturnedValue ExecutionEngine::throwError(const Value &value)
else
exceptionStackTrace = stackTrace();
if (debugger)
debugger->aboutToThrow();
if (QV4::Debugging::Debugger *debug = debugger())
debug->aboutToThrow();
return Encode::undefined();
}

View File

@ -137,9 +137,6 @@ public:
IdentifierTable *identifierTable;
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
Object *globalObject;
Function *globalCode;
@ -382,8 +379,19 @@ public:
ExecutionEngine(EvalISelFactory *iselFactory = 0);
~ExecutionEngine();
#ifdef QT_NO_QML_DEBUGGER
QV4::Debugging::Debugger *debugger() const { return nullptr; }
QV4::Profiling::Profiler *profiler() const { return nullptr; }
void setDebugger(Debugging::Debugger *) {}
void setProfiler(Profiling::Profiler *) {}
#else
QV4::Debugging::Debugger *debugger() const { return m_debugger; }
QV4::Profiling::Profiler *profiler() const { return m_profiler; }
void setDebugger(Debugging::Debugger *debugger);
void enableProfiler();
void setProfiler(Profiling::Profiler *profiler);
#endif // QT_NO_QML_DEBUGGER
ExecutionContext *pushGlobalContext();
void pushContext(Heap::ExecutionContext *context);
@ -484,6 +492,11 @@ public:
private:
void failStackLimitCheck(Scope &scope);
#ifndef QT_NO_QML_DEBUGGER
QV4::Debugging::Debugger *m_debugger;
QV4::Profiling::Profiler *m_profiler;
#endif
};
// This is a trick to tell the code generators that functions taking a NoThrowContext won't

View File

@ -283,7 +283,7 @@ void FunctionCtor::construct(const Managed *that, Scope &scope, CallData *callDa
return;
}
IR::Module module(scope.engine->debugger != 0);
IR::Module module(scope.engine->debugger() != 0);
QQmlJS::RuntimeCodegen cg(scope.engine, f->strictMode());
cg.generateFromFunctionExpression(QString(), function, fe, &module);
@ -535,6 +535,7 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData
ctx.function = f->d();
ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
ctx.constantTable = ctx.compilationUnit->constants;
ctx.outer = f->scope();
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)
@ -572,6 +573,7 @@ void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *cal
ctx.function = f->d();
ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
ctx.constantTable = ctx.compilationUnit->constants;
ctx.outer = f->scope();
ctx.locals = scope.alloc(f->varCount());
for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i)

View File

@ -147,8 +147,8 @@ static void insertHoleIntoPropertyData(Object *object, int idx)
static void removeFromPropertyData(Object *object, int idx, bool accessor = false)
{
int inlineSize = object->d()->inlineMemberSize;
int icSize = object->internalClass()->size;
int delta = (accessor ? 2 : 1);
int oldSize = object->internalClass()->size + delta;
int to = idx;
int from = to + delta;
if (from < inlineSize) {
@ -156,15 +156,15 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals
to = inlineSize - delta;
from = inlineSize;
}
if (to < inlineSize && from < icSize) {
if (to < inlineSize && from < oldSize) {
Q_ASSERT(from >= inlineSize);
memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value));
to = inlineSize;
from = inlineSize + delta;
}
if (from < icSize + delta) {
if (from < oldSize) {
Q_ASSERT(to >= inlineSize && from > to);
memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value));
memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value));
}
}

View File

@ -57,6 +57,40 @@
#include <QElapsedTimer>
#ifdef QT_NO_QML_DEBUGGER
#define Q_V4_PROFILE_ALLOC(engine, size, type) (!engine)
#define Q_V4_PROFILE_DEALLOC(engine, size, type) (!engine)
#define Q_V4_PROFILE(engine, function) (function->code(engine, function->codeData))
QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Profiling {
struct Profiler {};
}
}
QT_END_NAMESPACE
#else
#define Q_V4_PROFILE_ALLOC(engine, size, type)\
(engine->profiler() &&\
(engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler()->trackAlloc(size, type) : false)
#define Q_V4_PROFILE_DEALLOC(engine, size, type) \
(engine->profiler() &&\
(engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler()->trackDealloc(size, type) : false)
#define Q_V4_PROFILE(engine, function)\
(engine->profiler() &&\
(engine->profiler()->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
Profiling::FunctionCallProfiler::profileCall(engine->profiler(), engine, function) :\
function->code(engine, function->codeData))
QT_BEGIN_NAMESPACE
namespace QV4 {
@ -150,25 +184,8 @@ private:
qint64 m_end;
};
#define Q_V4_PROFILE_ALLOC(engine, size, type)\
(engine->profiler &&\
(engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler->trackAlloc(size, type) : size)
#define Q_V4_PROFILE_DEALLOC(engine, pointer, size, type) \
(engine->profiler &&\
(engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler->trackDealloc(pointer, size, type) : pointer)
#define Q_V4_PROFILE(engine, function)\
(engine->profiler &&\
(engine->profiler->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
Profiling::FunctionCallProfiler::profileCall(engine->profiler, engine, function) :\
function->code(engine, function->codeData))
class Q_QML_EXPORT Profiler : public QObject {
Q_OBJECT
Q_DISABLE_COPY(Profiler)
public:
struct SentMarker {
SentMarker() : m_function(nullptr) {}
@ -212,23 +229,22 @@ public:
Profiler(QV4::ExecutionEngine *engine);
size_t trackAlloc(size_t size, MemoryType type)
bool trackAlloc(size_t size, MemoryType type)
{
MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), (qint64)size, type};
m_memory_data.append(allocation);
return size;
return true;
}
void *trackDealloc(void *pointer, size_t size, MemoryType type)
bool trackDealloc(size_t size, MemoryType type)
{
MemoryAllocationProperties allocation = {m_timer.nsecsElapsed(), -(qint64)size, type};
m_memory_data.append(allocation);
return pointer;
return true;
}
quint64 featuresEnabled;
public slots:
void stopProfiling();
void startProfiling(quint64 features);
void reportData(bool trackLocations);
@ -290,4 +306,6 @@ Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
Q_DECLARE_METATYPE(QVector<QV4::Profiling::FunctionCallProperties>)
Q_DECLARE_METATYPE(QVector<QV4::Profiling::MemoryAllocationProperties>)
#endif // QT_NO_QML_DEBUGGER
#endif // QV4PROFILING_H

View File

@ -148,7 +148,7 @@ void Script::parse()
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
IR::Module module(v4->debugger != 0);
IR::Module module(v4->debugger() != 0);
QQmlJS::Engine ee, *engine = &ee;
Lexer lexer(engine);
@ -222,6 +222,7 @@ ReturnedValue Script::run()
ContextStateSaver stateSaver(valueScope, scope);
scope->d()->strictMode = vmFunction->isStrict();
scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
scope->d()->constantTable = vmFunction->compilationUnit->constants;
scope->d()->compilationUnit = vmFunction->compilationUnit;
return Q_V4_PROFILE(engine, vmFunction);

View File

@ -71,6 +71,7 @@ struct ContextStateSaver {
Value *savedContext;
bool strictMode;
Lookup *lookups;
const QV4::Value *constantTable;
CompiledData::CompilationUnit *compilationUnit;
int lineNumber;
@ -78,6 +79,7 @@ struct ContextStateSaver {
: savedContext(scope.alloc(1))
, strictMode(context->d()->strictMode)
, lookups(context->d()->lookups)
, constantTable(context->d()->constantTable)
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
{
@ -87,6 +89,7 @@ struct ContextStateSaver {
: savedContext(scope.alloc(1))
, strictMode(context->strictMode)
, lookups(context->lookups)
, constantTable(context->constantTable)
, compilationUnit(context->compilationUnit)
, lineNumber(context->lineNumber)
{
@ -98,6 +101,7 @@ struct ContextStateSaver {
Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m());
ctx->strictMode = strictMode;
ctx->lookups = lookups;
ctx->constantTable = constantTable;
ctx->compilationUnit = compilationUnit;
ctx->lineNumber = lineNumber;
}

View File

@ -531,7 +531,7 @@ public:
Q_ASSERT(d()->object);
Q_ASSERT(d()->isReference);
int status = -1;
QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding;
QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding;
void *a[] = { &d()->container, 0, &status, &flags };
QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
}

View File

@ -102,13 +102,13 @@ public:
Q_ALWAYS_INLINE quint64 rawValue() const { return _val; }
Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; }
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN || defined(QV4_USE_64_BIT_VALUE_ENCODING)
static inline int valueOffset() { return 0; }
static inline int tagOffset() { return 4; }
Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); }
Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; }
#else // !Q_LITTLE_ENDIAN
#else // !Q_LITTLE_ENDIAN && !defined(QV4_USE_64_BIT_VALUE_ENCODING)
static inline int valueOffset() { return 4; }
static inline int tagOffset() { return 0; }
Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(value) << 32 | tag; }

View File

@ -142,6 +142,7 @@ Q_QML_EXPORT int qt_v4DebuggerHook(const char *json);
} // extern "C"
#ifndef QT_NO_QML_DEBUGGER
static int qt_v4BreakpointCount = 0;
static bool qt_v4IsDebugging = true;
static bool qt_v4IsStepping = false;
@ -285,6 +286,7 @@ static void qt_v4CheckForBreak(QV4::ExecutionContext *context, QV4::Value **scop
}
}
#endif // QT_NO_QML_DEBUGGER
// End of debugger interface
using namespace QV4;
@ -400,7 +402,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth)));
{
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants());
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->constants);
// stack gets setup in push instruction
scopes[1] = 0;
QV4::Heap::ExecutionContext *scope = context->d();
@ -904,9 +906,10 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
return VALUE(instr.result).asReturnedValue();
MOTH_END_INSTR(Ret)
#ifndef QT_NO_QML_DEBUGGER
MOTH_BEGIN_INSTR(Debug)
engine->current->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
QV4::Debugging::Debugger *debugger = context->engine()->debugger();
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
if (qt_v4IsDebugging)
@ -918,6 +921,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
if (qt_v4IsDebugging)
qt_v4CheckForBreak(context, scopes, scopeDepth);
MOTH_END_INSTR(Line)
#endif // QT_NO_QML_DEBUGGER
MOTH_BEGIN_INSTR(LoadThis)
VALUE(instr.result) = context->thisObject();
@ -970,7 +974,7 @@ void **VME::instructionJumpTable()
QV4::ReturnedValue VME::exec(ExecutionEngine *engine, const uchar *code)
{
VME vme;
QV4::Debugging::Debugger *debugger = engine->debugger;
QV4::Debugging::Debugger *debugger = engine->debugger();
if (debugger)
debugger->enteringFunction();
QV4::ReturnedValue retVal = vme.run(engine, code);

View File

@ -185,7 +185,7 @@ struct MemoryManager::Data
~Data()
{
for (std::vector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
Q_V4_PROFILE_DEALLOC(engine, i->size(), Profiling::HeapPage);
i->deallocate();
}
}
@ -239,7 +239,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
#ifdef V4_USE_HEAPTRACK
heaptrack_report_free(m);
#endif
Q_V4_PROFILE_DEALLOC(engine, m, header->itemSize, Profiling::SmallItem);
Q_V4_PROFILE_DEALLOC(engine, header->itemSize, Profiling::SmallItem);
++(*itemsInUse);
}
// Relink all free blocks to rewrite references to any released chunk.
@ -302,10 +302,11 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
runGC();
// we use malloc for this
MemoryManager::Data::LargeItem *item = static_cast<MemoryManager::Data::LargeItem *>(
malloc(Q_V4_PROFILE_ALLOC(engine, size + sizeof(MemoryManager::Data::LargeItem),
Profiling::LargeItem)));
memset(item, 0, size + sizeof(MemoryManager::Data::LargeItem));
const size_t totalSize = size + sizeof(MemoryManager::Data::LargeItem);
Q_V4_PROFILE_ALLOC(engine, totalSize, Profiling::LargeItem);
MemoryManager::Data::LargeItem *item =
static_cast<MemoryManager::Data::LargeItem *>(malloc(totalSize));
memset(item, 0, totalSize);
item->next = m_d->largeItems;
item->size = size;
m_d->largeItems = item;
@ -338,9 +339,8 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
shift = m_d->maxShift;
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(m_d->pageSize, allocSize);
PageAllocation allocation = PageAllocation::allocate(
Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage);
PageAllocation allocation = PageAllocation::allocate(allocSize, OSAllocator::JSGCHeapPages);
m_d->heapChunks.push_back(allocation);
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
@ -507,7 +507,7 @@ void MemoryManager::sweep(bool lastSweep)
// Release that chunk if it could have been spared since the last GC run without any difference.
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
Q_V4_PROFILE_DEALLOC(engine, 0, chunkIter->size(), Profiling::HeapPage);
Q_V4_PROFILE_DEALLOC(engine, chunkIter->size(), Profiling::HeapPage);
#ifdef V4_USE_VALGRIND
VALGRIND_MEMPOOL_FREE(this, header);
#endif
@ -542,8 +542,8 @@ void MemoryManager::sweep(bool lastSweep)
m->vtable()->destroy(m);
*last = i->next;
free(Q_V4_PROFILE_DEALLOC(engine, i, i->size + sizeof(Data::LargeItem),
Profiling::LargeItem));
Q_V4_PROFILE_DEALLOC(engine, i->size + sizeof(Data::LargeItem), Profiling::LargeItem);
free(i);
i = *last;
}

View File

@ -22,7 +22,7 @@ exists("qqml_enable_gcov") {
LIBS_PRIVATE += -lgcov
}
greaterThan(QT_GCC_MAJOR_VERSION, 5) {
gcc:!intel_icc:greaterThan(QT_GCC_MAJOR_VERSION, 5) {
# Our code is bad. Temporary workaround.
QMAKE_CXXFLAGS += -fno-delete-null-pointer-checks
}

View File

@ -38,7 +38,6 @@ SOURCES += \
$$PWD/qqmlvaluetypeproxybinding.cpp \
$$PWD/qqmlglobal.cpp \
$$PWD/qqmlfile.cpp \
$$PWD/qqmlmemoryprofiler.cpp \
$$PWD/qqmlplatform.cpp \
$$PWD/qqmlbinding.cpp \
$$PWD/qqmlabstracturlinterceptor.cpp \
@ -107,7 +106,6 @@ HEADERS += \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
$$PWD/qqmlfile.h \
$$PWD/qqmlmemoryprofiler_p.h \
$$PWD/qqmlplatform_p.h \
$$PWD/qqmlbinding_p.h \
$$PWD/qqmlextensionplugin_p.h \

View File

@ -82,7 +82,7 @@ public:
// binding is not enabled or added to the object.
QObject *targetObject() const { return m_target.data(); }
virtual void setEnabled(bool e, QQmlPropertyPrivate::WriteFlags f = QQmlPropertyPrivate::DontRemoveBinding) = 0;
virtual void setEnabled(bool e, QQmlPropertyData::WriteFlags f = QQmlPropertyData::DontRemoveBinding) = 0;
void addToObject();
void removeFromObject();

Some files were not shown because too many files have changed in this diff Show More