Minor improvements to Context creation
authorLars Knoll <lars.knoll@digia.com>
Wed, 30 Jan 2013 16:11:09 +0000 (17:11 +0100)
committerSimon Hausmann <simon.hausmann@digia.com>
Thu, 31 Jan 2013 06:21:03 +0000 (07:21 +0100)
Avoid converting the this object for builtins, and
remove the GC blocker that's not needed anymore.
Move some parts of the code out to the caller
of initCallContext().

Change-Id: I8b11dd1604fb14940e4d4e9f403c2a8bfc837c4b
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/v4/qmljs_environment.cpp
src/v4/qmljs_environment.h
src/v4/qv4functionobject.cpp
src/v4/qv4globalobject.cpp
tests/TestExpectations

index 8ff93c1..76d0833 100644 (file)
@@ -492,61 +492,48 @@ void ExecutionContext::throwURIError(Value msg)
     throwError(Value::fromObject(engine->newURIErrorObject(this, msg)));
 }
 
-void ExecutionContext::initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc)
+void ExecutionContext::initCallContext(ExecutionContext *parent)
 {
-    MemoryManager::GCBlocker blockGC(parent->engine->memoryManager);
-
     engine = parent->engine;
     this->parent = parent;
-    outer = f->scope;
+    outer = function->scope;
     engine->current = this;
 
-    function = f;
-    strictMode = f->strictMode;
+    activation = 0;
+    withObject = 0;
 
-    thisObject = that;
-    if (!strictMode && !thisObject.isObject()) {
-        if (thisObject.isUndefined() || thisObject.isNull())
-            thisObject = engine->globalObject;
-        else
-            thisObject = thisObject.toObject(this);
-    }
+    strictMode = function->strictMode;
 
-    locals = function->varCount ? reinterpret_cast<Value *>(this + 1) : 0;
-    if (locals)
+    if (function->varCount) {
+        locals = reinterpret_cast<Value *>(this + 1);
         std::fill(locals, locals + function->varCount, Value::undefinedValue());
+    }
 
-    arguments = args;
-    argumentCount = argc;
-    if (function->needsActivation || argc < function->formalParameterCount){
+    uint argc = argumentCount;
+    if (function->needsActivation || argumentCount < function->formalParameterCount){
+        Value *args = arguments;
         argumentCount = qMax(argc, function->formalParameterCount);
         arguments = reinterpret_cast<Value *>(this + 1) + function->varCount;
         if (argc)
             std::copy(args, args + argc, arguments);
         if (argc < function->formalParameterCount)
             std::fill(arguments + argc, arguments + function->formalParameterCount, Value::undefinedValue());
-    }
 
-
-    activation = 0;
-    withObject = 0;
-
-    if (function->usesArgumentsObject) {
-        ArgumentsObject *args = new (engine->memoryManager) ArgumentsObject(this, function->formalParameterCount, argc);
-        args->prototype = engine->objectPrototype;
-        Value arguments = Value::fromObject(args);
-        createMutableBinding(engine->id_arguments, false);
-        setMutableBinding(this, engine->id_arguments, arguments);
+        if (function->usesArgumentsObject) {
+            ArgumentsObject *args = new (engine->memoryManager) ArgumentsObject(this, function->formalParameterCount, argc);
+            args->prototype = engine->objectPrototype;
+            Value arguments = Value::fromObject(args);
+            createMutableBinding(engine->id_arguments, false);
+            setMutableBinding(this, engine->id_arguments, arguments);
+        }
     }
 
     if (engine->debugger)
-        engine->debugger->aboutToCall(f, this);
+        engine->debugger->aboutToCall(function, this);
 }
 
 void ExecutionContext::leaveCallContext()
 {
-    if (!function->needsActivation)
-        locals = 0;
     engine->current = parent;
     parent = 0;
 
index 111c6ae..28f000b 100644 (file)
@@ -107,7 +107,7 @@ struct ExecutionContext
     ExecutionContext *createWithScope(Object *with);
     ExecutionContext *popScope();
 
-    void initCallContext(ExecutionContext *parent, const Value that, FunctionObject *f, Value *args, unsigned argc);
+    void initCallContext(ExecutionContext *parent);
     void leaveCallContext();
 
     void wireUpPrototype();
index f5e37de..41c06f0 100644 (file)
@@ -134,7 +134,12 @@ Value FunctionObject::construct(ExecutionContext *context, Value *args, int argc
     uint size = requiredMemoryForExecutionContect(this, argc);
     ExecutionContext *ctx = static_cast<ExecutionContext *>(needsActivation ? malloc(size) : alloca(size));
 
-    ctx->initCallContext(context, Value::fromObject(obj), this, args, argc);
+    ctx->thisObject = Value::fromObject(obj);
+    ctx->function = this;
+    ctx->arguments = args;
+    ctx->argumentCount = argc;
+
+    ctx->initCallContext(context);
     Value result = construct(ctx);
     ctx->leaveCallContext();
 
@@ -148,15 +153,24 @@ Value FunctionObject::call(ExecutionContext *context, Value thisObject, Value *a
     uint size = requiredMemoryForExecutionContect(this, argc);
     ExecutionContext *ctx = static_cast<ExecutionContext *>(needsActivation ? malloc(size) : alloca(size));
 
-
-    ctx->initCallContext(context, thisObject, this, args, argc);
-    if (isBuiltinFunction) {
+    if (!strictMode && !thisObject.isObject()) {
         // Built-in functions allow for the this object to be null or undefined. This overrides
         // the behaviour of changing thisObject to the global object if null/undefined and allows
         // the built-in functions for example to throw a type error if null is passed.
-        if (thisObject.isNull() || thisObject.isUndefined())
-            ctx->thisObject = thisObject;
+        if (thisObject.isUndefined() || thisObject.isNull()) {
+            if (!isBuiltinFunction)
+                thisObject = context->engine->globalObject;
+        } else {
+            thisObject = thisObject.toObject(context);
+        }
     }
+
+    ctx->thisObject = thisObject;
+    ctx->function = this;
+    ctx->arguments = args;
+    ctx->argumentCount = argc;
+
+    ctx->initCallContext(context);
     Value result = call(ctx);
     ctx->leaveCallContext();
     return result;
index 70ae41c..fe43011 100644 (file)
@@ -378,7 +378,11 @@ Value EvalFunction::evalCall(ExecutionContext *context, Value /*thisObject*/, Va
 
     if (strict) {
         ctx = k;
-        ctx->initCallContext(context, context->thisObject, this, args, argc);
+        ctx->thisObject = directCall ? context->thisObject : context->engine->globalObject;
+        ctx->function = this;
+        ctx->arguments = args;
+        ctx->argumentCount = argc;
+        ctx->initCallContext(context);
     }
 
     // set the correct strict mode flag on the context
index 39ace8b..9b1165c 100644 (file)
@@ -6,7 +6,6 @@
 10.4.2-1-2 failing
 10.4.3-1-104 failing
 10.4.3-1-106 failing
-10.4.3-1-17-s failing
 10.4.3-1-63-s failing
 10.4.3-1-82-s failing
 11.2.3-3_3 failing
@@ -53,4 +52,4 @@ Sbp_A4_T2 failing
 S12.4_A1 failing
 S15.2.4.4_A14 failing
 # Try/catch scoping issue
-S12.14_A4 failing
+S12.14_A4 failing
\ No newline at end of file