diff options
-rw-r--r-- | src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp | 19 | ||||
-rw-r--r-- | src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 16 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4debugging.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 45 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 36 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 29 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 13 | ||||
-rw-r--r-- | src/qml/memory/qv4mm.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 8 |
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); } } |