JS: remove legacy way to generate names, fix issue with duplication of some top-level names in no-optimization mode

Fix #860
This commit is contained in:
Alexey Andreev 2023-11-23 17:22:03 +01:00
parent 997a31b683
commit 86efdb0809
18 changed files with 48 additions and 173 deletions

View File

@ -38,7 +38,6 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.teavm.ast.ControlFlowEntry;
import org.teavm.backend.javascript.codegen.AliasProvider;
import org.teavm.backend.javascript.codegen.DefaultAliasProvider;
import org.teavm.backend.javascript.codegen.DefaultNamingStrategy;
import org.teavm.backend.javascript.codegen.MinifyingAliasProvider;
@ -124,7 +123,6 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
private MethodNodeCache astCache = EmptyMethodNodeCache.INSTANCE;
private final Set<MethodReference> asyncMethods = new HashSet<>();
private List<VirtualMethodContributor> customVirtualMethods = new ArrayList<>();
private int topLevelNameLimit = 500000;
private boolean strict;
private BoundCheckInsertion boundCheckInsertion = new BoundCheckInsertion();
private NullCheckInsertion nullCheckInsertion = new NullCheckInsertion(NullCheckFilter.EMPTY);
@ -212,10 +210,6 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
this.debugEmitter = debugEmitter;
}
public void setTopLevelNameLimit(int topLevelNameLimit) {
this.topLevelNameLimit = topLevelNameLimit;
}
public void setStrict(boolean strict) {
this.strict = strict;
}
@ -352,9 +346,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
}
private void emit(ListableClassHolderSource classes, Writer writer, BuildTarget target) {
AliasProvider aliasProvider = obfuscated
? new MinifyingAliasProvider(topLevelNameLimit)
: new DefaultAliasProvider(topLevelNameLimit);
var aliasProvider = obfuscated ? new MinifyingAliasProvider() : new DefaultAliasProvider();
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, controller.getUnprocessedClassSource());
DebugInformationEmitter debugEmitterToUse = debugEmitter;
if (debugEmitterToUse == null) {
@ -426,10 +418,12 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
var epilogue = rememberingWriter.save();
rememberingWriter.clear();
if (renderingContext.isMinifying()) {
var frequencyEstimator = new NameFrequencyEstimator();
declarations.replay(frequencyEstimator, RememberedSource.FILTER_REF);
epilogue.replay(frequencyEstimator, RememberedSource.FILTER_REF);
frequencyEstimator.apply(naming);
}
var sourceWriter = builder.build(writer);
sourceWriter.setDebugInformationEmitter(debugEmitterToUse);

View File

@ -22,19 +22,17 @@ import org.teavm.model.MethodReference;
public interface AliasProvider {
String getFieldAlias(FieldReference field);
ScopedName getStaticFieldAlias(FieldReference field);
String getStaticFieldAlias(FieldReference field);
ScopedName getStaticMethodAlias(MethodReference method);
String getStaticMethodAlias(MethodReference method);
String getMethodAlias(MethodDescriptor method);
ScopedName getClassAlias(String className);
String getClassAlias(String className);
String getFunctionAlias(String name);
ScopedName getClassInitAlias(String className);
String getScopeAlias();
String getClassInitAlias(String className);
void reserveName(String name);
}

View File

@ -26,21 +26,14 @@ import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
public class DefaultAliasProvider implements AliasProvider {
private int topLevelAliasLimit;
private final Map<String, ScopedName> classAliases = new HashMap<>();
private final Map<String, String> classAliases = new HashMap<>();
private final Set<String> knownAliases = new HashSet<>(200, 0.5f);
private final ObjectIntMap<String> knowAliasesCounter = new ObjectIntHashMap<>();
private final Set<String> knownScopedAliases = new HashSet<>(200, 0.5f);
private final ObjectIntMap<String> knowScopedAliasesCounter = new ObjectIntHashMap<>();
private final Set<String> knownVirtualAliases = new HashSet<>(200, 0.5f);
private final ObjectIntMap<String> knowVirtualAliasesCounter = new ObjectIntHashMap<>();
public DefaultAliasProvider(int topLevelAliasLimit) {
this.topLevelAliasLimit = topLevelAliasLimit;
}
@Override
public ScopedName getClassAlias(String cls) {
public String getClassAlias(String cls) {
return classAliases.computeIfAbsent(cls, key -> makeUniqueTopLevel(suggestAliasForClass(key)));
}
@ -95,7 +88,7 @@ public class DefaultAliasProvider implements AliasProvider {
}
@Override
public ScopedName getStaticMethodAlias(MethodReference method) {
public String getStaticMethodAlias(MethodReference method) {
String suggested = method.getDescriptor().getName();
switch (suggested) {
case "<init>":
@ -106,7 +99,7 @@ public class DefaultAliasProvider implements AliasProvider {
break;
}
return makeUniqueTopLevel(getClassAlias(method.getClassName()).value + "_" + suggested);
return makeUniqueTopLevel(getClassAlias(method.getClassName()) + "_" + suggested);
}
@Override
@ -115,8 +108,8 @@ public class DefaultAliasProvider implements AliasProvider {
}
@Override
public ScopedName getStaticFieldAlias(FieldReference field) {
return makeUniqueTopLevel(getClassAlias(field.getClassName()).value + "_" + field.getFieldName());
public String getStaticFieldAlias(FieldReference field) {
return makeUniqueTopLevel(getClassAlias(field.getClassName()) + "_" + field.getFieldName());
}
@Override
@ -125,25 +118,16 @@ public class DefaultAliasProvider implements AliasProvider {
}
@Override
public ScopedName getClassInitAlias(String className) {
public String getClassInitAlias(String className) {
return makeUniqueTopLevel(suggestAliasForClass(className) + "_$callClinit");
}
@Override
public String getScopeAlias() {
return makeUnique(knownAliases, knowAliasesCounter, "$java");
}
@Override
public void reserveName(String name) {
}
private ScopedName makeUniqueTopLevel(String suggested) {
if (knownAliases.size() < topLevelAliasLimit) {
return new ScopedName(false, makeUnique(knownAliases, knowAliasesCounter, suggested));
} else {
return new ScopedName(true, makeUnique(knownScopedAliases, knowScopedAliasesCounter, suggested));
}
private String makeUniqueTopLevel(String suggested) {
return makeUnique(knownAliases, knowAliasesCounter, suggested);
}
private String sanitize(String s) {

View File

@ -33,13 +33,12 @@ public class DefaultNamingStrategy implements NamingStrategy {
private final AliasProvider aliasProvider;
private final ClassReaderSource classSource;
private final Map<MethodDescriptor, String> aliases = new HashMap<>();
private final Map<Key, ScopedName> privateAliases = new HashMap<>();
private final Map<String, ScopedName> classAliases = new HashMap<>();
private final Map<Key, String> privateAliases = new HashMap<>();
private final Map<String, String> classAliases = new HashMap<>();
private final Map<FieldReference, String> fieldAliases = new HashMap<>();
private final Map<FieldReference, ScopedName> staticFieldAliases = new HashMap<>();
private final Map<FieldReference, String> staticFieldAliases = new HashMap<>();
private final Map<String, String> functionAliases = new HashMap<>();
private final Map<String, ScopedName> classInitAliases = new HashMap<>();
private String scopeName;
private final Map<String, String> classInitAliases = new HashMap<>();
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) {
this.aliasProvider = aliasProvider;
@ -47,7 +46,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
}
@Override
public ScopedName getNameFor(String cls) {
public String getNameFor(String cls) {
return classAliases.computeIfAbsent(cls, key -> aliasProvider.getClassAlias(cls));
}
@ -62,16 +61,16 @@ public class DefaultNamingStrategy implements NamingStrategy {
}
@Override
public ScopedName getFullNameFor(MethodReference method) {
public String getFullNameFor(MethodReference method) {
return getFullNameFor(method, NO_CLASSIFIER);
}
@Override
public ScopedName getNameForInit(MethodReference method) {
public String getNameForInit(MethodReference method) {
return getFullNameFor(method, INIT_CLASSIFIER);
}
private ScopedName getFullNameFor(MethodReference method, byte classifier) {
private String getFullNameFor(MethodReference method, byte classifier) {
MethodReference originalMethod = method;
method = getRealMethod(method);
if (method == null) {
@ -98,8 +97,8 @@ public class DefaultNamingStrategy implements NamingStrategy {
}
@Override
public ScopedName getFullNameFor(FieldReference field) {
ScopedName alias = staticFieldAliases.get(field);
public String getFullNameFor(FieldReference field) {
var alias = staticFieldAliases.get(field);
if (alias == null) {
FieldReference realField = getRealField(field);
if (realField.equals(field)) {
@ -118,18 +117,10 @@ public class DefaultNamingStrategy implements NamingStrategy {
}
@Override
public ScopedName getNameForClassInit(String className) {
public String getNameForClassInit(String className) {
return classInitAliases.computeIfAbsent(className, key -> aliasProvider.getClassInitAlias(key));
}
@Override
public String getScopeName() {
if (scopeName == null) {
scopeName = aliasProvider.getScopeAlias();
}
return scopeName;
}
@Override
public void reserveName(String name) {
aliasProvider.reserveName(name);

View File

@ -23,19 +23,12 @@ import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
public class MinifyingAliasProvider implements AliasProvider {
private int topLevelAliasLimit;
private static final String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private static final String startVirtualLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private int lastSuffix;
private int lastScopedSuffix;
private int lastVirtual;
private final Set<String> usedAliases = new HashSet<>();
private final Set<String> usedVirtualAliases = new HashSet<>();
private final Set<String> usedScopedAliases = new HashSet<>();
public MinifyingAliasProvider(int topLevelAliasLimit) {
this.topLevelAliasLimit = topLevelAliasLimit;
}
@Override
public String getFieldAlias(FieldReference field) {
@ -47,12 +40,12 @@ public class MinifyingAliasProvider implements AliasProvider {
}
@Override
public ScopedName getStaticFieldAlias(FieldReference field) {
public String getStaticFieldAlias(FieldReference field) {
return createTopLevelName();
}
@Override
public ScopedName getStaticMethodAlias(MethodReference method) {
public String getStaticMethodAlias(MethodReference method) {
return createTopLevelName();
}
@ -66,7 +59,7 @@ public class MinifyingAliasProvider implements AliasProvider {
}
@Override
public ScopedName getClassAlias(String className) {
public String getClassAlias(String className) {
return createTopLevelName();
}
@ -76,37 +69,20 @@ public class MinifyingAliasProvider implements AliasProvider {
}
@Override
public ScopedName getClassInitAlias(String className) {
public String getClassInitAlias(String className) {
return createTopLevelName();
}
@Override
public String getScopeAlias() {
String result;
do {
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
return result;
}
@Override
public void reserveName(String name) {
usedAliases.add(name);
}
private ScopedName createTopLevelName() {
if (usedAliases.size() < topLevelAliasLimit) {
private String createTopLevelName() {
String result;
do {
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
return new ScopedName(false, result);
} else {
String result;
do {
result = RenderingUtil.indexToId(lastScopedSuffix++, startLetters);
} while (!usedScopedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
return new ScopedName(true, result);
}
return result;
}
}

View File

@ -20,23 +20,21 @@ import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
public interface NamingStrategy {
ScopedName getNameFor(String cls);
String getNameFor(String cls);
String getNameFor(MethodDescriptor method);
ScopedName getNameForInit(MethodReference method);
String getNameForInit(MethodReference method);
ScopedName getFullNameFor(MethodReference method);
String getFullNameFor(MethodReference method);
String getNameFor(FieldReference field);
ScopedName getFullNameFor(FieldReference method);
String getFullNameFor(FieldReference method);
String getNameForFunction(String name);
ScopedName getNameForClassInit(String className);
String getScopeName();
String getNameForClassInit(String className);
void reserveName(String name);
}

View File

@ -151,8 +151,8 @@ public class OutputSourceWriter extends SourceWriter implements LocationProvider
return appendName(naming.getNameForClassInit(className));
}
private SourceWriter appendName(ScopedName name) {
append(name.value);
private SourceWriter appendName(String name) {
append(name);
return this;
}

View File

@ -1,26 +0,0 @@
/*
* Copyright 2019 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.javascript.codegen;
public class ScopedName {
public final boolean scoped;
public final String value;
public ScopedName(boolean scoped, String value) {
this.scoped = scoped;
this.value = value;
}
}

View File

@ -240,15 +240,6 @@ public final class TeaVMRunner {
private void parseGenerationOptions() {
tool.setObfuscated(commandLine.hasOption("m"));
tool.setStrict(commandLine.hasOption("strict"));
if (commandLine.hasOption("max-toplevel-names")) {
try {
tool.setMaxTopLevelNames(Integer.parseInt(commandLine.getOptionValue("max-toplevel-names")));
} catch (NumberFormatException e) {
System.err.println("'--max-toplevel-names' must be integer number");
printUsage();
}
}
}
private void parseDebugOptions() {

View File

@ -76,7 +76,6 @@ public class TeaVMTool {
private String targetFileName = "";
private boolean obfuscated = true;
private boolean strict;
private int maxTopLevelNames = 1000000;
private String mainClass;
private String entryPointName = "main";
private Properties properties = new Properties();
@ -134,10 +133,6 @@ public class TeaVMTool {
this.strict = strict;
}
public void setMaxTopLevelNames(int maxTopLevelNames) {
this.maxTopLevelNames = maxTopLevelNames;
}
public boolean isIncremental() {
return incremental;
}
@ -324,7 +319,6 @@ public class TeaVMTool {
javaScriptTarget = new JavaScriptTarget();
javaScriptTarget.setObfuscated(obfuscated);
javaScriptTarget.setStrict(strict);
javaScriptTarget.setTopLevelNameLimit(maxTopLevelNames);
debugEmitter = debugInformationGenerated || sourceMapsFileGenerated
? new DebugInformationBuilder(referenceCache) : null;

View File

@ -56,8 +56,6 @@ public interface BuildStrategy {
void setStrict(boolean strict);
void setMaxTopLevelNames(int maxTopLevelNames);
void setProperties(Properties properties);
void setTransformers(String[] transformers);

View File

@ -53,7 +53,6 @@ public class InProcessBuildStrategy implements BuildStrategy {
private boolean fastDependencyAnalysis;
private boolean obfuscated;
private boolean strict;
private int maxTopLevelNames = 1000000;
private boolean sourceMapsFileGenerated;
private boolean debugInformationGenerated;
private boolean sourceFilesCopied;
@ -157,11 +156,6 @@ public class InProcessBuildStrategy implements BuildStrategy {
this.strict = strict;
}
@Override
public void setMaxTopLevelNames(int maxTopLevelNames) {
this.maxTopLevelNames = maxTopLevelNames;
}
@Override
public void setTransformers(String[] transformers) {
this.transformers = transformers.clone();
@ -243,7 +237,6 @@ public class InProcessBuildStrategy implements BuildStrategy {
tool.setObfuscated(obfuscated);
tool.setStrict(strict);
tool.setMaxTopLevelNames(maxTopLevelNames);
tool.setIncremental(incremental);
tool.getTransformers().addAll(Arrays.asList(transformers));
tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));

View File

@ -134,11 +134,6 @@ public class RemoteBuildStrategy implements BuildStrategy {
request.strict = strict;
}
@Override
public void setMaxTopLevelNames(int maxTopLevelNames) {
request.maxTopLevelNames = maxTopLevelNames;
}
@Override
public void setTransformers(String[] transformers) {
request.transformers = transformers.clone();

View File

@ -156,7 +156,6 @@ public class BuildDaemon extends UnicastRemoteObject implements RemoteBuildServi
tool.setFastDependencyAnalysis(request.fastDependencyAnalysis);
tool.setObfuscated(request.obfuscated);
tool.setStrict(request.strict);
tool.setMaxTopLevelNames(request.maxTopLevelNames);
tool.setWasmVersion(request.wasmVersion);
tool.setMinHeapSize(request.minHeapSize);
tool.setMaxHeapSize(request.maxHeapSize);

View File

@ -41,7 +41,6 @@ public class RemoteBuildRequest implements Serializable {
public String cacheDirectory;
public boolean obfuscated;
public boolean strict;
public int maxTopLevelNames = 1000000;
public Properties properties;
public TeaVMOptimizationLevel optimizationLevel;
public boolean fastDependencyAnalysis;

View File

@ -829,7 +829,6 @@ public class CodeServlet extends HttpServlet {
jsTarget.setObfuscated(false);
jsTarget.setAstCache(astCache);
jsTarget.setDebugEmitter(debugInformationBuilder);
jsTarget.setTopLevelNameLimit(2000);
jsTarget.setStrict(true);
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
vm.setCacheStatus(classSource);

View File

@ -18,7 +18,6 @@ package org.teavm.gradle.tasks;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
import org.teavm.gradle.api.OptimizationLevel;
import org.teavm.tooling.TeaVMTargetType;
import org.teavm.tooling.builder.BuildStrategy;
@ -53,8 +52,5 @@ public abstract class GenerateJavaScriptTask extends TeaVMTask {
builder.setStrict(getStrict().get());
builder.setSourceMapsFileGenerated(getSourceMap().get());
builder.setEntryPointName(getEntryPointName().get());
if (getOptimization().get() == OptimizationLevel.NONE) {
builder.setMaxTopLevelNames(1000);
}
}
}

View File

@ -82,9 +82,6 @@ public class TeaVMCompileMojo extends AbstractMojo {
@Parameter(property = "teavm.strict", defaultValue = "false")
private boolean strict;
@Parameter(property = "teavm.maxTopLevelNames", defaultValue = "10000")
private int maxTopLevelNames = 10000;
@Parameter
private Properties properties;
@ -166,7 +163,6 @@ public class TeaVMCompileMojo extends AbstractMojo {
builder.setClassPathEntries(prepareClassPath());
builder.setObfuscated(minifying);
builder.setStrict(strict);
builder.setMaxTopLevelNames(maxTopLevelNames);
builder.setTargetDirectory(targetDirectory.getAbsolutePath());
if (transformers != null) {
builder.setTransformers(transformers);