Change the Context stack back to a singly linked list
authorLars Knoll <lars.knoll@digia.com>
Sun, 7 Apr 2013 15:23:36 +0000 (17:23 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Sun, 7 Apr 2013 19:24:35 +0000 (21:24 +0200)
The other implementation was too complicated, and only solved
one special case (indirect eval calls), but that one can be
solved by simply creating a GlobalContext when needed.

In addition it'll make it simpler to implement context
optimisations for simple methods in the future.

Speeds up the V8 benchmark by 3%

Change-Id: I61ac7753821e0174476094f51a9a4e934563f8e0
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/v4/qv4context.cpp
src/v4/qv4context.h
src/v4/qv4engine.cpp
src/v4/qv4engine.h
src/v4/qv4mm.cpp
src/v4/qv4runtime.cpp
src/v4/qv4v8.cpp

index c2ecec8..462ac96 100644 (file)
@@ -213,9 +213,6 @@ void CallContext::initCallContext(ExecutionEngine *engine)
         desc.enumerable = PropertyDescriptor::Enabled;
         activation->__defineOwnProperty__(this, engine->id_arguments, &desc);
     }
-
-    if (engine->debugger)
-        engine->debugger->aboutToCall(function, this);
 }
 
 
index e70ca8b..c26cc6b 100644 (file)
@@ -93,6 +93,7 @@ struct ExecutionContext
     Value thisObject;
 
     ExecutionEngine *engine;
+    ExecutionContext *parent;
     ExecutionContext *outer;
     Lookup *lookups;
     ExecutionContext *next; // used in the GC
