aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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"