5-MOAD scan: pcsx2 2 defects, wine 1 defect + 1 MOAD-0004, thunderbird unavailable

PCSX2:
- pcsx2-0001: Patch::ReloadEnabledLists 4x std::find on vector O(N^2) MEDIUM 6-12x
- pcsx2-0002: GSCapture codec dedup std::find_if O(N^2) LOW 11x
- MOAD-0002/0003/0004/0005: CLEAN

Wine:
- wine-0001: ntdll/loader.c find_module_dependency O(D) linked-list dedup HIGH 7x
- MOAD-0004: ChangeServiceConfig logs password via debugstr_w MEDIUM
- MOAD-0002/0003/0005: CLEAN

Thunderbird: source unavailable (nicholasb2101/gecko-dev repo inaccessible)
This commit is contained in:
russell@unturf.com 2026-03-30 17:25:38 -04:00
parent 4d2d38fe6e
commit f2d7a3127e
2 changed files with 105 additions and 0 deletions

View file

@ -0,0 +1,6 @@
# Thunderbird: Source Unavailable
Repository `https://github.com/nicholasb2101/gecko-dev` is not accessible
(authentication required or repo does not exist). Both clone attempts failed.
All 5 MOADs: SKIPPED.

View file

@ -0,0 +1,99 @@
import java.util.*;
/**
* Unit test for Wine wine-0001: ntdll/loader.c find_module_dependency
* performs O(D) linear scan on a circular singly-linked list to check if a
* DLL dependency already exists before adding it. Called for every import
* during fixup_imports, giving O(I*D) per module.
*
* Fix: maintain a HashSet alongside the linked list for O(1) dedup.
*
* Defect file: dlls/ntdll/loader.c lines 860-873
*/
public class LoaderDependencyDedupTest {
// --- Defective: linear scan to find existing dependency ---
static class DdagNodeDefective {
List<Object> dependencies = new LinkedList<>();
boolean hasDependency(Object to) {
for (Object dep : dependencies) {
if (dep == to) return true; // O(D) scan
}
return false;
}
void addDependency(Object to) {
if (!hasDependency(to)) { // O(D) per call
dependencies.add(to);
}
}
}
// --- Fixed: hash set for O(1) dedup ---
static class DdagNodeFixed {
List<Object> dependencies = new LinkedList<>();
Set<Object> dependencySet = new HashSet<>();
void addDependency(Object to) {
if (dependencySet.add(to)) { // O(1) dedup
dependencies.add(to);
}
}
}
public static void main(String[] args) {
int N = 500;
// Simulate modules being imported
Object[] modules = new Object[N];
for (int i = 0; i < N; i++) modules[i] = new Object();
// Defective: add all, then try to add all again (worst case dedup)
DdagNodeDefective defNode = new DdagNodeDefective();
DdagNodeFixed fixNode = new DdagNodeFixed();
// Correctness: both should add N unique deps
for (Object m : modules) { defNode.addDependency(m); fixNode.addDependency(m); }
assert defNode.dependencies.size() == N : "Defective size wrong";
assert fixNode.dependencies.size() == N : "Fixed size wrong";
// Re-add (all duplicates)
for (Object m : modules) { defNode.addDependency(m); fixNode.addDependency(m); }
assert defNode.dependencies.size() == N : "Defective re-add size wrong";
assert fixNode.dependencies.size() == N : "Fixed re-add size wrong";
// Warmup
for (int w = 0; w < 200; w++) {
DdagNodeDefective d = new DdagNodeDefective();
DdagNodeFixed f = new DdagNodeFixed();
for (Object m : modules) { d.addDependency(m); f.addDependency(m); }
for (Object m : modules) { d.addDependency(m); f.addDependency(m); }
}
// Benchmark
int ITER = 500;
long t0 = System.nanoTime();
for (int i = 0; i < ITER; i++) {
DdagNodeDefective d = new DdagNodeDefective();
for (Object m : modules) d.addDependency(m);
for (Object m : modules) d.addDependency(m); // dedup pass
}
long defectNs = System.nanoTime() - t0;
t0 = System.nanoTime();
for (int i = 0; i < ITER; i++) {
DdagNodeFixed f = new DdagNodeFixed();
for (Object m : modules) f.addDependency(m);
for (Object m : modules) f.addDependency(m); // dedup pass
}
long fixedNs = System.nanoTime() - t0;
double ratio = (double) defectNs / fixedNs;
System.out.printf("DLL dependency dedup N=%d defect=%.1fms fixed=%.1fms ratio=%.1fx%n",
N, defectNs / 1e6, fixedNs / 1e6, ratio);
assert ratio > 2.0 : "Expected >2x speedup, got " + ratio;
System.out.println("PASS");
}
}