diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2017-11-21 12:29:40 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2017-11-21 12:29:40 +0100 |
commit | d373d5e7d70e968cfba8957596ed6fe4f46990c8 (patch) | |
tree | c52bf2b0fbbfdb13d644b4050aa7a931ef4b7109 /src/plugins | |
parent | 9880acb424fd814501ba5fc4ae1caa989e23fafa (diff) | |
parent | 9af8a47746b69b6040fc149c1d24602a1e25b08f (diff) |
Merge remote-tracking branch 'origin/wip/new-backend' into dev
Conflicts:
src/qml/compiler/qv4isel_moth.cpp
src/qml/compiler/qv4jsir_p.h
src/qml/jsruntime/qv4engine_p.h
src/qml/jsruntime/qv4vme_moth.cpp
tests/auto/qml/qml.pro
Change-Id: Ia7b6ec24c7fcbcbb1786d9e798d2df294020ae37
Diffstat (limited to 'src/plugins')
8 files changed, 142 insertions, 187 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index 8ff0a3ca64..a538956e8e 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -55,47 +55,43 @@ QT_BEGIN_NAMESPACE -QV4::SimpleCallContext *QV4DataCollector::findContext(int frame) +QV4::CppStackFrame *QV4DataCollector::findFrame(int frame) { - QV4::ExecutionContext *ctx = engine()->currentContext; - while (ctx) { - QV4::SimpleCallContext *cCtxt = ctx->asSimpleCallContext(); - if (cCtxt && cCtxt->d()->v4Function) { - if (frame < 1) - return cCtxt; - --frame; - } - ctx = engine()->parentContext(ctx); + QV4::CppStackFrame *f = engine()->currentStackFrame; + while (f && frame) { + --frame; + f = f->parent; } + return f; +} - return 0; +QV4::Heap::ExecutionContext *QV4DataCollector::findContext(int frame) +{ + QV4::CppStackFrame *f = findFrame(frame); + + return f ? f->context()->d() : 0; } -QV4::Heap::SimpleCallContext *QV4DataCollector::findScope(QV4::ExecutionContext *ctxt, int scope) +QV4::Heap::CallContext *QV4DataCollector::findScope(QV4::Heap::ExecutionContext *ctx, int scope) { - if (!ctxt) + if (!ctx) return 0; - QV4::Scope s(ctxt); - QV4::ScopedContext ctx(s, ctxt); for (; scope > 0 && ctx; --scope) - ctx = ctx->d()->outer; + ctx = ctx->outer; - return (ctx && ctx->d()) ? ctx->asSimpleCallContext()->d() : 0; + return (ctx && ctx->type == QV4::Heap::ExecutionContext::Type_CallContext) ? + static_cast<QV4::Heap::CallContext *>(ctx) : 0; } QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeTypes(int frame) { QVector<QV4::Heap::ExecutionContext::ContextType> types; - QV4::Scope scope(engine()); - QV4::SimpleCallContext *sctxt = findContext(frame); - if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext) - return types; + QV4::Heap::ExecutionContext *it = findFrame(frame)->context()->d(); - QV4::ScopedContext it(scope, sctxt); - for (; it; it = it->d()->outer) - types.append(QV4::Heap::ExecutionContext::ContextType(it->d()->type)); + for (; it; it = it->outer) + types.append(QV4::Heap::ExecutionContext::ContextType(it->type)); return types; } @@ -109,7 +105,6 @@ int QV4DataCollector::encodeScopeType(QV4::Heap::ExecutionContext::ContextType s return 4; case QV4::Heap::ExecutionContext::Type_WithContext: return 2; - case QV4::Heap::ExecutionContext::Type_SimpleCallContext: case QV4::Heap::ExecutionContext::Type_CallContext: return 1; case QV4::Heap::ExecutionContext::Type_QmlContext: @@ -267,27 +262,17 @@ bool QV4DataCollector::collectScope(QJsonObject *dict, int frameNr, int scopeNr) QStringList names; QV4::Scope scope(engine()); + QV4::Scoped<QV4::CallContext> ctxt(scope, findScope(findContext(frameNr), scopeNr)); if (!ctxt) return false; Refs collectedRefs; QV4::ScopedValue v(scope); - int nFormals = ctxt->formalCount(); - for (unsigned i = 0, ei = nFormals; i != ei; ++i) { - QString qName; - if (QV4::Identifier *name = ctxt->formals()[nFormals - i - 1]) - qName = name->string; - names.append(qName); - v = ctxt->argument(i); - collectedRefs.append(collect(v)); - } - - for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) { - QString qName; - if (QV4::Identifier *name = ctxt->variables()[i]) - qName = name->string; - names.append(qName); + QV4::InternalClass *ic = ctxt->internalClass(); + for (uint i = 0; i < ic->size; ++i) { + QString name = ic->nameMap[i]->string; + names.append(name); v = ctxt->d()->locals[i]; collectedRefs.append(collect(v)); } @@ -338,7 +323,7 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int QV4::Scope scope(engine()); QV4::ScopedContext ctxt(scope, findContext(frameNr)); while (ctxt) { - if (QV4::SimpleCallContext *cCtxt = ctxt->asSimpleCallContext()) { + if (QV4::CallContext *cCtxt = ctxt->asCallContext()) { if (cCtxt->d()->activation) break; } @@ -346,7 +331,7 @@ QJsonObject QV4DataCollector::buildFrame(const QV4::StackFrame &stackFrame, int } if (ctxt) { - QV4::ScopedValue o(scope, ctxt->asSimpleCallContext()->d()->activation); + QV4::ScopedValue o(scope, ctxt->d()->activation); frame[QLatin1String("receiver")] = toRef(collect(o)); } diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h index de12e8d527..87be009de5 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h @@ -58,11 +58,12 @@ public: typedef uint Ref; typedef QVector<uint> Refs; - static QV4::Heap::SimpleCallContext *findScope(QV4::ExecutionContext *ctxt, int scope); + static QV4::Heap::CallContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope); static int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType); QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(int frame); - QV4::SimpleCallContext *findContext(int frame); + QV4::Heap::ExecutionContext *findContext(int frame); + QV4::CppStackFrame *findFrame(int frame); QV4DataCollector(QV4::ExecutionEngine *engine); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp index b82df9c6a9..1581cf637d 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp @@ -115,7 +115,7 @@ void QV4Debugger::resume(Speed speed) if (!m_returnedValue.isUndefined()) m_returnedValue.set(m_engine, QV4::Encode::undefined()); - m_currentContext.set(m_engine, *m_engine->currentContext); + m_currentFrame = m_engine->currentStackFrame; m_stepping = speed; m_runningCondition.wakeAll(); } @@ -158,7 +158,7 @@ QV4Debugger::ExecutionState QV4Debugger::currentExecutionState() const { ExecutionState state; state.fileName = getFunction()->sourceFile(); - state.lineNumber = engine()->current->lineNumber; + state.lineNumber = engine()->currentStackFrame->lineNumber(); return state; } @@ -187,7 +187,7 @@ void QV4Debugger::maybeBreakAtInstruction() switch (m_stepping) { case StepOver: - if (m_currentContext.asManaged()->d() != m_engine->current) + if (m_currentFrame != m_engine->currentStackFrame) break; // fall through case StepIn: @@ -203,7 +203,8 @@ void QV4Debugger::maybeBreakAtInstruction() pauseAndWait(PauseRequest); } else if (m_haveBreakPoints) { if (QV4::Function *f = getFunction()) { - const int lineNumber = engine()->current->lineNumber; + // lineNumber will be negative for Ret instructions, so those won't match + const int lineNumber = engine()->currentStackFrame->lineNumber(); if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber)) pauseAndWait(BreakPointHit); } @@ -216,9 +217,8 @@ void QV4Debugger::enteringFunction() return; QMutexLocker locker(&m_lock); - if (m_stepping == StepIn) { - m_currentContext.set(m_engine, *m_engine->currentContext); - } + if (m_stepping == StepIn) + m_currentFrame = m_engine->currentStackFrame; } void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal) @@ -229,13 +229,8 @@ void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal) QMutexLocker locker(&m_lock); - if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) { - if (QV4::ExecutionContext *parentContext - = m_engine->parentContext(m_engine->currentContext)) { - m_currentContext.set(m_engine, *parentContext); - } else { - m_currentContext.clear(); - } + if (m_stepping != NotStepping && m_currentFrame == m_engine->currentStackFrame) { + m_currentFrame = m_currentFrame->parent; m_stepping = StepOver; m_returnedValue.set(m_engine, retVal); } @@ -255,10 +250,8 @@ void QV4Debugger::aboutToThrow() QV4::Function *QV4Debugger::getFunction() const { - QV4::Scope scope(m_engine); - QV4::ExecutionContext *context = m_engine->currentContext; - if (QV4::Function *function = context->getFunction()) - return function; + if (m_engine->currentStackFrame) + return m_engine->currentStackFrame->v4Function; else return m_engine->globalCode; } diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h index 06014302e6..4a755f2b72 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h @@ -150,7 +150,7 @@ private: void runJobUnpaused(); QV4::ExecutionEngine *m_engine; - QV4::PersistentValue m_currentContext; + QV4::CppStackFrame *m_currentFrame = 0; QMutex m_lock; QWaitCondition m_runningCondition; State m_state; diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp index 9a34d5770a..87e75c49b5 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp @@ -79,20 +79,19 @@ void QV4DebuggerAgent::debuggerPaused(QV4Debugger *debugger, QV4Debugger::PauseR case QV4Debugger::PauseRequest: case QV4Debugger::BreakPointHit: { event.insert(QStringLiteral("event"), QStringLiteral("break")); - QVector<QV4::StackFrame> frames = debugger->stackTrace(1); - if (frames.isEmpty()) + QV4::CppStackFrame *frame = debugger->engine()->currentStackFrame; + if (!frame) break; - const QV4::StackFrame &topFrame = frames.first(); - body.insert(QStringLiteral("invocationText"), topFrame.function); - body.insert(QStringLiteral("sourceLine"), topFrame.line - 1); - if (topFrame.column > 0) - body.insert(QStringLiteral("sourceColumn"), topFrame.column); + body.insert(QStringLiteral("invocationText"), frame->function()); + body.insert(QStringLiteral("sourceLine"), qAbs(frame->lineNumber()) - 1); +// if (frame->column > 0) +// body.insert(QStringLiteral("sourceColumn"), frame->column); QJsonArray breakPoints; - foreach (int breakPointId, breakPointIds(topFrame.source, topFrame.line)) + foreach (int breakPointId, breakPointIds(frame->source(), frame->lineNumber())) breakPoints.push_back(breakPointId); body.insert(QStringLiteral("breakpoints"), breakPoints); - script.insert(QStringLiteral("name"), topFrame.source); + script.insert(QStringLiteral("name"), frame->source()); } break; case QV4Debugger::Throwing: // TODO: complete this! diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp index d57d7e7406..6f254c9e28 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp @@ -44,6 +44,7 @@ #include <private/qv4qmlcontext_p.h> #include <private/qv4qobjectwrapper_p.h> #include <private/qqmldebugservice_p.h> +#include <private/qv4jscall_p.h> #include <QtQml/qqmlengine.h> @@ -63,26 +64,21 @@ void JavaScriptJob::run() { QV4::Scope scope(engine); - QV4::ExecutionContextSaver saver(scope); - - QV4::ExecutionContext *ctx = engine->currentContext; + QV4::ScopedContext ctx(scope, engine->currentStackFrame ? engine->currentContext() + : engine->rootContext()); QObject scopeObject; - if (frameNr > 0) { - for (int i = 0; i < frameNr; ++i) { - ctx = engine->parentContext(ctx); - } - engine->pushContext(ctx); - ctx = engine->currentContext; - } + QV4::CppStackFrame *frame = engine->currentStackFrame; + + for (int i = 0; frame && i < frameNr; ++i) + frame = frame->parent; + if (frameNr > 0 && frame) + ctx = static_cast<QV4::ExecutionContext *>(&frame->jsFrame->context); if (context >= 0) { QQmlContext *extraContext = qmlContext(QQmlDebugService::objectForId(context)); - if (extraContext) { - engine->pushContext(QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), - &scopeObject)); - ctx = engine->currentContext; - } + if (extraContext) + ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(extraContext), &scopeObject); } else if (frameNr < 0) { // Use QML context if available QQmlEngine *qmlEngine = engine->qmlEngine(); if (qmlEngine) { @@ -102,18 +98,15 @@ void JavaScriptJob::run() } } } - if (!engine->qmlContext()) { - engine->pushContext(QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), - &scopeObject)); - ctx = engine->currentContext; - } - engine->pushContext(ctx->newWithContext(withContext->toObject(engine))); - ctx = engine->currentContext; + if (!engine->qmlContext()) + ctx = QV4::QmlContext::create(ctx, QQmlContextData::get(qmlRootContext), &scopeObject); } } - QV4::Script script(ctx, this->script); - script.strictMode = ctx->d()->strictMode; + QV4::Script script(ctx, QV4::Compiler::EvalCode, this->script); + if (const QV4::Function *function = frame ? frame->v4Function : engine->globalCode) + script.strictMode = function->isStrict(); + // In order for property lookups in QML to work, we need to disable fast v4 lookups. That // is a side-effect of inheritContext. script.inheritContext = true; @@ -214,12 +207,15 @@ void ValueLookupJob::run() // set if the engine is currently executing QML code. QScopedPointer<QObject> scopeObject; QV4::ExecutionEngine *engine = collector->engine(); + QV4::Scope scope(engine); + QV4::Heap::ExecutionContext *qmlContext = 0; if (engine->qmlEngine() && !engine->qmlContext()) { scopeObject.reset(new QObject); - engine->pushContext(QV4::QmlContext::create(engine->currentContext, + qmlContext = QV4::QmlContext::create(engine->currentContext(), QQmlContextData::get(engine->qmlEngine()->rootContext()), - scopeObject.data())); + scopeObject.data()); } + QV4::ScopedStackFrame frame(scope, qmlContext); for (const QJsonValue &handle : handles) { QV4DataCollector::Ref ref = handle.toInt(); if (!collector->isValidRef(ref)) { @@ -229,8 +225,6 @@ void ValueLookupJob::run() result[QString::number(ref)] = collector->lookupRef(ref, true); } flushRedundantRefs(); - if (scopeObject) - engine->popContext(); } const QString &ValueLookupJob::exceptionMessage() const diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp index fe00ed1e28..fca811cb28 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugservice.cpp @@ -42,7 +42,6 @@ #include "qqmlengine.h" #include <private/qv4engine_p.h> -#include <private/qv4isel_moth_p.h> #include <private/qv4function_p.h> #include <private/qqmldebugconnector_p.h> #include <private/qv8engine_p.h> @@ -706,7 +705,6 @@ void QV4DebugServiceImpl::engineAdded(QJSEngine *engine) QV4::ExecutionEngine *ee = QV8Engine::getV4(engine->handle()); if (QQmlDebugConnector *server = QQmlDebugConnector::instance()) { if (ee) { - ee->iselFactory.reset(new QV4::Moth::ISelFactory); QV4Debugger *debugger = new QV4Debugger(ee); if (state() == Enabled) ee->setDebugger(debugger); diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp index cff1728f49..eeedb59ce6 100644 --- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp @@ -49,7 +49,6 @@ #include <private/qv4objectiterator_p.h> #include <private/qv4identifier_p.h> #include <private/qv4runtime_p.h> -#include <private/qv4isel_moth_p.h> #include <private/qqmldebugpacket_p.h> #include <private/qqmldebugserviceinterfaces_p.h> @@ -208,7 +207,7 @@ private: void handleDebuggerDeleted(QObject *debugger); - void evaluateExpression(QV4::Scope &scope, const QString &expression); + QV4::ReturnedValue evaluateExpression(const QString &expression); bool checkCondition(const QString &expression); QStringList breakOnSignals; @@ -230,7 +229,7 @@ private: QV4::ExecutionEngine *m_engine; QQmlNativeDebugServiceImpl *m_service; - QV4::PersistentValue m_currentContext; + QV4::CppStackFrame *m_currentFrame = 0; Speed m_stepping; bool m_pauseRequested; bool m_runningJob; @@ -241,29 +240,31 @@ private: bool NativeDebugger::checkCondition(const QString &expression) { QV4::Scope scope(m_engine); - evaluateExpression(scope, expression); - return scope.result.booleanValue(); + QV4::ScopedValue r(scope, evaluateExpression(expression)); + return r->booleanValue(); } -void NativeDebugger::evaluateExpression(QV4::Scope &scope, const QString &expression) +QV4::ReturnedValue NativeDebugger::evaluateExpression(const QString &expression) { + QV4::Scope scope(m_engine); m_runningJob = true; - QV4::ExecutionContextSaver saver(scope); - - QV4::ExecutionContext *ctx = m_engine->currentContext; - m_engine->pushContext(ctx); + QV4::ExecutionContext *ctx = m_engine->currentStackFrame ? m_engine->currentContext() + : m_engine->rootContext(); - QV4::Script script(ctx, expression); - script.strictMode = ctx->d()->strictMode; + QV4::Script script(ctx, QV4::Compiler::EvalCode, expression); + if (const QV4::Function *function = m_engine->currentStackFrame + ? m_engine->currentStackFrame->v4Function : m_engine->globalCode) + script.strictMode = function->isStrict(); // In order for property lookups in QML to work, we need to disable fast v4 lookups. // That is a side-effect of inheritContext. script.inheritContext = true; script.parse(); if (!m_engine->hasException) - scope.result = script.run(); + return script.run(); m_runningJob = false; + return QV4::Encode::undefined(); } NativeDebugger::NativeDebugger(QQmlNativeDebugServiceImpl *service, QV4::ExecutionEngine *engine) @@ -314,19 +315,19 @@ void NativeDebugger::handleCommand(QJsonObject *response, const QString &cmd, handleContinue(response, NotStepping); } -static QString encodeContext(QV4::ExecutionContext *executionContext) +static QString encodeFrame(QV4::CppStackFrame *f) { QQmlDebugPacket ds; - ds << quintptr(executionContext); + ds << quintptr(f); return QString::fromLatin1(ds.data().toHex()); } -static void decodeContext(const QString &context, QV4::ExecutionContext **executionContext) +static void decodeFrame(const QString &f, QV4::CppStackFrame **frame) { - quintptr rawContext; - QQmlDebugPacket ds(QByteArray::fromHex(context.toLatin1())); - ds >> rawContext; - *executionContext = reinterpret_cast<QV4::ExecutionContext *>(rawContext); + quintptr rawFrame; + QQmlDebugPacket ds(QByteArray::fromHex(f.toLatin1())); + ds >> rawFrame; + *frame = reinterpret_cast<QV4::CppStackFrame *>(rawFrame); } void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &arguments) @@ -334,25 +335,24 @@ void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &a int limit = arguments.value(QLatin1String("limit")).toInt(0); QJsonArray frameArray; - QV4::ExecutionContext *executionContext = m_engine->currentContext; - for (int i = 0; i < limit && executionContext; ++i) { - if (QV4::Function *function = executionContext->getFunction()) { + QV4::CppStackFrame *f= m_engine->currentStackFrame; + for (int i = 0; i < limit && f; ++i) { + QV4::Function *function = f->v4Function; - QJsonObject frame; - frame.insert(QStringLiteral("language"), QStringLiteral("js")); - frame.insert(QStringLiteral("context"), encodeContext(executionContext)); + QJsonObject frame; + frame.insert(QStringLiteral("language"), QStringLiteral("js")); + frame.insert(QStringLiteral("context"), encodeFrame(f)); - if (QV4::Heap::String *functionName = function->name()) - frame.insert(QStringLiteral("function"), functionName->toQString()); - frame.insert(QStringLiteral("file"), function->sourceFile()); + if (QV4::Heap::String *functionName = function->name()) + frame.insert(QStringLiteral("function"), functionName->toQString()); + frame.insert(QStringLiteral("file"), function->sourceFile()); - int line = executionContext->d()->lineNumber; - frame.insert(QStringLiteral("line"), (line < 0 ? -line : line)); + int line = f->lineNumber(); + frame.insert(QStringLiteral("line"), (line < 0 ? -line : line)); - frameArray.push_back(frame); - } + frameArray.push_back(frame); - executionContext = m_engine->parentContext(executionContext); + f = f->parent; } response->insert(QStringLiteral("frames"), frameArray); @@ -457,15 +457,15 @@ void Collector::collect(QJsonArray *out, const QString &parentIName, const QStri void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &arguments) { TRACE_PROTOCOL("Build variables"); - QV4::ExecutionContext *executionContext = 0; - decodeContext(arguments.value(QLatin1String("context")).toString(), &executionContext); - if (!executionContext) { - setError(response, QStringLiteral("No execution context passed")); + QV4::CppStackFrame *frame = 0; + decodeFrame(arguments.value(QLatin1String("context")).toString(), &frame); + if (!frame) { + setError(response, QStringLiteral("No stack frame passed")); return; } - TRACE_PROTOCOL("Context: " << executionContext); + TRACE_PROTOCOL("Context: " << frame); - QV4::ExecutionEngine *engine = executionContext->engine(); + QV4::ExecutionEngine *engine = frame->v4Function->internalClass->engine; if (!engine) { setError(response, QStringLiteral("No execution engine passed")); return; @@ -481,28 +481,16 @@ void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &a QJsonArray output; QV4::Scope scope(engine); - if (QV4::SimpleCallContext *callContext = executionContext->asSimpleCallContext()) { - QV4::Value thisObject = callContext->thisObject(); - collector.collect(&output, QString(), QStringLiteral("this"), thisObject); - QV4::Identifier *const *variables = callContext->variables(); - QV4::Identifier *const *formals = callContext->formals(); - if (callContext->d()->type == QV4::Heap::ExecutionContext::Type_CallContext) { - QV4::CallContext *ctx = static_cast<QV4::CallContext *>(callContext); - for (unsigned i = 0, ei = ctx->variableCount(); i != ei; ++i) { - QString qName; - if (QV4::Identifier *name = variables[i]) - qName = name->string; - QV4::Value val = ctx->d()->locals[i]; - collector.collect(&output, QString(), qName, val); - } - } - for (unsigned i = 0, ei = callContext->formalCount(); i != ei; ++i) { - QString qName; - if (QV4::Identifier *name = formals[i]) - qName = name->string; - QV4::ReturnedValue rval = callContext->argument(i); - QV4::ScopedValue sval(scope, rval); - collector.collect(&output, QString(), qName, *sval); + QV4::ScopedValue thisObject(scope, frame->thisObject()); + collector.collect(&output, QString(), QStringLiteral("this"), thisObject); + QV4::Scoped<QV4::CallContext> callContext(scope, frame->callContext()); + if (callContext) { + QV4::InternalClass *ic = callContext->internalClass(); + QV4::ScopedValue v(scope); + for (uint i = 0; i < ic->size; ++i) { + QString name = ic->nameMap[i]->string; + v = callContext->d()->locals[i]; + collector.collect(&output, QString(), name, v); } } @@ -512,15 +500,15 @@ void NativeDebugger::handleVariables(QJsonObject *response, const QJsonObject &a void NativeDebugger::handleExpressions(QJsonObject *response, const QJsonObject &arguments) { TRACE_PROTOCOL("Evaluate expressions"); - QV4::ExecutionContext *executionContext = 0; - decodeContext(arguments.value(QLatin1String("context")).toString(), &executionContext); - if (!executionContext) { - setError(response, QStringLiteral("No execution context passed")); + QV4::CppStackFrame *frame = 0; + decodeFrame(arguments.value(QLatin1String("context")).toString(), &frame); + if (!frame) { + setError(response, QStringLiteral("No stack frame passed")); return; } TRACE_PROTOCOL("Context: " << executionContext); - QV4::ExecutionEngine *engine = executionContext->engine(); + QV4::ExecutionEngine *engine = frame->v4Function->internalClass->engine; if (!engine) { setError(response, QStringLiteral("No execution engine passed")); return; @@ -543,8 +531,7 @@ void NativeDebugger::handleExpressions(QJsonObject *response, const QJsonObject TRACE_PROTOCOL("Evaluate expression: " << expression); m_runningJob = true; - evaluateExpression(scope, expression); - QV4::ScopedValue result(scope, scope.result); + QV4::ScopedValue result(scope, evaluateExpression(expression)); m_runningJob = false; if (result->isUndefined()) { @@ -595,7 +582,7 @@ void NativeDebugger::handleContinue(QJsonObject *response, Speed speed) if (!m_returnedValue.isUndefined()) m_returnedValue.set(m_engine, QV4::Encode::undefined()); - m_currentContext.set(m_engine, *m_engine->currentContext); + m_currentFrame = m_engine->currentStackFrame; m_stepping = speed; } @@ -605,7 +592,7 @@ void NativeDebugger::maybeBreakAtInstruction() return; if (m_stepping == StepOver) { - if (m_currentContext.asManaged()->d() == m_engine->current) + if (m_currentFrame == m_engine->currentStackFrame) pauseAndWait(); return; } @@ -623,7 +610,8 @@ void NativeDebugger::maybeBreakAtInstruction() if (m_service->m_breakHandler->m_haveBreakPoints) { if (QV4::Function *function = getFunction()) { - const int lineNumber = m_engine->current->lineNumber; + // lineNumber will be negative for Ret instructions, so those won't match + const int lineNumber = m_engine->currentStackFrame->lineNumber(); if (reallyHitTheBreakPoint(function, lineNumber)) pauseAndWait(); } @@ -636,7 +624,7 @@ void NativeDebugger::enteringFunction() return; if (m_stepping == StepIn) { - m_currentContext.set(m_engine, *m_engine->currentContext); + m_currentFrame = m_engine->currentStackFrame; } } @@ -645,8 +633,8 @@ void NativeDebugger::leavingFunction(const QV4::ReturnedValue &retVal) if (m_runningJob) return; - if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) { - m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext)); + if (m_stepping != NotStepping && m_currentFrame == m_engine->currentStackFrame) { + m_currentFrame = m_currentFrame->parent; m_stepping = StepOver; m_returnedValue.set(m_engine, retVal); } @@ -668,9 +656,8 @@ void NativeDebugger::aboutToThrow() QV4::Function *NativeDebugger::getFunction() const { - QV4::ExecutionContext *context = m_engine->currentContext; - if (QV4::Function *function = context->getFunction()) - return function; + if (m_engine->currentStackFrame) + return m_engine->currentStackFrame->v4Function; else return m_engine->globalCode; } @@ -681,12 +668,11 @@ void NativeDebugger::pauseAndWait() event.insert(QStringLiteral("event"), QStringLiteral("break")); event.insert(QStringLiteral("language"), QStringLiteral("js")); - if (QV4::ExecutionContext *executionContext = m_engine->currentContext) { - if (QV4::Function *function = executionContext->getFunction()) { - event.insert(QStringLiteral("file"), function->sourceFile()); - int line = executionContext->d()->lineNumber; - event.insert(QStringLiteral("line"), (line < 0 ? -line : line)); - } + if (QV4::CppStackFrame *frame = m_engine->currentStackFrame) { + QV4::Function *function = frame->v4Function; + event.insert(QStringLiteral("file"), function->sourceFile()); + int line = frame->lineNumber(); + event.insert(QStringLiteral("line"), (line < 0 ? -line : line)); } m_service->emitAsynchronousMessageToClient(event); @@ -731,7 +717,6 @@ void QQmlNativeDebugServiceImpl::engineAboutToBeAdded(QJSEngine *engine) TRACE_PROTOCOL("Adding execution engine" << ee); if (ee) { NativeDebugger *debugger = new NativeDebugger(this, ee); - ee->iselFactory.reset(new QV4::Moth::ISelFactory); if (state() == Enabled) ee->setDebugger(debugger); m_debuggers.append(QPointer<NativeDebugger>(debugger)); |