Closed Bug 2035965 Opened 6 days ago Closed 5 days ago

ScanDominatorsForDefs(MBasicBlock*) uses parameter block instead of loop variable i, reducing scan to a single-block check

Categories

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

defect

Tracking

()

RESOLVED FIXED
152 Branch
Tracking Status
firefox152 --- fixed

People

(Reporter: zchengchen0411, Assigned: zchengchen0411)

References

(Blocks 1 open bug)

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36

Steps to reproduce:

Code audit of js/src/jit/ValueNumbering.cpp, specifically the single-argument overload of ScanDominatorsForDefs at lines 218–231.

Actual results:

The loop body uses the parameter block instead of the loop variable i:

static bool ScanDominatorsForDefs(MBasicBlock* block) {
  for (MBasicBlock* i = block;;) {
    if (BlockHasInterestingDefs(block)) {  // <-- should be `i`
      return true;
    }
    MBasicBlock* immediateDominator = i->immediateDominator();
    if (immediateDominator == i) {
      break;
    }
    i = immediateDominator;
  }
  return false;
}

Although i is updated on each iteration, it is never used in the loop body.
As a result, the function is effectively equivalent to:

  return BlockHasInterestingDefs(block);

The intended dominator-chain traversal does not actually occur.

Expected results:

The loop should call BlockHasInterestingDefs(i), so that it correctly walks up
the dominator tree and checks each ancestor block.

This matches both the function comment:

"Walk up the dominator tree from |block| to the root and test for any defs"

and the behavior of the related two-argument overload.

Potential impact:
This can suppress a necessary GVN rerun.

The path is reachable from IsDominatorRefined (around lines 265–266):

  if (block == old) {
    return block != now && ScanDominatorsForDefs(now);
  }

When a self-dominating block (e.g., a normal + OSR merge point that is not a
loop header) has a predecessor removed and ComputeNewDominator returns a new
dominator now != block, the scan is expected to walk up the dominator tree.

If now itself has no interesting definitions but one of its dominator
ancestors does, the buggy implementation returns false, incorrectly skipping
the GVN rerun.

Impact is limited to missed optimizations. There is no miscompilation or
memory safety issue. Triggering requires a specific CFG topology, so practical
impact is likely low.

Fix suggestion:

-    if (BlockHasInterestingDefs(block)) {
+    if (BlockHasInterestingDefs(i)) {

PR:
https://github.com/mozilla-firefox/firefox/pull/238

Summary: ScanDominatorsForDefs(MBasicBlock*) uses parameter blockinstead of loop variable i, reducing scan to a single-block check → ScanDominatorsForDefs(MBasicBlock*) uses parameter block instead of loop variable i, reducing scan to a single-block check

The single-argument overload of ScanDominatorsForDefs was intended to walk
up the dominator tree from |block| to the root, checking each block for
defs interesting to GVN. However, while the loop variable |i| is updated
on each iteration, the call to BlockHasInterestingDefs mistakenly uses
|block| instead of |i|. As a result, every iteration checks the same
starting block and the function effectively reduces to:

BlockHasInterestingDefs(block)

This path is reachable from IsDominatorRefined when |block == old| and
ComputeNewDominator returns a new dominator distinct from |block|. In
such cases, if the new dominator itself has no interesting defs but one
of its ancestors does, the buggy implementation returns false and
incorrectly suppresses a GVN rerun.

The impact is limited to missed optimization (a GVN pass not being
triggered). There is no correctness or memory safety issue.

Fix by using the loop variable |i|, matching the two-argument overload
and the function's documentation.

Assignee: nobody → zchengchen0411
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Attachment #9575318 - Attachment description: Bug 2035965 - Fix typo in single-arg ScanDominatorsForDefs r?jandem → Bug 2035965 - Fix: ScanDominatorsForDefs(MBasicBlock*) uses parameter block instead of loop variable i, reducing scan to a single-block check r?jandem
Duplicate of this bug: 2020686
Pushed by jdemooij@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/324238d55ce3 https://hg.mozilla.org/integration/autoland/rev/7eeb5171af70 Fix: ScanDominatorsForDefs(MBasicBlock*) uses parameter block instead of loop variable i, reducing scan to a single-block check r=jandem
Blocks: sm-js-perf
Severity: -- → S3
Priority: -- → P2
Status: ASSIGNED → RESOLVED
Closed: 5 days ago
Resolution: --- → FIXED
Target Milestone: --- → 152 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: