diff options
-rw-r--r-- | src/qml/jit/qv4assembler_p.h | 37 | ||||
-rw-r--r-- | tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 21 |
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" |