aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp19
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h2
-rw-r--r--src/qml/jsruntime/qv4context.cpp16
-rw-r--r--src/qml/jsruntime/qv4context_p.h21
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp45
-rw-r--r--src/qml/jsruntime/qv4engine_p.h36
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp29
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h13
-rw-r--r--src/qml/memory/qv4mm.cpp6
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp8
11 files changed, 100 insertions, 97 deletions
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index 2ef7713ac7..49dde9e8bf 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -43,13 +43,9 @@
QT_BEGIN_NAMESPACE
-QV4::Heap::CallContext *QV4DataCollector::findContext(QV4::Heap::ExecutionContext *ctxt, int frame)
+QV4::Heap::CallContext *QV4DataCollector::findContext(QV4::ExecutionEngine *engine, int frame)
{
- if (!ctxt)
- return 0;
-
- QV4::Scope scope(ctxt->engine);
- QV4::ScopedContext ctx(scope, ctxt);
+ QV4::ExecutionContext *ctx = engine->currentExecutionContext;
while (ctx) {
QV4::CallContext *cCtxt = ctx->asCallContext();
if (cCtxt && cCtxt->d()->function) {
@@ -57,7 +53,7 @@ QV4::Heap::CallContext *QV4DataCollector::findContext(QV4::Heap::ExecutionContex
return cCtxt->d();
--frame;
}
- ctx = ctx->d()->parent;
+ ctx = engine->parentContext(ctx);
}
return 0;
@@ -82,7 +78,7 @@ QVector<QV4::Heap::ExecutionContext::ContextType> QV4DataCollector::getScopeType
QVector<QV4::Heap::ExecutionContext::ContextType> types;
QV4::Scope scope(engine);
- QV4::Scoped<QV4::CallContext> sctxt(scope, findContext(engine->currentContext(), frame));
+ QV4::Scoped<QV4::CallContext> sctxt(scope, findContext(engine, frame));
if (!sctxt || sctxt->d()->type < QV4::Heap::ExecutionContext::Type_QmlContext)
return types;
@@ -384,7 +380,7 @@ void ArgumentCollectJob::run()
QV4::Scope scope(engine);
QV4::Scoped<QV4::CallContext> ctxt(
scope, QV4DataCollector::findScope(
- QV4DataCollector::findContext(engine->currentContext(), frameNr), scopeNr));
+ QV4DataCollector::findContext(engine, frameNr), scopeNr));
if (!ctxt)
return;
@@ -417,7 +413,7 @@ void LocalCollectJob::run()
QV4::Scope scope(engine);
QV4::Scoped<QV4::CallContext> ctxt(
scope, QV4DataCollector::findScope(
- QV4DataCollector::findContext(engine->currentContext(), frameNr), scopeNr));
+ QV4DataCollector::findContext(engine, frameNr), scopeNr));
if (!ctxt)
return;
@@ -448,8 +444,7 @@ void ThisCollectJob::run()
bool ThisCollectJob::myRun()
{
QV4::Scope scope(engine);
- QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine->currentContext(),
- frameNr));
+ QV4::ScopedContext ctxt(scope, QV4DataCollector::findContext(engine, frameNr));
while (ctxt) {
if (QV4::CallContext *cCtxt = ctxt->asCallContext())
if (cCtxt->d()->activation)
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
index 7d26d71bdf..f8cd0c1508 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h
@@ -45,7 +45,7 @@ public:
typedef uint Ref;
typedef QVector<uint> Refs;
- static QV4::Heap::CallContext *findContext(QV4::Heap::ExecutionContext *ctxt, int frame);
+ static QV4::Heap::CallContext *findContext(QV4::ExecutionEngine *engine, int frame);
static QV4::Heap::CallContext *findScope(QV4::Heap::ExecutionContext *ctxt, int scope);
static QVector<QV4::Heap::ExecutionContext::ContextType> getScopeTypes(
QV4::ExecutionEngine *engine, int frame);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 57c791e6a8..22dd0b17b9 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -83,14 +83,16 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi
return c;
}
-Heap::WithContext *ExecutionContext::newWithContext(Object *with)
+Heap::WithContext *ExecutionContext::newWithContext(Heap::Object *with)
{
return d()->engine->memoryManager->alloc<WithContext>(d(), with);
}
-Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const Value &exceptionValue)
+Heap::CatchContext *ExecutionContext::newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue)
{
- return d()->engine->memoryManager->alloc<CatchContext>(d(), exceptionVarName, exceptionValue);
+ Scope scope(this);
+ ScopedValue e(scope, exceptionValue);
+ return d()->engine->memoryManager->alloc<CatchContext>(d(), exceptionVarName, e);
}
Heap::QmlContext *ExecutionContext::newQmlContext(QmlContextWrapper *qml)
@@ -150,7 +152,7 @@ Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
global = eng->globalObject->d();
}
-Heap::WithContext::WithContext(ExecutionContext *outerContext, QV4::Object *with)
+Heap::WithContext::WithContext(ExecutionContext *outerContext, Object *with)
: Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_WithContext)
{
outer = outerContext;
@@ -158,10 +160,10 @@ Heap::WithContext::WithContext(ExecutionContext *outerContext, QV4::Object *with
lookups = outer->lookups;
compilationUnit = outer->compilationUnit;
- withObject = with ? with->d() : 0;
+ withObject = with;
}
-Heap::CatchContext::CatchContext(ExecutionContext *outerContext, QV4::String *exceptionVarName, const Value &exceptionValue)
+Heap::CatchContext::CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue)
: Heap::ExecutionContext(outerContext->engine, Heap::ExecutionContext::Type_CatchContext)
{
outer = outerContext;
@@ -170,7 +172,7 @@ Heap::CatchContext::CatchContext(ExecutionContext *outerContext, QV4::String *ex
lookups = outer->lookups;
compilationUnit = outer->compilationUnit;
- this->exceptionVarName = exceptionVarName->d();
+ this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index cccca8a4fd..2807d1e29c 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -89,7 +89,6 @@ struct ExecutionContext : Base {
CallData *callData;
ExecutionEngine *engine;
- Pointer<ExecutionContext> parent;
Pointer<ExecutionContext> outer;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
@@ -99,6 +98,18 @@ struct ExecutionContext : Base {
int lineNumber;
};
+inline
+ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
+ : engine(engine)
+ , outer(0)
+ , lookups(0)
+ , compilationUnit(0)
+ , type(t)
+ , strictMode(false)
+ , lineNumber(-1)
+{}
+
+
struct CallContext : ExecutionContext {
CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
: ExecutionContext(engine, t)
@@ -119,13 +130,13 @@ struct GlobalContext : ExecutionContext {
};
struct CatchContext : ExecutionContext {
- CatchContext(ExecutionContext *outerContext, QV4::String *exceptionVarName, const Value &exceptionValue);
+ CatchContext(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue);
Pointer<String> exceptionVarName;
Value exceptionValue;
};
struct WithContext : ExecutionContext {
- WithContext(ExecutionContext *outerContext, QV4::Object *with);
+ WithContext(ExecutionContext *outerContext, Object *with);
Pointer<Object> withObject;
};
@@ -150,8 +161,8 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
ExecutionEngine *engine() const { return d()->engine; }
Heap::CallContext *newCallContext(const FunctionObject *f, CallData *callData);
- Heap::WithContext *newWithContext(Object *with);
- Heap::CatchContext *newCatchContext(String *exceptionVarName, const Value &exceptionValue);
+ Heap::WithContext *newWithContext(Heap::Object *with);
+ Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue);
Heap::QmlContext *newQmlContext(QmlContextWrapper *qml);
Heap::QmlContext *newQmlContext(QQmlContextData *context, QObject *scopeObject);
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 1833215c42..8a60a81b93 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -249,7 +249,7 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->currentContext()) {
- m_currentContext.set(m_engine, m_engine->currentContext()->parent);
+ m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentExecutionContext));
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d6448f7030..5ea8205fad 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -200,6 +200,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, memoryManager(new QV4::MemoryManager(this))
, executableAllocator(new QV4::ExecutableAllocator)
, regExpAllocator(new QV4::ExecutableAllocator)
+ , currentExecutionContext(0)
, bumperPointerAllocator(new WTF::BumpPointerAllocator)
, jsStack(new WTF::PageAllocation)
, debugger(0)
@@ -508,9 +509,11 @@ void ExecutionEngine::initRootContext()
r->d()->callData->argc = 0;
r->d()->callData->thisObject = globalObject;
r->d()->callData->args[0] = Encode::undefined();
- current = r->d();
-
jsObjects[RootContect] = r;
+ jsObjects[IntegerNull] = Encode((int)0);
+
+ currentExecutionContext = static_cast<ExecutionContext *>(jsObjects + RootContect);
+ current = currentExecutionContext->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -520,13 +523,18 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- Scope scope(this);
- Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
- g->d()->callData = rootContext()->d()->callData;
- pushContext(g->d());
+ pushContext(rootContext()->d());
- Q_ASSERT(currentContext() == g->d());
- return g->d();
+ Q_ASSERT(currentContext() == rootContext()->d());
+ return currentContext();
+}
+
+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;
}
@@ -733,7 +741,7 @@ Heap::QmlContext *ExecutionEngine::qmlContext() const
// get the correct context when we're within a builtin function
if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
- ctx = ctx->parent;
+ ctx = parentContext(currentExecutionContext)->d();
if (!ctx->outer)
return 0;
@@ -793,7 +801,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
ScopedString name(scope);
QVector<StackFrame> stack;
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentExecutionContext;
ScopedFunctionObject function(scope);
while (c && frameLimit) {
function = c->getFunctionObject();
@@ -813,7 +821,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
stack.append(frame);
--frameLimit;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (frameLimit && globalCode) {
@@ -881,8 +889,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
return src;
QUrl base;
- Scope scope(this);
- ScopedContext c(scope, currentContext());
+ ExecutionContext *c = currentExecutionContext;
while (c) {
CallContext *callCtx = c->asCallContext();
if (callCtx && callCtx->d()->function) {
@@ -890,7 +897,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
base.setUrl(callCtx->d()->function->function->sourceFile());
break;
}
- c = c->d()->parent;
+ c = parentContext(c);
}
if (base.isEmpty() && globalCode)
@@ -940,16 +947,6 @@ void ExecutionEngine::markObjects()
setter->mark(this);
}
- Heap::ExecutionContext *c = currentContext();
- while (c) {
- Q_ASSERT(c->inUse());
- if (!c->isMarked()) {
- c->setMarkBit();
- c->vtable()->markObjects(c, this);
- }
- c = c->parent;
- }
-
classPool->markObjects(this);
for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd();
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 968c9d5df0..e9d505c858 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -88,6 +88,7 @@ public:
ExecutableAllocator *regExpAllocator;
QScopedPointer<EvalISelFactory> iselFactory;
+ ExecutionContext *currentExecutionContext;
Value *jsStackLimit;
quintptr cStackLimit;
@@ -128,6 +129,7 @@ public:
enum JSObjects {
RootContect,
+ IntegerNull, // Has to come after the RootContext to make the context stack safe
ObjectProto,
ArrayProto,
StringProto,
@@ -351,6 +353,7 @@ public:
void pushContext(Heap::ExecutionContext *context);
void pushContext(CallContext *context);
Heap::ExecutionContext *popContext();
+ ExecutionContext *parentContext(ExecutionContext *context) const;
Heap::Object *newObject();
Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
@@ -444,9 +447,12 @@ public:
inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context)
{
- Q_ASSERT(current && context);
- context->parent = current;
- current = context;
+ Q_ASSERT(currentExecutionContext && context);
+ Value *v = jsAlloca(2);
+ v[0] = Encode(context);
+ v[1] = Encode((int)(v - static_cast<Value *>(currentExecutionContext)));
+ currentExecutionContext = static_cast<ExecutionContext *>(v);
+ current = currentExecutionContext->d();
}
inline void ExecutionEngine::pushContext(CallContext *context)
@@ -457,27 +463,17 @@ inline void ExecutionEngine::pushContext(CallContext *context)
inline Heap::ExecutionContext *ExecutionEngine::popContext()
{
- Q_ASSERT(current->parent);
- current = current->parent;
- Q_ASSERT(current);
+ Q_ASSERT(jsStackTop > currentExecutionContext);
+ QV4::Value *offset = (currentExecutionContext + 1);
+ Q_ASSERT(offset->isInteger());
+ int o = offset->integerValue();
+ Q_ASSERT(o);
+ currentExecutionContext -= o;
+ current = currentExecutionContext->d();
return current;
}
inline
-Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
- : engine(engine)
- , parent(engine->currentContext())
- , outer(0)
- , lookups(0)
- , compilationUnit(0)
- , type(t)
- , strictMode(false)
- , lineNumber(-1)
-{
-}
-
-
-inline
void Heap::Base::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 5cc47aacd8..ca3195b405 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1175,14 +1175,6 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value &
return Runtime::typeofValue(engine, prop);
}
-void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
-{
- Scope scope(engine);
- ScopedObject obj(scope, o.toObject(engine));
- ScopedContext ctx(scope, engine->currentContext());
- engine->pushContext(ctx->newWithContext(obj));
-}
-
ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
{
if (!engine->hasException)
@@ -1190,18 +1182,29 @@ ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
return engine->catchException(0);
}
+/* The next three methods are a bit tricky. They can't open up a Scope, as that
+ * would mess up the pushing of the context.
+ *
+ * Instead the push/pop pair acts as a non local scope.
+ */
+void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine)
+{
+ engine->pushContext(engine->currentExecutionContext->newWithContext(o.toObject(engine)));
+ Q_ASSERT(engine->jsStackTop = engine->currentExecutionContext + 2);
+}
+
void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex)
{
- Scope scope(engine);
- ScopedValue v(scope, engine->catchException(0));
- ScopedString exceptionVarName(scope, engine->currentContext()->compilationUnit->runtimeStrings[exceptionVarNameIndex]);
- ScopedContext ctx(scope, engine->currentContext());
- engine->pushContext(ctx->newCatchContext(exceptionVarName, v));
+ ExecutionContext *c = engine->currentExecutionContext;
+ engine->pushContext(c->newCatchContext(c->d()->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0)));
+ Q_ASSERT(engine->jsStackTop = engine->currentExecutionContext + 2);
}
void Runtime::popScope(ExecutionEngine *engine)
{
+ Q_ASSERT(engine->jsStackTop = engine->currentExecutionContext + 2);
engine->popContext();
+ engine->jsStackTop -= 2;
}
void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 563b8b0e93..0f0d50bdee 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -73,6 +73,7 @@ struct Scope {
~Scope() {
#ifndef QT_NO_DEBUG
Q_ASSERT(engine->jsStackTop >= mark);
+ Q_ASSERT(engine->currentExecutionContext < mark);
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
#ifdef V4_USE_VALGRIND
@@ -414,20 +415,18 @@ struct ScopedProperty
struct ExecutionContextSaver
{
ExecutionEngine *engine;
- Value *savedContext;
+ ExecutionContext *savedContext;
ExecutionContextSaver(Scope &scope)
: engine(scope.engine)
- , savedContext(scope.alloc(1))
{
- savedContext->setM(scope.engine->currentContext());
-#if QT_POINTER_SIZE == 4
- savedContext->setTag(QV4::Value::Managed_Type);
-#endif
+ savedContext = engine->currentExecutionContext;
}
~ExecutionContextSaver()
{
- engine->current = static_cast<Heap::ExecutionContext *>(savedContext->heapObject());
+ Q_ASSERT(engine->jsStackTop > engine->currentExecutionContext);
+ engine->currentExecutionContext = savedContext;
+ engine->current = savedContext->d();
}
};
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index 5a7953679b..26a705961b 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -483,10 +483,10 @@ void MemoryManager::sweep(bool lastSweep)
// some execution contexts are allocated on the stack, make sure we clear their markBit as well
if (!lastSweep) {
- Heap::ExecutionContext *ctx = engine()->currentContext();
+ QV4::ExecutionContext *ctx = engine()->currentExecutionContext;
while (ctx) {
- ctx->clearMarkBit();
- ctx = ctx->parent;
+ ctx->d()->clearMarkBit();
+ ctx = engine()->parentContext(ctx);
}
}
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index ce86fd3923..f2f743a6cb 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -1737,10 +1737,10 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
int lastDot = path.lastIndexOf(QLatin1Char('.'));
int length = lastDot - (lastSlash + 1);
context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
- } else if (ctx->d()->parent) {
- ScopedContext parentCtx(scope, ctx->d()->parent);
+ } else {
+ ExecutionContext *parentCtx = scope.engine->parentContext(ctx);
// The first non-empty source URL in the call stack determines the translation context.
- while (parentCtx && context.isEmpty()) {
+ while (!!parentCtx && context.isEmpty()) {
if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) {
QString fileName = unit->fileName();
QUrl url(unit->fileName());
@@ -1753,7 +1753,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
}
context = QFileInfo(context).baseName();
}
- parentCtx = parentCtx->d()->parent;
+ parentCtx = scope.engine->parentContext(parentCtx);
}
}