Initial support for inplace assignments.
authorRoberto Raggi <roberto.raggi@nokia.com>
Fri, 18 May 2012 20:04:26 +0000 (22:04 +0200)
committerRoberto Raggi <roberto.raggi@nokia.com>
Fri, 18 May 2012 20:04:26 +0000 (22:04 +0200)
qmljs_runtime.cpp
qmljs_runtime.h
qv4codegen.cpp
qv4isel.cpp

index 40f0b96..b83cc32 100644 (file)
@@ -438,7 +438,7 @@ void __qmljs_set_activation_property(Context *ctx, String *name, Value *value)
     if (Value *prop = ctx->lookup(name)) {
         *prop = *value;
     } else
-        ctx->activation.objectValue->put(name, *value);
+        ctx->engine->globalObject.objectValue->put(name, *value);
 }
 
 void __qmljs_copy_activation_property(Context *ctx, String *name, String *other)
index 2dd4f85..9837a46 100644 (file)
@@ -555,6 +555,83 @@ inline void __qmljs_bit_and(Context *ctx, Value *result, const Value *left, cons
     __qmljs_init_number(result, lval & rval);
 }
 
+inline void __qmljs_inplace_bit_and(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_bit_xor(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_bit_or(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_bit_or(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_bit_xor(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_bit_xor(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_add(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_add(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_sub(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_sub(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_mul(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_mul(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_div(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_div(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_mod(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_mod(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_shl(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_shl(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_shr(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_shr(ctx, result, result, &v);
+}
+
+inline void __qmljs_inplace_ushr(Context *ctx, Value *result, double value)
+{
+    Value v;
+    __qmljs_init_number(&v, value);
+    __qmljs_ushr(ctx, result, result, &v);
+}
+
 inline void __qmljs_add(Context *ctx, Value *result, const Value *left, const Value *right)
 {
     Value pleft, pright;
index 9226749..6abd114 100644 (file)
@@ -920,11 +920,13 @@ bool Codegen::visit(BinaryExpression *ast)
     case QSOperator::InplaceRightShift:
     case QSOperator::InplaceURightShift:
     case QSOperator::InplaceXor: {
-        move(*left, *right, baseOp(ast->op));
         if (_expr.accept(nx)) {
-            // nothing to do
+            move(*left, *right, baseOp(ast->op));
         } else {
-            _expr.code = *left;
+            const unsigned t = _block->newTemp();
+            move(_block->TEMP(t), *right);
+            move(*left, _block->TEMP(t), baseOp(ast->op));
+            _expr.code = _block->TEMP(t);
         }
         break;
     }
index 42e0084..6120609 100644 (file)
@@ -676,26 +676,79 @@ void InstructionSelection::visitMove(IR::Move *s)
         // inplace assignment, e.g. x += 1, ++x, ...
         if (IR::Temp *t = s->target->asTemp()) {
             if (IR::Const *c = s->source->asConst()) {
+                amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
+                loadTempAddress(AMD64_RSI, t);
+                amd64_mov_reg_imm(_codePtr, AMD64_RAX, &c->value);
+                amd64_movsd_reg_regp(_codePtr, X86_XMM0, AMD64_RAX);
+
+                void (*op)(Context *, Value *, double);
+                switch (s->op) {
+                case QQmlJS::IR::OpBitAnd: op = __qmljs_inplace_bit_and; break;
+                case QQmlJS::IR::OpBitOr: op = __qmljs_inplace_bit_or; break;
+                case QQmlJS::IR::OpBitXor: op = __qmljs_inplace_bit_xor; break;
+                case QQmlJS::IR::OpAdd: op = __qmljs_inplace_add; break;
+                case QQmlJS::IR::OpSub: op = __qmljs_inplace_sub; break;
+                case QQmlJS::IR::OpMul: op = __qmljs_inplace_mul; break;
+                case QQmlJS::IR::OpDiv: op = __qmljs_inplace_div; break;
+                case QQmlJS::IR::OpMod: op = __qmljs_inplace_mod; break;
+                case QQmlJS::IR::OpLShift: op = __qmljs_inplace_shl; break;
+                case QQmlJS::IR::OpRShift: op = __qmljs_inplace_shr; break;
+                case QQmlJS::IR::OpURShift: op = __qmljs_inplace_ushr; break;
+                default:
+                    Q_UNREACHABLE();
+                    break;
+                }
+
+                amd64_call_code(_codePtr, op);
                 return;
             } else if (IR::Temp *t2 = s->source->asTemp()) {
+                amd64_mov_reg_reg(_codePtr, AMD64_RDI, AMD64_R14, 8);
+                loadTempAddress(AMD64_RSI, t);
+                loadTempAddress(AMD64_RDX, t);
+                loadTempAddress(AMD64_RCX, t2);
+                void (*op)(Context *, Value *, const Value *, const Value *);
+                switch (s->op) {
+                case QQmlJS::IR::OpBitAnd: op = __qmljs_bit_and; break;
+                case QQmlJS::IR::OpBitOr: op = __qmljs_bit_or; break;
+                case QQmlJS::IR::OpBitXor: op = __qmljs_bit_xor; break;
+                case QQmlJS::IR::OpAdd: op = __qmljs_add; break;
+                case QQmlJS::IR::OpSub: op = __qmljs_sub; break;
+                case QQmlJS::IR::OpMul: op = __qmljs_mul; break;
+                case QQmlJS::IR::OpDiv: op = __qmljs_div; break;
+                case QQmlJS::IR::OpMod: op = __qmljs_mod; break;
+                case QQmlJS::IR::OpLShift: op = __qmljs_shl; break;
+                case QQmlJS::IR::OpRShift: op = __qmljs_shr; break;
+                case QQmlJS::IR::OpURShift: op = __qmljs_ushr; break;
+                default:
+                    Q_UNREACHABLE();
+                    break;
+                }
+
+                amd64_call_code(_codePtr, op);
                 return;
             }
         } else if (IR::Name *n = s->target->asName()) {
             if (IR::Const *c = s->source->asConst()) {
+                assert(!"wip");
                 return;
             } else if (IR::Temp *t = s->source->asTemp()) {
+                assert(!"wip");
                 return;
             }
         } else if (IR::Subscript *ss = s->target->asSubscript()) {
             if (IR::Const *c = s->source->asConst()) {
+                assert(!"wip");
                 return;
             } else if (IR::Temp *t = s->source->asTemp()) {
+                assert(!"wip");
                 return;
             }
         } else if (IR::Member *m = s->target->asMember()) {
             if (IR::Const *c = s->source->asConst()) {
+                assert(!"wip");
                 return;
             } else if (IR::Temp *t = s->source->asTemp()) {
+                assert(!"wip");
                 return;
             }
         }
@@ -725,12 +778,12 @@ void InstructionSelection::visitCJump(IR::CJump *s)
         amd64_alu_reg_imm(_codePtr, X86_CMP, AMD64_RAX, BOOLEAN_TYPE);
 
         uchar *label1 = _codePtr;
-        amd64_branch32(_codePtr, X86_CC_NE, 0, 0);
+        amd64_branch8(_codePtr, X86_CC_NE, 0, 0);
 
         amd64_mov_reg_membase(_codePtr, AMD64_RAX, AMD64_RSI, offsetof(Value, booleanValue), 1);
 
         uchar *label2 = _codePtr;
-        amd64_jump32(_codePtr, 0);
+        amd64_jump8(_codePtr, 0);
 
         amd64_patch(label1, _codePtr);
         amd64_call_code(_codePtr, __qmljs_to_boolean);