aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2017-06-20 11:28:27 +0200
committerLars Knoll <lars.knoll@qt.io>2017-06-21 09:19:59 +0000
commit48d77ce4c83c2c1d2f3ee3d01c69550e115c3226 (patch)
treeb62edfd573502ded0ff436c250992684d3770567
parent5c86161fa28e951435a735a299b886fbfbe3bb16 (diff)
Add support for post increment/decrement
Change-Id: Ie3f03a548105fe49d29e3d60bf823435f21b0340 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/qml/compiler/qv4codegen.cpp77
-rw-r--r--src/qml/compiler/qv4codegen_p.h6
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp16
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h26
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp8
-rw-r--r--src/qml/compiler/qv4jsir.cpp6
-rw-r--r--src/qml/compiler/qv4jsir_p.h6
-rw-r--r--src/qml/compiler/qv4ssa.cpp12
-rw-r--r--src/qml/jit/qv4unop.cpp4
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp44
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h6
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp24
12 files changed, 147 insertions, 88 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 6567b9a1ce..56d28d2147 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -924,10 +924,8 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
return expr;
case Compl:
return Reference::fromConst(this, Runtime::method_complement(v));
- case Increment:
- return Reference::fromConst(this, Runtime::method_increment(v));
- case Decrement:
- return Reference::fromConst(this, Runtime::method_decrement(v));
+ default:
+ break;
}
}
}
@@ -960,17 +958,35 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
ucompl.result = dest.asLValue();
bytecodeGenerator->addInstruction(ucompl);
} break;
- case Increment: {
- Instruction::Increment inc;
+ case PreIncrement: {
+ Instruction::PreIncrement inc;
inc.source = expr.asRValue();
inc.result = dest.asLValue();
bytecodeGenerator->addInstruction(inc);
+ expr.store(dest);
} break;
- case Decrement: {
- Instruction::Decrement dec;
+ case PreDecrement: {
+ Instruction::PreDecrement dec;
dec.source = expr.asRValue();
dec.result = dest.asLValue();
bytecodeGenerator->addInstruction(dec);
+ expr.store(dest);
+ } break;
+ case PostIncrement: {
+ Instruction::PostIncrement inc;
+ inc.source = expr.asRValue();
+ inc.result = dest.asLValue();
+ bytecodeGenerator->addInstruction(inc);
+ expr.asLValue(); // mark expr as needsWriteBack
+ expr.writeBack();
+ } break;
+ case PostDecrement: {
+ Instruction::PostDecrement dec;
+ dec.source = expr.asRValue();
+ dec.result = dest.asLValue();
+ bytecodeGenerator->addInstruction(dec);
+ expr.asLValue(); // mark expr as needsWriteBack
+ expr.writeBack();
} break;
}
@@ -2175,13 +2191,7 @@ bool Codegen::visit(PostDecrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->decrementToken))
return false;
- Reference oldValue = unop(UPlus, expr);
-
- TempScope scope(this);
- Reference newValue = unop(Decrement, oldValue);
- expr.store(newValue);
-
- _expr.result = oldValue;
+ _expr.result = unop(PostDecrement, expr);
return false;
}
@@ -2201,14 +2211,7 @@ bool Codegen::visit(PostIncrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->incrementToken))
return false;
- Reference oldValue = unop(UPlus, expr);
-
- TempScope scope(this);
- Reference newValue = unop(Increment, oldValue);
- expr.store(newValue);
-
- _expr.result = oldValue;
-
+ _expr.result = unop(PostIncrement, expr);
return false;
}
@@ -2226,19 +2229,7 @@ bool Codegen::visit(PreDecrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->decrementToken))
return false;
- auto tmp = unop(Decrement, expr);
- if (_expr.accept(nx)) {
- bytecodeGenerator->setLocation(ast->decrementToken);
- expr.store(tmp);
- } else {
- if (!tmp.isTempLocalArg()) {
- auto tmp2 = Reference::fromTemp(this);
- tmp2.store(tmp);
- tmp = tmp2;
- }
- expr.store(tmp);
- _expr.result = tmp;
- }
+ _expr.result = unop(PreDecrement, expr);
return false;
}
@@ -2257,19 +2248,7 @@ bool Codegen::visit(PreIncrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->incrementToken))
return false;
- auto tmp = unop(Increment, expr);
- if (_expr.accept(nx)) {
- bytecodeGenerator->setLocation(ast->incrementToken);
- expr.store(tmp);
- } else {
- if (!tmp.isTempLocalArg()) {
- auto tmp2 = Reference::fromTemp(this);
- tmp2.store(tmp);
- tmp = tmp2;
- }
- expr.store(tmp);
- _expr.result = tmp;
- }
+ _expr.result = unop(PreIncrement, expr);
return false;
}
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 193681096e..db806f3f5e 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -463,8 +463,10 @@ protected:
enum UnaryOperation {
UPlus,
UMinus,
- Increment,
- Decrement,
+ PreIncrement,
+ PreDecrement,
+ PostIncrement,
+ PostDecrement,
Not,
Compl
};
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 3f234f1394..07ffdfae03 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -412,13 +412,21 @@ void dumpBytecode(const char *code, int len)
d << instr.result << ", " << instr.source;
MOTH_END_INSTR(UComplInt)
- MOTH_BEGIN_INSTR(Increment)
+ MOTH_BEGIN_INSTR(PreIncrement)
d << instr.result << ", " << instr.source;
- MOTH_END_INSTR(Increment)
+ MOTH_END_INSTR(PreIncrement)
- MOTH_BEGIN_INSTR(Decrement)
+ MOTH_BEGIN_INSTR(PreDecrement)
d << instr.result << ", " << instr.source;
- MOTH_END_INSTR(Decrement)
+ MOTH_END_INSTR(PreDecrement)
+
+ MOTH_BEGIN_INSTR(PostIncrement)
+ d << instr.result << ", " << instr.source;
+ MOTH_END_INSTR(PostIncrement)
+
+ MOTH_BEGIN_INSTR(PostDecrement)
+ d << instr.result << ", " << instr.source;
+ MOTH_END_INSTR(PostDecrement)
MOTH_BEGIN_INSTR(Binop)
d << instr.alu << ", " << instr.result << ", " << instr.lhs << ", " << instr.rhs;
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 6625018443..ab22053e29 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -146,8 +146,10 @@ QT_BEGIN_NAMESPACE
F(UMinus, uminus) \
F(UCompl, ucompl) \
F(UComplInt, ucomplInt) \
- F(Increment, increment) \
- F(Decrement, decrement) \
+ F(PreIncrement, preIncrement) \
+ F(PreDecrement, preDecrement) \
+ F(PostIncrement, postIncrement) \
+ F(PostDecrement, postDecrement) \
F(Binop, binop) \
F(Add, add) \
F(BitAnd, bitAnd) \
@@ -703,12 +705,22 @@ union Instr
Param source;
Param result;
};
- struct instr_increment {
+ struct instr_preIncrement {
MOTH_INSTR_HEADER
Param source;
Param result;
};
- struct instr_decrement {
+ struct instr_preDecrement {
+ MOTH_INSTR_HEADER
+ Param source;
+ Param result;
+ };
+ struct instr_postIncrement {
+ MOTH_INSTR_HEADER
+ Param source;
+ Param result;
+ };
+ struct instr_postDecrement {
MOTH_INSTR_HEADER
Param source;
Param result;
@@ -901,8 +913,10 @@ union Instr
instr_uminus uminus;
instr_ucompl ucompl;
instr_ucomplInt ucomplInt;
- instr_increment increment;
- instr_decrement decrement;
+ instr_preIncrement preIncrement;
+ instr_preDecrement preDecrement;
+ instr_postIncrement postIncrement;
+ instr_postDecrement postDecrement;
instr_binop binop;
instr_add add;
instr_bitAnd bitAnd;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 24fbe3c680..986529f600 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -754,15 +754,15 @@ void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *targ
addInstruction(ucompl);
return;
}
- case IR::OpIncrement: {
- Instruction::Increment inc;
+ case IR::OpPreIncrement: {
+ Instruction::PreIncrement inc;
inc.source = getParam(source);
inc.result = getResultParam(target);
addInstruction(inc);
return;
}
- case IR::OpDecrement: {
- Instruction::Decrement dec;
+ case IR::OpPreDecrement: {
+ Instruction::PreDecrement dec;
dec.source = getParam(source);
dec.result = getResultParam(target);
addInstruction(dec);
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 5a58380005..464eb008e7 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -90,8 +90,10 @@ const char *opname(AluOp op)
case OpUMinus: return "neg";
case OpUPlus: return "plus";
case OpCompl: return "invert";
- case OpIncrement: return "incr";
- case OpDecrement: return "decr";
+ case OpPreIncrement: return "pre-incr";
+ case OpPreDecrement: return "pre-decr";
+ case OpPostIncrement: return "post-incr";
+ case OpPostDecrement: return "post-decr";
case OpBitAnd: return "bitand";
case OpBitOr: return "bitor";
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 1b77dbf096..82632c391e 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -156,8 +156,10 @@ enum AluOp {
OpUMinus,
OpUPlus,
OpCompl,
- OpIncrement,
- OpDecrement,
+ OpPreIncrement,
+ OpPreDecrement,
+ OpPostIncrement,
+ OpPostDecrement,
OpBitAnd,
OpBitOr,
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 8cf5fac760..72a4a9e751 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1993,8 +1993,8 @@ private:
case OpUPlus:
case OpUMinus:
case OpNot:
- case OpIncrement:
- case OpDecrement:
+ case OpPreIncrement:
+ case OpPreDecrement:
if (e->expr->type == VarType || e->expr->type == StringType || e->expr->type == QObjectType)
markAsSideEffect();
break;
@@ -2342,8 +2342,8 @@ private:
case OpCompl: _ty.type = SInt32Type; return;
case OpNot: _ty.type = BoolType; return;
- case OpIncrement:
- case OpDecrement:
+ case OpPreIncrement:
+ case OpPreDecrement:
Q_ASSERT(!"Inplace operators should have been removed!");
Q_UNREACHABLE();
default:
@@ -4178,11 +4178,11 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
constOperand->type = SInt32Type;
doneSomething = true;
break;
- case OpIncrement:
+ case OpPreIncrement:
constOperand->value = constOperand->value + 1;
doneSomething = true;
break;
- case OpDecrement:
+ case OpPreDecrement:
constOperand->value = constOperand->value - 1;
doneSomething = true;
break;
diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp
index 78546e1509..829f46ed96 100644
--- a/src/qml/jit/qv4unop.cpp
+++ b/src/qml/jit/qv4unop.cpp
@@ -69,8 +69,8 @@ void Unop<JITAssembler>::generate(IR::Expr *source, IR::Expr *target)
case IR::OpCompl:
generateCompl(source, target);
return;
- case IR::OpIncrement: setOp(increment); break;
- case IR::OpDecrement: setOp(decrement); break;
+ case IR::OpIncrement: setOp(preIncrement); break;
+ case IR::OpDecrement: setOp(preDecrement); break;
default:
Q_UNREACHABLE();
} // switch
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 9737a18812..3342075f7f 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -1414,7 +1414,7 @@ QV4::ReturnedValue Runtime::method_setupArgumentsObject(ExecutionEngine *engine)
#endif // V4_BOOTSTRAP
-QV4::ReturnedValue Runtime::method_increment(const Value &value)
+QV4::ReturnedValue Runtime::method_preIncrement(const Value &value)
{
TRACE1(value);
@@ -1426,7 +1426,7 @@ QV4::ReturnedValue Runtime::method_increment(const Value &value)
}
}
-QV4::ReturnedValue Runtime::method_decrement(const Value &value)
+QV4::ReturnedValue Runtime::method_preDecrement(const Value &value)
{
TRACE1(value);
@@ -1438,6 +1438,46 @@ QV4::ReturnedValue Runtime::method_decrement(const Value &value)
}
}
+QV4::ReturnedValue Runtime::method_postIncrement(Value *value)
+{
+ TRACE1(value);
+
+ if (value->isNumber()) {
+ Value old = *value;
+ if (value->isInteger() && value->integerValue() < INT_MAX) {
+ *value = Primitive::fromInt32(value->integerValue() + 1);
+ } else {
+ *value = Primitive::fromDouble(value->doubleValue() + 1.0);
+ }
+ return old.asReturnedValue();
+ }
+
+ // ToNumber conversion needed:
+ double d = value->toNumberImpl();
+ *value = Primitive::fromDouble(d + 1.);
+ return Encode(d);
+}
+
+QV4::ReturnedValue Runtime::method_postDecrement(Value *value)
+{
+ TRACE1(value);
+
+ if (value->isNumber()) {
+ Value old = *value;
+ if (value->isInteger() && value->integerValue() > INT_MIN) {
+ *value = Primitive::fromInt32(value->integerValue() - 1);
+ } else {
+ *value = Primitive::fromDouble(value->doubleValue() - 1.0);
+ }
+ return old.asReturnedValue();
+ }
+
+ // ToNumber conversion needed:
+ double d = value->toNumber();
+ *value = Primitive::fromDouble(d - 1.);
+ return Encode(d);
+}
+
ReturnedValue Runtime::method_toDouble(const Value &value)
{
TRACE1(value);
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index 302facba06..fdb24d5ca2 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -160,8 +160,10 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
F(ReturnedValue, uMinus, (const Value &value)) \
F(ReturnedValue, uNot, (const Value &value)) \
F(ReturnedValue, complement, (const Value &value)) \
- F(ReturnedValue, increment, (const Value &value)) \
- F(ReturnedValue, decrement, (const Value &value)) \
+ F(ReturnedValue, preIncrement, (const Value &value)) \
+ F(ReturnedValue, preDecrement, (const Value &value)) \
+ F(ReturnedValue, postIncrement, (Value *value)) \
+ F(ReturnedValue, postDecrement, (Value *value)) \
\
/* binary operators */ \
F(ReturnedValue, instanceof, (ExecutionEngine *engine, const Value &left, const Value &right)) \
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 1f1e202a2d..5b026b2f0d 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -857,13 +857,23 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
VALUE(instr.result) = QV4::Encode((int)~VALUE(instr.source).integerValue());
MOTH_END_INSTR(UComplInt)
- MOTH_BEGIN_INSTR(Increment)
- STOREVALUE(instr.result, Runtime::method_increment(VALUE(instr.source)));
- MOTH_END_INSTR(Increment)
-
- MOTH_BEGIN_INSTR(Decrement)
- STOREVALUE(instr.result, Runtime::method_decrement(VALUE(instr.source)));
- MOTH_END_INSTR(Decrement)
+ MOTH_BEGIN_INSTR(PreIncrement)
+ STOREVALUE(instr.result, Runtime::method_preIncrement(VALUE(instr.source)));
+ MOTH_END_INSTR(PreIncrement)
+
+ MOTH_BEGIN_INSTR(PreDecrement)
+ STOREVALUE(instr.result, Runtime::method_preDecrement(VALUE(instr.source)));
+ MOTH_END_INSTR(PreDecrement)
+
+ MOTH_BEGIN_INSTR(PostIncrement)
+ //### we probably need a write-barrier for instr.source, because it will be written to
+ STOREVALUE(instr.result, Runtime::method_postIncrement(VALUEPTR(instr.source)));
+ MOTH_END_INSTR(PreIncrement)
+
+ MOTH_BEGIN_INSTR(PostDecrement)
+ //### we probably need a write-barrier for instr.source, because it will be written to
+ STOREVALUE(instr.result, Runtime::method_postDecrement(VALUEPTR(instr.source)));
+ MOTH_END_INSTR(PreDecrement)
MOTH_BEGIN_INSTR(Binop)
QV4::Runtime::BinaryOperation op = *reinterpret_cast<QV4::Runtime::BinaryOperation *>(reinterpret_cast<char *>(&engine->runtime.runtimeMethods[instr.alu]));