Backed out 4 changesets (bug 1132888) for SM-tc(r) failures a=backout
authorWes Kocher <wkocher@mozilla.com>
Fri, 04 Nov 2016 11:38:09 -0700
changeset 363910 9c43bca082b79800fc7e9217f41b87dc7e356636
parent 363909 4da7d22ebcd2fdd3047487d7c2e483093324263c
child 363911 7c9296be2a4f11a1ae6e018d128a5f1ae18cadb3
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-beta@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1132888
milestone52.0a1
backs outcd3ff163021bc877464113a006f3c412d81b7366
f596578a143e02a187656ff938db143208d4ceb8
5e2739dedc3a6633468e68427aa2c3d750ce0f81
e4b1a95a7f3997e90a1e278b82b17140ec235af8
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1132888) for SM-tc(r) failures a=backout Backed out changeset cd3ff163021b (bug 1132888) Backed out changeset f596578a143e (bug 1132888) Backed out changeset 5e2739dedc3a (bug 1132888) Backed out changeset e4b1a95a7f39 (bug 1132888)
js/src/jit-test/tests/ion/dce-with-rinstructions.js
js/src/jit-test/tests/ion/recover-objects.js
js/src/jit-test/tests/self-test/assertRecoveredOnBailout-0.js
js/src/jit-test/tests/self-test/assertRecoveredOnBailout-1.js
js/src/jit-test/tests/self-test/assertRecoveredOnBailout.js
js/src/jit/JitSpewer.cpp
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.h
js/src/jit/Recover.cpp
js/src/jit/Recover.h
js/src/jit/ValueNumbering.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/tests/lib/jittests.py
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -1,14 +1,13 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
 var i;
 
 var config = getBuildConfiguration();
