From f160ce2f2fc6118792bbf867b8f88b5d1e384c82 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 29 Jun 2018 16:46:36 +0300 Subject: [PATCH] Use class/method names to generate lambda class names. Reduce number of types propagated by dependency analyzer --- .../lambda/LambdaMetafactorySubstitutor.java | 25 +++++++++++++------ .../codegen/DefaultAliasProvider.java | 11 ++++++++ .../teavm/dependency/DependencyAnalyzer.java | 2 +- .../dependency/DependencyGraphBuilder.java | 13 +++++++++- .../org/teavm/dependency/DependencyNode.java | 1 + .../org/teavm/dependency/DynamicCallSite.java | 12 +++++++-- 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/classlib/src/main/java/org/teavm/classlib/impl/lambda/LambdaMetafactorySubstitutor.java b/classlib/src/main/java/org/teavm/classlib/impl/lambda/LambdaMetafactorySubstitutor.java index a1dbbd0af..7d90f24cb 100644 --- a/classlib/src/main/java/org/teavm/classlib/impl/lambda/LambdaMetafactorySubstitutor.java +++ b/classlib/src/main/java/org/teavm/classlib/impl/lambda/LambdaMetafactorySubstitutor.java @@ -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 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("", signature); ctor.setLevel(AccessLevel.PUBLIC); ProgramEmitter pe = ProgramEmitter.create(ctor, classSource); + pe.setCurrentLocation(location); ValueEmitter thisVar = pe.var(0, implementor); thisVar.invokeSpecial(implementor.getParent(), ""); @@ -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) { diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultAliasProvider.java b/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultAliasProvider.java index 98d280e77..d4165ea2b 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultAliasProvider.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultAliasProvider.java @@ -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()); }); } diff --git a/core/src/main/java/org/teavm/dependency/DependencyAnalyzer.java b/core/src/main/java/org/teavm/dependency/DependencyAnalyzer.java index d7887ce49..a2efe9f6f 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyAnalyzer.java +++ b/core/src/main/java/org/teavm/dependency/DependencyAnalyzer.java @@ -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"); diff --git a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index bb1616369..040d59e81 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -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 arguments, InvocationType type) { diff --git a/core/src/main/java/org/teavm/dependency/DependencyNode.java b/core/src/main/java/org/teavm/dependency/DependencyNode.java index 1bb4d1b0a..fd1cc99fe 100644 --- a/core/src/main/java/org/teavm/dependency/DependencyNode.java +++ b/core/src/main/java/org/teavm/dependency/DependencyNode.java @@ -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 + "["; } diff --git a/core/src/main/java/org/teavm/dependency/DynamicCallSite.java b/core/src/main/java/org/teavm/dependency/DynamicCallSite.java index 7d6731b2b..17df3a916 100644 --- a/core/src/main/java/org/teavm/dependency/DynamicCallSite.java +++ b/core/src/main/java/org/teavm/dependency/DynamicCallSite.java @@ -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 arguments; @@ -31,8 +33,10 @@ public class DynamicCallSite { private List bootstrapArguments; private DependencyAgent agent; - DynamicCallSite(MethodDescriptor calledMethod, ValueEmitter instance, List arguments, - MethodHandle bootstrapMethod, List bootstrapArguments, DependencyAgent agent) { + DynamicCallSite(MethodReference caller, MethodDescriptor calledMethod, ValueEmitter instance, + List arguments, MethodHandle bootstrapMethod, List 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; }