aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-08-08 10:56:34 +0200
committerLars Knoll <lars.knoll@qt.io>2017-08-10 08:19:18 +0000
commit5bc4f4d958a3b76f3435d61206ca0109f07aa1a3 (patch)
treecb2ef4772f2d343e9957271161ac32809bc5d0a6 /src/plugins
parent30e3664bf3668bda9a211fe7d1404f8f806dbf7b (diff)
Refactor context handling
Fix the push/pop context instructions to not modify the JS stack anymore, as that can cause conflicts with the VME (and was an ugly hack in any case). Instead, these instructions not return the old context, that is then stored in a temporary. Get rid of Engine::current and Engine::currentContext. The StackFrame structures do now contain the only and authoritive data. This finally gives us a nice setup where we create and destroy frames on the stack when entering/leaving functions. Change-Id: If161e3e941f59865c47ecfe1e094faf62b52bfa0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp38
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp24
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.h2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp38
-rw-r--r--src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp19
6 files changed, 47 insertions, 78 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index 6686e61a1c..76d5315004 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -55,47 +55,37 @@
QT_BEGIN_NAMESPACE
-QV4::CallContext *QV4DataCollector::findContext(int frame)
+QV4::Heap::CallContext *QV4DataCollector::findContext(int frame)
{
- QV4::ExecutionContext *ctx = engine()->currentContext;
- while (ctx) {
- QV4::CallContext *cCtxt = ctx->asCallContext();
- if (cCtxt && cCtxt->d()->v4Function) {
- if (frame < 1)
- return cCtxt;
- --frame;
- }
- ctx = engine()->parentContext(ctx);
+ QV4::EngineBase::StackFrame *f = engine()->currentStackFrame;
+ while (f && frame) {
+ --frame;
+ f = f->parent;
}
- return 0;
+ return f ? f->callContext() : 0;
}
-QV4::Heap::CallContext *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->asCallContext()->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::CallContext *sctxt = findContext(frame);
- if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
- return types;
+ QV4::Heap::ExecutionContext *it = findContext(frame);
- 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;
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index 2c2514a1b3..c924f10d8c 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -58,11 +58,11 @@ public:
typedef uint Ref;
typedef QVector<uint> Refs;
- static QV4::Heap::CallContext *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::CallContext *findContext(int frame);
+ QV4::Heap::CallContext *findContext(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 1bd8581fbb..c95d4ea99f 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();
}
@@ -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:
@@ -216,9 +216,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 +228,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 +249,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 cd412e573d..b2200c47fc 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::EngineBase::StackFrame *m_currentFrame = 0;
QMutex m_lock;
QWaitCondition m_runningCondition;
State m_state;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index 80ead1516a..45af1f44a5 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -63,26 +63,20 @@ void JavaScriptJob::run()
{
QV4::Scope scope(engine);
- QV4::ExecutionContextSaver saver(engine);
-
- QV4::ExecutionContext *ctx = engine->currentContext;
+ QV4::ScopedContext ctx(scope, engine->currentContext());
QObject scopeObject;
if (frameNr > 0) {
- for (int i = 0; i < frameNr; ++i) {
- ctx = engine->parentContext(ctx);
- }
- engine->pushContext(ctx);
- ctx = engine->currentContext;
+ QV4::EngineBase::StackFrame *f = engine->currentStackFrame;
+ for (int i = 0; i < frameNr; ++i)
+ f = f->parent;
+ ctx = static_cast<QV4::ExecutionContext *>(&f->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,13 +96,8 @@ 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);
}
}
@@ -214,12 +203,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 +221,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_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
index 7f11cea9ab..32c67b3986 100644
--- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
@@ -229,7 +229,7 @@ private:
QV4::ExecutionEngine *m_engine;
QQmlNativeDebugServiceImpl *m_service;
- QV4::PersistentValue m_currentContext;
+ QV4::EngineBase::StackFrame *m_currentFrame = 0;
Speed m_stepping;
bool m_pauseRequested;
bool m_runningJob;
@@ -249,10 +249,7 @@ QV4::ReturnedValue NativeDebugger::evaluateExpression(const QString &expression)
QV4::Scope scope(m_engine);
m_runningJob = true;
- QV4::ExecutionContextSaver saver(m_engine);
-
- QV4::ExecutionContext *ctx = m_engine->currentContext;
- m_engine->pushContext(ctx);
+ QV4::ExecutionContext *ctx = m_engine->currentContext();
QV4::Script script(ctx, expression);
script.strictMode = ctx->d()->v4Function->isStrict();
@@ -594,7 +591,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;
}
@@ -604,7 +601,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;
}
@@ -635,7 +632,7 @@ void NativeDebugger::enteringFunction()
return;
if (m_stepping == StepIn) {
- m_currentContext.set(m_engine, *m_engine->currentContext);
+ m_currentFrame = m_engine->currentStackFrame;
}
}
@@ -644,8 +641,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);
}
@@ -667,7 +664,7 @@ void NativeDebugger::aboutToThrow()
QV4::Function *NativeDebugger::getFunction() const
{
- QV4::ExecutionContext *context = m_engine->currentContext;
+ QV4::ExecutionContext *context = m_engine->currentContext();
if (QV4::Function *function = context->getFunction())
return function;
else