aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
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/qml
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/qml')
-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
24 files changed, 198 insertions, 230 deletions
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)