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)
return ctx->engine->newString(msg);
}
-DEFINE_MANAGED_VTABLE(ExecutionContext);
-
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
if (!activation)
void ExecutionContext::init(ExecutionEngine *eng)
{
+ marked = false;
engine = eng;
outer = 0;
thisObject = eng->globalObject;
function = 0;
lookups = 0;
+ locals = 0;
arguments = 0;
argumentCount = 0;
locals = 0;
void ExecutionContext::init(ExecutionContext *p, Object *with)
{
+ marked = false;
engine = p->engine;
outer = p;
thisObject = p->thisObject;
function = 0;
lookups = p->lookups;
+ locals = 0;
arguments = 0;
argumentCount = 0;
locals = 0;
void ExecutionContext::initForCatch(ExecutionContext *p, String *exceptionVarName, const Value &exceptionValue)
{
+ marked = false;
engine = p->engine;
outer = p;
thisObject = p->thisObject;
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)
void ExecutionContext::initCallContext(ExecutionEngine *engine)
{
+ marked = false;
this->engine = engine;
outer = function->scope;
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;
#include "qv4global.h"
#include <qv4runtime.h>
-#include "qv4managed.h"
QT_BEGIN_NAMESPACE
struct Value;
struct Object;
struct ExecutionEngine;
-struct ExecutionContext;
struct DeclarativeEnvironment;
struct Lookup;
String *buildFullMessage(ExecutionContext *ctx) const;
};
-struct ExecutionContext : public Managed
+struct ExecutionContext
{
+ ExecutionContext *next; // used in the GC
ExecutionEngine *engine;
ExecutionContext *outer;
Value thisObject;
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);
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
{
delete regExpCache;
delete globalObject.asObject();
- delete rootContext;
delete [] contextStack;
UnwindHelper::deregisterFunctions(functions);
qDeleteAll(functions);
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()
if (contextStack)
memcpy(newStack, contextStack, contextStackSize*sizeof(ExecutionContext *));
memset(newStack + contextStackSize, 0, (stackSize - contextStackSize)*sizeof(ExecutionContext *));
+ delete [] contextStack;
contextStackSize = stackSize;
contextStack = newStack;
}
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;
}
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;
}
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;
}
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();
private:
friend class MemoryManager;
- friend struct ExecutionContext;
friend struct Identifiers;
};
} } // namespace QQmlJS::VM
MemoryManager::MemoryManager()
- : m_d(new Data(true))
+ : m_d(new Data(true))\
+ , m_contextList(0)
{
setEnableGC(true);
#ifdef V4_USE_VALGRIND
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;
}
#define QV4GC_H
#include "qv4global.h"
+#include "qv4context.h"
#include <QScopedPointer>
namespace VM {
struct ExecutionEngine;
+struct ExecutionContext;
struct Managed;
class Q_V4_EXPORT MemoryManager
return o;
}
+ ExecutionContext *allocContext(uint size);
+
bool isGCBlocked() const;
void setGCBlocked(bool blockGC);
void runGC();
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