index eb0aab8..4e23fa2 100644 (file)
@@ -68,9 +68,6 @@ namespace VM {
 ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     : memoryManager(new QQmlJS::VM::MemoryManager)
     , executableAllocator(new QQmlJS::VM::ExecutableAllocator)
-    , contextStack(0)
-    , contextStackPosition(0)
-    , contextStackSize(0)
     , debugger(0)
     , globalObject(Value::nullValue())
     , globalCode(0)
@@ -243,7 +240,6 @@ ExecutionEngine::~ExecutionEngine()
 {
     delete regExpCache;
     delete globalObject.asObject();
-    delete [] contextStack;
     UnwindHelper::deregisterFunctions(functions);
     qDeleteAll(functions);
     delete memoryManager;
@@ -252,37 +248,18 @@ ExecutionEngine::~ExecutionEngine()
 
 void ExecutionEngine::initRootContext()
 {
-    ensureContextStackSize();
     rootContext = static_cast<GlobalContext *>(memoryManager->allocContext(sizeof(GlobalContext)));
     current = rootContext;
-    contextStack[0] = rootContext;
+    current->parent = 0;
     rootContext->init(this);
 }
 
-void ExecutionEngine::ensureContextStackSize()
-{
-    if (contextStackPosition < contextStackSize - 1)
-        return;
-
-    const int stackSize = qMax(32, 2*contextStackSize);
-    ExecutionContext **newStack = new ExecutionContext *[stackSize];
-    if (contextStack)
-        memcpy(newStack, contextStack, contextStackSize*sizeof(ExecutionContext *));
-    memset(newStack + contextStackSize, 0, (stackSize - contextStackSize)*sizeof(ExecutionContext *));
-    delete [] contextStack;
-    contextStackSize = stackSize;
-    contextStack = newStack;
-}
-
 WithContext *ExecutionEngine::newWithContext(Object *with)
 {
-    ensureContextStackSize();
-    assert(contextStack[contextStackPosition + 1] == 0);
-
     ExecutionContext *p = current;
     WithContext *w = static_cast<WithContext *>(memoryManager->allocContext(sizeof(WithContext)));
+    w->parent = current;
     current = w;
-    contextStack[++contextStackPosition] = current;
 
     w->init(p, with);
     return w;
@@ -290,13 +267,10 @@ WithContext *ExecutionEngine::newWithContext(Object *with)
 
 CatchContext *ExecutionEngine::newCatchContext(String *exceptionVarName, const Value &exceptionValue)
 {
-    ensureContextStackSize();
-    assert(contextStack[contextStackPosition + 1] == 0);
-
     ExecutionContext *p = current;
     CatchContext *c = static_cast<CatchContext *>(memoryManager->allocContext(sizeof(CatchContext)));
+    c->parent = current;
     current = c;
-    contextStack[++contextStackPosition] = current;
 
     c->init(p, exceptionVarName, exceptionValue);
     return c;
@@ -304,12 +278,9 @@ CatchContext *ExecutionEngine::newCatchContext(String *exceptionVarName, const V
 
 CallContext *ExecutionEngine::newCallContext(FunctionObject *f, const Value &thisObject, Value *args, int argc)
 {
-    ensureContextStackSize();
-    assert(contextStack[contextStackPosition + 1] == 0);
-
     CallContext *c = static_cast<CallContext *>(memoryManager->allocContext(requiredMemoryForExecutionContect(f, argc)));
+    c->parent = current;
     current = c;
-    contextStack[++contextStackPosition] = current;
 
     c->function = f;
     c->thisObject = thisObject;
@@ -322,9 +293,6 @@ CallContext *ExecutionEngine::newCallContext(FunctionObject *f, const Value &thi
 
 CallContext *ExecutionEngine::newCallContext(void *stackSpace, FunctionObject *f, const Value &thisObject, Value *args, int argc)
 {
-    ensureContextStackSize();
-    assert(contextStack[contextStackPosition + 1] == 0);
-
     CallContext *c;
     uint memory = requiredMemoryForExecutionContect(f, argc);
     if (f->needsActivation || memory > stackContextSize) {
@@ -335,10 +303,9 @@ CallContext *ExecutionEngine::newCallContext(void *stackSpace, FunctionObject *f
         c->next = (CallContext *)0x1;
 #endif
     }
+    c->parent = current;
     current = c;
 
-    contextStack[++contextStackPosition] = current;
-
     c->function = f;
     c->thisObject = thisObject;
     c->arguments = args;
@@ -351,30 +318,11 @@ CallContext *ExecutionEngine::newCallContext(void *stackSpace, FunctionObject *f
 
 ExecutionContext *ExecutionEngine::pushGlobalContext()
 {
-    ensureContextStackSize();
-    assert(contextStack[contextStackPosition + 1] == 0);
-
-    current = rootContext;
-
-    contextStack[++contextStackPosition] = current;
-    return current;
-}
-
-ExecutionContext *ExecutionEngine::popContext()
-{
-    assert(current == contextStack[contextStackPosition]);
+    GlobalContext *g = static_cast<GlobalContext *>(memoryManager->allocContext(sizeof(GlobalContext)));
+    *g = *rootContext;
+    g->parent = current;
+    current = g;
 
-    if (debugger)
-        debugger->justLeft(current);
-
-    CallContext *c = current->asCallContext();
-    if (c && !c->needsOwnArguments()) {
-        c->arguments = 0;
-        c->argumentCount = 0;
-    }
-
-    contextStack[contextStackPosition] = 0;
-    current = contextStack[--contextStackPosition];
     return current;
 }
 
@@ -558,8 +506,11 @@ void ExecutionEngine::markObjects()
         pd.set->mark();
     }
 
-    for (int i = 0; i <= contextStackPosition; ++i)
-        contextStack[i]->mark();
+    ExecutionContext *c = current;
+    while (c) {
+        c->mark();
+        c = c->parent;
+    }
 
     for (int i = 0; i < functions.size(); ++i)
         functions.at(i)->mark();
index 1537027..3991c80 100644 (file)
@@ -109,10 +109,6 @@ struct Q_V4_EXPORT ExecutionEngine
     ExecutableAllocator *executableAllocator;
     QScopedPointer<EvalISelFactory> iselFactory;
 
-    ExecutionContext **contextStack;
-    int contextStackPosition;
-    int contextStackSize;
-
     ExecutionContext *current;
     GlobalContext *rootContext;
 
@@ -245,19 +241,27 @@ struct Q_V4_EXPORT ExecutionEngine
     Value run(VM::Function *function, ExecutionContext *ctx = 0);
 
     void initRootContext();
-    void ensureContextStackSize();
 };
 
 inline void ExecutionEngine::pushContext(SimpleCallContext *context)
 {
-    ensureContextStackSize();
-    assert(contextStack[contextStackPosition + 1] == 0);
-
+    context->parent = current;
     current = context;
+}
 
-    contextStack[++contextStackPosition] = current;
+inline ExecutionContext *ExecutionEngine::popContext()
+{
+    CallContext *c = current->asCallContext();
+    if (c && !c->needsOwnArguments()) {
+        c->arguments = 0;
+        c->argumentCount = 0;
+    }
+
+    current = current->parent;
+    return current;
 }
 
+
 } // namespace VM
 } // namespace QQmlJS
 
index bc4bd66..19e0e3f 100644 (file)
@@ -237,10 +237,6 @@ void MemoryManager::mark()
 {
     m_d->engine->markObjects();
 
-    ExecutionEngine *e = engine();
-    for (int i = 0; i <= e->contextStackPosition; ++i)
-        e->contextStack[i]->mark();
-
     for (QHash<Managed *, uint>::const_iterator it = m_d->protectedObject.begin(); it != m_d->protectedObject.constEnd(); ++it)
         it.key()->mark();
 
index c889753..b539f9d 100644 (file)
@@ -119,7 +119,7 @@ QString numberToString(double num, int radix = 10)
 
 Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionValue)
 {
-    this->throwingContext = throwingContext;
+    this->throwingContext = throwingContext->engine->current;
     this->exception = PersistentValue(throwingContext->engine->memoryManager, exceptionValue);
     accepted = false;
 }
index 835c825..067e656 100644 (file)
@@ -334,17 +334,16 @@ Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit, StackTrace::Sta
 {
     StackTrace *trace = new StackTrace;
     VM::ExecutionEngine *engine = currentEngine();
-    VM::ExecutionContext **root = engine->contextStack;
-    VM::ExecutionContext **current = root + engine->contextStackPosition;
-    while (current >= root && frame_limit) {
-        if (CallContext *c = (*current)->asCallContext()) {
+    VM::ExecutionContext *current = engine->current;
+    while (current && frame_limit) {
+        if (CallContext *c = current->asCallContext()) {
             StackFrame *frame = new StackFrame(Value::fromVmValue(VM::Value::fromString(engine->id_null)),
                                                Value::fromVmValue(VM::Value::fromString(c->function->name)),
                                                0, 0);
             trace->frames.append(frame);
             --frame_limit;
         }
-        --current;
+        current = current->parent;
     }
 
     return Local<StackTrace>::New(Handle<StackTrace>(trace));