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 d2db6c86e2ad74a3b63e58fc1adff546dc666a13..3266a355db8329838958035d5f3643809cc25347 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 ee6399a4647ac429f52fbd9a4abd4d7c74c2dc22..7f4b8553cd46822475cbd8864f3b8234fcaf6fe9 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 f7f5f1506e4d775391bd98367ee7bfb0892a725a..15df292ee307846d0709c170e48625e781f388fc 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 b9b1a0042d3445d67adbcf50739dd57e79198e87..305362cea81b736f8fc00bb5be90cb206c2cd57d 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 ab30c5c3ab2bc8158e0940b00f2bbf00b23bd744..61d620f4d5b1ad6a74318ba2e059b885430110e0 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 4be1cb1cbc56d36743bdf4cab8aa5fe0b11d5803..35a770683ec5c6e87d701c9a5b7ba1861d3a5960 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 e06b39c981308ea6146fb327fb9c30d0aa7d87d0..77bf4bbca9d16ccab0f9e98777dcca9b1fb2dcd9 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 *);