aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-06-05 13:06:54 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-06-21 15:05:57 +0000
commit75306a2f438e1d2b3969a7a3b7ffd8e39b84cd11 (patch)
tree30e5f2e2ea27c0e7bc6bb22f385b7bca7ba8f9ef
parentcb9537d83046dfbfdbe4977999b606fed879d2d7 (diff)
Fix truncating of doubles to integers
When analyzing the data flow and determining that a double is or'ed with 0, we correctly assume a cast to an integer and insert a convert instruction in the IR instead of the actual bitwise or.. The JIT implements that, but the interpreter doesn't, resulting in incorrect values. This problem is specific to the SSA optimizer and the underlying isel requirements in 5.9 and does not apply to the design of the code generator in 5.11 and onwards. Task-number: QTBUG-68640 Change-Id: I954086b118b022bc6a8e00f17517c2d378825613 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h14
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp19
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp8
3 files changed, 41 insertions, 0 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index fbd513b537..5de5025a75 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -158,6 +158,8 @@ QT_BEGIN_NAMESPACE
F(ShlConst, shlConst) \
F(Mul, mul) \
F(Sub, sub) \
+ F(DoubleToInt, doubleToInt) \
+ F(DoubleToUInt, doubleToUInt) \
F(BinopContext, binopContext) \
F(LoadThis, loadThis) \
F(LoadQmlContext, loadQmlContext) \
@@ -769,6 +771,16 @@ union Instr
Param rhs;
Param result;
};
+ struct instr_doubleToInt {
+ MOTH_INSTR_HEADER
+ Param source;
+ Param result;
+ };
+ struct instr_doubleToUInt {
+ MOTH_INSTR_HEADER
+ Param source;
+ Param result;
+ };
struct instr_binopContext {
MOTH_INSTR_HEADER
uint alu; // offset inside the runtime methods
@@ -884,6 +896,8 @@ union Instr
instr_shlConst shlConst;
instr_mul mul;
instr_sub sub;
+ instr_doubleToInt doubleToInt;
+ instr_doubleToUInt doubleToUInt;
instr_binopContext binopContext;
instr_loadThis loadThis;
instr_loadQmlContext loadQmlContext;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index c29ffa10c2..ae50153c1f 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -375,6 +375,25 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex
void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
{
+ if (source->type == IR::DoubleType) {
+ switch (target->type) {
+ case IR::SInt32Type:
+ Instruction::DoubleToInt d2i;
+ d2i.source = getParam(source);
+ d2i.result = getParam(target);
+ addInstruction(d2i);
+ return;
+ case IR::UInt32Type:
+ Instruction::DoubleToUInt d2ui;
+ d2ui.source = getParam(source);
+ d2ui.result = getParam(target);
+ addInstruction(d2ui);
+ return;
+ default:
+ break;
+ }
+ }
+
// FIXME: do something more useful with this info
if (target->type & IR::NumberType && !(source->type & IR::NumberType))
unop(IR::OpUPlus, source, target);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 3d95353fc0..6b0540edac 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -892,6 +892,14 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code)
STOREVALUE(instr.result, Runtime::method_sub(VALUE(instr.lhs), VALUE(instr.rhs)));
MOTH_END_INSTR(Sub)
+ MOTH_BEGIN_INSTR(DoubleToInt)
+ STOREVALUE(instr.result, Encode(Runtime::method_doubleToInt(VALUE(instr.source).asDouble())));
+ MOTH_END_INSTR(DoubleToInt)
+
+ MOTH_BEGIN_INSTR(DoubleToUInt)
+ STOREVALUE(instr.result, Encode(Runtime::method_doubleToUInt(VALUE(instr.source).asDouble())));
+ MOTH_END_INSTR(DoubleToUInt)
+
MOTH_BEGIN_INSTR(BinopContext)
QV4::Runtime::BinaryOperationContext op = *reinterpret_cast<QV4::Runtime::BinaryOperationContext *>(reinterpret_cast<char *>(&engine->runtime.runtimeMethods[instr.alu]));
STOREVALUE(instr.result, op(engine, VALUE(instr.lhs), VALUE(instr.rhs)));