diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-11-14 14:53:28 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-22 14:54:33 +0100 |
commit | bf173fe5da381c88343296ca33ef6b06389c6d20 (patch) | |
tree | ddcf0b304fea1c4ac76ab0762eb263a27fd6f7f0 /src/qml/jsruntime | |
parent | 855784e5a72cb1a1309bcc832f84e4d0989bfba6 (diff) |
Turn execution contexts into Managed objects
This finally gives proper memory management for ExecutionContexts.
So far they had been garbage collected but where still allocated
using standard malloc/free(). This allows us to collect the
contexts faster and speed up context creation.
Change-Id: I02e642391d55eaa59ab3f4c2720a2ac71259caf4
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4argumentsobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context.cpp | 68 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 21 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mm.cpp | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4mm_p.h | 12 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4script.cpp | 17 |
9 files changed, 85 insertions, 62 deletions
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp index 4bf4d19576..749509c353 100644 --- a/src/qml/jsruntime/qv4argumentsobject.cpp +++ b/src/qml/jsruntime/qv4argumentsobject.cpp @@ -240,7 +240,7 @@ ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData) void ArgumentsObject::markObjects(Managed *that, ExecutionEngine *e) { ArgumentsObject *o = static_cast<ArgumentsObject *>(that); - o->context->mark(); + o->context->mark(e); for (int i = 0; i < o->mappedArguments.size(); ++i) o->mappedArguments.at(i).mark(e); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 97247ad368..372c9ce54b 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -51,9 +51,33 @@ using namespace QV4; +const ManagedVTable ExecutionContext::static_vtbl = +{ + call, + construct, + markObjects, + destroy, + 0 /*collectDeletables*/, + hasInstance, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + isEqualTo, + 0, + "ExecutionContext", +}; + CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData) { - CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(function, callData->argc))); + CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc))); + c->init(); engine->current = c; @@ -63,7 +87,6 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData c->realArgumentCount = callData->argc; c->strictMode = function->strictMode; - c->marked = false; c->outer = function->scope; #ifndef QT_NO_DEBUG assert(c->outer->next != (ExecutionContext *)0x1); @@ -92,7 +115,7 @@ CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData WithContext *ExecutionContext::newWithContext(ObjectRef with) { - WithContext *w = static_cast<WithContext *>(engine->memoryManager->allocContext(sizeof(WithContext))); + WithContext *w = new (engine->memoryManager) WithContext; engine->current = w; w->initWithContext(this, with); return w; @@ -100,7 +123,7 @@ WithContext *ExecutionContext::newWithContext(ObjectRef with) CatchContext *ExecutionContext::newCatchContext(const StringRef exceptionVarName, const ValueRef exceptionValue) { - CatchContext *c = static_cast<CatchContext *>(engine->memoryManager->allocContext(sizeof(CatchContext))); + CatchContext *c = new (engine->memoryManager) CatchContext; engine->current = c; c->initCatchContext(this, exceptionVarName, exceptionValue); return c; @@ -108,7 +131,8 @@ CatchContext *ExecutionContext::newCatchContext(const StringRef exceptionVarName CallContext *ExecutionContext::newQmlContext(FunctionObject *f, ObjectRef qml) { - CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocContext(requiredMemoryForExecutionContect(f, 0))); + CallContext *c = static_cast<CallContext *>(engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0))); + c->init(); engine->current = c; c->initQmlContext(this, qml, f); @@ -184,6 +208,7 @@ void GlobalContext::initGlobalContext(ExecutionEngine *eng) callData->tag = QV4::Value::_Integer_Type; callData->argc = 0; callData->thisObject = eng->globalObject; + callData->args[0] = Encode::undefined(); global = 0; } @@ -222,7 +247,6 @@ void CallContext::initQmlContext(ExecutionContext *parentContext, ObjectRef qml, this->callData->thisObject = Primitive::undefinedValue(); strictMode = true; - marked = false; this->outer = function->scope; #ifndef QT_NO_DEBUG assert(outer->next != (ExecutionContext *)0x1); @@ -285,36 +309,34 @@ bool CallContext::needsOwnArguments() const return function->needsActivation || callData->argc < static_cast<int>(function->formalParameterCount); } -void ExecutionContext::mark() +void ExecutionContext::markObjects(Managed *m, ExecutionEngine *engine) { - if (marked) - return; - marked = true; + ExecutionContext *ctx = static_cast<ExecutionContext *>(m); - if (outer) - outer->mark(); + if (ctx->outer) + ctx->outer->mark(engine); // ### shouldn't need these 3 lines - callData->thisObject.mark(engine); - for (int arg = 0; arg < callData->argc; ++arg) - callData->args[arg].mark(engine); + ctx->callData->thisObject.mark(engine); + for (int arg = 0; arg < ctx->callData->argc; ++arg) + ctx->callData->args[arg].mark(engine); - if (type >= Type_CallContext) { - QV4::CallContext *c = static_cast<CallContext *>(this); + if (ctx->type >= Type_CallContext) { + QV4::CallContext *c = static_cast<CallContext *>(ctx); for (unsigned local = 0, lastLocal = c->variableCount(); local < lastLocal; ++local) c->locals[local].mark(engine); if (c->activation) c->activation->mark(engine); c->function->mark(engine); - } else if (type == Type_WithContext) { - WithContext *w = static_cast<WithContext *>(this); + } else if (ctx->type == Type_WithContext) { + WithContext *w = static_cast<WithContext *>(ctx); w->withObject->mark(engine); - } else if (type == Type_CatchContext) { - CatchContext *c = static_cast<CatchContext *>(this); + } else if (ctx->type == Type_CatchContext) { + CatchContext *c = static_cast<CatchContext *>(ctx); c->exceptionVarName->mark(engine); c->exceptionValue.mark(engine); - } else if (type == Type_GlobalContext) { - GlobalContext *g = static_cast<GlobalContext *>(this); + } else if (ctx->type == Type_GlobalContext) { + GlobalContext *g = static_cast<GlobalContext *>(ctx); g->global->mark(engine); } } diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index ccb5cf98f8..9b080dc590 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -66,8 +66,21 @@ struct CallContext; struct CatchContext; struct WithContext; -struct Q_QML_EXPORT ExecutionContext +struct Q_QML_EXPORT ExecutionContext : public Managed { + Q_MANAGED + ExecutionContext() + : Managed(0) { + vtbl = &static_vtbl; + } + void init() { + _data = 0; + internalClass = 0; + inUse = 1; + extensible = 1; + vtbl = &static_vtbl; + } + enum Type { Type_GlobalContext = 0x1, Type_CatchContext = 0x2, @@ -79,7 +92,6 @@ struct Q_QML_EXPORT ExecutionContext Type type; bool strictMode; - bool marked; CallData *callData; @@ -104,7 +116,6 @@ struct Q_QML_EXPORT ExecutionContext { this->type = type; strictMode = false; - marked = false; this->engine = engine; parent = parentContext; outer = 0; @@ -148,10 +159,10 @@ struct Q_QML_EXPORT ExecutionContext // Can only be called from within catch(...), rethrows if no JS exception. ReturnedValue catchException(StackTrace *trace = 0); - void mark(); - inline CallContext *asCallContext(); inline const CallContext *asCallContext() const; + + static void markObjects(Managed *m, ExecutionEngine *e); }; struct CallContext : public ExecutionContext diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 84be89d31a..19aaee104f 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -382,7 +382,8 @@ void ExecutionEngine::enableDebugger() void ExecutionEngine::initRootContext() { - rootContext = static_cast<GlobalContext *>(memoryManager->allocContext(sizeof(GlobalContext) + sizeof(CallData))); + rootContext = static_cast<GlobalContext *>(memoryManager->allocManaged(sizeof(GlobalContext) + sizeof(CallData))); + rootContext->init(); current = rootContext; current->parent = 0; rootContext->initGlobalContext(this); @@ -395,9 +396,9 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other) ExecutionContext *ExecutionEngine::pushGlobalContext() { - GlobalContext *g = static_cast<GlobalContext *>(memoryManager->allocContext(sizeof(GlobalContext))); + GlobalContext *g = new (memoryManager) GlobalContext; ExecutionContext *oldNext = g->next; - *g = *rootContext; + memcpy(g, rootContext, sizeof(GlobalContext)); g->next = oldNext; g->parent = current; current = g; @@ -747,7 +748,7 @@ void ExecutionEngine::markObjects() ExecutionContext *c = current; while (c) { - c->mark(); + c->mark(this); c = c->parent; } diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index b4972904ee..c37d4f125d 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -388,6 +388,7 @@ struct ExecutionContextSaver inline void Managed::mark(QV4::ExecutionEngine *engine) { + Q_ASSERT(inUse); if (markBit) return; markBit = 1; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 8c3131c565..99797ec56b 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -213,7 +213,7 @@ void FunctionObject::markObjects(Managed *that, ExecutionEngine *e) // formalParameterList[i]->mark(); // for (uint i = 0; i < varCount; ++i) // varList[i]->mark(); - o->scope->mark(); + o->scope->mark(e); if (o->function) o->function->mark(e); diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index d57ad69262..9cac0cf90c 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -214,7 +214,6 @@ bool operator<(const MemoryManager::Data::Chunk &a, const MemoryManager::Data::C MemoryManager::MemoryManager() : m_d(new Data(true)) - , m_contextList(0) , m_persistentValues(0) , m_weakValues(0) { @@ -484,20 +483,6 @@ void MemoryManager::sweep(bool lastSweep) i = *last; } - ExecutionContext *ctx = m_contextList; - ExecutionContext **n = &m_contextList; - while (ctx) { - ExecutionContext *next = ctx->next; - if (!ctx->marked) { - free(ctx); - *n = next; - } else { - ctx->marked = false; - n = &ctx->next; - } - ctx = next; - } - deletable = *firstDeletable; while (deletable) { GCDeletable *next = deletable->next; diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h index f3258519de..7d28319536 100644 --- a/src/qml/jsruntime/qv4mm_p.h +++ b/src/qml/jsruntime/qv4mm_p.h @@ -103,8 +103,6 @@ public: return o; } - ExecutionContext *allocContext(uint size); - bool isGCBlocked() const; void setGCBlocked(bool blockGC); void runGC(); @@ -134,21 +132,11 @@ private: protected: QScopedPointer<Data> m_d; - ExecutionContext *m_contextList; public: PersistentValuePrivate *m_persistentValues; PersistentValuePrivate *m_weakValues; }; -inline ExecutionContext *MemoryManager::allocContext(uint size) -{ - ExecutionContext *newContext = (ExecutionContext *)malloc(size); - newContext->next = m_contextList; - m_contextList = newContext; - return newContext; -} - - } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 25791cff61..2f015ac83a 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -62,11 +62,18 @@ using namespace QV4; QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, ObjectRef qml) : FunctionObject(scope, scope->engine->id_eval) , qml(qml) + , qmlContext(0) { + Q_ASSERT(scope->inUse); + vtbl = &static_vtbl; function = f; function->compilationUnit->ref(); needsActivation = function->needsActivation(); + + Scope s(scope); + ScopedValue protectThis(s, this); + defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1)); qmlContext = scope->engine->current->newQmlContext(this, qml); @@ -76,10 +83,17 @@ QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, Function *f, Objec QmlBindingWrapper::QmlBindingWrapper(ExecutionContext *scope, ObjectRef qml) : FunctionObject(scope, scope->engine->id_eval) , qml(qml) + , qmlContext(0) { + Q_ASSERT(scope->inUse); + vtbl = &static_vtbl; function = 0; needsActivation = false; + + Scope s(scope); + ScopedValue protectThis(s, this); + defineReadonlyProperty(scope->engine->id_length, Primitive::fromInt32(1)); qmlContext = scope->engine->current->newQmlContext(this, qml); @@ -110,7 +124,8 @@ void QmlBindingWrapper::markObjects(Managed *m, ExecutionEngine *e) if (wrapper->qml) wrapper->qml->mark(e); FunctionObject::markObjects(m, e); - wrapper->qmlContext->mark(); + if (wrapper->qmlContext) + wrapper->qmlContext->mark(e); } DEFINE_MANAGED_VTABLE(QmlBindingWrapper); |