java-topology/defects/jsc/patch/jsc-0003-dfg-integer-range-liveathead-hashset.md

2 KiB
Raw Blame History

UNDF: UNDF-2026-000000588

jsc-0003: DFGIntegerRangeOptimizationPhase liveAtHead Vector::contains O(50×B×R×L) → O(50×B×R) with HashSet

Classification

Field Value
CWE CWE-407 Inefficient Algorithmic Complexity
Severity MEDIUM
Component Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp:1996
Function performForBasicBlock fixed-point loop
Hot path Integer range optimization pass — once per DFG compile for each function with integer ops
Status PATCHED (unit test PASS)

Defect

The integer range optimization phase runs a fixed-point loop (up to 50 iterations) over all basic blocks. Inside the loop, for each block, it iterates over relationshipMap entries (R relationships) and calls liveAtHead.contains(node) — an O(L) linear scan of a WTF::Vector<NodeFlowProjection>:

// DFGIntegerRangeOptimizationPhase.cpp:1996
Vector<NodeFlowProjection> liveAtHead = ...;  // L live nodes at block head

for (unsigned i = 50; i--;) {               // 50 fixed-point iterations
    for (BasicBlock* block : ...) {         // B blocks
        for (auto& entry : relationshipMap) { // R relationships
            if (liveAtHead.contains(node))  // O(L) linear scan per check
                ...
        }
    }
}

With 50 iterations × B=20 blocks × R=30 relationships × L=40 live nodes: 1,200,000 comparisons per compile for a medium-sized function with integer-heavy loops.

Fix

Replace Vector<NodeFlowProjection> liveAtHead with UncheckedKeyHashSet<NodeFlowProjection>. NodeFlowProjection already has a usable hash (it wraps a Node* + projection kind):

UncheckedKeyHashSet<NodeFlowProjection> liveAtHead;

// Populate once per block:
for (NodeFlowProjection proj : computeLiveAtHead(block))
    liveAtHead.add(proj);

// Contains check: O(1)
if (liveAtHead.contains(node)) { ... }

Speedup: ~40× at L=40 (1.2M → 30K comparisons for 50×B=20×R=30).