Closed Bug 2001279 Opened 7 months ago Closed 7 months ago

Assertion failure: cx_->hadResourceExhaustion(), at jit/WarpOracle.cpp:213

Categories

(Core :: JavaScript Engine: JIT, defect, P1)

All
Linux
defect

Tracking

()

RESOLVED FIXED
147 Branch
Tracking Status
firefox-esr140 --- unaffected
firefox145 --- wontfix
firefox146 --- wontfix
firefox147 --- fixed

People

(Reporter: gkw, Assigned: iain)

References

(Blocks 2 open bugs, Regression)

Details

(Keywords: regression, reporter-external, testcase)

Attachments

(2 files)

Attached file debug stack
s = newGlobal();
s.g = g;
function g(f) {
  for (var i = 0; i < 999; i++) {
    f();
  }
}
evalcx(
  `
    function mm2() {
      mm1() + 0;
    }
    for (var i = 0; i < 999; i++) {
      try {
        mm2();
      } catch (e) {}
    }
    mm1 = function() {};
    mm3 = function() {
      mm2();
    }
    for (var i = 0; i < 999; i++) {
      mm3();
    }
  `,
  s,
);
evalcx(
  `
    0;0;"use asm"; mm3 = function() { (function(){})() };
    g(mm3);
  `,
  s,
);
evalcx(
  `
    0;0;0;"use asm"; mm1 = function() {
      (function() {
        "use asm";
        function f() {};
        return f;
      })
      ({ function() {} })
    };
    for (var i = 0; i < 999; i++) {
      mm2();
    }
  `,
  s,
);
(gdb) bt
#0  0x00005555581473a2 in MOZ_CrashSequence (aAddress=0x0, aLine=213)
    at /home/msf2/shell-cache/js-dbg-64-linux-x86_64-70425199e9a5-597172/objdir-js/dist/include/mozilla/Assertions.h:237
#1  js::jit::WarpOracle::createSnapshot (this=0x7fffffffbb20) at /home/msf2/trees/firefox/js/src/jit/WarpOracle.cpp:212
#2  0x0000555558504c25 in js::jit::CreateWarpSnapshot (cx=0x7ffff5e3c200, mirGen=0x7ffff5cf6180, script=...)
    at /home/msf2/trees/firefox/js/src/jit/Ion.cpp:1709
#3  js::jit::IonCompile (cx=0x7ffff5e3c200, script=..., osrPc=<optimized out>) at /home/msf2/trees/firefox/js/src/jit/Ion.cpp:1816
#4  js::jit::Compile (cx=cx@entry=0x7ffff5e3c200, script=script@entry=..., osrFrame=osrFrame@entry=0x7fffffffbd88, osrPc=<optimized out>, osrPc@entry=0x0)
    at /home/msf2/trees/firefox/js/src/jit/Ion.cpp:2008
#5  0x0000555558505aab in BaselineCanEnterAtEntry (cx=0x7ffff5e3c200, script=..., frame=0x7fffffffbd88) at /home/msf2/trees/firefox/js/src/jit/Ion.cpp:2125
/snip
8b48bcac0033-586070
8b48bcac00332e0ca25035ff3b568e696c2f2802 is the first interesting commit
commit 8b48bcac00332e0ca25035ff3b568e696c2f2802
Author: Iain Ireland
Date:   Mon Sep 8 16:57:34 2025 +0000

    Bug 1943901: Do trial inlining from the baseline interpreter r=jandem

    Differential Revision: https://phabricator.services.mozilla.com/D263967

Run with --fuzzing-safe --no-threads --fast-warmup --baseline-warmup-threshold=100 --ion-warmup-threshold=50 --trial-inlining-warmup-threshold=50 --no-ggc, compile with AR=ar sh ~/trees/firefox/js/src/configure --enable-debug --enable-debug-symbols --with-ccache --enable-nspr-build --enable-ctypes --enable-gczeal --enable-rust-simd --disable-tests, tested on gh rev 70425199e9a5fa80aa7419fa51763013a67226e1.

Iain, is bug 1943901 a likely regressor?

Flags: needinfo?(iireland)

Set release status flags based on info from the regressing bug 1943901

It took a while to get to the bottom of this. I initially thought that the regressing patch was bug 1847258, but it turns out that it's possible to trigger the same issue without that patch. (At various points I also suspected weird evalcx interactions and Jan's constant global patches, but they were red herrings.) I think the underlying bug has been present since the initial version of trial inlining in bug 1646378.

The key points:

  1. We don't support Ion-compiling functions containing nested asm.js functions.
  2. If inlining fails with AbortReason::Disable, we unlink the call stub.

It turns out that, if you're very careful, you can:

  • Ion-compile a version of a function F that calls some other function G
  • Change the callee to a function B containing an asm.js lambda, which triggers a bailout and attaches a stub calling B.
  • Start a recompile that tries to monomorphically inline B into F, aborting the inlining.
  • Discard the stub calling B, leaving only the stub calling G.
  • Assert because now the transpiled CacheIR is identical to the initial compilation.

My first testcase jumped through a bunch of hoops to use monomorphic jithints to trick WarpOracle into inlining B into F, but then I realized that the hoops weren't necessary. Here's a simpler testcase:

// |jit-test| --no-threads
with ({}) {}

function foo() {
  target();
}

// A function that can be inlined
function good() {}

// A function that can't be inlined (because of the asm.js lambda)
function bad() {
  if (!bad) {
    function inner() {
      "use asm";
      function f() {}
      return f;
    }
  }
}

// Compile a version of foo that calls good without inlining it.
for (var i = 0; i < 1000; i++) {
  try { foo(); } catch {}
}
target = good;
for (var i = 0; i < 500; i++) {
  foo();
}

// Bail out of the ion-compiled version of foo, attach an IC that calls bad, and recompile.
target = bad;
for (var i = 0; i < 1500; i++) {
  foo();
}

After all that, I think the fix is probably just to clear the failedICHash when inlining aborts.

Flags: needinfo?(iireland)
Assignee: nobody → iireland
Status: NEW → ASSIGNED
Blocks: sm-opt-jits
Severity: -- → S3
Priority: -- → P1
Status: ASSIGNED → RESOLVED
Closed: 7 months ago
Resolution: --- → FIXED
Target Milestone: --- → 147 Branch
QA Whiteboard: [qa-triage-done-c148/b147]
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: