diff --git a/js/src/jit-test/tests/ion/dce-with-rinstructions.js b/js/src/jit-test/tests/ion/dce-with-rinstructions.js index 1f65d95b65ee..b594747664fc 100644 --- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js +++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js @@ -565,6 +565,112 @@ function rstr_split(i) { return i; } +var uceFault_regexp_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_test')) +function rregexp_test(i) { + var re = new RegExp("str\\d+" + i + "\\d+rts"); + var res = re.test("str01234567899876543210rts"); + if (uceFault_regexp_test(i) || uceFault_regexp_test(i)) { + assertEq(res, true); + } + return i; +} + +var uceFault_regexp_y_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_y_test')) +function rregexp_y_test(i) { + var re = new RegExp("str\\d+" + (i % 10), "y"); + var res = re.test("str00123456789"); + if (uceFault_regexp_y_test(i) || uceFault_regexp_y_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, false); + return i; +} + +var uceFault_regexp_y_literal_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_y_literal_test')) +function rregexp_y_literal_test(i) { + var re = /str\d*0/y; + var res = re.test("str00123456789"); + if (uceFault_regexp_y_literal_test(i) || uceFault_regexp_y_literal_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, false); + return i; +} + +var uceFault_regexp_g_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_g_test')) +function rregexp_g_test(i) { + var re = new RegExp("str\\d+" + (i % 10), "g"); + var res = re.test("str00123456789str00123456789"); + if (uceFault_regexp_g_test(i) || uceFault_regexp_g_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, false); + return i; +} + +var uceFault_regexp_g_literal_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_g_literal_test')) +function rregexp_g_literal_test(i) { + var re = /str\d*0/g; + var res = re.test("str00123456789str00123456789"); + if (uceFault_regexp_g_literal_test(i) || uceFault_regexp_g_literal_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, false); + return i; +} + +var uceFault_regexp_i_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_i_test')) +function rregexp_i_test(i) { + var re = new RegExp("str\\d+" + (i % 10), "i"); + var res = re.test("STR00123456789"); + if (uceFault_regexp_i_test(i) || uceFault_regexp_i_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, true); + return i; +} + +var uceFault_regexp_i_literal_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_i_literal_test')) +function rregexp_i_literal_test(i) { + var re = /str\d*0/i; + var res = re.test("STR00123456789"); + if (uceFault_regexp_i_literal_test(i) || uceFault_regexp_i_literal_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, true); + return i; +} + +var uceFault_regexp_m_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_m_test')) +function rregexp_m_test(i) { + var re = new RegExp("^str\\d+" + (i % 10), "m"); + var res = re.test("abc\nstr00123456789"); + if (uceFault_regexp_m_test(i) || uceFault_regexp_m_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, true); + return i; +} + +var uceFault_regexp_m_literal_test = eval(uneval(uceFault).replace('uceFault', 'uceFault_regexp_m_literal_test')) +function rregexp_m_literal_test(i) { + var re = /^str\d*0/m; + var res = re.test("abc\nstr00123456789"); + if (uceFault_regexp_m_literal_test(i) || uceFault_regexp_m_literal_test(i)) { + assertEq(res, true); + } + + assertEq(re.lastIndex == 0, true); + return i; +} + for (i = 0; i < 100; i++) { rbitnot_number(i); rbitnot_object(i); @@ -626,6 +732,15 @@ for (i = 0; i < 100; i++) { ratan2_number(i); ratan2_object(i); rstr_split(i); + rregexp_test(i); + rregexp_y_test(i); + rregexp_y_literal_test(i); + rregexp_g_test(i); + rregexp_g_literal_test(i); + rregexp_i_test(i); + rregexp_i_literal_test(i); + rregexp_m_test(i); + rregexp_m_literal_test(i); } // Test that we can refer multiple time to the same recover instruction, as well diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index ad627e5dce3f..40d2fa10c8cc 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -5699,6 +5699,16 @@ class MRegExpTest bool possiblyCalls() const { return true; } + + bool writeRecoverData(CompactBufferWriter &writer) const; + bool canRecoverOnBailout() const { + // RegExpTest has a side-effect on the regexp object's lastIndex + // when sticky or global flags are set. + // Return false unless we are sure it's not the case. + if (regexp()->isRegExp()) + return !regexp()->toRegExp()->source()->needUpdateLastIndex(); + return false; + } }; template diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp index b4bb36a9bbfb..75ee127620e9 100644 --- a/js/src/jit/Recover.cpp +++ b/js/src/jit/Recover.cpp @@ -885,6 +885,33 @@ RStringSplit::recover(JSContext *cx, SnapshotIterator &iter) const return true; } +bool +MRegExpTest::writeRecoverData(CompactBufferWriter &writer) const +{ + MOZ_ASSERT(canRecoverOnBailout()); + writer.writeUnsigned(uint32_t(RInstruction::Recover_RegExpTest)); + return true; +} + +RRegExpTest::RRegExpTest(CompactBufferReader &reader) +{ } + +bool +RRegExpTest::recover(JSContext *cx, SnapshotIterator &iter) const +{ + RootedString string(cx, iter.read().toString()); + RootedObject regexp(cx, &iter.read().toObject()); + bool resultBool; + + if (!js::regexp_test_raw(cx, regexp, string, &resultBool)) + return false; + + RootedValue result(cx); + result.setBoolean(resultBool); + iter.storeInstructionResult(result); + return true; +} + bool MNewObject::writeRecoverData(CompactBufferWriter &writer) const { diff --git a/js/src/jit/Recover.h b/js/src/jit/Recover.h index 8ce8fd7205c0..6c65f4069a37 100644 --- a/js/src/jit/Recover.h +++ b/js/src/jit/Recover.h @@ -45,6 +45,7 @@ namespace jit { _(Sqrt) \ _(Atan2) \ _(StringSplit) \ + _(RegExpTest) \ _(NewObject) \ _(NewArray) \ _(NewDerivedTypedObject) \ @@ -460,6 +461,18 @@ class RStringSplit MOZ_FINAL : public RInstruction bool recover(JSContext *cx, SnapshotIterator &iter) const; }; +class RRegExpTest MOZ_FINAL : public RInstruction +{ + public: + RINSTRUCTION_HEADER_(RegExpTest) + + virtual uint32_t numOperands() const { + return 2; + } + + bool recover(JSContext *cx, SnapshotIterator &iter) const; +}; + class RNewObject MOZ_FINAL : public RInstruction { private: