mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
JS: add ability to set limit for top-level names.
The purpose of this option is JS engines are too sensible for number of methods in closure, while they don't care about methods in an object.
This commit is contained in:
parent
1214534671
commit
ce13c05342
|
@ -179,6 +179,8 @@ public class ClassGenerator {
|
||||||
tryUsingGenerator(method);
|
tryUsingGenerator(method);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
} else if (method.getProgram() == null) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateMethodForwardDeclaration(method);
|
generateMethodForwardDeclaration(method);
|
||||||
|
|
|
@ -119,7 +119,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
|
private final Set<MethodReference> asyncFamilyMethods = new HashSet<>();
|
||||||
private ClassInitializerInsertionTransformer clinitInsertionTransformer;
|
private ClassInitializerInsertionTransformer clinitInsertionTransformer;
|
||||||
private List<VirtualMethodContributor> customVirtualMethods = new ArrayList<>();
|
private List<VirtualMethodContributor> customVirtualMethods = new ArrayList<>();
|
||||||
private boolean classScoped;
|
private int topLevelNameLimit = 10000;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClassHolderTransformer> getTransformers() {
|
public List<ClassHolderTransformer> getTransformers() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -197,8 +198,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
this.debugEmitter = debugEmitter;
|
this.debugEmitter = debugEmitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClassScoped(boolean classScoped) {
|
public void setTopLevelNameLimit(int topLevelNameLimit) {
|
||||||
this.classScoped = classScoped;
|
this.topLevelNameLimit = topLevelNameLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -324,11 +325,12 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AliasProvider aliasProvider = minifying ? new MinifyingAliasProvider() : new DefaultAliasProvider();
|
AliasProvider aliasProvider = minifying
|
||||||
|
? new MinifyingAliasProvider(topLevelNameLimit)
|
||||||
|
: new DefaultAliasProvider(topLevelNameLimit);
|
||||||
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, controller.getUnprocessedClassSource());
|
DefaultNamingStrategy naming = new DefaultNamingStrategy(aliasProvider, controller.getUnprocessedClassSource());
|
||||||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||||
builder.setMinified(minifying);
|
builder.setMinified(minifying);
|
||||||
builder.setClassScoped(classScoped);
|
|
||||||
SourceWriter sourceWriter = builder.build(writer);
|
SourceWriter sourceWriter = builder.build(writer);
|
||||||
|
|
||||||
DebugInformationEmitter debugEmitterToUse = debugEmitter;
|
DebugInformationEmitter debugEmitterToUse = debugEmitter;
|
||||||
|
@ -343,8 +345,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
controller.getDependencyInfo(), m -> isVirtual(virtualMethodContributorContext, m));
|
controller.getDependencyInfo(), m -> isVirtual(virtualMethodContributorContext, m));
|
||||||
renderingContext.setMinifying(minifying);
|
renderingContext.setMinifying(minifying);
|
||||||
Renderer renderer = new Renderer(sourceWriter, asyncMethods, asyncFamilyMethods,
|
Renderer renderer = new Renderer(sourceWriter, asyncMethods, asyncFamilyMethods,
|
||||||
controller.getDiagnostics(), renderingContext, classScoped);
|
controller.getDiagnostics(), renderingContext);
|
||||||
RuntimeRenderer runtimeRenderer = new RuntimeRenderer(classes, naming, sourceWriter);
|
RuntimeRenderer runtimeRenderer = new RuntimeRenderer(classes, sourceWriter);
|
||||||
renderer.setProperties(controller.getProperties());
|
renderer.setProperties(controller.getProperties());
|
||||||
renderer.setMinifying(minifying);
|
renderer.setMinifying(minifying);
|
||||||
renderer.setProgressConsumer(controller::reportProgress);
|
renderer.setProgressConsumer(controller::reportProgress);
|
||||||
|
@ -381,10 +383,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
|
|
||||||
renderer.prepare(clsNodes);
|
renderer.prepare(clsNodes);
|
||||||
runtimeRenderer.renderRuntime();
|
runtimeRenderer.renderRuntime();
|
||||||
if (classScoped) {
|
sourceWriter.append("var ").append(renderer.getNaming().getScopeName()).ws().append("=").ws()
|
||||||
sourceWriter.append("var ").append(Renderer.CONTAINER_OBJECT).ws().append("=").ws()
|
.append("Object.create(null);").newLine();
|
||||||
.append("Object.create(null);").newLine();
|
|
||||||
}
|
|
||||||
if (!renderer.render(clsNodes)) {
|
if (!renderer.render(clsNodes)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
int totalSize = sourceWriter.getOffset() - start;
|
int totalSize = sourceWriter.getOffset() - start;
|
||||||
printStats(renderer, totalSize);
|
printStats(renderer, totalSize);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RenderingException("IO Error occured", e);
|
throw new RenderingException("IO Error occurred", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,15 +22,17 @@ import org.teavm.model.MethodReference;
|
||||||
public interface AliasProvider {
|
public interface AliasProvider {
|
||||||
String getFieldAlias(FieldReference field);
|
String getFieldAlias(FieldReference field);
|
||||||
|
|
||||||
String getStaticFieldAlias(FieldReference field);
|
ScopedName getStaticFieldAlias(FieldReference field);
|
||||||
|
|
||||||
String getStaticMethodAlias(MethodReference method);
|
ScopedName getStaticMethodAlias(MethodReference method);
|
||||||
|
|
||||||
String getMethodAlias(MethodDescriptor method);
|
String getMethodAlias(MethodDescriptor method);
|
||||||
|
|
||||||
String getClassAlias(String className);
|
ScopedName getClassAlias(String className);
|
||||||
|
|
||||||
String getFunctionAlias(String name);
|
String getFunctionAlias(String name);
|
||||||
|
|
||||||
String getClassInitAlias(String className);
|
ScopedName getClassInitAlias(String className);
|
||||||
|
|
||||||
|
String getScopeAlias();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,16 +26,22 @@ import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public class DefaultAliasProvider implements AliasProvider {
|
public class DefaultAliasProvider implements AliasProvider {
|
||||||
private final Map<String, String> classAliases = new HashMap<>();
|
int topLevelAliasLimit;
|
||||||
|
private final Map<String, ScopedName> classAliases = new HashMap<>();
|
||||||
private final Set<String> knownAliases = new HashSet<>(200, 0.5f);
|
private final Set<String> knownAliases = new HashSet<>(200, 0.5f);
|
||||||
private final ObjectIntMap<String> knowAliasesCounter = new ObjectIntHashMap<>();
|
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 Set<String> knownVirtualAliases = new HashSet<>(200, 0.5f);
|
||||||
private final ObjectIntMap<String> knowVirtualAliasesCounter = new ObjectIntHashMap<>();
|
private final ObjectIntMap<String> knowVirtualAliasesCounter = new ObjectIntHashMap<>();
|
||||||
|
|
||||||
|
public DefaultAliasProvider(int topLevelAliasLimit) {
|
||||||
|
this.topLevelAliasLimit = topLevelAliasLimit;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClassAlias(String cls) {
|
public ScopedName getClassAlias(String cls) {
|
||||||
return classAliases.computeIfAbsent(cls, key -> makeUnique(knownAliases, knowAliasesCounter,
|
return classAliases.computeIfAbsent(cls, key -> makeUniqueTopLevel(suggestAliasForClass(key)));
|
||||||
suggestAliasForClass(key)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String suggestAliasForClass(String cls) {
|
private static String suggestAliasForClass(String cls) {
|
||||||
|
@ -89,18 +95,18 @@ public class DefaultAliasProvider implements AliasProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStaticMethodAlias(MethodReference method) {
|
public ScopedName getStaticMethodAlias(MethodReference method) {
|
||||||
String alias = method.getDescriptor().getName();
|
String suggested = method.getDescriptor().getName();
|
||||||
switch (alias) {
|
switch (suggested) {
|
||||||
case "<init>":
|
case "<init>":
|
||||||
alias = "_init_";
|
suggested = "_init_";
|
||||||
break;
|
break;
|
||||||
case "<clinit>":
|
case "<clinit>":
|
||||||
alias = "_clinit_";
|
suggested = "_clinit_";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeUnique(knownAliases, knowAliasesCounter, getClassAlias(method.getClassName()) + "_" + alias);
|
return makeUniqueTopLevel(getClassAlias(method.getClassName()).value + "_" + suggested);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,9 +115,8 @@ public class DefaultAliasProvider implements AliasProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStaticFieldAlias(FieldReference field) {
|
public ScopedName getStaticFieldAlias(FieldReference field) {
|
||||||
return makeUnique(knownAliases, knowAliasesCounter,
|
return makeUniqueTopLevel(getClassAlias(field.getClassName()).value + "_" + field.getFieldName());
|
||||||
getClassAlias(field.getClassName()) + "_" + field.getFieldName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,8 +125,21 @@ public class DefaultAliasProvider implements AliasProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClassInitAlias(String className) {
|
public ScopedName getClassInitAlias(String className) {
|
||||||
return makeUnique(knownAliases, knowAliasesCounter, suggestAliasForClass(className) + "_$callClinit");
|
return makeUniqueTopLevel(suggestAliasForClass(className) + "_$callClinit");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getScopeAlias() {
|
||||||
|
return makeUnique(knownAliases, knowAliasesCounter, "$java");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 makeUnique(Set<String> knowAliases, ObjectIntMap<String> indexMap, String alias) {
|
private String makeUnique(Set<String> knowAliases, ObjectIntMap<String> indexMap, String alias) {
|
||||||
|
|
|
@ -23,12 +23,13 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
private final AliasProvider aliasProvider;
|
private final AliasProvider aliasProvider;
|
||||||
private final ClassReaderSource classSource;
|
private final ClassReaderSource classSource;
|
||||||
private final Map<String, String> aliases = new HashMap<>();
|
private final Map<String, String> aliases = new HashMap<>();
|
||||||
private final Map<String, String> privateAliases = new HashMap<>();
|
private final Map<String, ScopedName> privateAliases = new HashMap<>();
|
||||||
private final Map<String, String> classAliases = new HashMap<>();
|
private final Map<String, ScopedName> classAliases = new HashMap<>();
|
||||||
private final Map<FieldReference, String> fieldAliases = new HashMap<>();
|
private final Map<FieldReference, String> fieldAliases = new HashMap<>();
|
||||||
private final Map<FieldReference, String> staticFieldAliases = new HashMap<>();
|
private final Map<FieldReference, ScopedName> staticFieldAliases = new HashMap<>();
|
||||||
private final Map<String, String> functionAliases = new HashMap<>();
|
private final Map<String, String> functionAliases = new HashMap<>();
|
||||||
private final Map<String, String> classInitAliases = new HashMap<>();
|
private final Map<String, ScopedName> classInitAliases = new HashMap<>();
|
||||||
|
private String scopeName;
|
||||||
|
|
||||||
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) {
|
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) {
|
||||||
this.aliasProvider = aliasProvider;
|
this.aliasProvider = aliasProvider;
|
||||||
|
@ -36,7 +37,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNameFor(String cls) {
|
public ScopedName getNameFor(String cls) {
|
||||||
return classAliases.computeIfAbsent(cls, key -> aliasProvider.getClassAlias(cls));
|
return classAliases.computeIfAbsent(cls, key -> aliasProvider.getClassAlias(cls));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,16 +53,16 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFullNameFor(MethodReference method) {
|
public ScopedName getFullNameFor(MethodReference method) {
|
||||||
return getFullNameFor(method, 'M');
|
return getFullNameFor(method, 'M');
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNameForInit(MethodReference method) {
|
public ScopedName getNameForInit(MethodReference method) {
|
||||||
return getFullNameFor(method, 'I');
|
return getFullNameFor(method, 'I');
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFullNameFor(MethodReference method, char classifier) {
|
private ScopedName getFullNameFor(MethodReference method, char classifier) {
|
||||||
MethodReference originalMethod = method;
|
MethodReference originalMethod = method;
|
||||||
method = getRealMethod(method);
|
method = getRealMethod(method);
|
||||||
if (method == null) {
|
if (method == null) {
|
||||||
|
@ -89,14 +90,14 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getFullNameFor(FieldReference field) {
|
public ScopedName getFullNameFor(FieldReference field) {
|
||||||
String alias = staticFieldAliases.get(field);
|
ScopedName alias = staticFieldAliases.get(field);
|
||||||
if (alias == null) {
|
if (alias == null) {
|
||||||
FieldReference realField = getRealField(field);
|
FieldReference realField = getRealField(field);
|
||||||
if (realField.equals(field)) {
|
if (realField.equals(field)) {
|
||||||
alias = aliasProvider.getStaticFieldAlias(realField);
|
alias = aliasProvider.getStaticFieldAlias(realField);
|
||||||
} else {
|
} else {
|
||||||
alias = getNameFor(realField);
|
alias = getFullNameFor(realField);
|
||||||
}
|
}
|
||||||
staticFieldAliases.put(field, alias);
|
staticFieldAliases.put(field, alias);
|
||||||
}
|
}
|
||||||
|
@ -109,10 +110,18 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNameForClassInit(String className) {
|
public ScopedName getNameForClassInit(String className) {
|
||||||
return classInitAliases.computeIfAbsent(className, key -> aliasProvider.getClassInitAlias(key));
|
return classInitAliases.computeIfAbsent(className, key -> aliasProvider.getClassInitAlias(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getScopeName() {
|
||||||
|
if (scopeName == null) {
|
||||||
|
scopeName = aliasProvider.getScopeAlias();
|
||||||
|
}
|
||||||
|
return scopeName;
|
||||||
|
}
|
||||||
|
|
||||||
private MethodReference getRealMethod(MethodReference methodRef) {
|
private MethodReference getRealMethod(MethodReference methodRef) {
|
||||||
String className = methodRef.getClassName();
|
String className = methodRef.getClassName();
|
||||||
while (className != null) {
|
while (className != null) {
|
||||||
|
@ -133,7 +142,6 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldReference getRealField(FieldReference fieldRef) {
|
private FieldReference getRealField(FieldReference fieldRef) {
|
||||||
String initialCls = fieldRef.getClassName();
|
|
||||||
String cls = fieldRef.getClassName();
|
String cls = fieldRef.getClassName();
|
||||||
while (cls != null) {
|
while (cls != null) {
|
||||||
ClassReader clsReader = classSource.get(cls);
|
ClassReader clsReader = classSource.get(cls);
|
||||||
|
|
|
@ -23,37 +23,37 @@ import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public class MinifyingAliasProvider implements AliasProvider {
|
public class MinifyingAliasProvider implements AliasProvider {
|
||||||
|
private int topLevelAliasLimit;
|
||||||
private static final String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
private static final String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
private static final String startVirtualLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
private static final String startVirtualLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
private int lastSuffix;
|
private int lastSuffix;
|
||||||
|
private int lastScopedSuffix;
|
||||||
private int lastVirtual;
|
private int lastVirtual;
|
||||||
private final Set<String> usedAliases = new HashSet<>();
|
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
|
@Override
|
||||||
public String getFieldAlias(FieldReference field) {
|
public String getFieldAlias(FieldReference field) {
|
||||||
String result;
|
String result;
|
||||||
do {
|
do {
|
||||||
result = RenderingUtil.indexToId(lastVirtual++, startVirtualLetters);
|
result = RenderingUtil.indexToId(lastVirtual++, startVirtualLetters);
|
||||||
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
} while (!usedVirtualAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStaticFieldAlias(FieldReference field) {
|
public ScopedName getStaticFieldAlias(FieldReference field) {
|
||||||
String result;
|
return createTopLevelName();
|
||||||
do {
|
|
||||||
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
|
|
||||||
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getStaticMethodAlias(MethodReference method) {
|
public ScopedName getStaticMethodAlias(MethodReference method) {
|
||||||
String result;
|
return createTopLevelName();
|
||||||
do {
|
|
||||||
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
|
|
||||||
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,17 +61,13 @@ public class MinifyingAliasProvider implements AliasProvider {
|
||||||
String result;
|
String result;
|
||||||
do {
|
do {
|
||||||
result = RenderingUtil.indexToId(lastVirtual++, startVirtualLetters);
|
result = RenderingUtil.indexToId(lastVirtual++, startVirtualLetters);
|
||||||
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
} while (!usedVirtualAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClassAlias(String className) {
|
public ScopedName getClassAlias(String className) {
|
||||||
String result;
|
return createTopLevelName();
|
||||||
do {
|
|
||||||
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
|
|
||||||
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,11 +76,32 @@ public class MinifyingAliasProvider implements AliasProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getClassInitAlias(String className) {
|
public ScopedName getClassInitAlias(String className) {
|
||||||
|
return createTopLevelName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getScopeAlias() {
|
||||||
String result;
|
String result;
|
||||||
do {
|
do {
|
||||||
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
|
result = RenderingUtil.indexToId(lastSuffix++, startLetters);
|
||||||
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
} while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ScopedName createTopLevelName() {
|
||||||
|
if (usedAliases.size() < topLevelAliasLimit) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,19 +20,21 @@ import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
public interface NamingStrategy {
|
public interface NamingStrategy {
|
||||||
String getNameFor(String cls);
|
ScopedName getNameFor(String cls);
|
||||||
|
|
||||||
String getNameFor(MethodDescriptor method);
|
String getNameFor(MethodDescriptor method);
|
||||||
|
|
||||||
String getNameForInit(MethodReference method);
|
ScopedName getNameForInit(MethodReference method);
|
||||||
|
|
||||||
String getFullNameFor(MethodReference method);
|
ScopedName getFullNameFor(MethodReference method);
|
||||||
|
|
||||||
String getNameFor(FieldReference field);
|
String getNameFor(FieldReference field);
|
||||||
|
|
||||||
String getFullNameFor(FieldReference method);
|
ScopedName getFullNameFor(FieldReference method);
|
||||||
|
|
||||||
String getNameForFunction(String name);
|
String getNameForFunction(String name);
|
||||||
|
|
||||||
String getNameForClassInit(String className);
|
ScopedName getNameForClassInit(String className);
|
||||||
|
|
||||||
|
String getScopeName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,6 @@
|
||||||
package org.teavm.backend.javascript.codegen;
|
package org.teavm.backend.javascript.codegen;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.teavm.backend.javascript.rendering.Renderer;
|
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -32,13 +31,11 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
private int column;
|
private int column;
|
||||||
private int line;
|
private int line;
|
||||||
private int offset;
|
private int offset;
|
||||||
private boolean classScoped;
|
|
||||||
|
|
||||||
SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth, boolean classScoped) {
|
SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
this.innerWriter = innerWriter;
|
this.innerWriter = innerWriter;
|
||||||
this.lineWidth = lineWidth;
|
this.lineWidth = lineWidth;
|
||||||
this.classScoped = classScoped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMinified(boolean minified) {
|
void setMinified(boolean minified) {
|
||||||
|
@ -50,10 +47,6 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(Object value) throws IOException {
|
|
||||||
return append(String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter append(int value) throws IOException {
|
public SourceWriter append(int value) throws IOException {
|
||||||
return append(String.valueOf(value));
|
return append(String.valueOf(value));
|
||||||
}
|
}
|
||||||
|
@ -102,8 +95,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) throws IOException {
|
public SourceWriter appendClass(String cls) throws IOException {
|
||||||
appendScopeIfNecessary();
|
return appendName(naming.getNameFor(cls));
|
||||||
return append(naming.getNameFor(cls));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(Class<?> cls) throws IOException {
|
public SourceWriter appendClass(Class<?> cls) throws IOException {
|
||||||
|
@ -115,8 +107,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendStaticField(FieldReference field) throws IOException {
|
public SourceWriter appendStaticField(FieldReference field) throws IOException {
|
||||||
appendScopeIfNecessary();
|
return appendName(naming.getFullNameFor(field));
|
||||||
return append(naming.getFullNameFor(field));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethod(MethodDescriptor method) throws IOException {
|
public SourceWriter appendMethod(MethodDescriptor method) throws IOException {
|
||||||
|
@ -128,8 +119,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethodBody(MethodReference method) throws IOException {
|
public SourceWriter appendMethodBody(MethodReference method) throws IOException {
|
||||||
appendScopeIfNecessary();
|
return appendName(naming.getFullNameFor(method));
|
||||||
return append(naming.getFullNameFor(method));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethodBody(String className, String name, ValueType... params) throws IOException {
|
public SourceWriter appendMethodBody(String className, String name, ValueType... params) throws IOException {
|
||||||
|
@ -145,19 +135,19 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendInit(MethodReference method) throws IOException {
|
public SourceWriter appendInit(MethodReference method) throws IOException {
|
||||||
appendScopeIfNecessary();
|
return appendName(naming.getNameForInit(method));
|
||||||
return append(naming.getNameForInit(method));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClassInit(String className) throws IOException {
|
public SourceWriter appendClassInit(String className) throws IOException {
|
||||||
appendScopeIfNecessary();
|
return appendName(naming.getNameForClassInit(className));
|
||||||
return append(naming.getNameForClassInit(className));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendScopeIfNecessary() throws IOException {
|
private SourceWriter appendName(ScopedName name) throws IOException {
|
||||||
if (classScoped) {
|
if (name.scoped) {
|
||||||
append(Renderer.CONTAINER_OBJECT).append(".");
|
append(naming.getScopeName()).append(".");
|
||||||
}
|
}
|
||||||
|
append(name.value);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendIndent() throws IOException {
|
private void appendIndent() throws IOException {
|
||||||
|
|
|
@ -18,7 +18,6 @@ package org.teavm.backend.javascript.codegen;
|
||||||
public class SourceWriterBuilder {
|
public class SourceWriterBuilder {
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private boolean minified;
|
private boolean minified;
|
||||||
private boolean classScoped;
|
|
||||||
private int lineWidth = 512;
|
private int lineWidth = 512;
|
||||||
|
|
||||||
public SourceWriterBuilder(NamingStrategy naming) {
|
public SourceWriterBuilder(NamingStrategy naming) {
|
||||||
|
@ -37,12 +36,8 @@ public class SourceWriterBuilder {
|
||||||
this.lineWidth = lineWidth;
|
this.lineWidth = lineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClassScoped(boolean classScoped) {
|
|
||||||
this.classScoped = classScoped;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SourceWriter build(Appendable innerWriter) {
|
public SourceWriter build(Appendable innerWriter) {
|
||||||
SourceWriter writer = new SourceWriter(naming, innerWriter, lineWidth, classScoped);
|
SourceWriter writer = new SourceWriter(naming, innerWriter, lineWidth);
|
||||||
writer.setMinified(minified);
|
writer.setMinified(minified);
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -700,7 +700,7 @@ public class AstWriter {
|
||||||
writer.append("let").ws().append('(');
|
writer.append("let").ws().append('(');
|
||||||
printList(node.getVariables().getVariables());
|
printList(node.getVariables().getVariables());
|
||||||
writer.append(')');
|
writer.append(')');
|
||||||
writer.append(node.getBody());
|
print(node.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void print(ParenthesizedExpression node, int precedence) throws IOException {
|
private void print(ParenthesizedExpression node, int precedence) throws IOException {
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.teavm.ast.RegularMethodNode;
|
||||||
import org.teavm.ast.VariableNode;
|
import org.teavm.ast.VariableNode;
|
||||||
import org.teavm.backend.javascript.codegen.NamingOrderer;
|
import org.teavm.backend.javascript.codegen.NamingOrderer;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||||
|
import org.teavm.backend.javascript.codegen.ScopedName;
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
|
@ -61,13 +62,11 @@ import org.teavm.vm.RenderingException;
|
||||||
import org.teavm.vm.TeaVMProgressFeedback;
|
import org.teavm.vm.TeaVMProgressFeedback;
|
||||||
|
|
||||||
public class Renderer implements RenderingManager {
|
public class Renderer implements RenderingManager {
|
||||||
public static final String CONTAINER_OBJECT = "$java";
|
|
||||||
private final NamingStrategy naming;
|
private final NamingStrategy naming;
|
||||||
private final SourceWriter writer;
|
private final SourceWriter writer;
|
||||||
private final ListableClassReaderSource classSource;
|
private final ListableClassReaderSource classSource;
|
||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
private boolean classScoped;
|
|
||||||
private final Properties properties = new Properties();
|
private final Properties properties = new Properties();
|
||||||
private final ServiceRepository services;
|
private final ServiceRepository services;
|
||||||
private DebugInformationEmitter debugEmitter = new DummyDebugInformationEmitter();
|
private DebugInformationEmitter debugEmitter = new DummyDebugInformationEmitter();
|
||||||
|
@ -86,7 +85,7 @@ public class Renderer implements RenderingManager {
|
||||||
private boolean threadLibraryUsed;
|
private boolean threadLibraryUsed;
|
||||||
|
|
||||||
public Renderer(SourceWriter writer, Set<MethodReference> asyncMethods, Set<MethodReference> asyncFamilyMethods,
|
public Renderer(SourceWriter writer, Set<MethodReference> asyncMethods, Set<MethodReference> asyncFamilyMethods,
|
||||||
Diagnostics diagnostics, RenderingContext context, boolean classScoped) {
|
Diagnostics diagnostics, RenderingContext context) {
|
||||||
this.naming = context.getNaming();
|
this.naming = context.getNaming();
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
this.classSource = context.getClassSource();
|
this.classSource = context.getClassSource();
|
||||||
|
@ -96,7 +95,6 @@ public class Renderer implements RenderingManager {
|
||||||
this.asyncFamilyMethods = new HashSet<>(asyncFamilyMethods);
|
this.asyncFamilyMethods = new HashSet<>(asyncFamilyMethods);
|
||||||
this.diagnostics = diagnostics;
|
this.diagnostics = diagnostics;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.classScoped = classScoped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLongLibraryUsed() {
|
public boolean isLongLibraryUsed() {
|
||||||
|
@ -272,6 +270,7 @@ public class Renderer implements RenderingManager {
|
||||||
for (ClassNode cls : classes) {
|
for (ClassNode cls : classes) {
|
||||||
estimator.estimate(cls);
|
estimator.estimate(cls);
|
||||||
}
|
}
|
||||||
|
naming.getScopeName();
|
||||||
orderer.apply(naming);
|
orderer.apply(naming);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,8 +298,8 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderDeclaration(ClassNode cls) throws RenderingException {
|
private void renderDeclaration(ClassNode cls) throws RenderingException {
|
||||||
String jsName = naming.getNameFor(cls.getName());
|
ScopedName jsName = naming.getNameFor(cls.getName());
|
||||||
debugEmitter.addClass(jsName, cls.getName(), cls.getParentName());
|
debugEmitter.addClass(jsName.value, cls.getName(), cls.getParentName());
|
||||||
try {
|
try {
|
||||||
renderFunctionDeclaration(jsName);
|
renderFunctionDeclaration(jsName);
|
||||||
writer.append("()").ws().append("{")
|
writer.append("()").ws().append("{")
|
||||||
|
@ -341,7 +340,7 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.outdent().append("}");
|
writer.outdent().append("}");
|
||||||
if (classScoped) {
|
if (jsName.scoped) {
|
||||||
writer.append(";");
|
writer.append(";");
|
||||||
}
|
}
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
|
@ -357,12 +356,14 @@ public class Renderer implements RenderingManager {
|
||||||
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
|
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
|
||||||
value = null;
|
value = null;
|
||||||
}
|
}
|
||||||
if (classScoped) {
|
|
||||||
writer.append(CONTAINER_OBJECT).append(".");
|
ScopedName fieldName = naming.getFullNameFor(fieldRef);
|
||||||
|
if (fieldName.scoped) {
|
||||||
|
writer.append(naming.getScopeName()).append(".");
|
||||||
} else {
|
} else {
|
||||||
writer.append("var ");
|
writer.append("var ");
|
||||||
}
|
}
|
||||||
writer.append(naming.getFullNameFor(fieldRef)).ws().append("=").ws();
|
writer.append(fieldName.value).ws().append("=").ws();
|
||||||
context.constantToString(writer, value);
|
context.constantToString(writer, value);
|
||||||
writer.append(";").softNewLine();
|
writer.append(";").softNewLine();
|
||||||
}
|
}
|
||||||
|
@ -403,12 +404,15 @@ public class Renderer implements RenderingManager {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
boolean isAsync = asyncMethods.contains(clinit.getReference());
|
boolean isAsync = asyncMethods.contains(clinit.getReference());
|
||||||
|
|
||||||
String clinitCalled = naming.getNameFor(cls.getName()) + "_$clinitCalled";
|
ScopedName className = naming.getNameFor(cls.getName());
|
||||||
|
String clinitCalled = (className.scoped ? naming.getScopeName() + "_" : "") + className.value
|
||||||
|
+ "_$clinitCalled";
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
writer.append("var ").append(clinitCalled).ws().append("=").ws().append("false;").softNewLine();
|
writer.append("var ").append(clinitCalled).ws().append("=").ws().append("false;").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFunctionDeclaration(naming.getNameForClassInit(cls.getName()));
|
ScopedName name = naming.getNameForClassInit(cls.getName());
|
||||||
|
renderFunctionDeclaration(name);
|
||||||
writer.append("()").ws()
|
writer.append("()").ws()
|
||||||
.append("{").softNewLine().indent();
|
.append("{").softNewLine().indent();
|
||||||
|
|
||||||
|
@ -454,7 +458,7 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.outdent().append("}");
|
writer.outdent().append("}");
|
||||||
if (classScoped) {
|
if (name.scoped) {
|
||||||
writer.append(";");
|
writer.append(";");
|
||||||
}
|
}
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
|
@ -703,7 +707,8 @@ public class Renderer implements RenderingManager {
|
||||||
private void renderInitializer(MethodNode method) throws IOException {
|
private void renderInitializer(MethodNode method) throws IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
debugEmitter.emitMethod(ref.getDescriptor());
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
renderFunctionDeclaration(naming.getNameForInit(ref));
|
ScopedName name = naming.getNameForInit(ref);
|
||||||
|
renderFunctionDeclaration(name);
|
||||||
writer.append("(");
|
writer.append("(");
|
||||||
for (int i = 0; i < ref.parameterCount(); ++i) {
|
for (int i = 0; i < ref.parameterCount(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
@ -724,7 +729,7 @@ public class Renderer implements RenderingManager {
|
||||||
writer.append(");").softNewLine();
|
writer.append(");").softNewLine();
|
||||||
writer.append("return " + instanceName + ";").softNewLine();
|
writer.append("return " + instanceName + ";").softNewLine();
|
||||||
writer.outdent().append("}");
|
writer.outdent().append("}");
|
||||||
if (classScoped) {
|
if (name.scoped) {
|
||||||
writer.append(";");
|
writer.append(";");
|
||||||
}
|
}
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
|
@ -790,7 +795,7 @@ public class Renderer implements RenderingManager {
|
||||||
|
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
debugEmitter.emitMethod(ref.getDescriptor());
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
String name = naming.getFullNameFor(ref);
|
ScopedName name = naming.getFullNameFor(ref);
|
||||||
|
|
||||||
renderFunctionDeclaration(name);
|
renderFunctionDeclaration(name);
|
||||||
writer.append("(");
|
writer.append("(");
|
||||||
|
@ -808,7 +813,7 @@ public class Renderer implements RenderingManager {
|
||||||
|
|
||||||
method.acceptVisitor(new MethodBodyRenderer(statementRenderer));
|
method.acceptVisitor(new MethodBodyRenderer(statementRenderer));
|
||||||
writer.outdent().append("}");
|
writer.outdent().append("}");
|
||||||
if (classScoped) {
|
if (name.scoped) {
|
||||||
writer.append(";");
|
writer.append(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,13 +823,13 @@ public class Renderer implements RenderingManager {
|
||||||
longLibraryUsed |= statementRenderer.isLongLibraryUsed();
|
longLibraryUsed |= statementRenderer.isLongLibraryUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFunctionDeclaration(String name) throws IOException {
|
private void renderFunctionDeclaration(ScopedName name) throws IOException {
|
||||||
if (classScoped) {
|
if (name.scoped) {
|
||||||
writer.append(CONTAINER_OBJECT).append(".").append(name).ws().append("=").ws();
|
writer.append(naming.getScopeName()).append(".").append(name.value).ws().append("=").ws();
|
||||||
}
|
}
|
||||||
writer.append("function");
|
writer.append("function");
|
||||||
if (!classScoped) {
|
if (!name.scoped) {
|
||||||
writer.append(" ").append(name);
|
writer.append(" ").append(name.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ import java.nio.charset.StandardCharsets;
|
||||||
import org.mozilla.javascript.CompilerEnvirons;
|
import org.mozilla.javascript.CompilerEnvirons;
|
||||||
import org.mozilla.javascript.Context;
|
import org.mozilla.javascript.Context;
|
||||||
import org.mozilla.javascript.ast.AstRoot;
|
import org.mozilla.javascript.ast.AstRoot;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
@ -48,12 +47,10 @@ public class RuntimeRenderer {
|
||||||
"setStackTrace", StackTraceElement[].class, void.class);
|
"setStackTrace", StackTraceElement[].class, void.class);
|
||||||
|
|
||||||
private final ClassReaderSource classSource;
|
private final ClassReaderSource classSource;
|
||||||
private final NamingStrategy naming;
|
|
||||||
private final SourceWriter writer;
|
private final SourceWriter writer;
|
||||||
|
|
||||||
public RuntimeRenderer(ClassReaderSource classSource, NamingStrategy naming, SourceWriter writer) {
|
public RuntimeRenderer(ClassReaderSource classSource, SourceWriter writer) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.naming = naming;
|
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,13 +68,16 @@ public class Inlining {
|
||||||
private InliningStrategy strategy;
|
private InliningStrategy strategy;
|
||||||
private MethodUsageCounter usageCounter;
|
private MethodUsageCounter usageCounter;
|
||||||
private Set<MethodReference> methodsUsedOnce = new HashSet<>();
|
private Set<MethodReference> methodsUsedOnce = new HashSet<>();
|
||||||
|
private boolean devirtualization;
|
||||||
|
|
||||||
public Inlining(ClassHierarchy hierarchy, DependencyInfo dependencyInfo, InliningStrategy strategy,
|
public Inlining(ClassHierarchy hierarchy, DependencyInfo dependencyInfo, InliningStrategy strategy,
|
||||||
ListableClassReaderSource classes, Predicate<MethodReference> externalMethods) {
|
ListableClassReaderSource classes, Predicate<MethodReference> externalMethods,
|
||||||
|
boolean devirtualization) {
|
||||||
this.hierarchy = hierarchy;
|
this.hierarchy = hierarchy;
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
this.dependencyInfo = dependencyInfo;
|
this.dependencyInfo = dependencyInfo;
|
||||||
this.strategy = strategy;
|
this.strategy = strategy;
|
||||||
|
this.devirtualization = devirtualization;
|
||||||
usageCounter = new MethodUsageCounter(externalMethods);
|
usageCounter = new MethodUsageCounter(externalMethods);
|
||||||
|
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
|
@ -156,8 +159,12 @@ public class Inlining {
|
||||||
}
|
}
|
||||||
instructionsToSkip = new HashSet<>();
|
instructionsToSkip = new HashSet<>();
|
||||||
|
|
||||||
while (applyOnce(program, method)) {
|
if (devirtualization) {
|
||||||
devirtualize(program, method, dependencyInfo);
|
while (applyOnce(program, method)) {
|
||||||
|
devirtualize(program, method, dependencyInfo);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
applyOnce(program, method);
|
||||||
}
|
}
|
||||||
depthsByBlock = null;
|
depthsByBlock = null;
|
||||||
instructionsToSkip = null;
|
instructionsToSkip = null;
|
||||||
|
|
|
@ -550,7 +550,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
Inlining inlining = new Inlining(new ClassHierarchy(classes), dependencyAnalyzer, inliningStrategy,
|
Inlining inlining = new Inlining(new ClassHierarchy(classes), dependencyAnalyzer, inliningStrategy,
|
||||||
classes, this::isExternal);
|
classes, this::isExternal, optimizationLevel == TeaVMOptimizationLevel.FULL);
|
||||||
List<MethodReference> methodReferences = inlining.getOrder();
|
List<MethodReference> methodReferences = inlining.getOrder();
|
||||||
int classCount = classes.getClassNames().size();
|
int classCount = classes.getClassNames().size();
|
||||||
int initialValue = compileProgressValue;
|
int initialValue = compileProgressValue;
|
||||||
|
|
|
@ -30,7 +30,7 @@ final class ResourceWriterHelper {
|
||||||
if (resource instanceof ResourceWriter) {
|
if (resource instanceof ResourceWriter) {
|
||||||
((ResourceWriter) resource).write(writer);
|
((ResourceWriter) resource).write(writer);
|
||||||
} else if (resource instanceof Number) {
|
} else if (resource instanceof Number) {
|
||||||
writer.append(resource);
|
writer.append(resource.toString());
|
||||||
} else if (resource instanceof Boolean) {
|
} else if (resource instanceof Boolean) {
|
||||||
writer.append(resource == Boolean.TRUE ? "true" : "false");
|
writer.append(resource == Boolean.TRUE ? "true" : "false");
|
||||||
} else if (resource instanceof String) {
|
} else if (resource instanceof String) {
|
||||||
|
|
|
@ -134,6 +134,13 @@ public final class TeaVMRunner {
|
||||||
.hasArg()
|
.hasArg()
|
||||||
.withDescription("Minimum heap size in bytes (for C and WebAssembly)")
|
.withDescription("Minimum heap size in bytes (for C and WebAssembly)")
|
||||||
.create());
|
.create());
|
||||||
|
options.addOption(OptionBuilder
|
||||||
|
.withLongOpt("max-toplevel-names")
|
||||||
|
.withArgName("number")
|
||||||
|
.hasArg()
|
||||||
|
.withDescription("Maximum number of names kept in top-level scope ("
|
||||||
|
+ "other will be put in a separate object. 10000 by default.")
|
||||||
|
.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
private TeaVMRunner(CommandLine commandLine) {
|
private TeaVMRunner(CommandLine commandLine) {
|
||||||
|
@ -215,10 +222,15 @@ public final class TeaVMRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseJavaScriptOptions() {
|
private void parseJavaScriptOptions() {
|
||||||
if (commandLine.hasOption("m")) {
|
tool.setMinifying(commandLine.hasOption("m"));
|
||||||
tool.setMinifying(true);
|
|
||||||
} else {
|
if (commandLine.hasOption("max-toplevel-names")) {
|
||||||
tool.setMinifying(false);
|
try {
|
||||||
|
tool.setMaxTopLevelNames(Integer.parseInt(commandLine.getOptionValue("max-toplevel-names")));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.err.println("'--max-toplevel-names' must be integer number");
|
||||||
|
printUsage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ public class TeaVMTool {
|
||||||
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
|
private TeaVMTargetType targetType = TeaVMTargetType.JAVASCRIPT;
|
||||||
private String targetFileName = "";
|
private String targetFileName = "";
|
||||||
private boolean minifying = true;
|
private boolean minifying = true;
|
||||||
|
private int maxTopLevelNames = 10000;
|
||||||
private String mainClass;
|
private String mainClass;
|
||||||
private String entryPointName = "main";
|
private String entryPointName = "main";
|
||||||
private Properties properties = new Properties();
|
private Properties properties = new Properties();
|
||||||
|
@ -124,6 +125,10 @@ public class TeaVMTool {
|
||||||
this.minifying = minifying;
|
this.minifying = minifying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMaxTopLevelNames(int maxTopLevelNames) {
|
||||||
|
this.maxTopLevelNames = maxTopLevelNames;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isIncremental() {
|
public boolean isIncremental() {
|
||||||
return incremental;
|
return incremental;
|
||||||
}
|
}
|
||||||
|
@ -291,6 +296,7 @@ public class TeaVMTool {
|
||||||
private TeaVMTarget prepareJavaScriptTarget() {
|
private TeaVMTarget prepareJavaScriptTarget() {
|
||||||
javaScriptTarget = new JavaScriptTarget();
|
javaScriptTarget = new JavaScriptTarget();
|
||||||
javaScriptTarget.setMinifying(minifying);
|
javaScriptTarget.setMinifying(minifying);
|
||||||
|
javaScriptTarget.setTopLevelNameLimit(maxTopLevelNames);
|
||||||
|
|
||||||
debugEmitter = debugInformationGenerated || sourceMapsFileGenerated
|
debugEmitter = debugInformationGenerated || sourceMapsFileGenerated
|
||||||
? new DebugInformationBuilder() : null;
|
? new DebugInformationBuilder() : null;
|
||||||
|
|
|
@ -54,6 +54,8 @@ public interface BuildStrategy {
|
||||||
|
|
||||||
void setMinifying(boolean minifying);
|
void setMinifying(boolean minifying);
|
||||||
|
|
||||||
|
void setMaxTopLevelNames(int maxTopLevelNames);
|
||||||
|
|
||||||
void setProperties(Properties properties);
|
void setProperties(Properties properties);
|
||||||
|
|
||||||
void setTransformers(String[] transformers);
|
void setTransformers(String[] transformers);
|
||||||
|
|
|
@ -52,6 +52,7 @@ public class InProcessBuildStrategy implements BuildStrategy {
|
||||||
private TeaVMOptimizationLevel optimizationLevel = TeaVMOptimizationLevel.ADVANCED;
|
private TeaVMOptimizationLevel optimizationLevel = TeaVMOptimizationLevel.ADVANCED;
|
||||||
private boolean fastDependencyAnalysis;
|
private boolean fastDependencyAnalysis;
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
|
private int maxTopLevelNames;
|
||||||
private boolean sourceMapsFileGenerated;
|
private boolean sourceMapsFileGenerated;
|
||||||
private boolean debugInformationGenerated;
|
private boolean debugInformationGenerated;
|
||||||
private boolean sourceFilesCopied;
|
private boolean sourceFilesCopied;
|
||||||
|
@ -150,6 +151,11 @@ public class InProcessBuildStrategy implements BuildStrategy {
|
||||||
this.minifying = minifying;
|
this.minifying = minifying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxTopLevelNames(int maxTopLevelNames) {
|
||||||
|
this.maxTopLevelNames = maxTopLevelNames;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTransformers(String[] transformers) {
|
public void setTransformers(String[] transformers) {
|
||||||
this.transformers = transformers.clone();
|
this.transformers = transformers.clone();
|
||||||
|
@ -209,6 +215,7 @@ public class InProcessBuildStrategy implements BuildStrategy {
|
||||||
tool.setSourceFilesCopied(sourceFilesCopied);
|
tool.setSourceFilesCopied(sourceFilesCopied);
|
||||||
|
|
||||||
tool.setMinifying(minifying);
|
tool.setMinifying(minifying);
|
||||||
|
tool.setMaxTopLevelNames(maxTopLevelNames);
|
||||||
tool.setIncremental(incremental);
|
tool.setIncremental(incremental);
|
||||||
tool.getTransformers().addAll(Arrays.asList(transformers));
|
tool.getTransformers().addAll(Arrays.asList(transformers));
|
||||||
tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));
|
tool.getClassesToPreserve().addAll(Arrays.asList(classesToPreserve));
|
||||||
|
|
|
@ -129,6 +129,11 @@ public class RemoteBuildStrategy implements BuildStrategy {
|
||||||
request.minifying = minifying;
|
request.minifying = minifying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaxTopLevelNames(int maxTopLevelNames) {
|
||||||
|
request.maxTopLevelNames = maxTopLevelNames;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTransformers(String[] transformers) {
|
public void setTransformers(String[] transformers) {
|
||||||
request.transformers = transformers.clone();
|
request.transformers = transformers.clone();
|
||||||
|
|
|
@ -156,6 +156,7 @@ public class BuildDaemon extends UnicastRemoteObject implements RemoteBuildServi
|
||||||
tool.setOptimizationLevel(request.optimizationLevel);
|
tool.setOptimizationLevel(request.optimizationLevel);
|
||||||
tool.setFastDependencyAnalysis(request.fastDependencyAnalysis);
|
tool.setFastDependencyAnalysis(request.fastDependencyAnalysis);
|
||||||
tool.setMinifying(request.minifying);
|
tool.setMinifying(request.minifying);
|
||||||
|
tool.setMaxTopLevelNames(request.maxTopLevelNames);
|
||||||
tool.setWasmVersion(request.wasmVersion);
|
tool.setWasmVersion(request.wasmVersion);
|
||||||
tool.setMinHeapSize(request.heapSize);
|
tool.setMinHeapSize(request.heapSize);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class RemoteBuildRequest implements Serializable {
|
||||||
public boolean incremental;
|
public boolean incremental;
|
||||||
public String cacheDirectory;
|
public String cacheDirectory;
|
||||||
public boolean minifying;
|
public boolean minifying;
|
||||||
|
public int maxTopLevelNames;
|
||||||
public Properties properties;
|
public Properties properties;
|
||||||
public TeaVMOptimizationLevel optimizationLevel;
|
public TeaVMOptimizationLevel optimizationLevel;
|
||||||
public boolean fastDependencyAnalysis;
|
public boolean fastDependencyAnalysis;
|
||||||
|
|
|
@ -745,7 +745,7 @@ public class CodeServlet extends HttpServlet {
|
||||||
jsTarget.setMinifying(false);
|
jsTarget.setMinifying(false);
|
||||||
jsTarget.setAstCache(astCache);
|
jsTarget.setAstCache(astCache);
|
||||||
jsTarget.setDebugEmitter(debugInformationBuilder);
|
jsTarget.setDebugEmitter(debugInformationBuilder);
|
||||||
jsTarget.setClassScoped(true);
|
jsTarget.setTopLevelNameLimit(500);
|
||||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||||
vm.setCacheStatus(classSource);
|
vm.setCacheStatus(classSource);
|
||||||
vm.addVirtualMethods(m -> true);
|
vm.addVirtualMethods(m -> true);
|
||||||
|
|
|
@ -80,6 +80,9 @@ public class TeaVMCompileMojo extends AbstractMojo {
|
||||||
@Parameter(property = "teavm.minifying", defaultValue = "true")
|
@Parameter(property = "teavm.minifying", defaultValue = "true")
|
||||||
private boolean minifying = true;
|
private boolean minifying = true;
|
||||||
|
|
||||||
|
@Parameter(property = "teavm.maxTopLevelNames", defaultValue = "10000")
|
||||||
|
private int maxTopLevelNames = 10000;
|
||||||
|
|
||||||
@Parameter
|
@Parameter
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
|
|
||||||
|
@ -148,6 +151,7 @@ public class TeaVMCompileMojo extends AbstractMojo {
|
||||||
try {
|
try {
|
||||||
builder.setClassPathEntries(prepareClassPath());
|
builder.setClassPathEntries(prepareClassPath());
|
||||||
builder.setMinifying(minifying);
|
builder.setMinifying(minifying);
|
||||||
|
builder.setMaxTopLevelNames(maxTopLevelNames);
|
||||||
builder.setTargetDirectory(targetDirectory.getAbsolutePath());
|
builder.setTargetDirectory(targetDirectory.getAbsolutePath());
|
||||||
if (transformers != null) {
|
if (transformers != null) {
|
||||||
builder.setTransformers(transformers);
|
builder.setTransformers(transformers);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user