diff options
-rw-r--r-- | src/v4/qv4argumentsobject.cpp | 1 | ||||
-rw-r--r-- | src/v4/qv4context.cpp | 132 | ||||
-rw-r--r-- | src/v4/qv4context.h | 39 | ||||
-rw-r--r-- | src/v4/qv4engine.cpp | 29 | ||||
-rw-r--r-- | src/v4/qv4managed.h | 1 | ||||
-rw-r--r-- | src/v4/qv4mm.cpp | 17 | ||||
-rw-r--r-- | src/v4/qv4mm.h | 14 |
7 files changed, 101 insertions, 132 deletions
diff --git a/src/v4/qv4argumentsobject.cpp b/src/v4/qv4argumentsobject.cpp index 7667aaac..b891d029 100644 --- a/src/v4/qv4argumentsobject.cpp +++ b/src/v4/qv4argumentsobject.cpp @@ -168,6 +168,7 @@ Value ArgumentsSetterFunction::call(Managed *setter, ExecutionContext *ctx, cons void ArgumentsObject::markObjects(Managed *that) { ArgumentsObject *o = static_cast<ArgumentsObject *>(that); + o->context->mark(); for (int i = 0; i < o->mappedArguments.size(); ++i) { Managed *m = o->mappedArguments.at(i).asManaged(); if (m) diff --git a/src/v4/qv4context.cpp b/src/v4/qv4context.cpp index 41b0b2ac..51a80f4a 100644 --- a/src/v4/qv4context.cpp +++ b/src/v4/qv4context.cpp @@ -79,8 +79,6 @@ String *DiagnosticMessage::buildFullMessage(ExecutionContext *ctx) const return ctx->engine->newString(msg); } -DEFINE_MANAGED_VTABLE(ExecutionContext); - void ExecutionContext::createMutableBinding(String *name, bool deletable) { if (!activation) @@ -177,6 +175,7 @@ unsigned int ExecutionContext::variableCount() const void ExecutionContext::init(ExecutionEngine *eng) { + marked = false; engine = eng; outer = 0; thisObject = eng->globalObject; @@ -184,6 +183,7 @@ void ExecutionContext::init(ExecutionEngine *eng) function = 0; lookups = 0; + locals = 0; arguments = 0; argumentCount = 0; locals = 0; @@ -197,6 +197,7 @@ void ExecutionContext::init(ExecutionEngine *eng) void ExecutionContext::init(ExecutionContext *p, Object *with) { + marked = false; engine = p->engine; outer = p; thisObject = p->thisObject; @@ -204,6 +205,7 @@ void ExecutionContext::init(ExecutionContext *p, Object *with) function = 0; lookups = p->lookups; + locals = 0; arguments = 0; argumentCount = 0; locals = 0; @@ -217,6 +219,7 @@ void ExecutionContext::init(ExecutionContext *p, Object *with) void ExecutionContext::initForCatch(ExecutionContext *p, String *exceptionVarName, const Value &exceptionValue) { + marked = false; engine = p->engine; outer = p; thisObject = p->thisObject; @@ -269,76 +272,29 @@ bool ExecutionContext::needsOwnArguments() const return function && (function->needsActivation || argumentCount < function->formalParameterCount); } -void ExecutionContext::destroy(Managed *that) -{ - ExecutionContext *ctx = static_cast<ExecutionContext *>(that); - if (ctx->locals) - delete [] ctx->locals; - ctx->_data = 0; - ctx->vtbl = 0; -} - -void ExecutionContext::markObjects(Managed *that) -{ - ExecutionContext *ctx = static_cast<ExecutionContext *>(that); - ctx->thisObject.mark(); - if (ctx->function) - ctx->function->mark(); - for (unsigned arg = 0, lastArg = ctx->argumentCount; arg < lastArg; ++arg) - ctx->arguments[arg].mark(); - for (unsigned local = 0, lastLocal = ctx->variableCount(); local < lastLocal; ++local) - ctx->locals[local].mark(); - if (ctx->activation) - ctx->activation->mark(); - if (ctx->withObject) - ctx->withObject->mark(); - if (ctx->exceptionVarName) - ctx->exceptionVarName->mark(); - ctx->exceptionValue.mark(); -} - -Value ExecutionContext::get(Managed *m, ExecutionContext *ctx, String *name, bool *hasProperty) -{ - Q_UNIMPLEMENTED(); - Q_UNREACHABLE(); -} - -Value ExecutionContext::getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty) -{ - Q_UNIMPLEMENTED(); - Q_UNREACHABLE(); -} - -void ExecutionContext::put(Managed *m, ExecutionContext *ctx, String *name, const Value &value) -{ -} - -void ExecutionContext::putIndexed(Managed *m, ExecutionContext *ctx, uint index, const Value &value) +void ExecutionContext::mark() { -} - -PropertyFlags ExecutionContext::query(Managed *m, ExecutionContext *ctx, String *name) -{ - Q_UNIMPLEMENTED(); - Q_UNREACHABLE(); -} - -PropertyFlags ExecutionContext::queryIndexed(Managed *m, ExecutionContext *ctx, uint index) -{ - Q_UNIMPLEMENTED(); - Q_UNREACHABLE(); -} - -bool ExecutionContext::deleteProperty(Managed *m, ExecutionContext *ctx, String *name) -{ - Q_UNIMPLEMENTED(); - Q_UNREACHABLE(); -} - -bool ExecutionContext::deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index) -{ - Q_UNIMPLEMENTED(); - Q_UNREACHABLE(); + if (marked) + return; + marked = true; + + if (outer) + outer->mark(); + + thisObject.mark(); + if (function) + function->mark(); + for (unsigned arg = 0, lastArg = argumentCount; arg < lastArg; ++arg) + arguments[arg].mark(); + for (unsigned local = 0, lastLocal = variableCount(); local < lastLocal; ++local) + locals[local].mark(); + if (activation) + activation->mark(); + if (withObject) + withObject->mark(); + if (exceptionVarName) + exceptionVarName->mark(); + exceptionValue.mark(); } void ExecutionContext::setProperty(String *name, const Value& value) @@ -583,6 +539,7 @@ void ExecutionContext::throwURIError(Value msg) void ExecutionContext::initCallContext(ExecutionEngine *engine) { + marked = false; this->engine = engine; outer = function->scope; @@ -599,27 +556,22 @@ void ExecutionContext::initCallContext(ExecutionEngine *engine) lookups = function->function->lookups; uint argc = argumentCount; - uint valuesToAlloc = function->varCount; - bool copyArgs = needsOwnArguments(); - if (copyArgs) - valuesToAlloc += qMax(argc, function->formalParameterCount); - - if (valuesToAlloc) { - locals = new Value[valuesToAlloc]; - if (function->varCount) - std::fill(locals, locals + function->varCount, Value::undefinedValue()); - - if (copyArgs) { - Value *args = arguments; - argumentCount = qMax(argc, function->formalParameterCount); - arguments = locals + function->varCount; - if (argc) - ::memcpy(arguments, args, argc * sizeof(Value)); - if (argc < function->formalParameterCount) - std::fill(arguments + argc, arguments + function->formalParameterCount, Value::undefinedValue()); - } + locals = (Value *)(this + 1); + if (function->varCount) + std::fill(locals, locals + function->varCount, Value::undefinedValue()); + + if (needsOwnArguments()) { + Value *args = arguments; + argumentCount = qMax(argc, function->formalParameterCount); + arguments = locals + function->varCount; + if (argc) + ::memcpy(arguments, args, argc * sizeof(Value)); + if (argc < function->formalParameterCount) + std::fill(arguments + argc, arguments + function->formalParameterCount, Value::undefinedValue()); + } + if (function->usesArgumentsObject) { ArgumentsObject *args = new (engine->memoryManager) ArgumentsObject(this, function->formalParameterCount, argc); args->prototype = engine->objectPrototype; diff --git a/src/v4/qv4context.h b/src/v4/qv4context.h index 35c586f2..d2b05bbf 100644 --- a/src/v4/qv4context.h +++ b/src/v4/qv4context.h @@ -43,7 +43,6 @@ #include "qv4global.h" #include <qv4runtime.h> -#include "qv4managed.h" QT_BEGIN_NAMESPACE @@ -53,7 +52,6 @@ namespace VM { struct Value; struct Object; struct ExecutionEngine; -struct ExecutionContext; struct DeclarativeEnvironment; struct Lookup; @@ -75,8 +73,9 @@ struct Q_V4_EXPORT DiagnosticMessage String *buildFullMessage(ExecutionContext *ctx) const; }; -struct ExecutionContext : public Managed +struct ExecutionContext { + ExecutionContext *next; // used in the GC ExecutionEngine *engine; ExecutionContext *outer; Value thisObject; @@ -91,33 +90,28 @@ struct ExecutionContext : public Managed String *exceptionVarName; Value exceptionValue; - String * const *formals() const; - unsigned int formalCount() const; - String * const *variables() const; - unsigned int variableCount() const; - bool strictMode; bool qmlObject; // ## temporary until we do proper QML contexts + bool marked; Object *activation; Object *withObject; - ExecutionContext() - : Managed() - , locals(0) - { vtbl = &static_vtbl; } + String * const *formals() const; + unsigned int formalCount() const; + String * const *variables() const; + unsigned int variableCount() const; void init(ExecutionEngine *e); void init(ExecutionContext *p, Object *with); void initForCatch(ExecutionContext *p, String *exceptionVarName, const QQmlJS::VM::Value &exceptionValue); + void initCallContext(QQmlJS::VM::ExecutionEngine *engine); void createMutableBinding(String *name, bool deletable); bool setMutableBinding(ExecutionContext *scope, String *name, const Value &value); Value getBindingValue(ExecutionContext *scope, String *name, bool strict) const; bool deleteBinding(ExecutionContext *ctx, String *name); - void initCallContext(QQmlJS::VM::ExecutionEngine *engine); - void wireUpPrototype(); void Q_NORETURN throwError(const Value &value); @@ -145,21 +139,12 @@ struct ExecutionContext : public Managed bool needsOwnArguments() const; -protected: - static void destroy(Managed *that); - static void markObjects(Managed *that); - static Value get(Managed *m, ExecutionContext *ctx, String *name, bool *hasProperty); - static Value getIndexed(Managed *m, ExecutionContext *ctx, uint index, bool *hasProperty); - static void put(Managed *m, ExecutionContext *ctx, String *name, const Value &value); - static void putIndexed(Managed *m, ExecutionContext *ctx, uint index, const Value &value); - static PropertyFlags query(Managed *m, ExecutionContext *ctx, String *name); - static PropertyFlags queryIndexed(Managed *m, ExecutionContext *ctx, uint index); - static bool deleteProperty(Managed *m, ExecutionContext *ctx, String *name); - static bool deleteIndexedProperty(Managed *m, ExecutionContext *ctx, uint index); - - static const ManagedVTable static_vtbl; + void mark(); }; +/* Function *f, int argc */ +#define requiredMemoryForExecutionContect(f, argc) \ + sizeof(ExecutionContext) + sizeof(Value) * (f->varCount + qMax((uint)argc, f->formalParameterCount)) } // namespace VM } // namespace QQmlJS diff --git a/src/v4/qv4engine.cpp b/src/v4/qv4engine.cpp index f7c0098c..d944de80 100644 --- a/src/v4/qv4engine.cpp +++ b/src/v4/qv4engine.cpp @@ -243,7 +243,6 @@ ExecutionEngine::~ExecutionEngine() { delete regExpCache; delete globalObject.asObject(); - delete rootContext; delete [] contextStack; UnwindHelper::deregisterFunctions(functions); qDeleteAll(functions); @@ -254,10 +253,10 @@ ExecutionEngine::~ExecutionEngine() void ExecutionEngine::initRootContext() { ensureContextStackSize(); - rootContext = new (memoryManager) ExecutionContext(); - rootContext->init(this); + rootContext = memoryManager->allocContext(sizeof(ExecutionContext)); current = rootContext; contextStack[0] = rootContext; + current->init(this); } void ExecutionEngine::ensureContextStackSize() @@ -270,6 +269,7 @@ void ExecutionEngine::ensureContextStackSize() if (contextStack) memcpy(newStack, contextStack, contextStackSize*sizeof(ExecutionContext *)); memset(newStack + contextStackSize, 0, (stackSize - contextStackSize)*sizeof(ExecutionContext *)); + delete [] contextStack; contextStackSize = stackSize; contextStack = newStack; } @@ -279,11 +279,11 @@ ExecutionContext *ExecutionEngine::newWithContext(Object *with) ensureContextStackSize(); assert(contextStack[contextStackPosition + 1] == 0); - ExecutionContext *ctx = new (memoryManager) ExecutionContext(); - ctx->init(current, with); - current = ctx; - + ExecutionContext *c = current; + current = memoryManager->allocContext(sizeof(ExecutionContext)); contextStack[++contextStackPosition] = current; + + current->init(c, with); return current; } @@ -292,11 +292,11 @@ ExecutionContext *ExecutionEngine::newCatchContext(String *exceptionVarName, con ensureContextStackSize(); assert(contextStack[contextStackPosition + 1] == 0); - ExecutionContext *ctx = new (memoryManager) ExecutionContext(); - ctx->initForCatch(current, exceptionVarName, exceptionValue); - current = ctx; - + ExecutionContext *c = current; + current = memoryManager->allocContext(sizeof(ExecutionContext)); contextStack[++contextStackPosition] = current; + + current->initForCatch(c, exceptionVarName, exceptionValue); return current; } @@ -305,14 +305,15 @@ ExecutionContext *ExecutionEngine::newCallContext(FunctionObject *f, const Value ensureContextStackSize(); assert(contextStack[contextStackPosition + 1] == 0); - current = new (memoryManager) ExecutionContext(); + current = memoryManager->allocContext(requiredMemoryForExecutionContect(f, argc)); + contextStack[++contextStackPosition] = current; + current->function = f; current->thisObject = thisObject; current->arguments = args; current->argumentCount = argc; current->initCallContext(this); - contextStack[++contextStackPosition] = current; return current; } @@ -530,6 +531,8 @@ void ExecutionEngine::markObjects() pd.set->mark(); } + for (int i = 0; i <= contextStackPosition; ++i) + contextStack[i]->mark(); for (int i = 0; i < functions.size(); ++i) functions.at(i)->mark(); diff --git a/src/v4/qv4managed.h b/src/v4/qv4managed.h index a69adf36..264c92c1 100644 --- a/src/v4/qv4managed.h +++ b/src/v4/qv4managed.h @@ -236,7 +236,6 @@ protected: private: friend class MemoryManager; - friend struct ExecutionContext; friend struct Identifiers; }; diff --git a/src/v4/qv4mm.cpp b/src/v4/qv4mm.cpp index 26c26c04..0281aeca 100644 --- a/src/v4/qv4mm.cpp +++ b/src/v4/qv4mm.cpp @@ -128,7 +128,8 @@ bool operator<(const MemoryManager::Data::Chunk &a, const MemoryManager::Data::C } } // namespace QQmlJS::VM MemoryManager::MemoryManager() - : m_d(new Data(true)) + : m_d(new Data(true))\ + , m_contextList(0) { setEnableGC(true); #ifdef V4_USE_VALGRIND @@ -280,6 +281,20 @@ std::size_t MemoryManager::sweep() for (QVector<Data::Chunk>::iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) freedCount += sweep(reinterpret_cast<char*>(i->memory.base()), i->memory.size(), i->chunkSize); + 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; + } + return freedCount; } diff --git a/src/v4/qv4mm.h b/src/v4/qv4mm.h index fdde7615..a41df835 100644 --- a/src/v4/qv4mm.h +++ b/src/v4/qv4mm.h @@ -43,6 +43,7 @@ #define QV4GC_H #include "qv4global.h" +#include "qv4context.h" #include <QScopedPointer> @@ -54,6 +55,7 @@ namespace QQmlJS { namespace VM { struct ExecutionEngine; +struct ExecutionContext; struct Managed; class Q_V4_EXPORT MemoryManager @@ -103,6 +105,8 @@ public: return o; } + ExecutionContext *allocContext(uint size); + bool isGCBlocked() const; void setGCBlocked(bool blockGC); void runGC(); @@ -131,8 +135,18 @@ private: protected: QScopedPointer<Data> m_d; + ExecutionContext *m_contextList; }; +inline ExecutionContext *MemoryManager::allocContext(uint size) +{ + ExecutionContext *newContext = (ExecutionContext *)malloc(size); + newContext->next = m_contextList; + m_contextList = newContext; + return newContext; +} + + } // namespace VM } // namespace QQmlJS |