-var max = 200;
 
 // Check that we are able to remove the operation inside recover test functions (denoted by "rop..."),
 // when we inline the first version of uceFault, and ensure that the bailout is correct
 // when uceFault is replaced (which cause an invalidation bailout)
 
 var uceFault = function (i) {
     if (i > 98)
         uceFault = function (i) { return true; };
@@ -1287,22 +1286,33 @@ function rhypot_object_4args(i) {
         assertEq(x, Math.sqrt(i * i + (i + 1) * (i + 1) + (i + 2) * (i + 2) + (i + 3) * (i + 3)));
     assertRecoveredOnBailout(x, false);
     return i;
 }
 
 var uceFault_random = eval(uneval(uceFault).replace('uceFault', 'uceFault_random'));
 function rrandom(i) {
     // setRNGState() exists only in debug builds
-    if(config.debug) setRNGState(2, 1+i);
 
-    var x = Math.random();
-    if (uceFault_random(i) || uceFault_random(i))
-        assertEq(x, config.debug ? setRNGState(2, 1+i) || Math.random() : x);
-    assertRecoveredOnBailout(x, true);
+    if(config.debug) {
+        setRNGState(2, 0);
+        var x = Math.random();
+        if (uceFault_random(i) || uceFault_random(i)) {
+            setRNGState(2, 0);
+            assertEq(x, Math.random());
+        }
+        assertRecoveredOnBailout(x, true);
+    } else {
+        var x = Math.random();
+        if (uceFault_random(i) || uceFault_random(i)) {
+            Math.random();
+        }
+        assertRecoveredOnBailout(x, true);
+    }
+
     return i;
 }
 
 var uceFault_sin_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_sin_number'));
 function rsin_number(i) {
     var x = Math.sin(i);
     if (uceFault_sin_number(i) || uceFault_sin_number(i))
         assertEq(x, Math.sin(i));
@@ -1338,18 +1348,17 @@ function rlog_object(i) {
     var x = Math.log(o); /* Evaluated with t == i, not t == 1000 */
     t = 1000;
     if (uceFault_log_object(i) || uceFault_log_object(i))
         assertEq(x, Math.log(99) /* log(99) */);
     assertRecoveredOnBailout(x, false);
     return i;
 }
 
-for (j = 100 - max; j < 100; j++) {
-    let i = j < 0 ? Math.abs(j) % 50 : j;
+for (i = 0; i < 100; i++) {
     rbitnot_number(i);
     rbitnot_object(i);
     rbitand_number(i);
     rbitand_object(i);
     rbitor_number(i);
     rbitor_object(i);
     rbitxor_number(i);
     rbitxor_object(i);
--- a/js/src/jit-test/tests/ion/recover-objects.js
+++ b/js/src/jit-test/tests/ion/recover-objects.js
@@ -1,35 +1,29 @@
 // |jit-test| test-join=--no-unboxed-objects; --ion-pgo=on
 //
 // Unboxed object optimization might not trigger in all cases, thus we ensure
 // that Scalar Replacement optimization is working well independently of the
 // object representation.
 
-var max = 200;
-
 // Ion eager fails the test below because we have not yet created any
 // template object in baseline before running the content of the top-level
 // function.
-if (getJitCompilerOptions()["ion.warmup.trigger"] <= max - 10)
-    setJitCompilerOption("ion.warmup.trigger", max - 10);
-
-// Force Inlining heuristics to always inline the functions which have the same
-// number of use count.
-setJitCompilerOption("ion.warmup.trigger", getJitCompilerOptions()["ion.warmup.trigger"]);
+if (getJitCompilerOptions()["ion.warmup.trigger"] <= 90)
+    setJitCompilerOption("ion.warmup.trigger", 90);
 
 // This test checks that we are able to remove the getprop & setprop with scalar
 // replacement, so we should not force inline caches, as this would skip the
 // generation of getprop & setprop instructions.
 if (getJitCompilerOptions()["ion.forceinlineCaches"])
     setJitCompilerOption("ion.forceinlineCaches", 0);
 
 function resumeHere() {}
 var uceFault = function (i) {
-    if (i > max - 2)
+    if (i > 98)
         uceFault = function (i) { return true; };
     return false;
 };
 
 
 // Without "use script" in the inner function, the arguments might be
 // observable.
 function inline_notSoEmpty1(a, b, c, d) {
@@ -85,17 +79,17 @@ function notSoEmpty2(i) {
     // This can only be recovered on bailout iff either we have type
     // information for the property access in the branch, or the branch is
     // removed before scalar replacement.
     assertRecoveredOnBailout(res, true);
 }
 
 // Check that we can recover objects with their content.
 var argFault_observeArg = function (i) {
-    if (i > max - 2)
+    if (i > 98)
         return inline_observeArg.arguments[0];
     return { test : i };
 };
 function inline_observeArg(obj, i) {
     return argFault_observeArg(i);
 }
 function observeArg(i) {
     var obj = { test: i };
@@ -136,36 +130,36 @@ function withinIf(i) {
         obj = undefined;
     }
     assertEq(x, i);
 }
 
 // Check case where one successor can have multiple times the same predecessor.
 function unknownLoad(i) {
     var obj = { foo: i };
-    // Unknown properties are inlined as undefined.
     assertEq(obj.bar, undefined);
-    assertRecoveredOnBailout(obj, true);
+    // Unknown properties are using GetPropertyCache.
+    assertRecoveredOnBailout(obj, false);
 }
 
 // Check with dynamic slots.
 function dynamicSlots(i) {
     var obj = {
         p0: i + 0, p1: i + 1, p2: i + 2, p3: i + 3, p4: i + 4, p5: i + 5, p6: i + 6, p7: i + 7, p8: i + 8, p9: i + 9, p10: i + 10,
         p11: i + 11, p12: i + 12, p13: i + 13, p14: i + 14, p15: i + 15, p16: i + 16, p17: i + 17, p18: i + 18, p19: i + 19, p20: i + 20,
         p21: i + 21, p22: i + 22, p23: i + 23, p24: i + 24, p25: i + 25, p26: i + 26, p27: i + 27, p28: i + 28, p29: i + 29, p30: i + 30,
         p31: i + 31, p32: i + 32, p33: i + 33, p34: i + 34, p35: i + 35, p36: i + 36, p37: i + 37, p38: i + 38, p39: i + 39, p40: i + 40,
         p41: i + 41, p42: i + 42, p43: i + 43, p44: i + 44, p45: i + 45, p46: i + 46, p47: i + 47, p48: i + 48, p49: i + 49, p50: i + 50
     };
     // Add a function call to capture a resumepoint at the end of the call or
     // inside the inlined block, such as the bailout does not rewind to the
     // beginning of the function.
     resumeHere(); bailout();
     assertEq(obj.p0 + obj.p10 + obj.p20 + obj.p30 + obj.p40, 5 * i + 100);
-    assertRecoveredOnBailout(obj, false);
+    assertRecoveredOnBailout(obj, true);
 }
 
 // Check that we can correctly recover allocations of new objects.
 function Point(x, y)
 {
     this.x = x;
     this.y = y;
 }
@@ -173,17 +167,17 @@ function Point(x, y)
 function createThisWithTemplate(i)
 {
     var p = new Point(i - 1, i + 1);
     bailout();
     assertEq(p.y - p.x, 2);
     assertRecoveredOnBailout(p, true);
 }
 
-for (var i = 0; i < max; i++) {
+for (var i = 0; i < 100; i++) {
     notSoEmpty1(i);
     notSoEmpty2(i);
     observeArg(i);
     complexPhi(i);
     withinIf(i);
     unknownLoad(i);
     dynamicSlots(i);
     createThisWithTemplate(i);
deleted file mode 100644
--- a/js/src/jit-test/tests/self-test/assertRecoveredOnBailout-1.js
+++ /dev/null
@@ -1,32 +0,0 @@
-// |jit-test| crash
-
-var opts = getJitCompilerOptions();
-if (!opts['ion.enable'] || !opts['baseline.enable'] ||
-    opts["ion.forceinlineCaches"] || opts["ion.check-range-analysis"])
-{
-    crash("Cannot test assertRecoveredOnBailout");
-}
-
-function g() {
-    return inIon();
-}
-
-// Wait until IonMonkey compilation finished.
-while(!(res = g()));
-
-// Check that we entered Ion succesfully.
-if (res !== true)
-    crash("Cannot enter IonMonkey");
-
-// Test that assertRecoveredOnBailout fails as expected.
-function f () {
-    var o = {};
-    assertRecoveredOnBailout(o, false);
-    return inIon();
-}
-
-// Wait until IonMonkey compilation finished.
-while(!(res = f()));
-
-// Ensure that we entered Ion.
-assertEq(res, true);
rename from js/src/jit-test/tests/self-test/assertRecoveredOnBailout-0.js
rename to js/src/jit-test/tests/self-test/assertRecoveredOnBailout.js
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -16,17 +16,16 @@
 # include <unistd.h>
 #endif
 
 #include "jsprf.h"
 
 #include "jit/Ion.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
-#include "jit/MIRGraph.h"
 
 #include "threading/LockGuard.h"
 
 #include "vm/HelperThreads.h"
 #include "vm/MutexIDs.h"
 
 #ifndef JIT_SPEW_DIR
 # if defined(_WIN32)
@@ -298,23 +297,16 @@ GraphSpewer::spewPass(const char* pass)
     c1Spewer_.spewPass(pass);
 
     jsonSpewer_.beginPass(pass);
     jsonSpewer_.spewMIR(graph_);
     jsonSpewer_.spewLIR(graph_);
     jsonSpewer_.endPass();
 
     ionspewer.spewPass(this);
-
-    // As this function is used for debugging, we ignore any of the previous
-    // failures and ensure there is enough ballast space, such that we do not
-    // exhaust the ballast space before running the next phase.
-    AutoEnterOOMUnsafeRegion oomUnsafe;
-    if (!graph_->alloc().ensureBallast())
-        oomUnsafe.crash("Could not ensure enough ballast space after spewing graph information.");
 }
 
 void
 GraphSpewer::spewPass(const char* pass, BacktrackingAllocator* ra)
 {
     if (!isSpewing())
         return;
 
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -2367,19 +2367,17 @@ IonBuilder::inlineTypedArray(CallInfo& c
             return InliningStatus_NotInlined;
 
         uint32_t len = AssertedCast<uint32_t>(providedLen);
 
         if (obj->length() != len)
             return InliningStatus_NotInlined;
 
         callInfo.setImplicitlyUsedUnchecked();
-        MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), obj);
-        current->add(templateConst);
-        ins = MNewTypedArray::New(alloc(), constraints(), templateConst,
+        ins = MNewTypedArray::New(alloc(), constraints(), obj,
                                   obj->group()->initialHeap(constraints()));
     }
 
     current->add(ins);
     current->push(ins);
     if (!resumeAfter(ins))
         return InliningStatus_Error;
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3360,51 +3360,56 @@ class MNewArrayDynamicLength
         return AliasSet::None();
     }
 
     bool appendRoots(MRootList& roots) const override {
         return roots.append(templateObject_);
     }
 };
 
-class MNewTypedArray
-  : public MUnaryInstruction,
-    public NoTypePolicy::Data
-{
+class MNewTypedArray : public MNullaryInstruction
+{
+    CompilerGCPointer<TypedArrayObject*> templateObject_;
     gc::InitialHeap initialHeap_;
 
-    MNewTypedArray(CompilerConstraintList* constraints, MConstant* templateConst,
+    MNewTypedArray(CompilerConstraintList* constraints, TypedArrayObject* templateObject,
                    gc::InitialHeap initialHeap)
-      : MUnaryInstruction(templateConst),
+      : templateObject_(templateObject),
         initialHeap_(initialHeap)
     {
-        MOZ_ASSERT(!templateObject()->isSingleton());
+        MOZ_ASSERT(!templateObject->isSingleton());
         setResultType(MIRType::Object);
-        setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject()));
+        setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject));
     }
 
   public:
     INSTRUCTION_HEADER(NewTypedArray)
-    TRIVIAL_NEW_WRAPPERS
+
+    static MNewTypedArray* New(TempAllocator& alloc,
+                               CompilerConstraintList* constraints,
+                               TypedArrayObject* templateObject,
+                               gc::InitialHeap initialHeap)
+    {
+        return new(alloc) MNewTypedArray(constraints, templateObject, initialHeap);
+    }
 
     TypedArrayObject* templateObject() const {
-        return &getOperand(0)->toConstant()->toObject().as<TypedArrayObject>();
+        return templateObject_;
     }
 
     gc::InitialHeap initialHeap() const {
         return initialHeap_;
     }
 
     virtual AliasSet getAliasSet() const override {
         return AliasSet::None();
     }
 
-    MOZ_MUST_USE bool writeRecoverData(CompactBufferWriter& writer) const override;
-    bool canRecoverOnBailout() const override {
-        return true;
+    bool appendRoots(MRootList& roots) const override {
+        return roots.append(templateObject_);
     }
 };
 
 class MNewTypedArrayDynamicLength
   : public MUnaryInstruction,
     public IntPolicy<0>::Data
 {
     CompilerObject templateObject_;
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -1297,44 +1297,16 @@ RNewObject::recover(JSContext* cx, Snaps
         return false;
 
     result.setObject(*resultObject);
     iter.storeInstructionResult(result);
     return true;
 }
 
 bool
-MNewTypedArray::writeRecoverData(CompactBufferWriter& writer) const
-{
-    MOZ_ASSERT(canRecoverOnBailout());
-    writer.writeUnsigned(uint32_t(RInstruction::Recover_NewTypedArray));
-    return true;
-}
-
-RNewTypedArray::RNewTypedArray(CompactBufferReader& reader)
-{
-}
-
-bool
-RNewTypedArray::recover(JSContext* cx, SnapshotIterator& iter) const
-{
-    RootedObject templateObject(cx, &iter.read().toObject());
-    RootedValue result(cx);
-
-    uint32_t length = templateObject.as<TypedArrayObject>()->length();
-    JSObject* resultObject = TypedArrayCreateWithTemplate(cx, templateObject, length);
-    if (!resultObject)
-        return false;
-
-    result.setObject(*resultObject);
-    iter.storeInstructionResult(result);
-    return true;
-}
-
-bool
 MNewArray::writeRecoverData(CompactBufferWriter& writer) const
 {
     MOZ_ASSERT(canRecoverOnBailout());
     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArray));
     writer.writeUnsigned(length());
     return true;
 }
 
--- a/js/src/jit/Recover.h
+++ b/js/src/jit/Recover.h
@@ -95,17 +95,16 @@ namespace jit {
     _(RegExpSearcher)                           \
     _(RegExpTester)                             \
     _(StringReplace)                            \
     _(TypeOf)                                   \
     _(ToDouble)                                 \
     _(ToFloat32)                                \
     _(TruncateToInt32)                          \
     _(NewObject)                                \
-    _(NewTypedArray)                            \
     _(NewArray)                                 \
     _(NewDerivedTypedObject)                    \
     _(CreateThisWithTemplate)                   \
     _(Lambda)                                   \
     _(SimdBox)                                  \
     _(ObjectState)                              \
     _(ArrayState)                               \
     _(AtomicIsLockFree)                         \
@@ -561,24 +560,16 @@ class RNewObject final : public RInstruc
     MNewObject::Mode mode_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(NewObject, 1)
 
     MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
 };
 
-class RNewTypedArray final : public RInstruction
-{
-  public:
-    RINSTRUCTION_HEADER_NUM_OP_(NewTypedArray, 1)
-
-    MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
-};
-
 class RNewArray final : public RInstruction
 {
   private:
     uint32_t count_;
 
   public:
     RINSTRUCTION_HEADER_NUM_OP_(NewArray, 1)
 
--- a/js/src/jit/ValueNumbering.cpp
+++ b/js/src/jit/ValueNumbering.cpp
@@ -722,18 +722,17 @@ ValueNumberer::visitDefinition(MDefiniti
 
         // The Nop is introduced to capture the result and make sure the operands
         // are not live anymore when there are no further uses. Though when
         // all operands are still needed the Nop doesn't decrease the liveness
         // and can get removed.
         MResumePoint* rp = nop->resumePoint();
         if (rp && rp->numOperands() > 0 &&
             rp->getOperand(rp->numOperands() - 1) == prev &&
-            !nop->block()->lastIns()->isThrow() &&
-            !prev->isAssertRecoveredOnBailout())
+            !nop->block()->lastIns()->isThrow())
         {
             size_t numOperandsLive = 0;
             for (size_t j = 0; j < prev->numOperands(); j++) {
                 for (size_t i = 0; i < rp->numOperands(); i++) {
                     if (prev->getOperand(j) == rp->getOperand(i)) {
                         numOperandsLive++;
                         break;
                     }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -6219,25 +6219,16 @@ JS_SetGlobalJitCompilerOption(JSContext*
         if (value == 0) {
             jit::JitOptions.forceInlineCaches = false;
             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable non-IC optimizations.");
         } else {
             jit::JitOptions.forceInlineCaches = true;
             JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable non-IC optimizations.");
         }
         break;
-      case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
-        if (value == 0) {
-            jit::JitOptions.checkRangeAnalysis = false;
-            JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable range analysis checks.");
-        } else {
-            jit::JitOptions.checkRangeAnalysis = true;
-            JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable range analysis checks.");
-        }
-        break;
       case JSJITCOMPILER_ION_ENABLE:
         if (value == 1) {
             JS::ContextOptionsRef(cx).setIon(true);
             JitSpew(js::jit::JitSpew_IonScripts, "Enable ion");
         } else if (value == 0) {
             JS::ContextOptionsRef(cx).setIon(false);
             JitSpew(js::jit::JitSpew_IonScripts, "Disable ion");
         }
@@ -6299,19 +6290,16 @@ JS_GetGlobalJitCompilerOption(JSContext*
       case JSJITCOMPILER_ION_WARMUP_TRIGGER:
         *valueOut = jit::JitOptions.forcedDefaultIonWarmUpThreshold.isSome()
                   ? jit::JitOptions.forcedDefaultIonWarmUpThreshold.ref()
                   : jit::OptimizationInfo::CompilerWarmupThreshold;
         break;
       case JSJITCOMPILER_ION_FORCE_IC:
         *valueOut = jit::JitOptions.forceInlineCaches;
         break;
-      case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS:
-        *valueOut = jit::JitOptions.checkRangeAnalysis;
-        break;
       case JSJITCOMPILER_ION_ENABLE:
         *valueOut = JS::ContextOptionsRef(cx).ion();
         break;
       case JSJITCOMPILER_BASELINE_ENABLE:
         *valueOut = JS::ContextOptionsRef(cx).baseline();
         break;
       case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE:
         *valueOut = rt->canUseOffthreadIonCompilation();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5731,17 +5731,16 @@ JS_SetOffthreadIonCompilationEnabled(JSC
 
 #define JIT_COMPILER_OPTIONS(Register)                                     \
     Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger")           \
     Register(ION_WARMUP_TRIGGER, "ion.warmup.trigger")                     \
     Register(ION_GVN_ENABLE, "ion.gvn.enable")                             \
     Register(ION_FORCE_IC, "ion.forceinlineCaches")                        \
     Register(ION_ENABLE, "ion.enable")                                     \
     Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \
-    Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis")         \
     Register(BASELINE_ENABLE, "baseline.enable")                           \
     Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
     Register(JUMP_THRESHOLD, "jump-threshold")                             \
     Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable")                 \
     Register(WASM_TEST_MODE, "wasm.test-mode")                             \
     Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets")
 
 typedef enum JSJitCompilerOption {
--- a/js/src/tests/lib/jittests.py
+++ b/js/src/tests/lib/jittests.py
@@ -115,17 +115,16 @@ class JitTest:
         self.test_also_noasmjs = False # True means run with and without asm.js
                                        # enabled.
         self.test_also_wasm_baseline = False # True means run with and and without
                                        # wasm baseline compiler enabled.
         self.test_also = [] # List of other configurations to test with.
         self.test_join = [] # List of other configurations to test with all existing variants.
         self.expect_error = '' # Errors to expect and consider passing
         self.expect_status = 0 # Exit status to expect from shell
-        self.expect_crash = False # Exit status or error output.
         self.is_module = False
         self.test_reflect_stringify = None  # Reflect.stringify implementation to test
 
         # Expected by the test runner. Always true for jit-tests.
         self.enable = True
 
     def copy(self):
         t = JitTest(self.path)
@@ -137,17 +136,16 @@ class JitTest:
         t.valgrind = self.valgrind
         t.tz_pacific = self.tz_pacific
         t.test_also_noasmjs = self.test_also_noasmjs
         t.test_also_wasm_baseline = self.test_also_noasmjs
         t.test_also = self.test_also
         t.test_join = self.test_join
         t.expect_error = self.expect_error
         t.expect_status = self.expect_status
-        t.expect_crash = self.expect_crash
         t.test_reflect_stringify = self.test_reflect_stringify
         t.enable = True
         t.is_module = self.is_module
         return t
 
     def copy_and_extend_jitflags(self, variant):
         t = self.copy()
         t.jitflags.extend(variant)
@@ -228,18 +226,16 @@ class JitTest:
                         if options.can_test_also_wasm_baseline:
                             test.test_also.append(['--wasm-always-baseline'])
                     elif name.startswith('test-also='):
                         test.test_also.append([name[len('test-also='):]])
                     elif name.startswith('test-join='):
                         test.test_join.append([name[len('test-join='):]])
                     elif name == 'module':
                         test.is_module = True
-                    elif name == 'crash':
-                        test.expect_crash = True
                     elif name.startswith('--'):
                         # // |jit-test| --ion-gvn=off; --no-sse4
                         test.jitflags.append(name)
                     else:
                         print('{}: warning: unrecognized |jit-test| attribute'
                               ' {}'.format(path, part))
 
         if options.valgrind_all:
@@ -369,29 +365,16 @@ def check_output(out, err, rc, timed_out
     for line in out.split('\n'):
         if line.startswith('Trace stats check failed'):
             return False
 
     for line in err.split('\n'):
         if 'Assertion failed:' in line:
             return False
 
-    if test.expect_crash:
-        if sys.platform == 'win32' and rc == 3 - 2 ** 31:
-            return True
-
-        if sys.platform != 'win32' and rc == -11:
-            return True
-
-        # When building with ASan enabled, ASan will convert the -11 returned
-        # value to 1. As a work-around we look for the error output which
-        # includes the crash reason.
-        if rc == 1 and ("Hit MOZ_CRASH" in err or "Assertion failure:" in err):
-            return True
-
     if rc != test.expect_status:
         # Tests which expect a timeout check for exit code 6.
         # Sometimes 0 is returned on Windows for unknown reasons.
         # See bug 899697.
         if sys.platform in ['win32', 'cygwin'] and rc == 0:
             return True
 
         # Allow a non-zero exit code if we want to allow OOM, but only if we