Create some execution contexts on the stack again
authorLars Knoll <lars.knoll@digia.com>
Wed, 3 Apr 2013 18:24:38 +0000 (20:24 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Thu, 4 Apr 2013 13:32:21 +0000 (15:32 +0200)
This seems to be working now, and speeds up our benchmarks
with another 20%.

Change-Id: Ib01bf8f66db91b0e06090eff705db79b0caf66ee
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/qv4functionobject.cpp

index 51a80f4..88365f4 100644 (file)
@@ -542,6 +542,9 @@ void ExecutionContext::initCallContext(ExecutionEngine *engine)
     marked = false;
     this->engine = engine;
     outer = function->scope;
+#ifndef QT_NO_DEBUG
+    assert(outer->next != (ExecutionContext *)0x1);
+#endif
 
     exceptionVarName = 0;
     exceptionValue = Value::undefinedValue();
index d2b05bb..454cedb 100644 (file)
@@ -145,6 +145,7 @@ struct ExecutionContext
 /* Function *f, int argc */
 #define requiredMemoryForExecutionContect(f, argc) \
     sizeof(ExecutionContext) + sizeof(Value) * (f->varCount + qMax((uint)argc, f->formalParameterCount))
+#define stackContextSize (sizeof(ExecutionContext) + 32*sizeof(Value))
 
 } // namespace VM
 } // namespace QQmlJS
index d944de8..f23ce33 100644 (file)
@@ -317,6 +317,33 @@ ExecutionContext *ExecutionEngine::newCallContext(FunctionObject *f, const Value
     return current;
 }
 
+ExecutionContext *ExecutionEngine::newCallContext(void *stackSpace, FunctionObject *f, const Value &thisObject, Value *args, int argc)
+{
+    ensureContextStackSize();
+    assert(contextStack[contextStackPosition + 1] == 0);
+
+    uint memory = requiredMemoryForExecutionContect(f, argc);
+    if (f->needsActivation || memory > stackContextSize) {
+        current = memoryManager->allocContext(memory);
+    } else {
+        current = (ExecutionContext *)stackSpace;
+#ifndef QT_NO_DEBUG
+        current->next = (ExecutionContext *)0x1;
+#endif
+    }
+
+    contextStack[++contextStackPosition] = current;
+
+    current->function = f;
+    current->thisObject = thisObject;
+    current->arguments = args;
+    current->argumentCount = argc;
+    current->initCallContext(this);
+
+    return current;
+}
+
+
 ExecutionContext *ExecutionEngine::pushGlobalContext()
 {
     ensureContextStackSize();
index a4b3bd8..b3dd3dc 100644 (file)
@@ -201,6 +201,7 @@ struct Q_V4_EXPORT ExecutionEngine
     ExecutionContext *newWithContext(Object *with);
     ExecutionContext *newCatchContext(String* exceptionVarName, const QQmlJS::VM::Value &exceptionValue);
     ExecutionContext *newCallContext(FunctionObject *f, const QQmlJS::VM::Value &thisObject, QQmlJS::VM::Value *args, int argc);
+    ExecutionContext *newCallContext(void *stackSpace, FunctionObject *f, const QQmlJS::VM::Value &thisObject, QQmlJS::VM::Value *args, int argc);
     ExecutionContext *pushGlobalContext();
     ExecutionContext *popContext();
 
index 83762e8..801291e 100644 (file)
@@ -103,6 +103,9 @@ FunctionObject::FunctionObject(ExecutionContext *scope)
     needsActivation = true;
     usesArgumentsObject = false;
     strictMode = false;
+#ifndef QT_NO_DEBUG
+     assert(scope->next != (ExecutionContext *)0x1);
+#endif
 }
 
 bool FunctionObject::hasInstance(Managed *that, ExecutionContext *ctx, const Value &value)
@@ -364,7 +367,8 @@ Value ScriptFunction::construct(Managed *that, ExecutionContext *context, Value
     if (proto.isObject())
         obj->prototype = proto.objectValue();
 
-    ExecutionContext *ctx = context->engine->newCallContext(f, Value::fromObject(obj), args, argc);
+    quintptr stackSpace[stackContextSize/sizeof(quintptr)];
+    ExecutionContext *ctx = context->engine->newCallContext(stackSpace, f, Value::fromObject(obj), args, argc);
 
     Value result = Value::undefinedValue();
     try {
@@ -384,7 +388,8 @@ Value ScriptFunction::call(Managed *that, ExecutionContext *context, const Value
 {
     ScriptFunction *f = static_cast<ScriptFunction *>(that);
     assert(f->function->code);
-    ExecutionContext *ctx = context->engine->newCallContext(f, thisObject, args, argc);
+    quintptr stackSpace[stackContextSize/sizeof(quintptr)];
+    ExecutionContext *ctx = context->engine->newCallContext(stackSpace, f, thisObject, args, argc);
 
     if (!f->strictMode && !thisObject.isObject()) {
         if (thisObject.isUndefined() || thisObject.isNull()) {