diff options
Diffstat (limited to 'src/plugins')
7 files changed, 257 insertions, 177 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index 0469cd51d6..ac46905f1c 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -44,6 +44,9 @@ QT_BEGIN_NAMESPACE +const QV4DataCollector::Ref QV4DataCollector::s_invalidRef = + std::numeric_limits<QV4DataCollector::Ref>::max(); + QV4::CallContext *QV4DataCollector::findContext(QV4::ExecutionEngine *engine, int frame) { QV4::ExecutionContext *ctx = engine->currentContext; @@ -90,21 +93,16 @@ QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeType return types; } - -QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine) - : m_engine(engine), m_collectedRefs(Q_NULLPTR) +QV4DataCollector::QV4DataCollector(QV4::ExecutionEngine *engine) : m_engine(engine) { - values.set(engine, engine->newArrayObject()); + m_values.set(engine, engine->newArrayObject()); } -QV4DataCollector::~QV4DataCollector() +QV4DataCollector::Ref QV4DataCollector::collect(const QV4::ScopedValue &value) { -} - -void QV4DataCollector::collect(const QV4::ScopedValue &value) -{ - if (m_collectedRefs) - m_collectedRefs->append(addRef(value)); + Ref ref = addRef(value); + m_collectedRefs.append(ref); + return ref; } const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::ExecutionEngine *engine, @@ -191,7 +189,8 @@ QV4DataCollector::Ref QV4DataCollector::addFunctionRef(const QString &functionNa dict.insert(QStringLiteral("handle"), qint64(ref)); dict.insert(QStringLiteral("type"), QStringLiteral("function")); dict.insert(QStringLiteral("name"), functionName); - specialRefs.insert(ref, dict); + m_specialRefs.insert(ref, dict); + m_collectedRefs.append(ref); return ref; } @@ -204,19 +203,25 @@ QV4DataCollector::Ref QV4DataCollector::addScriptRef(const QString &scriptName) dict.insert(QStringLiteral("handle"), qint64(ref)); dict.insert(QStringLiteral("type"), QStringLiteral("script")); dict.insert(QStringLiteral("name"), scriptName); - specialRefs.insert(ref, dict); + m_specialRefs.insert(ref, dict); + m_collectedRefs.append(ref); return ref; } +bool QV4DataCollector::isValidRef(QV4DataCollector::Ref ref) const +{ + QV4::Scope scope(engine()); + QV4::ScopedObject array(scope, m_values.value()); + return ref < array->getLength(); +} + void QV4DataCollector::collectScope(QJsonObject *dict, QV4Debugger *debugger, int frameNr, int scopeNr) { QStringList names; - Refs refs; if (debugger->state() == QV4Debugger::Paused) { - RefHolder holder(this, &refs); ArgumentCollectJob argumentsJob(m_engine, this, &names, frameNr, scopeNr); debugger->runInEngine(&argumentsJob); LocalCollectJob localsJob(m_engine, this, &names, frameNr, scopeNr); @@ -226,15 +231,36 @@ void QV4DataCollector::collectScope(QJsonObject *dict, QV4Debugger *debugger, in QV4::Scope scope(engine()); QV4::ScopedObject scopeObject(scope, engine()->newObject()); - Q_ASSERT(names.size() == refs.size()); - for (int i = 0, ei = refs.size(); i != ei; ++i) + Q_ASSERT(names.size() == m_collectedRefs.size()); + for (int i = 0, ei = m_collectedRefs.size(); i != ei; ++i) scopeObject->put(engine(), names.at(i), - QV4::Value::fromReturnedValue(getValue(refs.at(i)))); + QV4::Value::fromReturnedValue(getValue(m_collectedRefs.at(i)))); Ref scopeObjectRef = addRef(scopeObject); dict->insert(QStringLiteral("ref"), qint64(scopeObjectRef)); - if (m_collectedRefs) - m_collectedRefs->append(scopeObjectRef); + m_collectedRefs.append(scopeObjectRef); +} + +QJsonArray QV4DataCollector::flushCollectedRefs() +{ + QJsonArray refs; + std::sort(m_collectedRefs.begin(), m_collectedRefs.end()); + for (int i = 0, ei = m_collectedRefs.size(); i != ei; ++i) { + QV4DataCollector::Ref ref = m_collectedRefs.at(i); + if (i > 0 && ref == m_collectedRefs.at(i - 1)) + continue; + refs.append(lookupRef(ref)); + } + + m_collectedRefs.clear(); + return refs; +} + +void QV4DataCollector::clear() +{ + m_values.set(engine(), engine()->newArrayObject()); + m_collectedRefs.clear(); + m_specialRefs.clear(); } QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicate) @@ -257,10 +283,10 @@ QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicat // if we wouldn't do this, the putIndexed won't work. ExceptionStateSaver resetExceptionState(engine()); QV4::Scope scope(engine()); - QV4::ScopedObject array(scope, values.value()); + QV4::ScopedObject array(scope, m_values.value()); if (deduplicate) { for (Ref i = 0; i < array->getLength(); ++i) { - if (array->getIndexed(i) == value.rawValue() && !specialRefs.contains(i)) + if (array->getIndexed(i) == value.rawValue() && !m_specialRefs.contains(i)) return i; } } @@ -273,15 +299,15 @@ QV4DataCollector::Ref QV4DataCollector::addRef(QV4::Value value, bool deduplicat QV4::ReturnedValue QV4DataCollector::getValue(Ref ref) { QV4::Scope scope(engine()); - QV4::ScopedObject array(scope, values.value()); + QV4::ScopedObject array(scope, m_values.value()); Q_ASSERT(ref < array->getLength()); return array->getIndexed(ref, Q_NULLPTR); } bool QV4DataCollector::lookupSpecialRef(Ref ref, QJsonObject *dict) { - SpecialRefs::const_iterator it = specialRefs.constFind(ref); - if (it == specialRefs.cend()) + SpecialRefs::const_iterator it = m_specialRefs.constFind(ref); + if (it == m_specialRefs.cend()) return false; *dict = it.value(); @@ -317,14 +343,41 @@ QJsonObject QV4DataCollector::collectAsJson(const QString &name, const QV4::Scop if (value->isManaged() && !value->isString()) { Ref ref = addRef(value); dict.insert(QStringLiteral("ref"), qint64(ref)); - if (m_collectedRefs) - m_collectedRefs->append(ref); + m_collectedRefs.append(ref); } collectProperty(value, engine(), dict); return dict; } +void ValueLookupJob::run() +{ + foreach (const QJsonValue &handle, handles) { + QV4DataCollector::Ref ref = handle.toInt(); + if (!collector->isValidRef(ref)) { + exception = QString::fromLatin1("Invalid Ref: %1").arg(ref); + break; + } + result[QString::number(ref)] = collector->lookupRef(ref); + } + collectedRefs = collector->flushCollectedRefs(); +} + +const QString &ValueLookupJob::exceptionMessage() const +{ + return exception; +} + +const QJsonObject &ValueLookupJob::returnValue() const +{ + return result; +} + +const QJsonArray &ValueLookupJob::refs() const +{ + return collectedRefs; +} + ExpressionEvalJob::ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression, QV4DataCollector *collector) @@ -333,11 +386,12 @@ ExpressionEvalJob::ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, { } -void ExpressionEvalJob::handleResult(QV4::ScopedValue &result) +void ExpressionEvalJob::handleResult(QV4::ScopedValue &value) { if (hasExeption()) - exception = result->toQStringNoThrow(); - collector->collect(result); + exception = value->toQStringNoThrow(); + result = collector->lookupRef(collector->collect(value)); + collectedRefs = collector->flushCollectedRefs(); } const QString &ExpressionEvalJob::exceptionMessage() const @@ -345,6 +399,16 @@ const QString &ExpressionEvalJob::exceptionMessage() const return exception; } +const QJsonObject &ExpressionEvalJob::returnValue() const +{ + return result; +} + +const QJsonArray &ExpressionEvalJob::refs() const +{ + return collectedRefs; +} + GatherSourcesJob::GatherSourcesJob(QV4::ExecutionEngine *engine) : engine(engine) {} @@ -427,20 +491,15 @@ void LocalCollectJob::run() } ThisCollectJob::ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, - int frameNr, bool *foundThis) + int frameNr) : engine(engine) , collector(collector) , frameNr(frameNr) - , foundThis(foundThis) + , thisRef(QV4DataCollector::s_invalidRef) {} void ThisCollectJob::run() { - *foundThis = myRun(); -} - -bool ThisCollectJob::myRun() -{ QV4::Scope scope(engine); QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine, frameNr)); while (ctxt) { @@ -451,23 +510,33 @@ bool ThisCollectJob::myRun() } if (!ctxt) - return false; + return; QV4::ScopedValue o(scope, ctxt->asCallContext()->d()->activation); - collector->collect(o); - return true; + thisRef = collector->collect(o); +} + +QV4DataCollector::Ref ThisCollectJob::foundRef() const +{ + return thisRef; } ExceptionCollectJob::ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector) : engine(engine) , collector(collector) + , exception(QV4DataCollector::s_invalidRef) {} void ExceptionCollectJob::run() { QV4::Scope scope(engine); QV4::ScopedValue v(scope, *engine->exceptionValue); - collector->collect(v); + exception = collector->collect(v); +} + +QV4DataCollector::Ref ExceptionCollectJob::exceptionValue() const +{ + return exception; } QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h index bfa3bd2fe1..d1ff98f9b0 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h @@ -38,6 +38,9 @@ #include <private/qv4engine_p.h> #include <private/qv4persistent_p.h> +#include <QtCore/QJsonObject> +#include <QtCore/QJsonArray> + QT_BEGIN_NAMESPACE class QV4DataCollector @@ -45,6 +48,7 @@ class QV4DataCollector public: typedef uint Ref; typedef QVector<uint> Refs; + static const Ref s_invalidRef; static QV4::CallContext *findContext(QV4::ExecutionEngine *engine, int frame); static QV4::Heap::CallContext *findScope(QV4::ExecutionContext *ctxt, int scope); @@ -52,22 +56,21 @@ public: QV4::ExecutionEngine *engine, int frame); QV4DataCollector(QV4::ExecutionEngine *engine); - ~QV4DataCollector(); - - void collect(const QV4::ScopedValue &value); - - QJsonObject lookupRef(Ref ref); + Ref collect(const QV4::ScopedValue &value); Ref addFunctionRef(const QString &functionName); Ref addScriptRef(const QString &scriptName); + bool isValidRef(Ref ref) const; + QJsonObject lookupRef(Ref ref); + void collectScope(QJsonObject *dict, QV4Debugger *debugger, int frameNr, int scopeNr); QV4::ExecutionEngine *engine() const { return m_engine; } + QJsonArray flushCollectedRefs(); + void clear(); private: - friend class RefHolder; - Ref addRef(QV4::Value value, bool deduplicate = true); QV4::ReturnedValue getValue(Ref ref); bool lookupSpecialRef(Ref ref, QJsonObject *dict); @@ -77,40 +80,43 @@ private: void collectArgumentsInContext(); QV4::ExecutionEngine *m_engine; - Refs *m_collectedRefs; - QV4::PersistentValue values; + Refs m_collectedRefs; + QV4::PersistentValue m_values; typedef QHash<Ref, QJsonObject> SpecialRefs; - SpecialRefs specialRefs; + SpecialRefs m_specialRefs; }; -class RefHolder { -public: - RefHolder(QV4DataCollector *collector, QV4DataCollector::Refs *target) : - m_collector(collector), m_previousRefs(collector->m_collectedRefs) - { - m_collector->m_collectedRefs = target; - } - - ~RefHolder() - { - std::swap(m_collector->m_collectedRefs, m_previousRefs); - } +class ValueLookupJob: public QV4Debugger::Job +{ + QV4DataCollector *collector; + const QJsonArray handles; + QJsonObject result; + QJsonArray collectedRefs; + QString exception; -private: - QV4DataCollector *m_collector; - QV4DataCollector::Refs *m_previousRefs; +public: + ValueLookupJob(const QJsonArray &handles, QV4DataCollector *collector) : + collector(collector), handles(handles) {} + void run(); + const QString &exceptionMessage() const; + const QJsonObject &returnValue() const; + const QJsonArray &refs() const; }; class ExpressionEvalJob: public QV4Debugger::JavaScriptJob { QV4DataCollector *collector; QString exception; + QJsonObject result; + QJsonArray collectedRefs; public: ExpressionEvalJob(QV4::ExecutionEngine *engine, int frameNr, const QString &expression, QV4DataCollector *collector); - virtual void handleResult(QV4::ScopedValue &result); + virtual void handleResult(QV4::ScopedValue &value); const QString &exceptionMessage() const; + const QJsonObject &returnValue() const; + const QJsonArray &refs() const; }; class GatherSourcesJob: public QV4Debugger::Job @@ -157,23 +163,24 @@ class ThisCollectJob: public QV4Debugger::Job QV4::ExecutionEngine *engine; QV4DataCollector *collector; int frameNr; - bool *foundThis; + QV4DataCollector::Ref thisRef; public: - ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, int frameNr, - bool *foundThis); + ThisCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector, int frameNr); void run(); - bool myRun(); + QV4DataCollector::Ref foundRef() const; }; class ExceptionCollectJob: public QV4Debugger::Job { QV4::ExecutionEngine *engine; QV4DataCollector *collector; + QV4DataCollector::Ref exception; public: ExceptionCollectJob(QV4::ExecutionEngine *engine, QV4DataCollector *collector); void run(); + QV4DataCollector::Ref exceptionValue() const; }; QT_END_NAMESPACE diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp index 014de1f4cb..a7ef1ede6b 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qv4debugger.h" +#include "qv4datacollector.h" #include <private/qv4scopedvalue_p.h> #include <private/qv4script_p.h> @@ -127,6 +128,7 @@ QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine) , m_returnedValue(engine, QV4::Primitive::undefinedValue()) , m_gatherSources(0) , m_runningJob(0) + , m_collector(new QV4DataCollector(engine)) { static int debuggerId = qRegisterMetaType<QV4Debugger*>(); static int pauseReasonId = qRegisterMetaType<QV4Debugger::PauseReason>(); @@ -134,11 +136,21 @@ QV4Debugger::QV4Debugger(QV4::ExecutionEngine *engine) Q_UNUSED(pauseReasonId); } +QV4Debugger::~QV4Debugger() +{ + delete m_collector; +} + QV4::ExecutionEngine *QV4Debugger::engine() const { return m_engine; } +QV4DataCollector *QV4Debugger::collector() const +{ + return m_collector; +} + void QV4Debugger::pause() { QMutexLocker locker(&m_lock); @@ -300,6 +312,14 @@ QV4::Function *QV4Debugger::getFunction() const return context->d()->engine->globalCode; } +void QV4Debugger::runJobUnpaused() +{ + QMutexLocker locker(&m_lock); + if (m_runningJob) + m_runningJob->run(); + m_jobIsRunning.wakeAll(); +} + void QV4Debugger::pauseAndWait(PauseReason reason) { if (m_runningJob) @@ -352,7 +372,10 @@ void QV4Debugger::runInEngine_havingLock(QV4Debugger::Job *job) Q_ASSERT(m_runningJob == 0); m_runningJob = job; - m_runningCondition.wakeAll(); + if (state() == Paused) + m_runningCondition.wakeAll(); + else + QMetaObject::invokeMethod(this, "runJobUnpaused", Qt::QueuedConnection); m_jobIsRunning.wait(&m_lock); m_runningJob = 0; } diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h index 8662259264..abb43f82f3 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h @@ -55,6 +55,7 @@ QT_BEGIN_NAMESPACE +class QV4DataCollector; class QV4Debugger : public QV4::Debugging::Debugger { Q_OBJECT @@ -110,8 +111,10 @@ public: }; QV4Debugger(QV4::ExecutionEngine *engine); + ~QV4Debugger(); QV4::ExecutionEngine *engine() const; + QV4DataCollector *collector() const; void pause(); void resume(Speed speed); @@ -153,6 +156,9 @@ public: signals: void debuggerPaused(QV4Debugger *self, QV4Debugger::PauseReason reason); +private slots: + void runJobUnpaused(); + private: // requires lock to be held void pauseAndWait(PauseReason reason); @@ -174,6 +180,7 @@ private: Job *m_gatherSources; Job *m_runningJob; + QV4DataCollector *m_collector; QWaitCondition m_jobIsRunning; }; diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp index 8bd9547032..c563a97fe2 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp @@ -63,7 +63,7 @@ void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseR { Q_UNUSED(reason); - m_debugService->clearHandles(debugger->engine()); + debugger->collector()->clear(); QJsonObject event, body, script; event.insert(QStringLiteral("type"), QStringLiteral("event")); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp index dea1fae779..6524a1ff28 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp @@ -114,9 +114,9 @@ protected: response.insert(QStringLiteral("running"), debugService->debuggerAgent.isRunning()); } - void addRefs() + void addRefs(const QJsonArray &refs) { - response.insert(QStringLiteral("refs"), debugService->buildRefs()); + response.insert(QStringLiteral("refs"), refs); } void createErrorResponse(const QString &msg) @@ -169,6 +169,7 @@ public: QJsonObject body; body.insert(QStringLiteral("V8Version"), QLatin1String("this is not V8, this is V4 in Qt " QT_VERSION_STR)); + body.insert(QStringLiteral("UnpausedEvaluate"), true); addBody(body); } }; @@ -296,7 +297,7 @@ public: body.insert(QStringLiteral("frames"), frameArray); } addBody(body); - addRefs(); + addRefs(debugger->collector()->flushCollectedRefs()); } }; @@ -333,7 +334,7 @@ public: addSuccess(true); addRunning(); addBody(frame); - addRefs(); + addRefs(debugger->collector()->flushCollectedRefs()); } }; @@ -374,7 +375,7 @@ public: addSuccess(true); addRunning(); addBody(scope); - addRefs(); + addRefs(debugger->collector()->flushCollectedRefs()); } }; @@ -389,17 +390,32 @@ public: QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); QJsonArray handles = arguments.value(QStringLiteral("handles")).toArray(); - QJsonObject body; - foreach (const QJsonValue &handle, handles) - body[QString::number(handle.toInt())] = debugService->lookup(handle.toInt()); + QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); + if (!debugger) { + const QList<QV4Debugger *> &debuggers = debugService->debuggerAgent.debuggers(); + if (debuggers.count() > 1) { + createErrorResponse(QStringLiteral("Cannot lookup values if multiple debuggers are running and none is paused")); + return; + } else if (debuggers.count() == 0) { + createErrorResponse(QStringLiteral("No debuggers available to lookup values")); + return; + } + debugger = debuggers.first(); + } - // response: - addCommand(); - addRequestSequence(); - addSuccess(true); - addRunning(); - addBody(body); - addRefs(); + ValueLookupJob job(handles, debugger->collector()); + debugger->runInEngine(&job); + if (!job.exceptionMessage().isEmpty()) { + createErrorResponse(job.exceptionMessage()); + } else { + // response: + addCommand(); + addRequestSequence(); + addSuccess(true); + addRunning(); + addBody(job.returnValue()); + addRefs(job.refs()); + } } }; @@ -587,27 +603,34 @@ public: virtual void handleRequest() { QV4Debugger *debugger = debugService->debuggerAgent.pausedDebugger(); - if (debugger) { - QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); - QString expression = arguments.value(QStringLiteral("expression")).toString(); - const int frame = arguments.value(QStringLiteral("frame")).toInt(0); - - QV4DataCollector *collector = debugService->collector(); - RefHolder holder(collector, debugService->refs()); - ExpressionEvalJob job(debugger->engine(), frame, expression, collector); - debugger->runInEngine(&job); - if (job.hasExeption()) { - createErrorResponse(job.exceptionMessage()); - } else { - addCommand(); - addRequestSequence(); - addSuccess(true); - addRunning(); - addBody(collector->lookupRef(debugService->refs()->last())); - addRefs(); + + if (!debugger) { + const QList<QV4Debugger *> &debuggers = debugService->debuggerAgent.debuggers(); + if (debuggers.count() > 1) { + createErrorResponse(QStringLiteral("Cannot evaluate expressions if multiple debuggers are running and none is paused")); + return; + } else if (debuggers.count() == 0) { + createErrorResponse(QStringLiteral("No debuggers available to evaluate expressions")); + return; } + debugger = debuggers.first(); + } + + QJsonObject arguments = req.value(QStringLiteral("arguments")).toObject(); + QString expression = arguments.value(QStringLiteral("expression")).toString(); + const int frame = arguments.value(QStringLiteral("frame")).toInt(0); + + ExpressionEvalJob job(debugger->engine(), frame, expression, debugger->collector()); + debugger->runInEngine(&job); + if (job.hasExeption()) { + createErrorResponse(job.exceptionMessage()); } else { - createErrorResponse(QStringLiteral("Debugger has to be paused for evaluate to work.")); + addCommand(); + addRequestSequence(); + addSuccess(true); + addRunning(); + addBody(job.returnValue()); + addRefs(job.refs()); } } }; @@ -805,11 +828,6 @@ void QV4DebugServiceImpl::send(QJsonObject v8Payload) emit messageToClient(name(), packMessage("v8message", responseData)); } -void QV4DebugServiceImpl::clearHandles(QV4::ExecutionEngine *engine) -{ - theCollector.reset(new QV4DataCollector(engine)); -} - QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, int frameNr, QV4Debugger *debugger) { @@ -818,38 +836,34 @@ QJsonObject QV4DebugServiceImpl::buildFrame(const QV4::StackFrame &stackFrame, i QJsonObject frame; frame[QLatin1String("index")] = frameNr; frame[QLatin1String("debuggerFrame")] = false; - ref = theCollector->addFunctionRef(stackFrame.function); - collectedRefs.append(ref); + ref = debugger->collector()->addFunctionRef(stackFrame.function); frame[QLatin1String("func")] = toRef(ref); - ref = theCollector->addScriptRef(stackFrame.source); - collectedRefs.append(ref); + ref = debugger->collector()->addScriptRef(stackFrame.source); frame[QLatin1String("script")] = toRef(ref); frame[QLatin1String("line")] = stackFrame.line - 1; if (stackFrame.column >= 0) frame[QLatin1String("column")] = stackFrame.column; QJsonArray scopes; - if (debugger->state() == QV4Debugger::Paused) { - RefHolder holder(theCollector.data(), &collectedRefs); - bool foundThis = false; - ThisCollectJob job(debugger->engine(), theCollector.data(), frameNr, &foundThis); - debugger->runInEngine(&job); - if (foundThis) - frame[QLatin1String("receiver")] = toRef(collectedRefs.last()); + Q_ASSERT (debugger->state() == QV4Debugger::Paused); + + ThisCollectJob job(debugger->engine(), debugger->collector(), frameNr); + debugger->runInEngine(&job); + if (job.foundRef() != QV4DataCollector::s_invalidRef) + frame[QLatin1String("receiver")] = toRef(job.foundRef()); + + // Only type and index are used by Qt Creator, so we keep it easy: + QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = + QV4DataCollector::getScopeTypes(debugger->engine(), frameNr); + for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) { + int type = encodeScopeType(scopeTypes[i]); + if (type == -1) + continue; - // Only type and index are used by Qt Creator, so we keep it easy: - QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = - QV4DataCollector::getScopeTypes(debugger->engine(), frameNr); - for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) { - int type = encodeScopeType(scopeTypes[i]); - if (type == -1) - continue; - - QJsonObject scope; - scope[QLatin1String("index")] = i; - scope[QLatin1String("type")] = type; - scopes.push_back(scope); - } + QJsonObject scope; + scope[QLatin1String("index")] = i; + scope[QLatin1String("type")] = type; + scopes.push_back(scope); } frame[QLatin1String("scopes")] = scopes; @@ -883,8 +897,7 @@ QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr, QV4Debugge QJsonObject scope; QJsonObject object; - RefHolder holder(theCollector.data(), &collectedRefs); - theCollector->collectScope(&object, debugger, frameNr, scopeNr); + debugger->collector()->collectScope(&object, debugger, frameNr, scopeNr); if (debugger->state() == QV4Debugger::Paused) { QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = @@ -900,27 +913,6 @@ QJsonObject QV4DebugServiceImpl::buildScope(int frameNr, int scopeNr, QV4Debugge return scope; } -QJsonValue QV4DebugServiceImpl::lookup(QV4DataCollector::Ref refId) -{ - RefHolder holder(theCollector.data(), &collectedRefs); - return theCollector->lookupRef(refId); -} - -QJsonArray QV4DebugServiceImpl::buildRefs() -{ - QJsonArray refs; - std::sort(collectedRefs.begin(), collectedRefs.end()); - for (int i = 0, ei = collectedRefs.size(); i != ei; ++i) { - QV4DataCollector::Ref ref = collectedRefs.at(i); - if (i > 0 && ref == collectedRefs.at(i - 1)) - continue; - refs.append(lookup(ref)); - } - - collectedRefs.clear(); - return refs; -} - QJsonValue QV4DebugServiceImpl::toRef(QV4DataCollector::Ref ref) { QJsonObject dict; @@ -928,16 +920,6 @@ QJsonValue QV4DebugServiceImpl::toRef(QV4DataCollector::Ref ref) return dict; } -QV4DataCollector *QV4DebugServiceImpl::collector() const -{ - return theCollector.data(); -} - -QV4DataCollector::Refs *QV4DebugServiceImpl::refs() -{ - return &collectedRefs; -} - void QV4DebugServiceImpl::selectFrame(int frameNr) { theSelectedFrame = frameNr; diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h index 678ebe43b8..2d9932b838 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.h @@ -78,19 +78,13 @@ public: void send(QJsonObject v8Payload); QJsonObject buildScope(int frameNr, int scopeNr, QV4Debugger *debugger); - QJsonArray buildRefs(); - QJsonValue lookup(QV4DataCollector::Ref refId); QJsonValue toRef(QV4DataCollector::Ref ref); QJsonObject buildFrame(const QV4::StackFrame &stackFrame, int frameNr, QV4Debugger *debugger); int selectedFrame() const; void selectFrame(int frameNr); - void clearHandles(QV4::ExecutionEngine *engine); - - QV4DataCollector *collector() const; QV4DebuggerAgent debuggerAgent; - QV4DataCollector::Refs *refs(); protected: void messageReceived(const QByteArray &) Q_DECL_OVERRIDE; @@ -108,9 +102,7 @@ private: QStringList breakOnSignals; static int sequence; - QV4DataCollector::Refs collectedRefs; - QScopedPointer<QV4DataCollector> theCollector; int theSelectedFrame; void addHandler(V8CommandHandler* handler); |