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:
commit
175f53860a
|
@ -41,7 +41,7 @@
|
|||
#include "pieslice.h"
|
||||
|
||||
PieChart::PieChart(QQuickItem *parent)
|
||||
: QQuickItem(parent)
|
||||
: QQuickItem(parent), m_pieSlice(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include <QPainter>
|
||||
|
||||
PieSlice::PieSlice(QQuickItem *parent)
|
||||
: QQuickPaintedItem(parent)
|
||||
: QQuickPaintedItem(parent), m_fromAngle(0), m_angleSpan(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,8 @@ SUBDIRS = samegame \
|
|||
tweetsearch \
|
||||
maroon \
|
||||
photosurface \
|
||||
photoviewer \
|
||||
stocqt
|
||||
|
||||
qtHaveModule(xmlpatterns): SUBDIRS += rssnews
|
||||
|
||||
EXAMPLE_FILES = \
|
||||
photoviewer
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -74,7 +74,7 @@ Q_SIGNALS:
|
|||
void readyRead();
|
||||
void invalidPacket();
|
||||
|
||||
private Q_SLOTS:
|
||||
private:
|
||||
void aboutToClose();
|
||||
void bytesWritten(qint64 bytes);
|
||||
void readyToRead();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -72,7 +72,6 @@ public:
|
|||
void setBreakOnThrow(bool onoff);
|
||||
void clearAllPauseRequests();
|
||||
|
||||
public slots:
|
||||
void debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseReason reason);
|
||||
void handleDebuggerDeleted(QObject *debugger);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QQmlDebugServer : protected QQmlDebugConnector
|
||||
class QQmlDebugServer : public QQmlDebugConnector
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
|
@ -682,9 +682,11 @@ void QSGD3D12EnginePrivate::releaseResources()
|
|||
commandQueue = nullptr;
|
||||
copyCommandQueue = nullptr;
|
||||
|
||||
#ifndef Q_OS_WINRT
|
||||
dcompTarget = nullptr;
|
||||
dcompVisual = nullptr;
|
||||
dcompDevice = nullptr;
|
||||
#endif
|
||||
|
||||
swapChain = nullptr;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -729,7 +729,7 @@ Rectangle {
|
|||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressed: root.activated(mouse.x, mouse.y)
|
||||
onRelased: root.deactivated()
|
||||
onReleased: root.deactivated()
|
||||
}
|
||||
}
|
||||
\endqml
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = ⅇ
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue