Converting more methods to the new calling convention
authorLars Knoll <lars.knoll@digia.com>
Tue, 16 Oct 2012 13:10:47 +0000 (15:10 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 16 Oct 2012 14:57:09 +0000 (16:57 +0200)
Change-Id: I5199a9e5439644cc259f131c8b0ba6a941989615
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
llvm_runtime.cpp
moth/qv4vme_moth.cpp
qmljs_runtime.cpp
qmljs_runtime.h
qv4array.cpp
qv4ecmaobjects.cpp
qv4isel_masm.cpp
qv4isel_masm_p.h

index b69c883..31bdd90 100644 (file)
@@ -228,7 +228,8 @@ void __qmljs_llvm_call_activation_property(Context *context, Value *result, Stri
 
 void __qmljs_llvm_call_value(Context *context, Value *result, const Value *thisObject, const Value *func, Value *args, int argc)
 {
-    __qmljs_call_value(context, result, thisObject, func, args, argc);
+    Value that = thisObject ? *thisObject : Value::undefinedValue();
+    *result = __qmljs_call_value(context, that, func, args, argc);
 }
 
 void __qmljs_llvm_construct_activation_property(Context *context, Value *result, String *name, Value *args, int argc)
@@ -258,7 +259,7 @@ void __qmljs_llvm_get_property(Context *ctx, Value *result, Value *object, Strin
 
 void __qmljs_llvm_call_property(Context *context, Value *result, const Value *base, String *name, Value *args, int argc)
 {
-    __qmljs_call_property(context, result, base, name, args, argc);
+    *result = __qmljs_call_property(context, *base, name, args, argc);
 }
 
 void __qmljs_llvm_construct_property(Context *context, Value *result, const Value *base, String *name, Value *args, int argc)
index f244f1c..3bbbfe6 100644 (file)
@@ -133,7 +133,7 @@ void VME::operator()(QQmlJS::VM::Context *context, const uchar *code
 
     MOTH_BEGIN_INSTR(Call)
         VM::Value *args = stack.data() + instr.args;
-        __qmljs_call_value(context, &tempRegister, /*thisObject=*/0, &tempRegister, args, instr.argc);
+        tempRegister = __qmljs_call_value(context, VM::Value::undefinedValue(), &tempRegister, args, instr.argc);
     MOTH_END_INSTR(Call)
 
     MOTH_BEGIN_INSTR(Jump)
index 55fbc9f..45de64a 100644 (file)
@@ -368,11 +368,8 @@ void Context::initCallContext(ExecutionEngine *e, const Value *object, FunctionO
         std::fill(locals, locals + varCount, Value::undefinedValue());
 }
 
-void Context::leaveCallContext(FunctionObject *f, Value *returnValue)
+void Context::leaveCallContext(FunctionObject *f)
 {
-    if (returnValue)
-        *returnValue = result;
-
     if (! f->needsActivation) {
         delete[] locals;
         locals = 0;
@@ -395,7 +392,8 @@ void Context::leaveConstructorContext(FunctionObject *f, Value *returnValue)
     if (! thisObject.isObject())
         thisObject.objectValue()->prototype = engine->objectPrototype;
 
-    leaveCallContext(f, returnValue);
+    leaveCallContext(f);
+    *returnValue = result;
 }
 
 extern "C" {
@@ -820,8 +818,7 @@ void __qmljs_object_default_value(Context *ctx, Value *result, const Value *obje
 
     Value conv = oo->getProperty(ctx, meth1);
     if (!conv.isUndefined() && conv.isFunctionObject()) {
-        Value r;
-        __qmljs_call_value(ctx, &r, object, &conv, 0, 0);
+        Value r = __qmljs_call_value(ctx, *object, &conv, 0, 0);
         if (r.isPrimitive()) {
             *result = r;
             return;
@@ -830,8 +827,7 @@ void __qmljs_object_default_value(Context *ctx, Value *result, const Value *obje
 
     conv = oo->getProperty(ctx, meth2);
     if (!conv.isUndefined() && conv.isFunctionObject()) {
-        Value r;
-        __qmljs_call_value(ctx, &r, object, &conv, 0, 0);
+        Value r = __qmljs_call_value(ctx, *object, &conv, 0, 0);
         if (r.isPrimitive()) {
             *result = r;
             return;
@@ -1116,17 +1112,16 @@ Value __qmljs_call_activation_property(Context *context, String *name, Value *ar
         context->throwReferenceError(Value::fromString(name));
         return Value::undefinedValue();
     }
-    Value result;
-    __qmljs_call_value(context, &result, /*thisObject=*/ 0, func, args, argc);
+    Value result = __qmljs_call_value(context, Value::undefinedValue(), func, args, argc);
     return result;
 }
 
-void __qmljs_call_property(Context *context, Value *result, const Value *base, String *name, Value *args, int argc)
+Value __qmljs_call_property(Context *context, const Value base, String *name, Value *args, int argc)
 {
     Value baseObject;
     Value thisObject;
-    if (base) {
-        baseObject = *base;
+    if (!base.isUndefined()) {
+        baseObject = base;
         if (!baseObject.isObject())
             __qmljs_to_object(context, &baseObject, &baseObject);
         assert(baseObject.isObject());
@@ -1136,6 +1131,7 @@ void __qmljs_call_property(Context *context, Value *result, const Value *base, S
         thisObject = Value::nullValue();
     }
     Value func = baseObject.property(context, name);
+    Value result;
     if (FunctionObject *f = func.asFunctionObject()) {
         Context k;
         Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
@@ -1145,27 +1141,33 @@ void __qmljs_call_property(Context *context, Value *result, const Value *base, S
             context->hasUncaughtException = ctx->hasUncaughtException; // propagate the exception
             context->result = ctx->result;
         }
-        ctx->leaveCallContext(f, result);
+        ctx->leaveCallContext(f);
+        result = ctx->result;
     } else {
         context->throwTypeError();
     }
+    return result;
 }
 
-void __qmljs_call_value(Context *context, Value *result, const Value *thisObject, const Value *func, Value *args, int argc)
+Value __qmljs_call_value(Context *context, const Value thisObject, const Value *func, Value *args, int argc)
 {
+    Value result;
     if (FunctionObject *f = func->asFunctionObject()) {
         Context k;
         Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
-        ctx->initCallContext(context->engine, thisObject, f, args, argc);
+        const Value *that = thisObject.isUndefined() ? 0 : &thisObject;
+        ctx->initCallContext(context->engine, that, f, args, argc);
         f->call(ctx);
         if (ctx->hasUncaughtException) {
             context->hasUncaughtException = ctx->hasUncaughtException; // propagate the exception
             context->result = ctx->result;
         }
-        ctx->leaveCallContext(f, result);
+        ctx->leaveCallContext(f);
+        result = ctx->result;
     } else {
         context->throwTypeError();
     }
+    return result;
 }
 
 Value __qmljs_construct_activation_property(Context *context, String *name, Value *args, int argc)
index fbcca89..9c5c7cf 100644 (file)
@@ -90,8 +90,8 @@ extern "C" {
 
 // context
 Value __qmljs_call_activation_property(Context *, String *name, Value *args, int argc);
-void __qmljs_call_property(Context *context, Value *result, const Value *base, String *name, Value *args, int argc);
-void __qmljs_call_value(Context *context, Value *result, const Value *thisObject, const Value *func, Value *args, int argc);
+Value __qmljs_call_property(Context *context, const Value base, String *name, Value *args, int argc);
+Value __qmljs_call_value(Context *context, const Value thisObject, const Value *func, Value *args, int argc);
 
 Value __qmljs_construct_activation_property(Context *, String *name, Value *args, int argc);
 void __qmljs_construct_property(Context *context, Value *result, const Value *base, String *name, Value *args, int argc);
@@ -648,7 +648,7 @@ struct Context {
 #endif
 
     void initCallContext(ExecutionEngine *e, const Value *object, FunctionObject *f, Value *args, unsigned argc);
-    void leaveCallContext(FunctionObject *f, Value *r);
+    void leaveCallContext(FunctionObject *f);
 
     void initConstructorContext(ExecutionEngine *e, const Value *object, FunctionObject *f, Value *args, unsigned argc);
     void leaveConstructorContext(FunctionObject *f, Value *returnValue);
index a2f2f9e..7923b1e 100644 (file)
@@ -53,8 +53,7 @@ bool ArrayElementLessThan::operator()(const Value &v1, const Value &v2) const
         return true;
     if (!m_comparefn.isUndefined()) {
         Value args[] = { v1, v2 };
-        Value result;
-        __qmljs_call_value(m_context, &result, 0, &m_comparefn, args, 2);
+        Value result = __qmljs_call_value(m_context, Value::undefinedValue(), &m_comparefn, args, 2);
         return result.toNumber(m_context) <= 0;
     }
     return v1.toString(m_context)->toQString() < v2.toString(m_context)->toQString();
index 16476a2..1f0f82f 100644 (file)
@@ -1550,8 +1550,7 @@ void ArrayPrototype::method_every(Context *ctx)
                 args[0] = v;
                 args[1] = Value::fromDouble(k);
                 args[2] = ctx->thisObject;
-                Value r;
-                __qmljs_call_value(ctx, &r, &thisArg, &callback, args, 3);
+                Value r = __qmljs_call_value(ctx, thisArg, &callback, args, 3);
                 ok = __qmljs_to_boolean(r, ctx);
             }
             ctx->result = Value::fromBoolean(ok);
@@ -1580,8 +1579,7 @@ void ArrayPrototype::method_some(Context *ctx)
                 args[0] = v;
                 args[1] = Value::fromDouble(k);
                 args[2] = ctx->thisObject;
-                Value r;
-                __qmljs_call_value(ctx, &r, &thisArg, &callback, args, 3);
+                Value r = __qmljs_call_value(ctx, thisArg, &callback, args, 3);
                 ok = __qmljs_to_boolean(r, ctx);
             }
             ctx->result = Value::fromBoolean(ok);
@@ -1606,12 +1604,11 @@ void ArrayPrototype::method_forEach(Context *ctx)
                 Value v = instance->value.at(k);
                 if (v.isUndefined())
                     continue;
-                Value r;
                 Value args[3];
                 args[0] = v;
                 args[1] = Value::fromDouble(k);
                 args[2] = ctx->thisObject;
-                __qmljs_call_value(ctx, &r, &thisArg, &callback, args, 3);
+                Value r = __qmljs_call_value(ctx, thisArg, &callback, args, 3);
             }
         }
     } else {
@@ -1634,12 +1631,11 @@ void ArrayPrototype::method_map(Context *ctx)
                 Value v = instance->value.at(k);
                 if (v.isUndefined())
                     continue;
-                Value r;
                 Value args[3];
                 args[0] = v;
                 args[1] = Value::fromDouble(k);
                 args[2] = ctx->thisObject;
-                __qmljs_call_value(ctx, &r, &thisArg, &callback, args, 3);
+                Value r = __qmljs_call_value(ctx, thisArg, &callback, args, 3);
                 a->value.assign(k, r);
             }
             ctx->result = Value::fromObject(a);
@@ -1663,12 +1659,11 @@ void ArrayPrototype::method_filter(Context *ctx)
                 Value v = instance->value.at(k);
                 if (v.isUndefined())
                     continue;
-                Value r;
                 Value args[3];
                 args[0] = v;
                 args[1] = Value::fromDouble(k);
                 args[2] = ctx->thisObject;
-                __qmljs_call_value(ctx, &r, &thisArg, &callback, args, 3);
+                Value r = __qmljs_call_value(ctx, thisArg, &callback, args, 3);
                 if (__qmljs_to_boolean(r, ctx)) {
                     const uint index = a->value.size();
                     a->value.resize(index + 1);
@@ -1699,13 +1694,12 @@ void ArrayPrototype::method_reduce(Context *ctx)
                 continue;
             }
 
-            Value r;
             Value args[4];
             args[0] = acc;
             args[1] = v;
             args[2] = Value::fromDouble(k);
             args[3] = ctx->thisObject;
-            __qmljs_call_value(ctx, &r, 0, &callback, args, 4);
+            Value r = __qmljs_call_value(ctx, Value::undefinedValue(), &callback, args, 4);
             acc = r;
         }
         ctx->result = acc;
@@ -1731,13 +1725,12 @@ void ArrayPrototype::method_reduceRight(Context *ctx)
                 continue;
             }
 
-            Value r;
             Value args[4];
             args[0] = acc;
             args[1] = v;
             args[2] = Value::fromDouble(k);
             args[3] = ctx->thisObject;
-            __qmljs_call_value(ctx, &r, 0, &callback, args, 4);
+            Value r = __qmljs_call_value(ctx, Value::undefinedValue(), &callback, args, 4);
             acc = r;
         }
         ctx->result = acc;
@@ -1807,7 +1800,7 @@ void FunctionPrototype::method_apply(Context *ctx)
             return;
         }
 
-        __qmljs_call_value(ctx, &ctx->result, &thisObject, &ctx->thisObject, args.data(), args.size());
+        ctx->result = __qmljs_call_value(ctx, thisObject, &ctx->thisObject, args.data(), args.size());
     } else {
         ctx->throwTypeError();
     }
@@ -1821,7 +1814,7 @@ void FunctionPrototype::method_call(Context *ctx)
         QVector<Value> args(ctx->argumentCount ? ctx->argumentCount - 1 : 0);
         if (ctx->argumentCount)
             qCopy(ctx->arguments + 1, ctx->arguments + ctx->argumentCount, args.begin());
-        __qmljs_call_value(ctx, &ctx->result, &thisArg, &ctx->thisObject, args.data(), args.size());
+        ctx->result = __qmljs_call_value(ctx, thisArg, &ctx->thisObject, args.data(), args.size());
     } else {
         ctx->throwTypeError();
     }
index fc5c743..47f9f88 100644 (file)
@@ -228,7 +228,7 @@ void InstructionSelection::callValue(IR::Call *call, IR::Temp *result)
 
     int argc = prepareVariableArguments(call->args);
     IR::Temp* thisObject = 0;
-    generateFunctionCall(__qmljs_call_value, ContextRegister, result, baseTemp, thisObject, baseAddressForCallArguments(), TrustedImm32(argc));
+    generateFunctionCall2(result, __qmljs_call_value, ContextRegister, baseTemp, thisObject, baseAddressForCallArguments(), TrustedImm32(argc));
     checkExceptions();
 }
 
@@ -239,8 +239,7 @@ void InstructionSelection::callProperty(IR::Call *call, IR::Temp *result)
     assert(member->base->asTemp() != 0);
 
     int argc = prepareVariableArguments(call->args);
-    IR::Temp* thisObject = 0;
-    generateFunctionCall(__qmljs_call_property, ContextRegister, result, member->base->asTemp(), identifier(*member->name), baseAddressForCallArguments(), TrustedImm32(argc));
+    generateFunctionCall2(result, __qmljs_call_property, ContextRegister, member->base->asTemp(), identifier(*member->name), baseAddressForCallArguments(), TrustedImm32(argc));
     checkExceptions();
 }
 
@@ -259,7 +258,6 @@ void InstructionSelection::constructProperty(IR::New *call, IR::Temp *result)
     assert(member->base->asTemp() != 0);
 
     int argc = prepareVariableArguments(call->args);
-    IR::Temp* thisObject = 0;
     generateFunctionCall(__qmljs_construct_property, ContextRegister, result, member->base->asTemp(), identifier(*member->name), baseAddressForCallArguments(), TrustedImm32(argc));
     checkExceptions();
 }
index b8a133e..580ecea 100644 (file)
@@ -293,9 +293,13 @@ private:
 
     void loadArgument1(IR::Temp* temp, RegisterID dest)
     {
-        assert(temp);
-        Pointer addr = loadTempAddress(dest, temp);
-        loadPtr(addr, dest);
+        if (!temp) {
+            VM::Value undefined = VM::Value::undefinedValue();
+            move(TrustedImmPtr((const void *)undefined.val), dest);
+        } else {
+            Pointer addr = loadTempAddress(dest, temp);
+            loadPtr(addr, dest);
+        }
     }
 
     void loadArgument1(VM::String* string, RegisterID dest)
@@ -509,26 +513,40 @@ private:
         callFunctionEpilogue();
     }
 
