From df9acd13cd7bec991f1fd116284427ae56488aaa Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Wed, 25 Mar 2015 10:49:52 +0000 Subject: [PATCH] Bug 1144738 - Check for invalidated script when updating SetPropertyIC cache r=jandem --- js/src/jit-test/tests/gc/bug-1144738.js | 32 +++++++++++++++++++ js/src/jit/IonCaches.cpp | 42 ++++++++++++++----------- 2 files changed, 56 insertions(+), 18 deletions(-) create mode 100644 js/src/jit-test/tests/gc/bug-1144738.js diff --git a/js/src/jit-test/tests/gc/bug-1144738.js b/js/src/jit-test/tests/gc/bug-1144738.js new file mode 100644 index 000000000000..ef121faaf8a5 --- /dev/null +++ b/js/src/jit-test/tests/gc/bug-1144738.js @@ -0,0 +1,32 @@ +// |jit-test| error: ReferenceError; --fuzzing-safe; --thread-count=1; --ion-eager +const ALL_TESTS = [ + "CONTEXT_OBJECT_PROPERTY_DOT_REFERENCE_IS_FUNCTION", + ]; +function r(keyword, tests) { + function Reserved(keyword, tests) { + this.keyword = keyword; + if (tests) + this.tests = tests; + else + this.tests = ALL_TESTS; + } + return new Reserved(keyword, tests); +} +for (var i = 2; i >= 0; i--) { + gc(); + gczeal(14, 17); + [ + r("break"), + r("case"), + r("catch"), + r("continue"), + ]; + [ + r("true"), + r("null"), + r("each"), + r("let") + ]; +} +Failure; + diff --git a/js/src/jit/IonCaches.cpp b/js/src/jit/IonCaches.cpp index 781487a68473..b0bd6adcad5d 100644 --- a/js/src/jit/IonCaches.cpp +++ b/js/src/jit/IonCaches.cpp @@ -3271,25 +3271,31 @@ SetPropertyIC::update(JSContext *cx, HandleScript outerScript, size_t cacheIndex if (!SetProperty(cx, obj, name, value, cache.strict(), cache.pc())) return false; - // The property did not exist before, now we can try to inline the property add. - bool checkTypeset; - if (!addedSetterStub && canCache == MaybeCanAttachAddSlot && - IsPropertyAddInlineable(&obj->as(), id, cache.value(), oldShape, - cache.needsTypeBarrier(), &checkTypeset)) - { - if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset)) - return false; - addedSetterStub = true; - } + // A GC may have caused cache.value() to become stale as it is not traced. + // In this case the IonScript will have been invalidated, so check for that. + // Assert no further GC is possible past this point. + JS::AutoAssertNoAlloc nogc; + if (!ion->invalidated()) { + // The property did not exist before, now we can try to inline the property add. + bool checkTypeset; + if (!addedSetterStub && canCache == MaybeCanAttachAddSlot && + IsPropertyAddInlineable(&obj->as(), id, cache.value(), oldShape, + cache.needsTypeBarrier(), &checkTypeset)) + { + if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset)) + return false; + addedSetterStub = true; + } - checkTypeset = false; - if (!addedSetterStub && cache.canAttachStub() && - CanAttachAddUnboxedExpando(cx, obj, oldShape, id, cache.value(), - cache.needsTypeBarrier(), &checkTypeset)) - { - if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset)) - return false; - addedSetterStub = true; + checkTypeset = false; + if (!addedSetterStub && cache.canAttachStub() && + CanAttachAddUnboxedExpando(cx, obj, oldShape, id, cache.value(), + cache.needsTypeBarrier(), &checkTypeset)) + { + if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset)) + return false; + addedSetterStub = true; + } } if (!addedSetterStub)