Skip to content

Commit

Permalink
tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
CoolMineman committed Dec 10, 2022
1 parent 7514277 commit f1c8d01
Show file tree
Hide file tree
Showing 4 changed files with 1,168 additions and 348 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void compile() {
long s2 = System.currentTimeMillis() - s;
System.out.println(s2);
if (JvmUtil.CURRENT_JAVA_VERSION == 8) // TestMod.java produces different cp order in j8 and j17
TestUtil.assertSha256(b.jar, "e0dbaa897a5f86f77e3fec2a7fd43dbf4df830a10b9c75dd0ae23f28e5da3c67");
TestUtil.assertSha256(b.jar, "daad101c55eaedccbe8b9650666c63f1e6a5541911c9e202aa71184a2366e4ad");
} catch (Exception e) {
e.printStackTrace();
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void compile() {
long s2 = System.currentTimeMillis() - s;
System.out.println(s2);
// Seems to work accross java versions for now
TestUtil.assertSha256(b.jar, "8be3cb61a62c2ee9d3694a49eedb4131e25b0f830dc15661282dd27e708b9cc8");
TestUtil.assertSha256(b.jar, "fdfeb367b463839e2207b0c8bc887f1879b2157da838e51b1b0e98487c86e6ce");
} catch (Exception e) {
e.printStackTrace();
throw e;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;

import io.github.coolcrabs.brachyura.recombobulator.AccessFlags;
Expand All @@ -22,16 +26,16 @@
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;

public class InheritanceMap {
public HashMap<Mutf8Slice, HashMap<NameDescPair, InheritanceGroup>> inheritanceMap;
public ConcurrentHashMap<Mutf8Slice, Map<NameDescPair, InheritanceGroup>> inheritanceMap;
public ConcurrentHashMap<Mutf8Slice, Object2IntMap<NameDescPair>> inheritanceInfoMap;
public ConcurrentHashMap<Mutf8Slice, ConcurrentLinkedQueue<Mutf8Slice>> aboveMap;
public ConcurrentHashMap<Mutf8Slice, Collection<Mutf8Slice>> belowMap;

int curId = 0;
public int curId = 1;

public void initCapacity(int size) {
if (inheritanceMap == null) {
inheritanceMap = new HashMap<>(size);
inheritanceMap = new ConcurrentHashMap<>(size);
inheritanceInfoMap = new ConcurrentHashMap<>(size);
aboveMap = new ConcurrentHashMap<>(size);
belowMap = new ConcurrentHashMap<>(size);
Expand Down Expand Up @@ -65,10 +69,28 @@ public void load(Collection<Entry<Mutf8Slice, Supplier<ClassInfo>>> classes, boo
aboveMap.computeIfAbsent(b, k -> new ConcurrentLinkedQueue<>()).add(name);
}
Object2IntMap<NameDescPair> iinfo = new Object2IntOpenHashMap<>(ci.methods.size());
HashMap<NameDescPair, InheritanceGroup> imap = new HashMap<>(ci.methods.size());
for (MethodInfo mi : ci.methods) {
iinfo.put(new NameDescPair(RecombobulatorRemapper.utf8(ci.pool, mi.name_index), RecombobulatorRemapper.utf8(ci.pool, mi.descriptor_index)), mi.access_flags);
NameDescPair ndp = new NameDescPair(RecombobulatorRemapper.utf8(ci.pool, mi.name_index), RecombobulatorRemapper.utf8(ci.pool, mi.descriptor_index));
iinfo.put(ndp, mi.access_flags);
imap.put(ndp, new InheritanceGroup());
}
inheritanceInfoMap.put(name, iinfo);
inheritanceInfoMap.compute(name, (k, v) -> {
if (v == null) {
return iinfo;
} else {
v.putAll(iinfo);
return v;
}
});
inheritanceMap.compute(name, (k, v) -> {
if (v == null) {
return imap;
} else {
v.putAll(imap);
return v;
}
});
})
);
}
Expand All @@ -81,106 +103,132 @@ public void load(Collection<Entry<Mutf8Slice, Supplier<ClassInfo>>> classes, boo
}
futures.clear();
// Build method inheritance groups
//TODO: was hard to multithread but might be worth it
for (Entry<Mutf8Slice, Supplier<ClassInfo>> e : classes) {
ClassInfo ci = e.getValue().get();
Mutf8Slice clsName = e.getKey();
HashMap<NameDescPair, InheritanceGroup> mIgroupMap = getMethodMap(clsName, ci.methods.size());
Object2IntMap<NameDescPair> mIinfoMap = getIInfoMap(clsName);
for (MethodInfo methodInfo : ci.methods) {
NameDescPair methodKey = new NameDescPair(RecombobulatorRemapper.utf8(ci.pool, methodInfo.name_index), RecombobulatorRemapper.utf8(ci.pool, methodInfo.descriptor_index));
InheritanceGroup igroup = mIgroupMap.computeIfAbsent(methodKey, k -> new InheritanceGroup(curId++, canRemap));
int acc = mIinfoMap.getInt(methodKey); // Will always be present
if (canPropogate(acc)) { // Can propogate
ConcurrentHashMap<Mutf8Slice, ? extends Collection<Mutf8Slice>> directionMap = aboveMap;
for (int i = 0; i < 2; i++) { // Loop twice once for up once for down
ArrayList<Mutf8Slice> la = new ArrayList<>();
ArrayList<Mutf8Slice> lb = new ArrayList<>();
la.add(clsName);
while (!la.isEmpty()) {
for (Mutf8Slice lai : la) {
Collection<Mutf8Slice> nextInDirection = directionMap.get(lai);
if (nextInDirection != null) lb.addAll(nextInDirection);
}
ArrayList<Mutf8Slice> temp = la;
la = lb;
lb = temp;
lb.clear();
for (Mutf8Slice lai : la) {
Object2IntMap<NameDescPair> laiIinfoMap = getIInfoMap(lai);
HashMap<NameDescPair, InheritanceGroup> laiIgroupMap = getMethodMap(lai, laiIinfoMap.size());
int laiAcc = laiIinfoMap.getOrDefault(methodKey, AccessFlags.ACC_PRIVATE); // private can't propogate so use as default
if (canPropogate(laiAcc)) {
laiIgroupMap.compute(methodKey, (k, v) -> {
if (v != null) {
igroup.join(v);
futures.add(
threadpool.submit(() -> {
ClassInfo ci = e.getValue().get();
Mutf8Slice clsName = e.getKey();
Map<NameDescPair, InheritanceGroup> mIgroupMap = inheritanceMap.get(clsName);
Object2IntMap<NameDescPair> mIinfoMap = getIInfoMap(clsName);
for (MethodInfo methodInfo : ci.methods) {
NameDescPair methodKey = new NameDescPair(RecombobulatorRemapper.utf8(ci.pool, methodInfo.name_index), RecombobulatorRemapper.utf8(ci.pool, methodInfo.descriptor_index));
InheritanceGroup igroup = mIgroupMap.get(methodKey);
if (igroup == null) {
System.out.println("SAD!");
}
int acc = mIinfoMap.getInt(methodKey); // Will always be present
if (canPropogate(acc)) { // Can propogate
ConcurrentHashMap<Mutf8Slice, ? extends Collection<Mutf8Slice>> directionMap = aboveMap;
for (int i = 0; i < 2; i++) { // Loop twice once for up once for down
ArrayList<Mutf8Slice> la = new ArrayList<>();
ArrayList<Mutf8Slice> lb = new ArrayList<>();
la.add(clsName);
while (!la.isEmpty()) {
for (Mutf8Slice lai : la) {
Collection<Mutf8Slice> nextInDirection = directionMap.get(lai);
if (nextInDirection != null) lb.addAll(nextInDirection);
}
ArrayList<Mutf8Slice> temp = la;
la = lb;
lb = temp;
lb.clear();
for (Mutf8Slice lai : la) {
Object2IntMap<NameDescPair> laiIinfoMap = getIInfoMap(lai);
Map<NameDescPair, InheritanceGroup> laiIgroupMap = inheritanceMap.getOrDefault(lai, Collections.emptyMap());
int laiAcc = laiIinfoMap.getOrDefault(methodKey, AccessFlags.ACC_PRIVATE); // private can't propogate so use as default
if (canPropogate(laiAcc)) {
igroup.join(laiIgroupMap.get(methodKey));
}
return igroup;
});
}
}
directionMap = belowMap;
}
}
directionMap = belowMap;
}
})
);
}
for (Future<?> f : futures) {
try {
f.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
for (Map<NameDescPair, InheritanceGroup> a : inheritanceMap.values()) {
for (InheritanceGroup b : a.values()) {
if (b.id == 0) {
setId(curId++, b);
}
}
}
}

static void setId(int id, InheritanceGroup g) {
g.id = id;
for (InheritanceGroup g0 : g.children) {
setId(id, g0);
}
}

static final boolean canPropogate(int acc) {
return (acc & AccessFlags.ACC_STATIC) == 0 && (acc & AccessFlags.ACC_PRIVATE) == 0;
}

private HashMap<NameDescPair, InheritanceGroup> getMethodMap(Mutf8Slice clsName, int size) {
return inheritanceMap.computeIfAbsent(clsName, c -> new HashMap<>(size));
}

Object2IntMap<NameDescPair> getIInfoMap(Mutf8Slice clsName) {
return inheritanceInfoMap.getOrDefault(clsName, Object2IntMaps.emptyMap());
}

public static class InheritanceGroup {
public int id;
public boolean canRemap;
InheritanceGroup down;
InheritanceGroup up;

public InheritanceGroup(int id, boolean canRemap) {
this.id = id;
this.canRemap = canRemap;
}
InheritanceGroup parent;
AtomicBoolean lock = new AtomicBoolean();
//todo evaluate data structure
LinkedList<InheritanceGroup> children = new LinkedList<>();

public void join(InheritanceGroup o) {
if (o.id == this.id) return;
InheritanceGroup a = this;
while (a.down != null) a = a.down;
InheritanceGroup b = o;
while (b.up != null) b = b.up;
a.down = b;
b.up = a;
if (a.canRemap != b.canRemap) {
if (a.canRemap) {
InheritanceGroup a0 = a;
for (;;) {
a0.canRemap = false;
a0 = a0.up;
if (a0 == null) break;
}
} else { // b.canRemap
InheritanceGroup b0 = b;
for (;;) {
b0.canRemap = false;
b0 = b0.down;
if (b0 == null) break;
InheritanceGroup a = o;
InheritanceGroup b = this;
// If there is a better way to do this without spin locks I couldn't find it
for (;;) {
a = getTop(a);
b = getTop(b);
if (a == b) return;
AtomicBoolean al = a.lock;
AtomicBoolean bl = b.lock;
boolean alock = al.compareAndSet(false, true);
if (alock) {
try {
boolean block = bl.compareAndSet(false, true);
if (block) {
try {
if (a.parent == null && b.parent == null) {
b.parent = a;
a.children.add(b);
break;
}
} finally {
bl.set(false);
}
}
} finally {
al.set(false);
}
}
}
InheritanceGroup c = b;
}

public static InheritanceGroup getTop(InheritanceGroup g) {
InheritanceGroup r = g;
for (;;) {
c.id = id;
c = c.down;
if (c == null) break;
InheritanceGroup p = r.parent;
if (p == null) {
break;
}
r = p;
}
return r;
}
}
}
Loading

0 comments on commit f1c8d01

Please sign in to comment.