mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.cache.NoCache;
|
||||
import org.teavm.dependency.BootstrapMethodSubstitutor;
|
||||
import org.teavm.dependency.DynamicCallSite;
|
||||
|
@ -29,6 +31,7 @@ import org.teavm.model.FieldHolder;
|
|||
import org.teavm.model.MethodHandle;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.PrimitiveType;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.emit.ProgramEmitter;
|
||||
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_MARKERS = 2;
|
||||
private static final int FLAG_BRIDGES = 4;
|
||||
private int lambdaIndex;
|
||||
private Map<String, Integer> lambdaIdsByMethod = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public ValueEmitter substitute(DynamicCallSite callSite, ProgramEmitter callerPe) {
|
||||
|
@ -50,7 +53,11 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
|||
ClassReaderSource classSource = callSite.getAgent().getClassSource();
|
||||
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);
|
||||
if (samClass != null && samClass.hasModifier(ElementModifier.INTERFACE)) {
|
||||
implementor.setParent("java.lang.Object");
|
||||
|
@ -61,15 +68,16 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
|||
|
||||
int capturedVarCount = callSite.getCalledMethod().parameterCount();
|
||||
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()));
|
||||
createBridge(classSource, implementor, callSite.getCalledMethod().getName(), instantiatedMethodType,
|
||||
samMethodType);
|
||||
samMethodType, callerPe.getCurrentLocation());
|
||||
|
||||
MethodHolder worker = new MethodHolder(callSite.getCalledMethod().getName(), instantiatedMethodType);
|
||||
worker.getAnnotations().add(new AnnotationHolder(NoCache.class.getName()));
|
||||
worker.setLevel(AccessLevel.PUBLIC);
|
||||
ProgramEmitter pe = ProgramEmitter.create(worker, callSite.getAgent().getClassSource());
|
||||
pe.setCurrentLocation(callerPe.getCurrentLocation());
|
||||
ValueEmitter thisVar = pe.var(0, implementor);
|
||||
ValueEmitter[] arguments = new ValueEmitter[instantiatedMethodType.length - 1];
|
||||
for (int i = 0; i < arguments.length; ++i) {
|
||||
|
@ -119,7 +127,7 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
|||
for (int i = 0; i < bridgeCount; ++i) {
|
||||
ValueType[] bridgeType = callSite.getBootstrapArguments().get(bootstrapArgIndex++).getMethodType();
|
||||
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);
|
||||
signature[types.length] = ValueType.VOID;
|
||||
MethodHolder ctor = new MethodHolder("<init>", signature);
|
||||
ctor.setLevel(AccessLevel.PUBLIC);
|
||||
|
||||
ProgramEmitter pe = ProgramEmitter.create(ctor, classSource);
|
||||
pe.setCurrentLocation(location);
|
||||
ValueEmitter thisVar = pe.var(0, implementor);
|
||||
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,
|
||||
ValueType[] bridgeTypes) {
|
||||
ValueType[] bridgeTypes, TextLocation location) {
|
||||
if (Arrays.equals(types, bridgeTypes)) {
|
||||
return;
|
||||
}
|
||||
|
@ -293,6 +303,7 @@ public class LambdaMetafactorySubstitutor implements BootstrapMethodSubstitutor
|
|||
bridge.setLevel(AccessLevel.PUBLIC);
|
||||
bridge.getModifiers().add(ElementModifier.BRIDGE);
|
||||
ProgramEmitter pe = ProgramEmitter.create(bridge, classSource);
|
||||
pe.setCurrentLocation(location);
|
||||
ValueEmitter thisVar = pe.var(0, implementor);
|
||||
ValueEmitter[] arguments = new ValueEmitter[bridgeTypes.length - 1];
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@ public class DependencyAnalyzer implements DependencyInfo {
|
|||
if (methodRef.getDescriptor().getResultType() == ValueType.VOID) {
|
||||
resultNode = null;
|
||||
} else {
|
||||
resultNode = createNode();
|
||||
resultNode = createNode(methodRef.getDescriptor().getResultType());
|
||||
resultNode.method = methodRef;
|
||||
if (shouldTag) {
|
||||
resultNode.setTag(methodRef + ":RESULT");
|
||||
|
|
|
@ -242,7 +242,8 @@ class DependencyGraphBuilder {
|
|||
for (int k = 0; k < indy.getArguments().size(); ++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(),
|
||||
ValueType.object(methodDep.getMethod().getOwnerName())) : null,
|
||||
arguments, indy.getBootstrapMethod(), indy.getBootstrapArguments(),
|
||||
|
@ -579,6 +580,9 @@ class DependencyGraphBuilder {
|
|||
@Override
|
||||
public void getElement(VariableReader receiver, VariableReader array, VariableReader index,
|
||||
ArrayElementType type) {
|
||||
if (isPrimitive(type)) {
|
||||
return;
|
||||
}
|
||||
DependencyNode arrayNode = nodes[array.getIndex()];
|
||||
DependencyNode receiverNode = nodes[receiver.getIndex()];
|
||||
if (arrayNode != null && receiverNode != null && receiverNode != arrayNode.getArrayItem()) {
|
||||
|
@ -589,6 +593,9 @@ class DependencyGraphBuilder {
|
|||
@Override
|
||||
public void putElement(VariableReader array, VariableReader index, VariableReader value,
|
||||
ArrayElementType type) {
|
||||
if (isPrimitive(type)) {
|
||||
return;
|
||||
}
|
||||
DependencyNode valueNode = nodes[value.getIndex()];
|
||||
DependencyNode arrayNode = nodes[array.getIndex()];
|
||||
if (valueNode != null && arrayNode != null && valueNode != arrayNode.getArrayItem()) {
|
||||
|
@ -596,6 +603,10 @@ class DependencyGraphBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private boolean isPrimitive(ArrayElementType type) {
|
||||
return type != ArrayElementType.OBJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(VariableReader receiver, VariableReader instance, MethodReference method,
|
||||
List<? extends VariableReader> arguments, InvocationType type) {
|
||||
|
|
|
@ -268,6 +268,7 @@ public class DependencyNode implements ValueDependencyInfo {
|
|||
? ((ValueType.Array) typeFilter).getItemType()
|
||||
: null;
|
||||
arrayItemNode = new DependencyNode(dependencyAnalyzer, itemTypeFilter, degree + 1);
|
||||
arrayItemNode.method = method;
|
||||
if (DependencyAnalyzer.shouldTag) {
|
||||
arrayItemNode.tag = tag + "[";
|
||||
}
|
||||
|
|
|
@ -20,10 +20,12 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodHandle;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.RuntimeConstant;
|
||||
import org.teavm.model.emit.ValueEmitter;
|
||||
|
||||
public class DynamicCallSite {
|
||||
private MethodReference caller;
|
||||
private MethodDescriptor calledMethod;
|
||||
private ValueEmitter instance;
|
||||
private List<ValueEmitter> arguments;
|
||||
|
@ -31,8 +33,10 @@ public class DynamicCallSite {
|
|||
private List<RuntimeConstant> bootstrapArguments;
|
||||
private DependencyAgent agent;
|
||||
|
||||
DynamicCallSite(MethodDescriptor calledMethod, ValueEmitter instance, List<ValueEmitter> arguments,
|
||||
MethodHandle bootstrapMethod, List<RuntimeConstant> bootstrapArguments, DependencyAgent agent) {
|
||||
DynamicCallSite(MethodReference caller, MethodDescriptor calledMethod, ValueEmitter instance,
|
||||
List<ValueEmitter> arguments, MethodHandle bootstrapMethod, List<RuntimeConstant> bootstrapArguments,
|
||||
DependencyAgent agent) {
|
||||
this.caller = caller;
|
||||
this.calledMethod = calledMethod;
|
||||
this.instance = instance;
|
||||
this.arguments = Collections.unmodifiableList(new ArrayList<>(arguments));
|
||||
|
@ -41,6 +45,10 @@ public class DynamicCallSite {
|
|||
this.agent = agent;
|
||||
}
|
||||
|
||||
public MethodReference getCaller() {
|
||||
return caller;
|
||||
}
|
||||
|
||||
public MethodDescriptor getCalledMethod() {
|
||||
return calledMethod;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user