diff options
-rw-r--r-- | main.cpp | 19 | ||||
-rw-r--r-- | qmljs_runtime.cpp | 34 | ||||
-rw-r--r-- | qmljs_runtime.h | 1 | ||||
-rw-r--r-- | qv4codegen.cpp | 2 | ||||
-rw-r--r-- | qv4isel.cpp | 71 | ||||
-rw-r--r-- | qv4isel_p.h | 1 | ||||
-rw-r--r-- | tests/obj.1.js | 8 | ||||
-rw-r--r-- | tests/simple2.js | 2 |
8 files changed, 130 insertions, 8 deletions
@@ -23,7 +23,9 @@ static inline bool protect(const void *addr, size_t size) } namespace builtins { + using namespace QQmlJS::VM; + struct Print: FunctionObject { virtual void call(Context *ctx) @@ -38,6 +40,18 @@ struct Print: FunctionObject 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 @@ -82,8 +96,13 @@ void evaluate(QQmlJS::Engine *engine, const QString &fileName, const QString &co 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), diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index 29cb423ef6..8dfcb827bd 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -219,9 +219,14 @@ void __qmljs_set_activation_property_string(Context *ctx, String *name, String * 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) @@ -361,10 +366,29 @@ void __qmljs_call_activation_property(Context *context, Value *result, String *n 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"); } } diff --git a/qmljs_runtime.h b/qmljs_runtime.h index 438206bed1..61aa230c85 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -42,6 +42,7 @@ extern "C" { Context *__qmljs_new_context(Context *current, Value *thisObject, size_t argc); void __qmljs_dispose_context(Context *ctx); void __qmljs_call_activation_property(Context *, Value *result, String *name); +void __qmljs_construct_activation_property(Context *, Value *result, String *name); // constructors void __qmljs_init_undefined(Context *ctx, Value *result); diff --git a/qv4codegen.cpp b/qv4codegen.cpp index f350dfb636..a53b78511d 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -244,7 +244,7 @@ void Codegen::operator()(AST::Program *node, IR::Module *module) IR::Expr *Codegen::member(IR::Expr *base, const QString *name) { - if (base->asTemp() || base->asName()) + if (base->asTemp() /*|| base->asName()*/) return _block->MEMBER(base, name); else { const unsigned t = _block->newTemp(); diff --git a/qv4isel.cpp b/qv4isel.cpp index 1cb3bc31ff..4fb6ca0153 100644 --- a/qv4isel.cpp +++ b/qv4isel.cpp @@ -204,6 +204,42 @@ void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *resu 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()) { @@ -321,6 +357,20 @@ void InstructionSelection::visitMove(IR::Move *s) 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); @@ -435,6 +485,25 @@ void InstructionSelection::visitMove(IR::Move *s) 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, ... @@ -472,7 +541,7 @@ void InstructionSelection::visitCJump(IR::CJump *s) 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); diff --git a/qv4isel_p.h b/qv4isel_p.h index 753da042ea..360fc38e6c 100644 --- a/qv4isel_p.h +++ b/qv4isel_p.h @@ -22,6 +22,7 @@ protected: int tempOffset(IR::Temp *t); void loadTempAddress(int reg, IR::Temp *t); void callActivationProperty(IR::Call *call, IR::Temp *result); + void constructActivationProperty(IR::New *call, IR::Temp *result); virtual void visitExp(IR::Exp *); virtual void visitEnter(IR::Enter *); diff --git a/tests/obj.1.js b/tests/obj.1.js new file mode 100644 index 0000000000..de2bd6318e --- /dev/null +++ b/tests/obj.1.js @@ -0,0 +1,8 @@ + +var point = { x: 123, y: 321 } +print(point, point.x, point.y) + +var obj = {} +obj.x = 123 +obj.str = "ciao" +print(obj, obj.str, obj.x) diff --git a/tests/simple2.js b/tests/simple2.js index 484d1fe68c..4a9f966da1 100644 --- a/tests/simple2.js +++ b/tests/simple2.js @@ -6,7 +6,7 @@ function main() var c = 10 var d = 100 - for (i = 0; i < 1000000; i = i + 1) { + for (var i = 0; i < 1000000; i = i + 1) { if (a == 1) d = d + a + b * c else |