diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/ClassGenerator.java b/classlib/src/main/java/org/teavm/classlib/java/lang/ClassGenerator.java index 79f88e3dd..4cb07244a 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/ClassGenerator.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/ClassGenerator.java @@ -291,7 +291,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin { private void initClass(SourceWriter writer, MemberReader member) throws IOException { if (member.hasModifier(ElementModifier.STATIC)) { - writer.appendClass(member.getOwnerName()).append("_$callClinit();").softNewLine(); + writer.append(writer.getNaming().getNameForClassInit(member.getOwnerName())).append("();").softNewLine(); } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java b/classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java index 7189a4ab4..8e39926d9 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java @@ -84,7 +84,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin { } private void generateCurrentTimeMillis(SourceWriter writer) throws IOException { - writer.append(writer.getNaming().getNameFor("java.lang.System")).append("_$callClinit();").softNewLine(); + writer.append(writer.getNaming().getNameForClassInit("java.lang.System")).append("();").softNewLine(); writer.append("return Long_fromNumber(new Date().getTime());").softNewLine(); } diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/AliasProvider.java b/core/src/main/java/org/teavm/backend/javascript/codegen/AliasProvider.java index b4f141f79..2b4887c0f 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/AliasProvider.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/AliasProvider.java @@ -31,4 +31,6 @@ public interface AliasProvider { String getClassAlias(String className); String getFunctionAlias(String name); + + String getClassInitAlias(String className); } 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 d4165ea2b..8affb173d 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 @@ -30,38 +30,40 @@ public class DefaultAliasProvider implements AliasProvider { @Override public String getClassAlias(String cls) { - return classAliases.computeIfAbsent(cls, key -> { - StringBuilder alias = new StringBuilder(); - int lastIndex = 0; - while (true) { - int index = cls.indexOf('.', lastIndex); - if (index == -1) { - if (lastIndex > 0) { - alias.append("_"); - } - alias.append(cls.substring(lastIndex)); - break; - } else { - if (index > lastIndex) { - alias.append(cls.charAt(lastIndex)); - } - lastIndex = index + 1; + return classAliases.computeIfAbsent(cls, key -> makeUnique(knownAliases, suggestAliasForClass(key))); + } + + private static String suggestAliasForClass(String cls) { + StringBuilder alias = new StringBuilder(); + int lastIndex = 0; + while (true) { + int index = cls.indexOf('.', lastIndex); + if (index == -1) { + if (lastIndex > 0) { + alias.append("_"); } - } - - for (int i = 1; i < alias.length(); ++i) { - char c = alias.charAt(i); - if (!Character.isJavaIdentifierPart(c)) { - alias.setCharAt(i, '_'); + alias.append(cls.substring(lastIndex)); + break; + } else { + if (index > lastIndex) { + alias.append(cls.charAt(lastIndex)); } + lastIndex = index + 1; } + } - if (!Character.isJavaIdentifierStart(alias.charAt(0))) { - alias.setCharAt(0, '_'); + for (int i = 1; i < alias.length(); ++i) { + char c = alias.charAt(i); + if (!Character.isJavaIdentifierPart(c)) { + alias.setCharAt(i, '_'); } + } - return makeUnique(knownAliases, alias.toString()); - }); + if (!Character.isJavaIdentifierStart(alias.charAt(0))) { + alias.setCharAt(0, '_'); + } + + return alias.toString(); } @Override @@ -111,6 +113,11 @@ public class DefaultAliasProvider implements AliasProvider { return name; } + @Override + public String getClassInitAlias(String className) { + return makeUnique(knownAliases, suggestAliasForClass(className) + "_$callClinit"); + } + private String makeUnique(Set knowAliases, String alias) { String uniqueAlias = alias; int index = 1; diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultNamingStrategy.java b/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultNamingStrategy.java index d1d7f0338..fcdb927f0 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultNamingStrategy.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/DefaultNamingStrategy.java @@ -28,6 +28,7 @@ public class DefaultNamingStrategy implements NamingStrategy { private final Map fieldAliases = new HashMap<>(); private final Map staticFieldAliases = new HashMap<>(); private final Map functionAliases = new HashMap<>(); + private final Map classInitAliases = new HashMap<>(); public DefaultNamingStrategy(AliasProvider aliasProvider, ClassReaderSource classSource) { this.aliasProvider = aliasProvider; @@ -99,7 +100,12 @@ public class DefaultNamingStrategy implements NamingStrategy { @Override public String getNameForFunction(String name) throws NamingException { - return functionAliases.computeIfAbsent(name, key -> aliasProvider.getFunctionAlias(name)); + return functionAliases.computeIfAbsent(name, key -> aliasProvider.getFunctionAlias(key)); + } + + @Override + public String getNameForClassInit(String className) throws NamingException { + return classInitAliases.computeIfAbsent(className, key -> aliasProvider.getClassInitAlias(key)); } private MethodReference getRealMethod(MethodReference methodRef) { diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/MinifyingAliasProvider.java b/core/src/main/java/org/teavm/backend/javascript/codegen/MinifyingAliasProvider.java index 2accfdf91..ee940fbec 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/MinifyingAliasProvider.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/MinifyingAliasProvider.java @@ -67,11 +67,24 @@ public class MinifyingAliasProvider implements AliasProvider { @Override public String getClassAlias(String className) { - return RenderingUtil.indexToId(lastSuffix++, startLetters); + String result; + do { + result = RenderingUtil.indexToId(lastSuffix++, startLetters); + } while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result)); + return result; } @Override public String getFunctionAlias(String className) { return RenderingUtil.indexToId(lastSuffix++, startLetters); } + + @Override + public String getClassInitAlias(String className) { + String result; + do { + result = RenderingUtil.indexToId(lastSuffix++, startLetters); + } while (!usedAliases.add(result) || RenderingUtil.KEYWORDS.contains(result)); + return result; + } } diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/NameFrequencyConsumer.java b/core/src/main/java/org/teavm/backend/javascript/codegen/NameFrequencyConsumer.java index 7d9ea86f9..182b8fd23 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/NameFrequencyConsumer.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/NameFrequencyConsumer.java @@ -28,6 +28,8 @@ public interface NameFrequencyConsumer { void consume(String className); + void consumeClassInit(String className); + void consume(FieldReference field); void consumeFunction(String name); diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/NamingOrderer.java b/core/src/main/java/org/teavm/backend/javascript/codegen/NamingOrderer.java index 52a83e184..676d5248d 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/NamingOrderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/NamingOrderer.java @@ -24,7 +24,7 @@ public class NamingOrderer implements NameFrequencyConsumer { private Map entries = new HashMap<>(); @Override - public void consume(final MethodReference method) { + public void consume(MethodReference method) { String key = "R:" + method; Entry entry = entries.get(key); if (entry == null) { @@ -37,7 +37,7 @@ public class NamingOrderer implements NameFrequencyConsumer { @Override - public void consumeInit(final MethodReference method) { + public void consumeInit(MethodReference method) { String key = "I:" + method; Entry entry = entries.get(key); if (entry == null) { @@ -49,7 +49,7 @@ public class NamingOrderer implements NameFrequencyConsumer { } @Override - public void consume(final MethodDescriptor method) { + public void consume(MethodDescriptor method) { String key = "r:" + method; Entry entry = entries.get(key); if (entry == null) { @@ -61,7 +61,7 @@ public class NamingOrderer implements NameFrequencyConsumer { } @Override - public void consume(final String className) { + public void consume(String className) { String key = "c:" + className; Entry entry = entries.get(key); if (entry == null) { @@ -73,7 +73,19 @@ public class NamingOrderer implements NameFrequencyConsumer { } @Override - public void consume(final FieldReference field) { + public void consumeClassInit(String className) { + String key = "C:" + className; + Entry entry = entries.get(key); + if (entry == null) { + entry = new Entry(); + entry.operation = naming -> naming.getNameForClassInit(className); + entries.put(key, entry); + } + entry.frequency++; + } + + @Override + public void consume(FieldReference field) { String key = "f:" + field; Entry entry = entries.get(key); if (entry == null) { @@ -85,7 +97,7 @@ public class NamingOrderer implements NameFrequencyConsumer { } @Override - public void consumeFunction(final String name) { + public void consumeFunction(String name) { String key = "n:" + name; Entry entry = entries.get(key); if (entry == null) { diff --git a/core/src/main/java/org/teavm/backend/javascript/codegen/NamingStrategy.java b/core/src/main/java/org/teavm/backend/javascript/codegen/NamingStrategy.java index f0554cd1b..508e0b16f 100644 --- a/core/src/main/java/org/teavm/backend/javascript/codegen/NamingStrategy.java +++ b/core/src/main/java/org/teavm/backend/javascript/codegen/NamingStrategy.java @@ -33,4 +33,6 @@ public interface NamingStrategy { String getFullNameFor(FieldReference method) throws NamingException; String getNameForFunction(String name) throws NamingException; + + String getNameForClassInit(String className) throws NamingException; } diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/NameFrequencyEstimator.java b/core/src/main/java/org/teavm/backend/javascript/rendering/NameFrequencyEstimator.java index 31f3cd4da..6ed711667 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/NameFrequencyEstimator.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/NameFrequencyEstimator.java @@ -147,7 +147,7 @@ class NameFrequencyEstimator extends RecursiveVisitor implements MethodNodeVisit @Override public void visit(InitClassStatement statement) { - consumer.consume(statement.getClassName()); + consumer.consumeClassInit(statement.getClassName()); } @Override diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java index 4d7da2d8c..96c3998a0 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/Renderer.java @@ -430,7 +430,7 @@ public class Renderer implements RenderingManager { .append("false;").softNewLine(); } - writer.append("function ").appendClass(cls.getName()).append("_$callClinit()").ws() + writer.append("function ").append(naming.getNameForClassInit(cls.getName())).append("()").ws() .append("{").softNewLine().indent(); if (isAsync) { @@ -479,7 +479,7 @@ public class Renderer implements RenderingManager { } private void renderEraseClinit(ClassNode cls) throws IOException { - writer.appendClass(cls.getName()).append("_$callClinit").ws().append("=").ws() + writer.append(naming.getNameForClassInit(cls.getName())).ws().append("=").ws() .appendClass(cls.getName()).append(".$clinit").ws().append("=").ws() .append("function(){};").newLine(); } @@ -518,7 +518,7 @@ public class Renderer implements RenderingManager { MethodReader clinit = classSource.get(cls.getName()).getMethod( new MethodDescriptor("", ValueType.VOID)); if (clinit != null) { - writer.appendClass(cls.getName()).append("_$callClinit"); + writer.append(naming.getNameForClassInit(cls.getName())); } else { writer.append('0'); } diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java index 5a85eb571..c6c9aaedd 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java @@ -437,7 +437,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor { if (statement.getLocation() != null) { pushLocation(statement.getLocation()); } - writer.appendClass(statement.getClassName()).append("_$callClinit();").softNewLine(); + writer.append(naming.getNameForClassInit(statement.getClassName())).append("();").softNewLine(); if (statement.isAsync()) { emitSuspendChecker(); }