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);
}
}
-ScriptFunction::ScriptFunction(IR::Function *function)
- : function(function)
+ScriptFunction::ScriptFunction(Context *context, IR::Function *function)
+ : context(context)
+ , function(function)
{
formalParameterCount = function->formals.size();
if (formalParameterCount) {
};
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);
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)
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);
}
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);
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);
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();
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;
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()) {
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 *);