java-topology/docs/timeline.md
russell@unturf.com db29a08762 undefect. CWE-407 — 92 sites, 42 ecosystems
B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections.
Squash of 94 local commits onto remote master.
2026-03-26 19:48:18 -04:00

2.8 KiB
Raw Blame History

Timeline — java-topology

2026-03-23

Session opened. Sparse shallow clone of jdk.compiler confirmed present. Branch: master.

Investigation started. Searched all .java files for Graph, Topology, graph, topology hits.

Primary targets identified:

  • util/GraphUtils.java — core graph algorithm library
  • util/Dependencies.java — symbol completion dependency graph
  • comp/Infer.java — type inference graph solver (uses Tarjan)
  • comp/DeferredAttr.java — stuck expression resolution (uses Tarjan)
  • comp/Modules.java — module graph, transitive closure

Defect confirmed: GraphUtils.java:186 — Tarjan's SCC algorithm uses stack.contains(n) (O(n) linear scan on ListBuffer) instead of n.active (O(1) boolean field that exists on TarjanNode for exactly this purpose). Makes Tarjan O(V²) instead of O(V+E).

Ticket opened: 0001-tarjan-ov2-stack-contains

Tests created: tests/unit/, tests/integration/, tests/functional/ — 74 tests all passing. make -C tests all.

Before/after timing confirmed:

  • Algorithm level: 23x speedup at V=800, ~4x growth ratio BEFORE vs ~2x AFTER.
  • End-to-end compilation: no measurable difference at typical inference var counts (V=46).

2026-03-23 (continued)

Stack-wide defect survey. Fox pointed out the algorithm propagates up the full stack. Extracted all JDK module classes from jimage and scanned bytecode for Deque/List/Stack.contains() in graph/topology/dependency code.

Additional defect sites confirmed:

Ticket Location Defect Module
0002 Infer$GraphSolver$InferenceGraph.findNode() O(N) ArrayList scan, called O(N³) total via buildStuckGraph()canInfluence() jdk.compiler
0003 ModuleHashesBuilder$TopoSorter.visit() Deque.contains() for on-stack check — same pattern as 0001, different module java.base
0004 Dependencies$GraphDependencies$Node.addDependency() List.contains() dedup on every add jdk.compiler

Pattern confirmed: The same O(n) membership check on a linear collection, used where O(1) is possible and a dedicated flag/set already exists or trivially could. Not one bug — a systemic pattern replicated across at least 4 locations in 2 modules.

Cascade analysis:

  • buildStuckGraph() is O(N³) due to N² calls to canInfluence(), each doing O(N) findNode() + uncached O(V+E) closure() — independent of 0001.
  • ModuleHashesBuilder is in java.base — affects every jlink build.
  • Fix 0001 alone: algorithm is correct but callers are still slow.
  • Fix 0001+0002+0003: full stack improvement.

Next: Tickets for 00020004. Additional dot diagrams. Tests for 0002 (closure caching, findNode indexing).