-    template <typename ArgRet, typename Arg1, typename Arg2, typename Arg3>
-    void generateFunctionCallImp2(ArgRet r, const char* functionName, FunctionPtr function, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+    template <typename ArgRet, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+    void generateFunctionCallImp2(ArgRet r, const char* functionName, FunctionPtr function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
     {
         callFunctionPrologue();
         loadArgument1(arg1, RegisterArgument1);
         loadArgument1(arg2, RegisterArgument2);
         loadArgument1(arg3, RegisterArgument3);
+        loadArgument1(arg4, RegisterArgument4);
         callAbsolute(functionName, function);
         storeArgument(ReturnValueRegister, r);
         callFunctionEpilogue();
     }
 
-    template <typename ArgRet, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-    void generateFunctionCallImp2(ArgRet r, const char* functionName, FunctionPtr function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+    template <typename ArgRet, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+    void generateFunctionCallImp2(ArgRet r, const char* functionName, FunctionPtr function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
     {
         callFunctionPrologue();
         loadArgument1(arg1, RegisterArgument1);
         loadArgument1(arg2, RegisterArgument2);
         loadArgument1(arg3, RegisterArgument3);
         loadArgument1(arg4, RegisterArgument4);
+        loadArgument1(arg5, RegisterArgument5);
+        callAbsolute(functionName, function);
+        storeArgument(ReturnValueRegister, r);
+        callFunctionEpilogue();
+    }
+
+    template <typename ArgRet, typename Arg1, typename Arg2, typename Arg3>
+    void generateFunctionCallImp2(ArgRet r, const char* functionName, FunctionPtr function, Arg1 arg1, Arg2 arg2, Arg3 arg3)
+    {
+        callFunctionPrologue();
+        loadArgument1(arg1, RegisterArgument1);
+        loadArgument1(arg2, RegisterArgument2);
+        loadArgument1(arg3, RegisterArgument3);
         callAbsolute(functionName, function);
         storeArgument(ReturnValueRegister, r);
         callFunctionEpilogue();