aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-11-14 14:53:28 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-22 14:54:33 +0100
commitbf173fe5da381c88343296ca33ef6b06389c6d20 (patch)
treeddcf0b304fea1c4ac76ab0762eb263a27fd6f7f0 /src/qml/jsruntime
parent855784e5a72cb1a1309bcc832f84e4d0989bfba6 (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.cpp2
-rw-r--r--src/qml/jsruntime/qv4context.cpp68
-rw-r--r--src/qml/jsruntime/qv4context_p.h21
-rw-r--r--src/qml/jsruntime/qv4engine.cpp9
-rw-r--r--src/qml/jsruntime/qv4engine_p.h1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4mm.cpp15
-rw-r--r--src/qml/jsruntime/qv4mm_p.h12
-rw-r--r--src/qml/jsruntime/qv4script.cpp17
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);