From 43670ed3ca767579168e18da84023ac1a48819ab Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Mon, 7 Jul 2014 18:00:22 +0400 Subject: [PATCH] Adds string pool --- .../java/org/teavm/javascript/Renderer.java | 39 +++++++++++++++++-- .../src/main/java/org/teavm/vm/TeaVM.java | 1 + .../resources/org/teavm/javascript/runtime.js | 9 +++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index d2fc37126..64efd13dd 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -35,8 +35,6 @@ import org.teavm.model.*; * @author Alexey Andreev */ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext { - private static final MethodReference internRef = new MethodReference("java.lang.String", "intern", - ValueType.object("java.lang.String")); private static final String variableNames = "abcdefghijkmnopqrstuvwxyz"; private NamingStrategy naming; private SourceWriter writer; @@ -44,6 +42,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext private ClassLoader classLoader; private boolean minifying; private Map injectorMap = new HashMap<>(); + private Map stringPoolMap = new HashMap<>(); + private List stringPool = new ArrayList<>(); private Properties properties = new Properties(); private ServiceRepository services; @@ -107,6 +107,24 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext this.properties.putAll(properties); } + public void renderStringPool() throws RenderingException { + if (stringPool.isEmpty()) { + return; + } + try { + writer.append("$rt_stringPool(["); + for (int i = 0; i < stringPool.size(); ++i) { + if (i > 0) { + writer.append(',').ws(); + } + writer.append('"').append(escapeString(stringPool.get(i))).append('"'); + } + writer.append("]);").newLine(); + } catch (IOException e) { + throw new RenderingException("IO error", e); + } + } + public void renderRuntime() throws RenderingException { try { renderRuntimeCls(); @@ -114,6 +132,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext renderRuntimeUnwrapString(); renderRuntimeObjcls(); renderRuntimeNullCheck(); + renderRuntimeIntern(); } catch (NamingException e) { throw new RenderingException("Error rendering runtime methods. See a cause for details", e); } catch (IOException e) { @@ -199,6 +218,13 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.outdent().append("}").newLine(); } + private void renderRuntimeIntern() throws IOException { + writer.append("$rt_intern = function(str) {").indent().softNewLine(); + writer.append("return ").appendMethodBody(new MethodReference(String.class, "intern", String.class)) + .append("(str);").softNewLine(); + writer.outdent().append("}").newLine(); + } + private void renderRuntimeObjcls() throws IOException { writer.append("$rt_objcls = function() { return ").appendClass("java.lang.Object").append("; }").newLine(); } @@ -972,7 +998,14 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext ValueType type = (ValueType)cst; return "$rt_cls(" + typeToClsString(naming, type) + ")"; } else if (cst instanceof String) { - return naming.getFullNameFor(internRef) + "($rt_str(\"" + escapeString((String)cst) + "\"))"; + String string = (String)cst; + Integer index = stringPoolMap.get(string); + if (index == null) { + index = stringPool.size(); + stringPool.add(string); + stringPoolMap.put(string, index); + } + return "$rt_s(" + index + ")"; } else if (cst instanceof Long) { long value = (Long)cst; if (value == 0) { diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index 3a9c78e2a..5957dbd33 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -356,6 +356,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { listener.afterClass(cls); } } + renderer.renderStringPool(); for (Map.Entry entry : entryPoints.entrySet()) { sourceWriter.append(entry.getKey()).ws().append("=").ws().appendMethodBody(entry.getValue().reference) .append(";").softNewLine(); diff --git a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js index 7b1809cdf..29db04f2b 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -381,6 +381,15 @@ function $rt_virtualMethods(cls) { } } } +function $rt_stringPool(strings) { + $rt_stringPool_instance = new Array(strings.length); + for (var i = 0; i < strings.length; ++i) { + $rt_stringPool_instance[i] = $rt_intern($rt_str(strings[i])); + } +} +function $rt_s(index) { + return $rt_stringPool_instance[index]; +} Long = function(lo, hi) { this.lo = lo | 0;