From 0ee994e91390e7ac71b9319ff5a731a886aa2d22 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 7 Nov 2023 18:46:01 +0100 Subject: [PATCH] Improve class initializer elimination --- .../teavm/backend/javascript/JavaScriptTarget.java | 3 ++- .../javascript/rendering/RuntimeRenderer.java | 8 ++++++-- .../javascript/templating/JavaScriptTemplate.java | 2 +- .../backend/javascript/templating/LetJoiner.java | 3 +-- .../javascript/templating/TemplatingAstWriter.java | 13 +++++++++++-- .../model/analysis/ClassInitializerAnalysis.java | 2 +- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java b/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java index 337e310e1..641559d48 100644 --- a/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java +++ b/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java @@ -461,7 +461,8 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost { int start = sourceWriter.getOffset(); - RuntimeRenderer runtimeRenderer = new RuntimeRenderer(classes, sourceWriter); + RuntimeRenderer runtimeRenderer = new RuntimeRenderer(classes, sourceWriter, + controller.getClassInitializerInfo()); runtimeRenderer.prepareAstParts(renderer.isThreadLibraryUsed()); declarations.replay(runtimeRenderer.sink, RememberedSource.FILTER_REF); epilogue.replay(runtimeRenderer.sink, RememberedSource.FILTER_REF); diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/RuntimeRenderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/RuntimeRenderer.java index daf8f0e9b..b8daedcaf 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/RuntimeRenderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/RuntimeRenderer.java @@ -33,6 +33,7 @@ import org.teavm.backend.javascript.templating.RemovablePartsFinder; import org.teavm.backend.javascript.templating.TemplatingAstTransformer; import org.teavm.backend.javascript.templating.TemplatingAstWriter; import org.teavm.model.ClassReaderSource; +import org.teavm.model.analysis.ClassInitializerInfo; import org.teavm.vm.RenderingException; public class RuntimeRenderer { @@ -41,10 +42,13 @@ public class RuntimeRenderer { private final RemovablePartsFinder removablePartsFinder = new RemovablePartsFinder(); private final ClassReaderSource classSource; private final SourceWriter writer; + private final ClassInitializerInfo classInitializerInfo; - public RuntimeRenderer(ClassReaderSource classSource, SourceWriter writer) { + public RuntimeRenderer(ClassReaderSource classSource, SourceWriter writer, + ClassInitializerInfo classInitializerInfo) { this.classSource = classSource; this.writer = writer; + this.classInitializerInfo = classInitializerInfo; } public void prepareAstParts(boolean threadLibraryUsed) { @@ -76,7 +80,7 @@ public class RuntimeRenderer { } private void renderHandWrittenRuntime(AstRoot ast) { - var astWriter = new TemplatingAstWriter(writer, null, null); + var astWriter = new TemplatingAstWriter(writer, null, null, classInitializerInfo); astWriter.hoist(ast); astWriter.print(ast); } diff --git a/core/src/main/java/org/teavm/backend/javascript/templating/JavaScriptTemplate.java b/core/src/main/java/org/teavm/backend/javascript/templating/JavaScriptTemplate.java index c111a599d..12f54f708 100644 --- a/core/src/main/java/org/teavm/backend/javascript/templating/JavaScriptTemplate.java +++ b/core/src/main/java/org/teavm/backend/javascript/templating/JavaScriptTemplate.java @@ -75,7 +75,7 @@ public class JavaScriptTemplate { var thisFragment = parameters.apply(0); var body = node.getBody(); return (writer, precedence) -> { - var astWriter = new TemplatingAstWriter(writer, nameParameters, node); + var astWriter = new TemplatingAstWriter(writer, nameParameters, node, null); for (var entry : fragments.entrySet()) { astWriter.setFragment(entry.getKey(), entry.getValue()); } diff --git a/core/src/main/java/org/teavm/backend/javascript/templating/LetJoiner.java b/core/src/main/java/org/teavm/backend/javascript/templating/LetJoiner.java index e57431e5b..5fcb08c7f 100644 --- a/core/src/main/java/org/teavm/backend/javascript/templating/LetJoiner.java +++ b/core/src/main/java/org/teavm/backend/javascript/templating/LetJoiner.java @@ -19,7 +19,6 @@ import org.mozilla.javascript.ast.AstNode; import org.mozilla.javascript.ast.AstRoot; import org.mozilla.javascript.ast.Block; import org.mozilla.javascript.ast.FunctionNode; -import org.mozilla.javascript.ast.IfStatement; import org.mozilla.javascript.ast.Scope; import org.mozilla.javascript.ast.VariableDeclaration; import org.teavm.backend.javascript.ast.AstVisitor; @@ -51,7 +50,7 @@ public class LetJoiner extends AstVisitor { private void visitMany(AstNode node) { VariableDeclaration previous = null; - for (var childNode = node.getFirstChild(); childNode != null; ) { + for (var childNode = node.getFirstChild(); childNode != null;) { var nextNode = childNode.getNext(); var child = (AstNode) childNode; if (child instanceof VariableDeclaration) { diff --git a/core/src/main/java/org/teavm/backend/javascript/templating/TemplatingAstWriter.java b/core/src/main/java/org/teavm/backend/javascript/templating/TemplatingAstWriter.java index 0a5225ccd..eaeded4f2 100644 --- a/core/src/main/java/org/teavm/backend/javascript/templating/TemplatingAstWriter.java +++ b/core/src/main/java/org/teavm/backend/javascript/templating/TemplatingAstWriter.java @@ -30,14 +30,18 @@ import org.teavm.backend.javascript.rendering.DefaultGlobalNameWriter; import org.teavm.model.FieldReference; import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodReference; +import org.teavm.model.analysis.ClassInitializerInfo; public class TemplatingAstWriter extends AstWriter { private Map names; private Scope scope; private Map fragments = new HashMap<>(); + private ClassInitializerInfo classInitializerInfo; - public TemplatingAstWriter(SourceWriter writer, Map names, Scope scope) { + public TemplatingAstWriter(SourceWriter writer, Map names, Scope scope, + ClassInitializerInfo classInitializerInfo) { super(writer, new DefaultGlobalNameWriter(writer)); + this.classInitializerInfo = classInitializerInfo; this.names = names; this.scope = scope; if (names != null) { @@ -132,7 +136,12 @@ public class TemplatingAstWriter extends AstWriter { if (!(classArg instanceof StringLiteral)) { return false; } - writer.appendClassInit(((StringLiteral) classArg).getValue()); + var className = ((StringLiteral) classArg).getValue(); + if (classInitializerInfo == null || classInitializerInfo.isDynamicInitializer(className)) { + writer.appendClassInit(className); + } else { + writer.append("(()").ws().append("=>").ws().append("{})"); + } return true; } diff --git a/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java b/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java index e820baf07..210b8714b 100644 --- a/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java +++ b/core/src/main/java/org/teavm/model/analysis/ClassInitializerAnalysis.java @@ -279,7 +279,7 @@ public class ClassInitializerAnalysis implements ClassInitializerInfo { } void analyzeInitializer(String className) { - if (className.equals(currentClass)) { + if (className.equals(currentClass) || className.equals(methodInfo.method.getClassName())) { return; }