}
namespace builtins {
+
using namespace QQmlJS::VM;
+
struct Print: FunctionObject
{
virtual void call(Context *ctx)
std::cout << std::endl;
}
};
+
+struct ObjectCtor: FunctionObject
+{
+ virtual void construct(Context *ctx)
+ {
+ __qmljs_init_object(ctx, &ctx->result, new Object());
+ }
+
+ virtual void call(Context *) {
+ assert(!"not here");
+ }
+};
} // builtins
VM::Context *ctx = new VM::Context;
ctx->init();
ctx->activation = VM::Value::object(ctx, new VM::ArgumentsObject(ctx));
+
ctx->activation.objectValue->put(VM::String::get(ctx, QLatin1String("print")),
VM::Value::object(ctx, new builtins::Print()));
+
+ ctx->activation.objectValue->put(VM::String::get(ctx, QLatin1String("Object")),
+ VM::Value::object(ctx, new builtins::ObjectCtor()));
+
foreach (IR::Function *function, module.functions) {
if (function->name && ! function->name->isEmpty()) {
ctx->activation.objectValue->put(VM::String::get(ctx, *function->name),
void __qmljs_get_property(Context *ctx, Value *result, Value *object, String *name)
{
- Q_UNUSED(ctx);
- Q_ASSERT(object->type == OBJECT_TYPE);
- object->objectValue->get(name, result);
+ if (object->type == OBJECT_TYPE) {
+ object->objectValue->get(name, result);
+ } else {
+ Value o;
+ __qmljs_to_object(ctx, &o, object);
+ assert(o.type == OBJECT_TYPE);
+ __qmljs_get_property(ctx, result, &o, name);
+ }
}
void __qmljs_get_activation_property(Context *ctx, Value *result, String *name)
if (result)
__qmljs_copy(result, &context->result);
} else {
- Q_ASSERT(!"not a function");
+ assert(!"not a function");
+ }
+ } else {
+ assert(!"not a callable object");
+ }
+}
+
+void __qmljs_construct_activation_property(Context *context, Value *result, String *name)
+{
+ Value func;
+ context->parent->activation.objectValue->get(name, &func);
+ if (func.type == OBJECT_TYPE) {
+ if (FunctionObject *f = func.objectValue->asFunctionObject()) {
+ context->formals = f->formalParameterList;
+ context->formalCount = f->formalParameterCount;
+ f->construct(context);
+ if (result)
+ __qmljs_copy(result, &context->result);
+ } else {
+ assert(!"not a function");
}
} else {
- Q_ASSERT(!"not a callable object");
+ assert(!"not a callable object");
}
}
amd64_call_code(_codePtr, __qmljs_dispose_context);
}
+void InstructionSelection::constructActivationProperty(IR::New *call, IR::Temp *result)
+{
+ 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;
+ }
+
+ String *id = identifier(*call->base->asName()->id);
+ 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);
+ amd64_mov_reg_imm(_codePtr, AMD64_RDX, id);
+ amd64_call_code(_codePtr, __qmljs_construct_activation_property);
+ amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R15, 8);
+ amd64_call_code(_codePtr, __qmljs_dispose_context);
+}
+
void InstructionSelection::visitExp(IR::Exp *s)
{
if (IR::Call *c = s->expr->asCall()) {
amd64_mov_reg_imm(_codePtr, AMD64_RDX, new String(*str->value));
amd64_call_code(_codePtr, __qmljs_init_string);
return;
+ } else if (IR::New *ctor = s->source->asNew()) {
+ constructActivationProperty(ctor, t);
+ return;
+ } else if (IR::Member *m = s->source->asMember()) {
+ //__qmljs_get_property(ctx, result, object, name);
+ if (IR::Temp *base = m->base->asTemp()) {
+ amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
+ loadTempAddress(AMD64_RSI, t);
+ loadTempAddress(AMD64_RDX, base);
+ amd64_mov_reg_imm(_codePtr, AMD64_RCX, identifier(*m->name));
+ amd64_call_code(_codePtr, __qmljs_get_property);
+ return;
+ }
+ assert(!"todo");
} else if (IR::Unop *u = s->source->asUnop()) {
if (IR::Temp *e = u->expr->asTemp()) {
amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
return;
}
}
+ } else if (IR::Member *m = s->target->asMember()) {
+ if (IR::Temp *base = m->base->asTemp()) {
+ if (IR::Const *c = s->source->asConst()) {
+ amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
+ loadTempAddress(AMD64_RSI, base);
+ amd64_mov_reg_imm(_codePtr, AMD64_RDX, identifier(*m->name));
+ amd64_mov_reg_imm(_codePtr, AMD64_RAX, &c->value);
+ amd64_movsd_reg_regp(_codePtr, X86_XMM0, AMD64_RAX);
+ amd64_call_code(_codePtr, __qmljs_set_property_number);
+ return;
+ } else if (IR::String *str = s->source->asString()) {
+ amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
+ loadTempAddress(AMD64_RSI, base);
+ amd64_mov_reg_imm(_codePtr, AMD64_RDX, identifier(*m->name));
+ amd64_mov_reg_imm(_codePtr, AMD64_RCX, VM::String::get(0, *str->value));
+ amd64_call_code(_codePtr, __qmljs_set_property_string);
+ return;
+ }
+ }
}
} else {
// inplace assignment, e.g. x += 1, ++x, ...
amd64_call_code(_codePtr, __qmljs_to_boolean);
amd64_patch(label2, _codePtr);
- amd64_alu_reg_imm_size(_codePtr, X86_CMP, X86_EAX, 0, 4);
+ amd64_alu_reg_imm_size(_codePtr, X86_CMP, AMD64_RAX, 0, 4);
_patches[s->iftrue].append(_codePtr);
amd64_branch32(_codePtr, X86_CC_NZ, 0, 1);