aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.cpp19
-rw-r--r--qmljs_runtime.cpp34
-rw-r--r--qmljs_runtime.h1
-rw-r--r--qv4codegen.cpp2
-rw-r--r--qv4isel.cpp71
-rw-r--r--qv4isel_p.h1
-rw-r--r--tests/obj.1.js8
-rw-r--r--tests/simple2.js2
8 files changed, 130 insertions, 8 deletions
diff --git a/main.cpp b/main.cpp
index 5ca39262ed..d2db6c86e2 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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