mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Use class/method names to generate lambda class names. Reduce number of types propagated by dependency analyzer
This commit is contained in:
parent
2eea5cba5e
commit
f160ce2f2f
|
@ -16,6 +16,8 @@
|
||||||
package org.teavm.classlib.impl.lambda;
|
package org.teavm.classlib.impl.lambda;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import org.teavm.cache.NoCache;
|
import org.teavm.cache.NoCache;
|
||||||
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
||||||
import org.teavm.dependency.DynamicCallSite;
|
import org.teavm.dependency.DynamicCallSite;
|
||||||
|
@ -29,6 +31,7 @@ import org.teavm.model.FieldHolder;
|
||||||
import org.teavm.model.MethodHandle;
|
import org.teavm.model.MethodHandle;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.PrimitiveType;
|
import org.teavm.model.PrimitiveType;
|
||||||
|
import org.teavm.model.TextLocation;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
import org.teavm.model.emit.ProgramEmitter;
|
import org.teavm.model.emit.ProgramEmitter;
|
||||||
import org.teavm.model.emit.ValueEmitter;
|
import org.teavm.model.emit.ValueEmitter;
|
||||||
|
@ -37,7 +40,7 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
private static final int FLAG_SERIALIZABLE = 1;
|
private static final int FLAG_SERIALIZABLE = 1;
|
||||||
private static final int FLAG_MARKERS = 2;
|
private static final int FLAG_MARKERS = 2;
|
||||||
private static final int FLAG_BRIDGES = 4;
|
private static final int FLAG_BRIDGES = 4;
|
||||||
private int lambdaIndex;
|
private Map<String, Integer> lambdaIdsByMethod = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueEmitter substitute(DynamicCallSite callSite, ProgramEmitter callerPe) {
|
public ValueEmitter substitute(DynamicCallSite callSite, ProgramEmitter callerPe) {
|
||||||
|
@ -50,7 +53,11 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
ClassReaderSource classSource = callSite.getAgent().getClassSource();
|
ClassReaderSource classSource = callSite.getAgent().getClassSource();
|
||||||
ClassReader samClass = classSource.get(samName);
|
ClassReader samClass = classSource.get(samName);
|
||||||
|
|
||||||
ClassHolder implementor = new ClassHolder("$$LAMBDA" + (lambdaIndex++) + "$$");
|
String key = callSite.getCaller().getClassName() + "$" + callSite.getCaller().getName();
|
||||||
|
int id = lambdaIdsByMethod.getOrDefault(key, 0);
|
||||||
|
lambdaIdsByMethod.put(key, id + 1);
|
||||||
|
|
||||||
|
ClassHolder implementor = new ClassHolder(key + "$lambda$_" + id);
|
||||||
implementor.setLevel(AccessLevel.PUBLIC);
|
implementor.setLevel(AccessLevel.PUBLIC);
|
||||||
if (samClass != null && samClass.hasModifier(ElementModifier.INTERFACE)) {
|
if (samClass != null && samClass.hasModifier(ElementModifier.INTERFACE)) {
|
||||||
implementor.setParent("java.lang.Object");
|
implementor.setParent("java.lang.Object");
|
||||||
|
@ -61,15 +68,16 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
|
|
||||||
int capturedVarCount = callSite.getCalledMethod().parameterCount();
|
int capturedVarCount = callSite.getCalledMethod().parameterCount();
|
||||||
MethodHolder ctor = createConstructor(classSource, implementor,
|
MethodHolder ctor = createConstructor(classSource, implementor,
|
||||||
Arrays.copyOfRange(invokedType, 0, capturedVarCount));
|
Arrays.copyOfRange(invokedType, 0, capturedVarCount), callerPe.getCurrentLocation());
|
||||||
ctor.getAnnotations().add(new AnnotationHolder(NoCache.class.getName()));
|
ctor.getAnnotations().add(new AnnotationHolder(NoCache.class.getName()));
|
||||||
createBridge(classSource, implementor, callSite.getCalledMethod().getName(), instantiatedMethodType,
|
createBridge(classSource, implementor, callSite.getCalledMethod().getName(), instantiatedMethodType,
|
||||||
samMethodType);
|
samMethodType, callerPe.getCurrentLocation());
|
||||||
|
|
||||||
MethodHolder worker = new MethodHolder(callSite.getCalledMethod().getName(), instantiatedMethodType);
|
MethodHolder worker = new MethodHolder(callSite.getCalledMethod().getName(), instantiatedMethodType);
|
||||||
worker.getAnnotations().add(new AnnotationHolder(NoCache.class.getName()));
|
worker.getAnnotations().add(new AnnotationHolder(NoCache.class.getName()));
|
||||||
worker.setLevel(AccessLevel.PUBLIC);
|
worker.setLevel(AccessLevel.PUBLIC);
|
||||||
ProgramEmitter pe = ProgramEmitter.create(worker, callSite.getAgent().getClassSource());
|
ProgramEmitter pe = ProgramEmitter.create(worker, callSite.getAgent().getClassSource());
|
||||||
|
pe.setCurrentLocation(callerPe.getCurrentLocation());
|
||||||
ValueEmitter thisVar = pe.var(0, implementor);
|
ValueEmitter thisVar = pe.var(0, implementor);
|
||||||
ValueEmitter[] arguments = new ValueEmitter[instantiatedMethodType.length - 1];
|
ValueEmitter[] arguments = new ValueEmitter[instantiatedMethodType.length - 1];
|
||||||
for (int i = 0; i < arguments.length; ++i) {
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
|
@ -119,7 +127,7 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
for (int i = 0; i < bridgeCount; ++i) {
|
for (int i = 0; i < bridgeCount; ++i) {
|
||||||
ValueType[] bridgeType = callSite.getBootstrapArguments().get(bootstrapArgIndex++).getMethodType();
|
ValueType[] bridgeType = callSite.getBootstrapArguments().get(bootstrapArgIndex++).getMethodType();
|
||||||
createBridge(classSource, implementor, callSite.getCalledMethod().getName(), instantiatedMethodType,
|
createBridge(classSource, implementor, callSite.getCalledMethod().getName(), instantiatedMethodType,
|
||||||
bridgeType);
|
bridgeType, callerPe.getCurrentLocation());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,13 +267,15 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodHolder createConstructor(ClassReaderSource classSource, ClassHolder implementor, ValueType[] types) {
|
private MethodHolder createConstructor(ClassReaderSource classSource, ClassHolder implementor, ValueType[] types,
|
||||||
|
TextLocation location) {
|
||||||
ValueType[] signature = Arrays.copyOf(types, types.length + 1);
|
ValueType[] signature = Arrays.copyOf(types, types.length + 1);
|
||||||
signature[types.length] = ValueType.VOID;
|
signature[types.length] = ValueType.VOID;
|
||||||
MethodHolder ctor = new MethodHolder("<init>", signature);
|
MethodHolder ctor = new MethodHolder("<init>", signature);
|
||||||
ctor.setLevel(AccessLevel.PUBLIC);
|
ctor.setLevel(AccessLevel.PUBLIC);
|
||||||
|
|
||||||
ProgramEmitter pe = ProgramEmitter.create(ctor, classSource);
|
ProgramEmitter pe = ProgramEmitter.create(ctor, classSource);
|
||||||
|
pe.setCurrentLocation(location);
|
||||||
ValueEmitter thisVar = pe.var(0, implementor);
|
ValueEmitter thisVar = pe.var(0, implementor);
|
||||||
thisVar.invokeSpecial(implementor.getParent(), "<init>");
|
thisVar.invokeSpecial(implementor.getParent(), "<init>");
|
||||||
|
|
||||||
|
@ -283,7 +293,7 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createBridge(ClassReaderSource classSource, ClassHolder implementor, String name, ValueType[] types,
|
private void createBridge(ClassReaderSource classSource, ClassHolder implementor, String name, ValueType[] types,
|
||||||
ValueType[] bridgeTypes) {
|
ValueType[] bridgeTypes, TextLocation location) {
|
||||||
if (Arrays.equals(types, bridgeTypes)) {
|
if (Arrays.equals(types, bridgeTypes)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -293,6 +303,7 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
||||||
bridge.setLevel(AccessLevel.PUBLIC);
|
bridge.setLevel(AccessLevel.PUBLIC);
|
||||||
bridge.getModifiers().add(ElementModifier.BRIDGE);
|
bridge.getModifiers().add(ElementModifier.BRIDGE);
|
||||||
ProgramEmitter pe = ProgramEmitter.create(bridge, classSource);
|
ProgramEmitter pe = ProgramEmitter.create(bridge, classSource);
|
||||||
|
pe.setCurrentLocation(location);
|
||||||
ValueEmitter thisVar = pe.var(0, implementor);
|
ValueEmitter thisVar = pe.var(0, implementor);
|
||||||
ValueEmitter[] arguments = new ValueEmitter[bridgeTypes.length - 1];
|
ValueEmitter[] arguments = new ValueEmitter[bridgeTypes.length - 1];
|
||||||
for (int i = 0; i < arguments.length; ++i) {
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
|
|
|
@ -49,6 +49,17 @@ public class DefaultAliasProvider implements AliasProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < alias.length(); ++i) {
|
||||||
|
char c = alias.charAt(i);
|
||||||
|
if (!Character.isJavaIdentifierPart(c)) {
|
||||||
|
alias.setCharAt(i, '_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Character.isJavaIdentifierStart(alias.charAt(0))) {
|
||||||
|
alias.setCharAt(0, '_');
|
||||||
|
}
|
||||||
|
|
||||||
return makeUnique(knownAliases, alias.toString());
|
return makeUnique(knownAliases, alias.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -435,7 +435,7 @@ public class DependencyAnalyzer implements DependencyInfo {
|
||||||
if (methodRef.getDescriptor().getResultType() == ValueType.VOID) {
|
if (methodRef.getDescriptor().getResultType() == ValueType.VOID) {
|
||||||
resultNode = null;
|
resultNode = null;
|
||||||
} else {
|
} else {
|
||||||
resultNode = createNode();
|
resultNode = createNode(methodRef.getDescriptor().getResultType());
|
||||||
resultNode.method = methodRef;
|
resultNode.method = methodRef;
|
||||||
if (shouldTag) {
|
if (shouldTag) {
|
||||||
resultNode.setTag(methodRef + ":RESULT");
|
resultNode.setTag(methodRef + ":RESULT");
|
||||||
|
|
|
@ -242,7 +242,8 @@ class DependencyGraphBuilder {
|
||||||
for (int k = 0; k < indy.getArguments().size(); ++k) {
|
for (int k = 0; k < indy.getArguments().size(); ++k) {
|
||||||
arguments.add(pe.var(indy.getArguments().get(k), indy.getMethod().parameterType(k)));
|
arguments.add(pe.var(indy.getArguments().get(k), indy.getMethod().parameterType(k)));
|
||||||
}
|
}
|
||||||
DynamicCallSite callSite = new DynamicCallSite(indy.getMethod(),
|
DynamicCallSite callSite = new DynamicCallSite(
|
||||||
|
methodDep.getReference(), indy.getMethod(),
|
||||||
indy.getInstance() != null ? pe.var(indy.getInstance(),
|
indy.getInstance() != null ? pe.var(indy.getInstance(),
|
||||||
ValueType.object(methodDep.getMethod().getOwnerName())) : null,
|
ValueType.object(methodDep.getMethod().getOwnerName())) : null,
|
||||||
arguments, indy.getBootstrapMethod(), indy.getBootstrapArguments(),
|
arguments, indy.getBootstrapMethod(), indy.getBootstrapArguments(),
|
||||||
|
@ -579,6 +580,9 @@ class DependencyGraphBuilder {
|
||||||
@Override
|
@Override
|
||||||
public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
|
public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
|
||||||
ArrayElementType type) {
|
ArrayElementType type) {
|
||||||
|
if (isPrimitive(type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
DependencyNode arrayNode = nodes[array.getIndex()];
|
DependencyNode arrayNode = nodes[array.getIndex()];
|
||||||
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
||||||
if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) {
|
if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) {
|
||||||
|
@ -589,6 +593,9 @@ class DependencyGraphBuilder {
|
||||||
@Override
|
@Override
|
||||||
public void putElement(VariableReader array, VariableReader index, VariableReader value,
|
public void putElement(VariableReader array, VariableReader index, VariableReader value,
|
||||||
ArrayElementType type) {
|
ArrayElementType type) {
|
||||||
|
if (isPrimitive(type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
DependencyNode valueNode = nodes[value.getIndex()];
|
DependencyNode valueNode = nodes[value.getIndex()];
|
||||||
DependencyNode arrayNode = nodes[array.getIndex()];
|
DependencyNode arrayNode = nodes[array.getIndex()];
|
||||||
if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) {
|
if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) {
|
||||||
|
@ -596,6 +603,10 @@ class DependencyGraphBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPrimitive(ArrayElementType type) {
|
||||||
|
return type != ArrayElementType.OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||||
List<? extends VariableReader> arguments, InvocationType type) {
|
List<? extends VariableReader> arguments, InvocationType type) {
|
||||||
|
|
|
@ -268,6 +268,7 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||||
? ((ValueType.Array) typeFilter).getItemType()
|
? ((ValueType.Array) typeFilter).getItemType()
|
||||||
: null;
|
: null;
|
||||||
arrayItemNode = new DependencyNode(dependencyAnalyzer, itemTypeFilter, degree + 1);
|
arrayItemNode = new DependencyNode(dependencyAnalyzer, itemTypeFilter, degree + 1);
|
||||||
|
arrayItemNode.method = method;
|
||||||
if (DependencyAnalyzer.shouldTag) {
|
if (DependencyAnalyzer.shouldTag) {
|
||||||
arrayItemNode.tag = tag + "[";
|
arrayItemNode.tag = tag + "[";
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,12 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodHandle;
|
import org.teavm.model.MethodHandle;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.RuntimeConstant;
|
import org.teavm.model.RuntimeConstant;
|
||||||
import org.teavm.model.emit.ValueEmitter;
|
import org.teavm.model.emit.ValueEmitter;
|
||||||
|
|
||||||
public class DynamicCallSite {
|
public class DynamicCallSite {
|
||||||
|
private MethodReference caller;
|
||||||
private MethodDescriptor calledMethod;
|
private MethodDescriptor calledMethod;
|
||||||
private ValueEmitter instance;
|
private ValueEmitter instance;
|
||||||
private List<ValueEmitter> arguments;
|
private List<ValueEmitter> arguments;
|
||||||
|
@ -31,8 +33,10 @@ public class DynamicCallSite {
|
||||||
private List<RuntimeConstant> bootstrapArguments;
|
private List<RuntimeConstant> bootstrapArguments;
|
||||||
private DependencyAgent agent;
|
private DependencyAgent agent;
|
||||||
|
|
||||||
DynamicCallSite(MethodDescriptor calledMethod, ValueEmitter instance, List<ValueEmitter> arguments,
|
DynamicCallSite(MethodReference caller, MethodDescriptor calledMethod, ValueEmitter instance,
|
||||||
MethodHandle bootstrapMethod, List<RuntimeConstant> bootstrapArguments, DependencyAgent agent) {
|
List<ValueEmitter> arguments, MethodHandle bootstrapMethod, List<RuntimeConstant> bootstrapArguments,
|
||||||
|
DependencyAgent agent) {
|
||||||
|
this.caller = caller;
|
||||||
this.calledMethod = calledMethod;
|
this.calledMethod = calledMethod;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.arguments = Collections.unmodifiableList(new ArrayList<>(arguments));
|
this.arguments = Collections.unmodifiableList(new ArrayList<>(arguments));
|
||||||
|
@ -41,6 +45,10 @@ public class DynamicCallSite {
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MethodReference getCaller() {
|
||||||
|
return caller;
|
||||||
|
}
|
||||||
|
|
||||||
public MethodDescriptor getCalledMethod() {
|
public MethodDescriptor getCalledMethod() {
|
||||||
return calledMethod;
|
return calledMethod;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user