From: Roberto Raggi Date: Wed, 9 May 2012 13:47:55 +0000 (+0200) Subject: Add callValue. X-Git-Tag: submit/tizen/20131211.000705~670^2~659^2~1213 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=908cc655471ed5da3622ce05f30e864bf67b1f1f;p=platform%2Fupstream%2Fqtdeclarative.git Add callValue. --- diff --git a/main.cpp b/main.cpp index d2db6c86e..3266a355d 100644 --- 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); diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp index ee6399a46..7f4b8553c 100644 --- a/qmljs_objects.cpp +++ b/qmljs_objects.cpp @@ -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) { diff --git a/qmljs_objects.h b/qmljs_objects.h index f7f5f1506..15df292ee 100644 --- a/qmljs_objects.h +++ b/qmljs_objects.h @@ -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); diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index b9b1a0042..305362cea 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -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); diff --git a/qmljs_runtime.h b/qmljs_runtime.h index ab30c5c3a..61d620f4d 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -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); diff --git a/qv4isel.cpp b/qv4isel.cpp index 4be1cb1cb..35a770683 100644 --- a/qv4isel.cpp +++ b/qv4isel.cpp @@ -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()) { diff --git a/qv4isel_p.h b/qv4isel_p.h index e06b39c98..77bf4bbca 100644 --- a/qv4isel_p.h +++ b/qv4isel_p.h @@ -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 *);