Add callValue.
authorRoberto Raggi <roberto.raggi@nokia.com>
Wed, 9 May 2012 13:47:55 +0000 (15:47 +0200)
committerRoberto Raggi <roberto.raggi@nokia.com>
Wed, 9 May 2012 13:47:55 +0000 (15:47 +0200)
main.cpp
qmljs_objects.cpp
qmljs_objects.h
qmljs_runtime.cpp
qmljs_runtime.h
qv4isel.cpp
qv4isel_p.h

index d2db6c8..3266a35 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -106,7 +106,7 @@ void evaluate(QQmlJS::Engine *engine, const QString &fileName, const QString &co
         foreach (IR::Function *function, module.functions) {
             if (function->name && ! function->name->isEmpty()) {
                 ctx->activation.objectValue->put(VM::String::get(ctx, *function->name),
-                                                 VM::Value::object(ctx, new VM::ScriptFunction(function)));
+                                                 VM::Value::object(ctx, new VM::ScriptFunction(ctx, function)));
             }
         }
         codeByName.value(QLatin1String("%entry"))->code(ctx);
index ee6399a..7f4b855 100644 (file)
@@ -123,8 +123,9 @@ void FunctionObject::construct(Context *ctx)
     }
 }
 
-ScriptFunction::ScriptFunction(IR::Function *function)
-    : function(function)
+ScriptFunction::ScriptFunction(Context *context, IR::Function *function)
+    : context(context)
+    , function(function)
 {
     formalParameterCount = function->formals.size();
     if (formalParameterCount) {
index f7f5f15..15df292 100644 (file)
@@ -246,9 +246,10 @@ struct FunctionObject: Object {
 };
 
 struct ScriptFunction: FunctionObject {
+    Context *context;
     IR::Function *function;
 
-    ScriptFunction(IR::Function *function);
+    ScriptFunction(Context *context, IR::Function *function);
     virtual ~ScriptFunction();
 
     virtual void call(Context *ctx);
index b9b1a00..305362c 100644 (file)
@@ -17,7 +17,7 @@ extern "C" {
 
 void __qmljs_init_closure(Context *ctx, Value *result, IR::Function *clos)
 {
-    __qmljs_init_object(ctx, result, new ScriptFunction(clos));
+    __qmljs_init_object(ctx, result, new ScriptFunction(ctx, clos));
 }
 
 void __qmljs_string_literal_undefined(Context *ctx, Value *result)
@@ -200,7 +200,7 @@ void __qmljs_set_property_string(Context *ctx, Value *object, String *name, Stri
 void __qmljs_set_property_closure(Context *ctx, Value *object, String *name, IR::Function *function)
 {
     Value value;
-    __qmljs_init_object(ctx, &value, new VM::ScriptFunction(function));
+    __qmljs_init_object(ctx, &value, new VM::ScriptFunction(ctx, function));
     object->objectValue->put(name, value, /*flag*/ 0);
 }
 
@@ -387,7 +387,25 @@ void __qmljs_call_property(Context *context, Value *result, Value *base, String
     thisObject.objectValue->get(name, &func);
     if (func.type == OBJECT_TYPE) {
         if (FunctionObject *f = func.objectValue->asFunctionObject()) {
-            context->thisObject = thisObject;
+            __qmljs_init_null(context, &context->thisObject);
+            context->formals = f->formalParameterList;
+            context->formalCount = f->formalParameterCount;
+            f->call(context);
+            if (result)
+                __qmljs_copy(result, &context->result);
+        } else {
+            assert(!"not a function");
+        }
+    } else {
+        assert(!"not a callable object");
+    }
+}
+
+void __qmljs_call_value(Context *context, Value *result, Value *func)
+{
+    if (func->type == OBJECT_TYPE) {
+        if (FunctionObject *f = func->objectValue->asFunctionObject()) {
+            __qmljs_init_null(context, &context->thisObject);
             context->formals = f->formalParameterList;
             context->formalCount = f->formalParameterCount;
             f->call(context);
index ab30c5c..61d620f 100644 (file)
@@ -50,6 +50,7 @@ void __qmljs_call_activation_property(Context *, Value *result, String *name);
 void __qmljs_construct_activation_property(Context *, Value *result, String *name);
 void __qmljs_call_property(Context *context, Value *result, Value *base, String *name);
 void __qmljs_construct_property(Context *context, Value *result, Value *base, String *name);
+void __qmljs_call_value(Context *context, Value *result, Value *func);
 
 // constructors
 void __qmljs_init_undefined(Context *ctx, Value *result);
index 4be1cb1..35a7706 100644 (file)
@@ -212,6 +212,45 @@ void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *resu
     amd64_call_code(_codePtr, __qmljs_dispose_context);
 }
 
+
+void InstructionSelection::callValue(IR::Call *call, IR::Temp *result)
+{
+    IR::Temp *baseTemp = call->base->asTemp();
+    assert(baseTemp != 0);
+
+    int argc = 0;
+    for (IR::ExprList *it = call->args; it; it = it->next)
+        ++argc;
+
+    amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
+    amd64_alu_reg_reg(_codePtr, X86_XOR, AMD64_RSI, AMD64_RSI);
+    amd64_mov_reg_imm(_codePtr, AMD64_RDX, argc);
+    amd64_call_code(_codePtr, __qmljs_new_context);
+
+    amd64_mov_reg_reg(_codePtr, AMD64_R15, AMD64_RAX, 8);
+
+    argc = 0;
+    for (IR::ExprList *it = call->args; it; it = it->next) {
+        IR::Temp *t = it->expr->asTemp();
+        Q_ASSERT(t != 0);
+        amd64_mov_reg_membase(_codePtr, AMD64_RAX, AMD64_R15, offsetof(Context, arguments), 8);
+        amd64_lea_membase(_codePtr, AMD64_RDI, AMD64_RAX, argc * sizeof(Value));
+        loadTempAddress(AMD64_RSI, t);
+        amd64_call_code(_codePtr, __qmljs_copy);
+        ++argc;
+    }
+
+    amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R15, 8);
+    if (result)
+        loadTempAddress(AMD64_RSI, result);
+    else
+        amd64_alu_reg_reg(_codePtr, X86_XOR, AMD64_RSI, AMD64_RSI);
+    loadTempAddress(AMD64_RDX, baseTemp);
+    amd64_call_code(_codePtr, __qmljs_call_value);
+    amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R15, 8);
+    amd64_call_code(_codePtr, __qmljs_dispose_context);
+}
+
 void InstructionSelection::callProperty(IR::Call *call, IR::Temp *result)
 {
     IR::Member *member = call->base->asMember();
@@ -297,6 +336,9 @@ void InstructionSelection::visitExp(IR::Exp *s)
         if (c->base->asName()) {
             callActivationProperty(c, 0);
             return;
+        } else if (c->base->asTemp()) {
+            callValue(c, 0);
+            return;
         } else if (c->base->asMember()) {
             callProperty(c, 0);
             return;
@@ -558,6 +600,9 @@ void InstructionSelection::visitMove(IR::Move *s)
                 if (c->base->asName()) {
                     callActivationProperty(c, t);
                     return;
+                } else if (c->base->asTemp()) {
+                    callValue(c, t);
+                    return;
                 }
             }
         } else if (IR::Member *m = s->target->asMember()) {
index e06b39c..77bf4bb 100644 (file)
@@ -24,6 +24,7 @@ protected:
     void callActivationProperty(IR::Call *call, IR::Temp *result);
     void callProperty(IR::Call *call, IR::Temp *result);
     void constructActivationProperty(IR::New *call, IR::Temp *result);
+    void callValue(IR::Call *call, IR::Temp *result);
 
     virtual void visitExp(IR::Exp *);
     virtual void visitEnter(IR::Enter *);