mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
C: pack virtual tables
This commit is contained in:
parent
063a9f049e
commit
9de7df6fdf
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model.classes;
|
package org.teavm.model.classes;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.IntArrayList;
|
||||||
import com.carrotsearch.hppc.ObjectIntHashMap;
|
import com.carrotsearch.hppc.ObjectIntHashMap;
|
||||||
import com.carrotsearch.hppc.ObjectIntMap;
|
import com.carrotsearch.hppc.ObjectIntMap;
|
||||||
|
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -28,6 +30,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import org.teavm.common.Graph;
|
||||||
|
import org.teavm.common.GraphBuilder;
|
||||||
import org.teavm.common.LCATree;
|
import org.teavm.common.LCATree;
|
||||||
import org.teavm.model.AccessLevel;
|
import org.teavm.model.AccessLevel;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
|
@ -36,6 +40,7 @@ import org.teavm.model.ListableClassReaderSource;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.util.GraphColorer;
|
||||||
|
|
||||||
public class VirtualTableBuilder {
|
public class VirtualTableBuilder {
|
||||||
private ListableClassReaderSource classes;
|
private ListableClassReaderSource classes;
|
||||||
|
@ -47,6 +52,10 @@ public class VirtualTableBuilder {
|
||||||
private ObjectIntMap<String> classTreeIndexes;
|
private ObjectIntMap<String> classTreeIndexes;
|
||||||
private List<String> classList;
|
private List<String> classList;
|
||||||
private VirtualTableProvider result;
|
private VirtualTableProvider result;
|
||||||
|
private List<MethodDescriptor> methodDescriptors;
|
||||||
|
private ObjectIntMap<MethodDescriptor> methodDescriptorIndexes;
|
||||||
|
private int[] methodColors;
|
||||||
|
private int methodColorCount;
|
||||||
|
|
||||||
public VirtualTableBuilder(ListableClassReaderSource classes) {
|
public VirtualTableBuilder(ListableClassReaderSource classes) {
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
|
@ -71,6 +80,7 @@ public class VirtualTableBuilder {
|
||||||
|
|
||||||
classChildren = new HashMap<>();
|
classChildren = new HashMap<>();
|
||||||
buildClassChildren();
|
buildClassChildren();
|
||||||
|
pack();
|
||||||
liftEntries();
|
liftEntries();
|
||||||
|
|
||||||
buildResult();
|
buildResult();
|
||||||
|
@ -269,7 +279,9 @@ public class VirtualTableBuilder {
|
||||||
TableBuilder table = tables.get(className);
|
TableBuilder table = tables.get(className);
|
||||||
EntryBuilder entry = table.entries.get(method);
|
EntryBuilder entry = table.entries.get(method);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
table.entries.put(method, new EntryBuilder());
|
entry = new EntryBuilder();
|
||||||
|
entry.fake = true;
|
||||||
|
table.entries.put(method, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (className.equals(toClass)) {
|
if (className.equals(toClass)) {
|
||||||
|
@ -283,6 +295,45 @@ public class VirtualTableBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pack() {
|
||||||
|
methodDescriptorIndexes = new ObjectIntHashMap<>();
|
||||||
|
methodDescriptors = new ArrayList<>();
|
||||||
|
|
||||||
|
GraphBuilder graphBuilder = new GraphBuilder();
|
||||||
|
for (String className : classes.getClassNames()) {
|
||||||
|
TableBuilder table = tables.get(className);
|
||||||
|
MethodDescriptor[] methods = table.entries.keySet().toArray(new MethodDescriptor[0]);
|
||||||
|
for (int i = 0; i < methods.length; ++i) {
|
||||||
|
for (int j = i + 1; j < methods.length; ++j) {
|
||||||
|
int a = getMethodIndex(methods[i]);
|
||||||
|
int b = getMethodIndex(methods[j]);
|
||||||
|
graphBuilder.addEdge(a, b);
|
||||||
|
graphBuilder.addEdge(b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph interferenceGraph = graphBuilder.build();
|
||||||
|
methodColors = new int[methodDescriptors.size()];
|
||||||
|
Arrays.fill(methodColors, -1);
|
||||||
|
new GraphColorer().colorize(interferenceGraph, methodColors);
|
||||||
|
int colorCount = 0;
|
||||||
|
for (int i = 0; i < methodColors.length; ++i) {
|
||||||
|
colorCount = Math.max(colorCount, methodColors[i]--);
|
||||||
|
}
|
||||||
|
methodColorCount = colorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMethodIndex(MethodDescriptor method) {
|
||||||
|
int index = methodDescriptorIndexes.getOrDefault(method, -1);
|
||||||
|
if (index < 0) {
|
||||||
|
index = methodDescriptors.size();
|
||||||
|
methodDescriptors.add(method);
|
||||||
|
methodDescriptorIndexes.put(method, index);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
private void buildResult() {
|
private void buildResult() {
|
||||||
result = new VirtualTableProvider();
|
result = new VirtualTableProvider();
|
||||||
buildResultForClasses();
|
buildResultForClasses();
|
||||||
|
@ -296,7 +347,10 @@ public class VirtualTableBuilder {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildResultForClass(className, new Context(), null);
|
Context context = new Context();
|
||||||
|
context.indexes = new int[methodColorCount];
|
||||||
|
Arrays.fill(context.indexes, -1);
|
||||||
|
buildResultForClass(className, context, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,30 +358,52 @@ public class VirtualTableBuilder {
|
||||||
TableBuilder table = tables.get(className);
|
TableBuilder table = tables.get(className);
|
||||||
ClassReader cls = classes.get(className);
|
ClassReader cls = classes.get(className);
|
||||||
|
|
||||||
int start = context.methods.size();
|
int colorsStart = context.colors.size();
|
||||||
|
int initialMethodsStart = parent != null ? parent.size() : 0;
|
||||||
|
int methodsStart = initialMethodsStart;
|
||||||
|
IntArrayList resolvedIndexes = new IntArrayList();
|
||||||
Map<MethodDescriptor, VirtualTableEntry> resultEntries = new HashMap<>();
|
Map<MethodDescriptor, VirtualTableEntry> resultEntries = new HashMap<>();
|
||||||
for (MethodDescriptor method : table.entries.keySet()) {
|
for (MethodDescriptor method : table.entries.keySet()) {
|
||||||
|
int color = methodColors[methodDescriptorIndexes.get(method)];
|
||||||
EntryBuilder entry = table.entries.get(method);
|
EntryBuilder entry = table.entries.get(method);
|
||||||
int index = context.indexes.getOrDefault(method, -1);
|
int index = context.indexes[color];
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
index = context.indexes.size();
|
index = context.colors.size();
|
||||||
context.indexes.put(method, index);
|
context.indexes[color] = index;
|
||||||
context.methods.add(method);
|
context.colors.add(color);
|
||||||
|
context.methods.add(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.implementor != null) {
|
if (entry.implementor != null) {
|
||||||
VirtualTableEntry resultEntry = new VirtualTableEntry(method, entry.implementor, index);
|
VirtualTableEntry resultEntry = new VirtualTableEntry(method, entry.implementor, index);
|
||||||
resultEntries.put(method, resultEntry);
|
resultEntries.put(method, resultEntry);
|
||||||
|
|
||||||
propagateInterfaceIndexes(cls, method, index);
|
propagateInterfaceIndexes(cls, method, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context.methods.get(index) == null && !entry.fake) {
|
||||||
|
context.methods.set(index, method);
|
||||||
|
resolvedIndexes.add(index);
|
||||||
|
while (index < methodsStart) {
|
||||||
|
methodsStart -= parent.getMethods().size();
|
||||||
|
parent = parent.getParent();
|
||||||
|
if (parent == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MethodDescriptor> newMethods = context.methods.subList(start, context.methods.size());
|
List<MethodDescriptor> newMethods = context.methods.subList(methodsStart, context.methods.size());
|
||||||
|
Set<MethodDescriptor> methodSet = new HashSet<>();
|
||||||
|
for (MethodDescriptor method : newMethods) {
|
||||||
|
if (method != null) {
|
||||||
|
methodSet.add(method);
|
||||||
|
}
|
||||||
|
}
|
||||||
List<? extends MethodDescriptor> readonlyNewMethods = Collections.unmodifiableList(
|
List<? extends MethodDescriptor> readonlyNewMethods = Collections.unmodifiableList(
|
||||||
Arrays.asList(newMethods.toArray(new MethodDescriptor[0])));
|
Arrays.asList(newMethods.toArray(new MethodDescriptor[0])));
|
||||||
VirtualTable resultTable = new VirtualTable(className, parent, readonlyNewMethods,
|
VirtualTable resultTable = new VirtualTable(className, parent, readonlyNewMethods,
|
||||||
new HashSet<>(readonlyNewMethods), resultEntries);
|
methodSet, resultEntries);
|
||||||
result.virtualTables.put(className, resultTable);
|
result.virtualTables.put(className, resultTable);
|
||||||
|
|
||||||
List<String> children = classChildren.get(className);
|
List<String> children = classChildren.get(className);
|
||||||
|
@ -337,11 +413,14 @@ public class VirtualTableBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newMethods = context.methods.subList(start, context.methods.size());
|
for (int i = colorsStart; i < context.colors.size(); ++i) {
|
||||||
for (MethodDescriptor method : newMethods) {
|
context.indexes[context.colors.get(i)] = -1;
|
||||||
context.indexes.remove(method);
|
|
||||||
}
|
}
|
||||||
newMethods.clear();
|
context.colors.removeRange(colorsStart, context.colors.size());
|
||||||
|
for (IntCursor resolvedIndex : resolvedIndexes) {
|
||||||
|
context.methods.set(resolvedIndex.value, null);
|
||||||
|
}
|
||||||
|
context.methods.subList(initialMethodsStart, context.methods.size()).clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void propagateInterfaceIndexes(ClassReader cls, MethodDescriptor method, int index) {
|
private void propagateInterfaceIndexes(ClassReader cls, MethodDescriptor method, int index) {
|
||||||
|
@ -422,6 +501,7 @@ public class VirtualTableBuilder {
|
||||||
MethodReference implementor;
|
MethodReference implementor;
|
||||||
EntryBuilder[] parents;
|
EntryBuilder[] parents;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
boolean fake;
|
||||||
|
|
||||||
void addParent(EntryBuilder parent) {
|
void addParent(EntryBuilder parent) {
|
||||||
if (parents == null) {
|
if (parents == null) {
|
||||||
|
@ -434,7 +514,8 @@ public class VirtualTableBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Context {
|
static class Context {
|
||||||
ObjectIntMap<MethodDescriptor> indexes = new ObjectIntHashMap<>();
|
int[] indexes;
|
||||||
|
IntArrayList colors = new IntArrayList();
|
||||||
List<MethodDescriptor> methods = new ArrayList<>();
|
List<MethodDescriptor> methods = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user