aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2018-03-09 13:04:53 +0100
committerJani Heikkinen <jani.heikkinen@qt.io>2018-03-20 07:05:18 +0000
commitdc0136b8ba25c60f24fece5959d5487cea18b250 (patch)
tree4011c78534a7ae5bd5ba32ebdec9be7b34ed0eaf
parentdfd5cc04a6745cd90e6459ffd99d59ed14471f15 (diff)
Fix JITted code for jump strict-not-equal undefined on 32bit
The generated code for jump-on-strict-not-equal-undefined used the same logic (but with inverted conditions) as the equal case. For equality, one can jump to else if the value parts are not the same. So, for not-equal, if the value parts are the same, it would jump to the else block if they are the same. Meaning, an encoded int value of 0 (which is strict-not-equal to undefined) would end up being evaluated as equal. Task-number: QTBUG-66832 Change-Id: I5c6b8e9b11be53ae21a7164e0a1e0cbfd204f401 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> (cherry picked from commit 86702c3be53fda404ebe331207f9062675c952e0)
-rw-r--r--src/qml/jit/qv4assembler_p.h37
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp21
2 files changed, 48 insertions, 10 deletions
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 8b5b307e84..87f73ccd6f 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -294,21 +294,38 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo
static void generateCJumpOnUndefined(JITAssembler *as,
RelationalCondition cond, IR::Expr *right,
- RegisterID scratchRegister, RegisterID tagRegister,
+ RegisterID scratchRegister, RegisterID varReg,
IR::BasicBlock *nextBlock, IR::BasicBlock *currentBlock,
IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock)
{
- Pointer tagAddr = as->loadAddress(scratchRegister, right);
- as->load32(tagAddr, tagRegister);
- Jump j = as->branch32(JITAssembler::invert(cond), tagRegister, TrustedImm32(0));
- as->addPatch(falseBlock, j);
-
- tagAddr.offset += 4;
- as->load32(tagAddr, tagRegister);
- const TrustedImm32 tag(QV4::Value::Managed_Type_Internal);
Q_ASSERT(nextBlock == as->nextBlock());
Q_UNUSED(nextBlock);
- as->generateCJumpOnCompare(cond, tagRegister, tag, currentBlock, trueBlock, falseBlock);
+
+ const typename JITAssembler::TrustedImm32 undefinedTag(QV4::Value::Managed_Type_Internal);
+ const typename JITAssembler::TrustedImm32 undefinedValue(0);
+
+ typename JITAssembler::Pointer varAddr = as->loadAddress(scratchRegister, right);
+ typename JITAssembler::Pointer tagAddr = varAddr;
+ tagAddr.offset += 4;
+ const typename JITAssembler::RegisterID tagReg = varReg;
+
+ if (cond == JITAssembler::Equal) {
+ as->load32(tagAddr, tagReg);
+ // if the tags are not the same, we can fail already:
+ Jump j = as->branch32(JITAssembler::NotEqual, tagReg, undefinedTag);
+ as->addPatch(falseBlock, j);
+ as->load32(varAddr, varReg);
+ // ok, tags are the same, so if the values are the same then we're done
+ as->generateCJumpOnCompare(JITAssembler::Equal, varReg, undefinedValue, currentBlock, trueBlock, falseBlock);
+ } else { // strict not equal:
+ as->load32(varAddr, varReg);
+ // if the values are not the same, we're done
+ Jump j = as->branch32(JITAssembler::NotEqual, varReg, undefinedValue);
+ as->addPatch(trueBlock, j);
+ as->load32(tagAddr, tagReg);
+ // ok, so the values are the same, now check the tags
+ as->generateCJumpOnCompare(JITAssembler::NotEqual, tagReg, undefinedTag, currentBlock, trueBlock, falseBlock);
+ }
}
static void convertVarToSInt32(JITAssembler *as, IR::Expr *source, IR::Expr *target)
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 6318b12f9f..172fb8f91c 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -340,6 +340,7 @@ private slots:
void qtbug_60547();
void anotherNaN();
void callPropertyOnUndefined();
+ void jumpStrictNotEqualUndefined();
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -8294,6 +8295,26 @@ void tst_qqmlecmascript::callPropertyOnUndefined()
QVERIFY(!v.isError()); // well, more importantly: this shouldn't fail on an assert.
}
+void tst_qqmlecmascript::jumpStrictNotEqualUndefined()
+{
+ QJSEngine engine;
+ QJSValue v = engine.evaluate(QString::fromLatin1(
+ "var ok = 0\n"
+ "var foo = 0\n"
+ "if (foo !== void 1)\n"
+ " ++ok;\n"
+ "else\n"
+ " --ok;\n"
+ "if (foo === void 1)\n"
+ " --ok;\n"
+ "else\n"
+ " ++ok;\n"
+ "ok\n"
+ ));
+ QVERIFY(!v.isError());
+ QCOMPARE(v.toInt(), 2);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"