aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--src/qml/compiler/qv4codegen.cpp5
-rw-r--r--src/qml/compiler/qv4compilercontrolflow_p.h24
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp16
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h21
-rw-r--r--src/qml/jsapi/qjsengine.cpp11
-rw-r--r--src/qml/jsruntime/qv4context.cpp31
-rw-r--r--src/qml/jsruntime/qv4engine.cpp19
-rw-r--r--src/qml/jsruntime/qv4engine_p.h57
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h9
-rw-r--r--src/qml/jsruntime/qv4function_p.h2
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp16
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h12
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp13
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp56
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h6
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h38
-rw-r--r--src/qml/jsruntime/qv4script.cpp3
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp67
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp3
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp8
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp3
30 files changed, 245 insertions, 308 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
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 2a474eaad5..a0f1ce5879 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2466,13 +2466,10 @@ bool Codegen::visit(WithStatement *ast)
if (hasError)
return false;
src = src.storeOnStack(); // trigger load before we setup the exception handler, so exceptions here go to the right place
+ src.loadInAccumulator();
ControlFlowWith flow(this);
- src.loadInAccumulator();
- Instruction::CallBuiltinPushScope pushScope;
- bytecodeGenerator->addInstruction(pushScope);
-
statement(ast->statement);
return false;
diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h
index 2735761246..bbfe9e2deb 100644
--- a/src/qml/compiler/qv4compilercontrolflow_p.h
+++ b/src/qml/compiler/qv4compilercontrolflow_p.h
@@ -274,6 +274,13 @@ struct ControlFlowWith : public ControlFlowUnwind
: ControlFlowUnwind(cg, With)
{
needsLookupByName = true;
+
+ savedContextRegister = Moth::StackSlot::createRegister(generator()->newRegister());
+
+ // assumes the with object is in the accumulator
+ Instruction::CallBuiltinPushWithContext pushScope;
+ pushScope.reg = savedContextRegister;
+ generator()->addInstruction(pushScope);
generator()->setExceptionHandler(&unwindLabel);
}
@@ -282,11 +289,13 @@ struct ControlFlowWith : public ControlFlowUnwind
unwindLabel.link();
generator()->setExceptionHandler(parentExceptionHandler());
- Instruction::CallBuiltinPopScope pop;
+ Instruction::CallBuiltinPopContext pop;
+ pop.reg = savedContextRegister;
generator()->addInstruction(pop);
emitUnwindHandler();
}
+ Moth::StackSlot savedContextRegister;
};
struct ControlFlowCatch : public ControlFlowUnwind
@@ -330,12 +339,16 @@ struct ControlFlowCatch : public ControlFlowUnwind
needsLookupByName = true;
insideCatch = true;
+ Codegen::RegisterScope scope(cg);
+
// exceptions inside the try block go here
exceptionLabel.link();
Reference name = Reference::fromName(cg, catchExpression->name.toString());
- Instruction::CallBuiltinPushCatchScope pushCatchScope;
- pushCatchScope.name = name.unqualifiedNameIndex;
- generator()->addInstruction(pushCatchScope);
+ Moth::StackSlot savedContextReg = Moth::StackSlot::createRegister(generator()->newRegister());
+ Instruction::CallBuiltinPushCatchContext pushCatch;
+ pushCatch.name = name.unqualifiedNameIndex;
+ pushCatch.reg = savedContextReg;
+ generator()->addInstruction(pushCatch);
// clear the unwind temp for exceptions, we want to resume normal code flow afterwards
Reference::storeConstOnStack(cg, QV4::Encode::undefined(), controlFlowTemp);
generator()->setExceptionHandler(&catchUnwindLabel);
@@ -347,7 +360,8 @@ struct ControlFlowCatch : public ControlFlowUnwind
// exceptions inside catch and break/return statements go here
catchUnwindLabel.link();
- Instruction::CallBuiltinPopScope pop;
+ Instruction::CallBuiltinPopContext pop;
+ pop.reg = savedContextReg;
generator()->addInstruction(pop);
// break/continue/return statements in try go here
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index ea351dcc76..db68c2d76f 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -276,15 +276,17 @@ void dumpBytecode(const char *code, int len, int nFormals)
MOTH_BEGIN_INSTR(CallBuiltinUnwindException)
MOTH_END_INSTR(CallBuiltinUnwindException)
- MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
- d << instr.name;
- MOTH_END_INSTR(CallBuiltinPushCatchScope)
+ MOTH_BEGIN_INSTR(CallBuiltinPushCatchContext)
+ d << instr.reg.dump(nFormals) << ", " << instr.name;
+ MOTH_END_INSTR(CallBuiltinPushCatchContext)
- MOTH_BEGIN_INSTR(CallBuiltinPushScope)
- MOTH_END_INSTR(CallBuiltinPushScope)
+ MOTH_BEGIN_INSTR(CallBuiltinPushWithContext)
+ d << instr.reg.dump(nFormals);
+ MOTH_END_INSTR(CallBuiltinPushWithContext)
- MOTH_BEGIN_INSTR(CallBuiltinPopScope)
- MOTH_END_INSTR(CallBuiltinPopScope)
+ MOTH_BEGIN_INSTR(CallBuiltinPopContext)
+ d << instr.reg.dump(nFormals);
+ MOTH_END_INSTR(CallBuiltinPopContext)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 54d085e820..52d0497926 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -111,9 +111,9 @@ QT_BEGIN_NAMESPACE
F(GetException, getException) \
F(SetException, setException) \
F(CallBuiltinUnwindException, callBuiltinUnwindException) \
- F(CallBuiltinPushCatchScope, callBuiltinPushCatchScope) \
- F(CallBuiltinPushScope, callBuiltinPushScope) \
- F(CallBuiltinPopScope, callBuiltinPopScope) \
+ F(CallBuiltinPushCatchContext, callBuiltinPushCatchContext) \
+ F(CallBuiltinPushWithContext, callBuiltinPushWithContext) \
+ F(CallBuiltinPopContext, callBuiltinPopContext) \
F(CallBuiltinForeachIteratorObject, callBuiltinForeachIteratorObject) \
F(CallBuiltinForeachNextPropertyName, callBuiltinForeachNextPropertyName) \
F(CallBuiltinDeleteMember, callBuiltinDeleteMember) \
@@ -443,15 +443,18 @@ union Instr
struct instr_callBuiltinUnwindException {
MOTH_INSTR_HEADER
};
- struct instr_callBuiltinPushCatchScope {
+ struct instr_callBuiltinPushCatchContext {
MOTH_INSTR_HEADER
int name;
+ StackSlot reg;
};
- struct instr_callBuiltinPushScope {
+ struct instr_callBuiltinPushWithContext {
MOTH_INSTR_HEADER
+ StackSlot reg;
};
- struct instr_callBuiltinPopScope {
+ struct instr_callBuiltinPopContext {
MOTH_INSTR_HEADER
+ StackSlot reg;
};
struct instr_callBuiltinForeachIteratorObject {
MOTH_INSTR_HEADER
@@ -729,9 +732,9 @@ union Instr
instr_setException setException;
instr_setExceptionHandler setExceptionHandler;
instr_callBuiltinUnwindException callBuiltinUnwindException;
- instr_callBuiltinPushCatchScope callBuiltinPushCatchScope;
- instr_callBuiltinPushScope callBuiltinPushScope;
- instr_callBuiltinPopScope callBuiltinPopScope;
+ instr_callBuiltinPushCatchContext callBuiltinPushCatchContext;
+ instr_callBuiltinPushWithContext callBuiltinPushWithContext;
+ instr_callBuiltinPopContext callBuiltinPopContext;
instr_callBuiltinForeachIteratorObject callBuiltinForeachIteratorObject;
instr_callBuiltinForeachNextPropertyName callBuiltinForeachNextPropertyName;
instr_callBuiltinDeleteMember callBuiltinDeleteMember;
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 5027975d84..16aa5dc728 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -438,14 +438,9 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
{
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
- QV4::ExecutionContextSaver saver(v4);
-
- QV4::ExecutionContext *ctx = v4->currentContext;
- if (ctx->d() != v4->rootContext()->d())
- ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
- QV4::Script script(ctx, program, fileName, lineNumber);
+ QV4::Script script(v4->rootContext(), program, fileName, lineNumber);
script.strictMode = false;
if (v4->currentStackFrame)
script.strictMode = v4->currentStackFrame->v4Function->isStrict();
@@ -458,7 +453,9 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
if (scope.engine->hasException)
result = v4->catchException();
- return QJSValue(v4, result->asReturnedValue());
+ QJSValue retval(v4, result->asReturnedValue());
+
+ return retval;
}
/*!
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index ddb5dc4ea5..c9565468ad 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -232,18 +232,16 @@ bool ExecutionContext::deleteProperty(String *name)
// Do a standard call with this execution context as the outer scope
ReturnedValue ExecutionContext::call(ExecutionEngine *engine, CallData *callData, Function *function, const FunctionObject *f)
{
- Scope scope(engine);
- ExecutionContextSaver ctxSaver(engine);
-
- Scoped<CallContext> ctx(scope, newCallContext(function, callData));
+ Heap::CallContext *ctx = newCallContext(function, callData);
if (f)
- ctx->d()->function.set(engine, f->d());
- engine->pushContext(ctx);
+ ctx->function.set(engine, f->d());
- ReturnedValue res = Q_V4_PROFILE(engine, function, f);
+ ReturnedValue res = Q_V4_PROFILE(engine, ctx, function, f);
- if (function->hasQmlDependencies)
- QQmlPropertyCapture::registerQmlDependencies(engine, function->compiledFunction);
+ if (function->hasQmlDependencies) {
+ Q_ASSERT(d()->type == Heap::ExecutionContext::Type_QmlContext);
+ QQmlPropertyCapture::registerQmlDependencies(static_cast<QmlContext *>(this), engine, function->compiledFunction);
+ }
return res;
}
@@ -258,17 +256,12 @@ ReturnedValue QV4::ExecutionContext::simpleCall(ExecutionEngine *engine, CallDat
for (int i = callData->argc; i < (int)function->nFormals; ++i)
callData->args[i] = Encode::undefined();
- ExecutionContext *old = engine->currentContext;
- engine->currentContext = this;
- engine->current = d();
-
- ReturnedValue res = Q_V4_PROFILE(engine, function, 0);
+ ReturnedValue res = Q_V4_PROFILE(engine, d(), function, 0);
- if (function->hasQmlDependencies)
- QQmlPropertyCapture::registerQmlDependencies(engine, function->compiledFunction);
-
- engine->currentContext = old;
- engine->current = old->d();
+ if (function->hasQmlDependencies) {
+ Q_ASSERT(d()->type == Heap::ExecutionContext::Type_QmlContext);
+ QQmlPropertyCapture::registerQmlDependencies(static_cast<QmlContext *>(this), engine, function->compiledFunction);
+ }
engine->jsStackTop = jsStackTop;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 08f4f29763..d10d1d0413 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -527,9 +527,6 @@ void ExecutionEngine::initRootContext()
r->d()->callData->args[0] = Encode::undefined();
jsObjects[RootContext] = r;
jsObjects[IntegerNull] = Encode((int)0);
-
- currentContext = static_cast<ExecutionContext *>(jsObjects + RootContext);
- current = currentContext->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -537,12 +534,10 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
return new (classPool) InternalClass(other);
}
-ExecutionContext *ExecutionEngine::pushGlobalContext()
+Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- pushContext(rootContext()->d());
-
- Q_ASSERT(current == rootContext()->d());
- return currentContext;
+ setCurrentContext(rootContext()->d());
+ return currentContext()->d();
}
InternalClass *ExecutionEngine::newInternalClass(const VTable *vtable, Object *prototype)
@@ -746,11 +741,9 @@ Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
Heap::QmlContext *ExecutionEngine::qmlContext() const
{
- Heap::ExecutionContext *ctx = current;
-
- // get the correct context when we're within a builtin function
- if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
- ctx = parentContext(currentContext)->d();
+ if (!currentStackFrame)
+ return 0;
+ Heap::ExecutionContext *ctx = currentContext()->d();
if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !ctx->outer)
return 0;
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index a628af94cd..3fc79fd67d 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -354,11 +354,11 @@ public:
void setProfiler(Profiling::Profiler *profiler);
#endif // QT_NO_QML_DEBUGGER
- ExecutionContext *pushGlobalContext();
- void pushContext(Heap::ExecutionContext *context);
- void pushContext(ExecutionContext *context);
- void popContext();
- ExecutionContext *parentContext(ExecutionContext *context) const;
+ Heap::ExecutionContext *pushGlobalContext();
+ void setCurrentContext(Heap::ExecutionContext *context);
+ ExecutionContext *currentContext() const {
+ return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
+ }
InternalClass *newInternalClass(const VTable *vtable, Object *prototype);
@@ -469,39 +469,9 @@ struct NoThrowEngine;
#endif
-inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
+inline void ExecutionEngine::setCurrentContext(Heap::ExecutionContext *context)
{
- Q_ASSERT(currentContext && context);
- Value *v = jsAlloca(2);
- v[0] = Encode(context);
- v[1] = Encode((int)(v - static_cast<Value *>(currentContext)));
- currentContext = static_cast<ExecutionContext *>(v);
- current = currentContext->d();
-}
-
-inline void ExecutionEngine::pushContext(ExecutionContext *context)
-{
- pushContext(context->d());
-}
-
-
-inline void ExecutionEngine::popContext()
-{
- Q_ASSERT(jsStackTop > currentContext);
- QV4::Value *offset = (currentContext + 1);
- Q_ASSERT(offset->isInteger());
- int o = offset->integerValue();
- Q_ASSERT(o);
- currentContext -= o;
- current = currentContext->d();
-}
-
-inline ExecutionContext *ExecutionEngine::parentContext(ExecutionContext *context) const
-{
- Value *offset = static_cast<Value *>(context) + 1;
- Q_ASSERT(offset->isInteger());
- int o = offset->integerValue();
- return o ? context - o : 0;
+ currentStackFrame->jsFrame->context = context;
}
inline
@@ -554,6 +524,19 @@ inline bool ExecutionEngine::checkStackLimits()
return false;
}
+inline QV4::ExecutionContext *EngineBase::StackFrame::context() const
+{
+ return static_cast<ExecutionContext *>(&jsFrame->context);
+}
+
+inline QV4::Heap::CallContext *EngineBase::StackFrame::callContext() const
+{
+ Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\
+ while (ctx->type != Heap::ExecutionContext::Type_CallContext)
+ ctx = ctx->outer;
+ return static_cast<Heap::CallContext *>(ctx);
+}
+
} // namespace QV4
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 2aa6910a1c..71cedfd093 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -62,7 +62,7 @@ namespace QV4 {
#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
#pragma pack(push, 1)
#endif
-struct EngineBase {
+struct Q_QML_EXPORT EngineBase {
struct JSStackFrame {
// callData is directly before this
Value jsFunction;
@@ -80,9 +80,10 @@ struct EngineBase {
QString source() const;
QString function() const;
+ QV4::ExecutionContext *context() const;
+ QV4::Heap::CallContext *callContext() const;
};
- Heap::ExecutionContext *current = 0;
StackFrame *currentStackFrame = 0;
Value *jsStackTop = 0;
@@ -99,7 +100,6 @@ struct EngineBase {
Value *jsStackLimit = 0;
Value *jsStackBase = 0;
- ExecutionContext *currentContext = 0;
IdentifierTable *identifierTable = 0;
Object *globalObject = 0;
@@ -135,8 +135,7 @@ struct EngineBase {
#endif
Q_STATIC_ASSERT(std::is_standard_layout<EngineBase>::value);
-Q_STATIC_ASSERT(offsetof(EngineBase, current) == 0);
-Q_STATIC_ASSERT(offsetof(EngineBase, currentStackFrame) == offsetof(EngineBase, current) + QT_POINTER_SIZE);
+Q_STATIC_ASSERT(offsetof(EngineBase, currentStackFrame) == 0);
Q_STATIC_ASSERT(offsetof(EngineBase, jsStackTop) == offsetof(EngineBase, currentStackFrame) + QT_POINTER_SIZE);
Q_STATIC_ASSERT(offsetof(EngineBase, hasException) == offsetof(EngineBase, jsStackTop) + QT_POINTER_SIZE);
Q_STATIC_ASSERT(offsetof(EngineBase, memoryManager) == offsetof(EngineBase, hasException) + QT_POINTER_SIZE);
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index a6b2c0c5d0..0976d22550 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -63,7 +63,7 @@ struct Q_QML_EXPORT Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- typedef ReturnedValue (*Code)(Function *, const FunctionObject *);
+ typedef ReturnedValue (*Code)(Heap::ExecutionContext *c, Function *, const FunctionObject *);
Code code;
const uchar *codeData;
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index f210ff2659..761a8282ae 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -343,16 +343,14 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
return Encode::undefined();
ExecutionEngine *v4 = engine();
- Scope scope(v4);
- ExecutionContextSaver ctxSaver(scope.engine);
+ bool isStrict = v4->currentContext()->d()->v4Function->isStrict();
- ExecutionContext *currentContext = v4->currentContext;
- ExecutionContext *ctx = currentContext;
+ Scope scope(v4);
+ ScopedContext ctx(scope, v4->currentContext());
if (!directCall) {
- // the context for eval should be the global scope, so we fake a root
- // context
- ctx = v4->pushGlobalContext();
+ // the context for eval should be the global scope
+ ctx = v4->rootContext();
}
String *scode = callData->args[0].stringValue();
@@ -363,7 +361,7 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
bool inheritContext = !ctx->d()->v4Function->isStrict();
Script script(ctx, code, QStringLiteral("eval code"));
- script.strictMode = (directCall && currentContext->d()->v4Function->isStrict());
+ script.strictMode = (directCall && isStrict);
script.inheritContext = inheritContext;
script.parse();
if (v4->hasException)
@@ -385,7 +383,7 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall) const
// set the correct v4 function for the context
ctx->d()->v4Function = function;
- return Q_V4_PROFILE(ctx->engine(), function, 0);
+ return Q_V4_PROFILE(v4, ctx->d(), function, 0);
}
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index adf9853f62..be38690a49 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -61,7 +61,7 @@
#define Q_V4_PROFILE_ALLOC(engine, size, type) (!engine)
#define Q_V4_PROFILE_DEALLOC(engine, size, type) (!engine)
-#define Q_V4_PROFILE(engine, function, jsFunction) (function->code(function, jsFunction))
+#define Q_V4_PROFILE(engine, context, function, jsFunction) (function->code(context, function, jsFunction))
QT_BEGIN_NAMESPACE
@@ -85,11 +85,11 @@ QT_END_NAMESPACE
(engine->profiler()->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler()->trackDealloc(size, type) : false)
-#define Q_V4_PROFILE(engine, function, jsFunction)\
+#define Q_V4_PROFILE(engine, context, function, jsFunction)\
(Q_UNLIKELY(engine->profiler()) &&\
(engine->profiler()->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
- Profiling::FunctionCallProfiler::profileCall(engine->profiler(), function, jsFunction) :\
- function->code(function, jsFunction))
+ Profiling::FunctionCallProfiler::profileCall(engine->profiler(), context, function, jsFunction) :\
+ function->code(context, function, jsFunction))
QT_BEGIN_NAMESPACE
@@ -279,10 +279,10 @@ public:
profiler->m_data.append(FunctionCall(function, startTime, profiler->m_timer.nsecsElapsed()));
}
- static ReturnedValue profileCall(Profiler *profiler, Function *function, const FunctionObject *jsFunction)
+ static ReturnedValue profileCall(Profiler *profiler, Heap::ExecutionContext *context, Function *function, const FunctionObject *jsFunction)
{
FunctionCallProfiler callProfiler(profiler, function);
- return function->code(function, jsFunction);
+ return function->code(context, function, jsFunction);
}
Profiler *profiler;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index d7f10ece97..84b3571069 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1848,7 +1848,7 @@ const QMetaObject *Heap::QObjectMethod::metaObject()
return object()->metaObject();
}
-QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) const
+QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionEngine *engine) const
{
QString result;
if (const QMetaObject *metaObject = d()->metaObject()) {
@@ -1867,15 +1867,15 @@ QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx) co
result = QLatin1String("null");
}
- return ctx->engine()->newString(result)->asReturnedValue();
+ return engine->newString(result)->asReturnedValue();
}
-QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const
+QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionEngine *engine, const Value *args, int argc) const
{
if (!d()->object())
return Encode::undefined();
if (QQmlData::keepAliveDuringGarbageCollection(d()->object()))
- return ctx->engine()->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
+ return engine->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
int delay = 0;
if (argc > 0)
@@ -1898,11 +1898,10 @@ ReturnedValue QObjectMethod::call(const Managed *m, CallData *callData)
ReturnedValue QObjectMethod::callInternal(CallData *callData) const
{
ExecutionEngine *v4 = engine();
- ExecutionContext *context = v4->currentContext;
if (d()->index == DestroyMethod)
- return method_destroy(context, callData->args, callData->argc);
+ return method_destroy(v4, callData->args, callData->argc);
else if (d()->index == ToStringMethod)
- return method_toString(context);
+ return method_toString(v4);
QQmlObjectOrGadget object(d()->object());
if (!d()->object()) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 3999b641f9..d7cc91925b 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -234,8 +234,8 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
int methodIndex() const { return d()->index; }
QObject *object() const { return d()->object(); }
- QV4::ReturnedValue method_toString(QV4::ExecutionContext *ctx) const;
- QV4::ReturnedValue method_destroy(QV4::ExecutionContext *ctx, const Value *args, int argc) const;
+ QV4::ReturnedValue method_toString(QV4::ExecutionEngine *engine) const;
+ QV4::ReturnedValue method_destroy(QV4::ExecutionEngine *ctx, const Value *args, int argc) const;
static ReturnedValue call(const Managed *, CallData *callData);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 81f1efbff0..cbe8de4d28 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -310,7 +310,8 @@ ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId)
{
QV4::Function *clos = static_cast<CompiledData::CompilationUnit*>(engine->currentStackFrame->v4Function->compilationUnit)->runtimeFunctions[functionId];
Q_ASSERT(clos);
- return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue();
+ ExecutionContext *current = static_cast<ExecutionContext *>(&engine->currentStackFrame->jsFrame->context);
+ return FunctionObject::createScriptFunction(current, clos)->asReturnedValue();
}
bool Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, const Value &index)
@@ -347,7 +348,7 @@ bool Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- return engine->currentContext->deleteProperty(name);
+ return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).deleteProperty(name);
}
QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &lval, const Value &rval)
@@ -742,7 +743,7 @@ bool Runtime::method_setActivationProperty(ExecutionEngine *engine, int nameInde
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- return engine->currentContext->setProperty(name, value);
+ return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).setProperty(name, value);
}
ReturnedValue Runtime::method_getProperty(ExecutionEngine *engine, const Value &object, int nameIndex)
@@ -769,7 +770,7 @@ ReturnedValue Runtime::method_getActivationProperty(ExecutionEngine *engine, int
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- return engine->currentContext->getProperty(name);
+ return static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name);
}
#endif // V4_BOOTSTRAP
@@ -1023,7 +1024,7 @@ ReturnedValue Runtime::method_callActivationProperty(ExecutionEngine *engine, in
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject base(scope);
- ScopedValue func(scope, engine->currentContext->getPropertyAndBase(name, base.getRef()));
+ ScopedValue func(scope, static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getPropertyAndBase(name, base.getRef()));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1129,7 +1130,7 @@ ReturnedValue Runtime::method_constructActivationProperty(ExecutionEngine *engin
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- ScopedValue func(scope, engine->currentContext->getProperty(name));
+ ScopedValue func(scope, static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name));
if (scope.engine->hasException)
return Encode::undefined();
@@ -1216,7 +1217,7 @@ QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameI
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- ScopedValue prop(scope, engine->currentContext->getProperty(name));
+ ScopedValue prop(scope, static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
return method_typeofValue(engine, prop);
@@ -1234,35 +1235,34 @@ ReturnedValue Runtime::method_unwindException(ExecutionEngine *engine)
*
* Instead the push/pop pair acts as a non local scope.
*/
-void Runtime::method_pushWithScope(const Value &o, NoThrowEngine *engine)
+ReturnedValue Runtime::method_pushWithContext(const Value &o, NoThrowEngine *engine)
{
- QV4::Value *v = engine->jsAlloca(1);
- Heap::Object *withObject = o.toObject(engine);
- *v = withObject;
- engine->pushContext(engine->currentContext->newWithContext(withObject));
- Q_ASSERT(engine->jsStackTop == engine->currentContext + 2);
+ Q_ASSERT(o.isObject());
+ ExecutionContext *c = engine->currentContext();
+ ReturnedValue oldContext = c->asReturnedValue();
+ const Object &obj = static_cast<const Object &>(o);
+ engine->setCurrentContext(c->newWithContext(obj.d()));
+ return oldContext;
}
-void Runtime::method_pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex)
+ReturnedValue Runtime::method_pushCatchContext(NoThrowEngine *engine, int exceptionVarNameIndex)
{
- engine->jsAlloca(1); // keep this symmetric with pushWithScope
- ExecutionContext *c = engine->currentContext;
- engine->pushContext(c->newCatchContext(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0)));
- Q_ASSERT(engine->jsStackTop == engine->currentContext + 2);
+ ExecutionContext *c = engine->currentContext();
+ ReturnedValue oldContext = c->asReturnedValue();
+ engine->setCurrentContext(c->newCatchContext(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0)));
+ return oldContext;
}
-void Runtime::method_popScope(NoThrowEngine *engine)
+void Runtime::method_popContext(NoThrowEngine *engine, const Value &oldContext)
{
- Q_ASSERT(engine->jsStackTop == engine->currentContext + 2);
- engine->popContext();
- engine->jsStackTop -= 3;
+ engine->setCurrentContext(static_cast<const ExecutionContext &>(oldContext).d());
}
void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
{
Scope scope(engine);
ScopedString name(scope, engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[nameIndex]);
- engine->currentContext->createMutableBinding(name, deletable);
+ static_cast<ExecutionContext &>(engine->currentStackFrame->jsFrame->context).createMutableBinding(name, deletable);
}
ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
@@ -1314,16 +1314,16 @@ ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::
QV4::ReturnedValue Runtime::method_createMappedArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext);
- QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext);
+ Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext);
+ QV4::CallContext *c = static_cast<QV4::CallContext *>(&engine->currentStackFrame->jsFrame->context);
QV4::InternalClass *ic = engine->internalClasses[EngineBase::Class_ArgumentsObject];
return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), c, false)->asReturnedValue();
}
QV4::ReturnedValue Runtime::method_createUnmappedArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext);
- QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext);
+ Q_ASSERT(engine->currentContext()->d()->type == Heap::ExecutionContext::Type_CallContext);
+ QV4::CallContext *c = static_cast<QV4::CallContext *>(&engine->currentStackFrame->jsFrame->context);
QV4::InternalClass *ic = engine->internalClasses[EngineBase::Class_StrictArgumentsObject];
return engine->memoryManager->allocObject<ArgumentsObject>(ic, engine->objectPrototype(), c, true)->asReturnedValue();
}
@@ -1427,7 +1427,7 @@ QV4::ReturnedValue Runtime::method_getQmlSingleton(QV4::NoThrowEngine *engine, i
void Runtime::method_convertThisToObject(ExecutionEngine *engine)
{
- Value *t = &engine->current->callData->thisObject;
+ Value *t = &engine->currentContext()->d()->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index d67761ccfc..3e448eb02b 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -127,9 +127,9 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
/* exceptions & scopes */ \
F(void, throwException, (ExecutionEngine *engine, const Value &value)) \
F(ReturnedValue, unwindException, (ExecutionEngine *engine)) \
- F(void, pushWithScope, (const Value &o, NoThrowEngine *engine)) \
- F(void, pushCatchScope, (NoThrowEngine *engine, int exceptionVarNameIndex)) \
- F(void, popScope, (NoThrowEngine *engine)) \
+ F(ReturnedValue, pushWithContext, (const Value &o, NoThrowEngine *engine)) \
+ F(ReturnedValue, pushCatchContext, (NoThrowEngine *engine, int exceptionVarNameIndex)) \
+ F(void, popContext, (NoThrowEngine *engine, const Value &oldContext)) \
\
/* closures */ \
F(ReturnedValue, closure, (ExecutionEngine *engine, int functionId)) \
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 5e3e71a30f..26b15838f3 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -371,6 +371,25 @@ struct ScopedCallData {
CallData *ptr;
};
+struct ScopedStackFrame {
+ Scope &scope;
+ EngineBase::StackFrame frame;
+
+ ScopedStackFrame(Scope &scope, Heap::ExecutionContext *context)
+ : scope(scope)
+ {
+ frame.parent = scope.engine->currentStackFrame;
+ if (!context)
+ return;
+ frame.jsFrame = reinterpret_cast<EngineBase::JSStackFrame *>(scope.alloc(sizeof(EngineBase::JSStackFrame)/sizeof(Value)));
+ frame.jsFrame->context = context;
+ frame.v4Function = frame.parent ? frame.parent->v4Function : 0;
+ scope.engine->currentStackFrame = &frame;
+ }
+ ~ScopedStackFrame() {
+ scope.engine->currentStackFrame = frame.parent;
+ }
+};
inline Value &Value::operator =(const ScopedValue &v)
{
@@ -399,25 +418,6 @@ struct ScopedProperty
Property *property;
};
-struct ExecutionContextSaver
-{
- ExecutionEngine *engine;
- ExecutionContext *savedContext;
-
- ExecutionContextSaver(ExecutionEngine *engine)
- : engine(engine)
- {
- savedContext = engine->currentContext;
- }
- ~ExecutionContextSaver()
- {
- Q_ASSERT(engine->jsStackTop > engine->currentContext);
- engine->currentContext = savedContext;
- engine->current = savedContext->d();
- }
-};
-
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 1b28882280..ef85ce43de 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -148,11 +148,10 @@ ReturnedValue Script::run()
if (qmlContext.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- ExecutionContextSaver ctxSaver(valueScope.engine);
ContextStateSaver stateSaver(valueScope, scope);
scope->d()->v4Function = vmFunction;
- return Q_V4_PROFILE(engine, vmFunction, 0);
+ return Q_V4_PROFILE(engine, scope->d(), vmFunction, 0);
} else {
Scoped<QmlContext> qml(valueScope, qmlContext.value());
ScopedCallData callData(valueScope);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 97e9a90b5a..20c4f2ece6 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -373,10 +373,9 @@ static struct InstrCount {
if (engine->hasException) \
goto catchException
-static inline QV4::Heap::ExecutionContext *getScope(QV4::Heap::ExecutionContext *functionScope,
- int level)
+static inline QV4::Heap::ExecutionContext *getScope(EngineBase::JSStackFrame *frame, int level)
{
- QV4::Heap::ExecutionContext *scope = functionScope;
+ QV4::Heap::ExecutionContext *scope = static_cast<ExecutionContext &>(frame->context).d();
while (level > 0) {
--level;
scope = scope->outer;
@@ -385,46 +384,40 @@ static inline QV4::Heap::ExecutionContext *getScope(QV4::Heap::ExecutionContext
return scope;
}
-static inline ReturnedValue loadScopedLocal(ExecutionEngine *engine, int index, int scope)
+static inline ReturnedValue loadScopedLocal(EngineBase::StackFrame &frame, int index, int scope)
{
- auto ctxt = getScope(engine->current, scope);
+ auto ctxt = getScope(frame.jsFrame, scope);
Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
auto cc = static_cast<Heap::CallContext *>(ctxt);
return cc->locals[index].asReturnedValue();
}
-static inline void storeScopedLocal(ExecutionEngine *engine, int index, int scope,
+static inline void storeScopedLocal(ExecutionEngine *engine, EngineBase::StackFrame &frame, int index, int scope,
const QV4::Value &value)
{
- auto ctxt = getScope(engine->current, scope);
+ auto ctxt = getScope(frame.jsFrame, scope);
Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
auto cc = static_cast<Heap::CallContext *>(ctxt);
- if (Q_UNLIKELY(engine->writeBarrierActive))
- QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, value);
- else
- *(cc->locals.values + index) = value;
+ QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, value);
}
-static inline ReturnedValue loadScopedArg(ExecutionEngine *engine, int index, int scope)
+static inline ReturnedValue loadScopedArg(EngineBase::StackFrame &frame, int index, int scope)
{
- auto ctxt = getScope(engine->current, scope);
+ auto ctxt = getScope(frame.jsFrame, scope);
Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
auto cc = static_cast<Heap::CallContext *>(ctxt);
return cc->callData->args[index].asReturnedValue();
}
-static inline void storeScopedArg(ExecutionEngine *engine, int index, int scope,
+static inline void storeScopedArg(ExecutionEngine *engine, EngineBase::StackFrame &frame, int index, int scope,
const QV4::Value &value)
{
- auto ctxt = getScope(engine->current, scope);
+ auto ctxt = getScope(frame.jsFrame, scope);
Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
auto cc = static_cast<Heap::CallContext *>(ctxt);
- if (Q_UNLIKELY(engine->writeBarrierActive))
- QV4::WriteBarrier::write(engine, cc, cc->callData->args + index, value);
- else
- *(cc->callData->args + index) = value;
+ QV4::WriteBarrier::write(engine, cc, cc->callData->args + index, value);
}
static inline const QV4::Value &constant(Function *function, int index)
@@ -432,7 +425,7 @@ static inline const QV4::Value &constant(Function *function, int index)
return function->compilationUnit->constants[index];
}
-QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunction)
+QV4::ReturnedValue VME::exec(Heap::ExecutionContext *context, Function *function, const FunctionObject *jsFunction)
{
qt_v4ResolvePendingBreakpointsHook();
@@ -458,13 +451,14 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
if (!function->canUseSimpleFunction()) {
int nFormals = function->nFormals;
stack = scope.alloc(nFormals + 1 + function->compiledFunction->nRegisters + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value));
- memcpy(stack, &engine->current->callData->thisObject, (nFormals + 1)*sizeof(Value));
+// ### why copy those on the stack again?
+ memcpy(stack, &context->callData->thisObject, (nFormals + 1)*sizeof(Value));
stack += nFormals + 1;
} else {
stack = scope.alloc(function->compiledFunction->nRegisters + sizeof(EngineBase::JSStackFrame)/sizeof(QV4::Value));
}
frame.jsFrame = reinterpret_cast<EngineBase::JSStackFrame *>(stack);
- frame.jsFrame->context = engine->current;
+ frame.jsFrame->context = context;
if (jsFunction)
frame.jsFrame->jsFunction = *jsFunction;
@@ -504,21 +498,21 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
MOTH_END_INSTR(MoveReg)
MOTH_BEGIN_INSTR(LoadScopedLocal)
- accumulator = loadScopedLocal(engine, instr.index, instr.scope);
+ accumulator = loadScopedLocal(frame, instr.index, instr.scope);
MOTH_END_INSTR(LoadScopedLocal)
MOTH_BEGIN_INSTR(StoreScopedLocal)
CHECK_EXCEPTION;
- storeScopedLocal(engine, instr.index, instr.scope, accumulator);
+ storeScopedLocal(engine, frame, instr.index, instr.scope, accumulator);
MOTH_END_INSTR(StoreScopedLocal)
MOTH_BEGIN_INSTR(LoadScopedArgument)
- accumulator = loadScopedArg(engine, instr.index, instr.scope);
+ accumulator = loadScopedArg(frame, instr.index, instr.scope);
MOTH_END_INSTR(LoadScopedArgument)
MOTH_BEGIN_INSTR(StoreScopedArgument)
CHECK_EXCEPTION;
- storeScopedArg(engine, instr.index, instr.scope, accumulator);
+ storeScopedArg(engine, frame, instr.index, instr.scope, accumulator);
MOTH_END_INSTR(StoreScopedArgument)
MOTH_BEGIN_INSTR(LoadRuntimeString)
@@ -675,18 +669,19 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
STORE_ACCUMULATOR(Runtime::method_unwindException(engine));
MOTH_END_INSTR(CallBuiltinUnwindException)
- MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
- Runtime::method_pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
- MOTH_END_INSTR(CallBuiltinPushCatchScope)
+ MOTH_BEGIN_INSTR(CallBuiltinPushCatchContext)
+ STACK_VALUE(instr.reg) = Runtime::method_pushCatchContext(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
+ MOTH_END_INSTR(CallBuiltinPushCatchContext)
- MOTH_BEGIN_INSTR(CallBuiltinPushScope)
- Runtime::method_pushWithScope(accumulator, static_cast<QV4::NoThrowEngine*>(engine));
+ MOTH_BEGIN_INSTR(CallBuiltinPushWithContext)
+ accumulator = accumulator.toObject(engine);
CHECK_EXCEPTION;
- MOTH_END_INSTR(CallBuiltinPushScope)
+ STACK_VALUE(instr.reg) = Runtime::method_pushWithContext(accumulator, static_cast<QV4::NoThrowEngine*>(engine));
+ MOTH_END_INSTR(CallBuiltinPushWithContext)
- MOTH_BEGIN_INSTR(CallBuiltinPopScope)
- Runtime::method_popScope(static_cast<QV4::NoThrowEngine*>(engine));
- MOTH_END_INSTR(CallBuiltinPopScope)
+ MOTH_BEGIN_INSTR(CallBuiltinPopContext)
+ Runtime::method_popContext(static_cast<QV4::NoThrowEngine*>(engine), STACK_VALUE(instr.reg));
+ MOTH_END_INSTR(CallBuiltinPopContext)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
STORE_ACCUMULATOR(Runtime::method_foreachIterator(engine, accumulator));
@@ -1101,7 +1096,7 @@ QV4::ReturnedValue VME::exec(Function *function, const FunctionObject *jsFunctio
#endif // QT_NO_QML_DEBUGGER
MOTH_BEGIN_INSTR(LoadThis)
- STORE_ACCUMULATOR(engine->currentContext->thisObject());
+ STORE_ACCUMULATOR(static_cast<ExecutionContext &>(frame.jsFrame->context).thisObject());
MOTH_END_INSTR(LoadThis)
MOTH_BEGIN_INSTR(LoadQmlContext)
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 5055af65fd..04efb2cb06 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -65,7 +65,7 @@ namespace Moth {
class VME
{
public:
- static QV4::ReturnedValue exec(QV4::Function *, const FunctionObject *jsFunction = 0);
+ static QV4::ReturnedValue exec(Heap::ExecutionContext *context, QV4::Function *, const FunctionObject *jsFunction = 0);
};
} // namespace Moth
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 3b15157ff5..0ebeb48ea4 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1210,8 +1210,7 @@ void QQmlComponentPrivate::setInitialProperties(QV4::ExecutionEngine *engine, QV
if (engine->hasException)
return;
- QV4::ExecutionContextSaver saver(scope.engine);
- engine->pushContext(qmlContext);
+ QV4::ScopedStackFrame frame(scope, qmlContext->d());
while (1) {
name = it.nextPropertyNameAsString(val);
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 231708da70..417698b5e8 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -339,7 +339,7 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration dur
}
}
-void QQmlPropertyCapture::registerQmlDependencies(const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
+void QQmlPropertyCapture::registerQmlDependencies(QV4::QmlContext *context, const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
{
// Let the caller check and avoid the function call :)
Q_ASSERT(compiledFunction->hasQmlDependencies());
@@ -356,8 +356,8 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::ExecutionEngine *en
capture->expression->m_permanentDependenciesRegistered = true;
- QV4::Heap::QmlContext *context = engine->qmlContext();
- QQmlContextData *qmlContext = context->qml()->context->contextData();
+ QV4::Heap::QQmlContextWrapper *wrapper = context->d()->qml();
+ QQmlContextData *qmlContext = wrapper->context->contextData();
const QV4::CompiledData::LEUInt32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
@@ -377,7 +377,7 @@ void QQmlPropertyCapture::registerQmlDependencies(const QV4::ExecutionEngine *en
QQmlPropertyCapture::Permanently);
}
- QObject *scopeObject = context->qml()->scopeObject;
+ QObject *scopeObject = wrapper->scopeObject;
const QV4::CompiledData::LEUInt32 *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
for (int i = 0; i < scopePropertyDependencyCount; ++i) {
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 84be5b673f..f6993436f1 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -203,7 +203,7 @@ public:
Permanently
};
- static void registerQmlDependencies(const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
+ static void registerQmlDependencies(QV4::QmlContext *context, const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
void captureProperty(QQmlNotifier *, Duration duration = OnlyOnce);
void captureProperty(QObject *, int, int, Duration duration = OnlyOnce);
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 0672618225..eebf6ccd1e 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -224,8 +224,6 @@ public:
void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(e->handle());
- v4->pushGlobalContext();
if (scriptCallback && scriptApi(e).isUndefined()) {
setScriptApi(e, scriptCallback(e, e));
} else if (qobjectCallback && !qobjectApi(e)) {
@@ -241,7 +239,6 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
QObject *o = component.create();
setQObjectApi(e, o);
}
- v4->popContext();
}
void QQmlType::SingletonInstanceInfo::destroy(QQmlEngine *e)