From 1b835192802a2bde66f6ae10519ea8a53aa0dffd Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 7 Dec 2018 00:52:05 +0300 Subject: [PATCH] Reduce minumus JS runtime a little --- .../backend/javascript/JavaScriptTarget.java | 17 +++++++++- .../javascript/rendering/RuntimeRenderer.java | 33 ++++++++++++++----- .../org/teavm/backend/javascript/runtime.js | 13 ++++++-- .../java/org/teavm/junit/TeaVMTestRunner.java | 1 + 4 files changed, 52 insertions(+), 12 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 bfe199804..a620499c4 100644 --- a/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java +++ b/core/src/main/java/org/teavm/backend/javascript/JavaScriptTarget.java @@ -100,6 +100,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost { private TeaVMTargetController controller; private boolean minifying = true; + private boolean stackTraceIncluded = false; private final Map methodGenerators = new HashMap<>(); private final Map methodInjectors = new HashMap<>(); private final List> generatorProviders = new ArrayList<>(); @@ -194,6 +195,10 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost { return true; } + public void setStackTraceIncluded(boolean stackTraceIncluded) { + this.stackTraceIncluded = stackTraceIncluded; + } + @Override public List getHostExtensions() { return Collections.singletonList(this); @@ -219,7 +224,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost { dependencyAnalyzer.linkField(new FieldReference(String.class.getName(), "characters"), null); - dependencyAnalyzer.linkMethod(new MethodReference(Object.class, "clone", Object.class), null).use(); + dependencyAnalyzer.linkMethod(new MethodReference(Object.class, "clone", Object.class), null); MethodDependency exceptionCons = dependencyAnalyzer.linkMethod(new MethodReference( NoClassDefFoundError.class, "", String.class, void.class), null); @@ -246,6 +251,16 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost { exceptionCons.getVariable(1).propagate(stringType); exceptionCons.use(); + if (stackTraceIncluded) { + includeStackTraceMethods(dependencyAnalyzer); + } + } + + public static void includeStackTraceMethods(DependencyAnalyzer dependencyAnalyzer) { + MethodDependency dep; + + DependencyType stringType = dependencyAnalyzer.getType("java.lang.String"); + dep = dependencyAnalyzer.linkMethod(new MethodReference( StackTraceElement.class, "", String.class, String.class, String.class, int.class, void.class), null); 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 308cb3053..b96c1b151 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 @@ -44,6 +44,10 @@ public class RuntimeRenderer { String.class, String.class); private static final MethodDescriptor CURRENT_THREAD_METHOD = new MethodDescriptor("currentThread", Thread.class); + private static final MethodReference STACK_TRACE_ELEM_INIT = new MethodReference(StackTraceElement.class, + "", String.class, String.class, String.class, int.class, void.class); + private static final MethodReference SET_STACK_TRACE_METHOD = new MethodReference(Throwable.class, + "setStackTrace", StackTraceElement[].class, void.class); private final ClassReaderSource classSource; private final NamingStrategy naming; @@ -197,26 +201,37 @@ public class RuntimeRenderer { } private void renderCreateStackTraceElement() throws IOException { + ClassReader cls = classSource.get(STACK_TRACE_ELEM_INIT.getClassName()); + boolean supported = cls != null && cls.getMethod(STACK_TRACE_ELEM_INIT.getDescriptor()) != null; + writer.append("function $rt_createStackElement(") .append("className,").ws() .append("methodName,").ws() .append("fileName,").ws() .append("lineNumber)").ws().append("{").indent().softNewLine(); writer.append("return "); - writer.append(writer.getNaming().getNameForInit(new MethodReference(StackTraceElement.class, - "", String.class, String.class, String.class, int.class, void.class))); - writer.append("(className,").ws() - .append("methodName,").ws() - .append("fileName,").ws() - .append("lineNumber);").softNewLine(); + if (supported) { + writer.append(writer.getNaming().getNameForInit(STACK_TRACE_ELEM_INIT)); + writer.append("(className,").ws() + .append("methodName,").ws() + .append("fileName,").ws() + .append("lineNumber)"); + } else { + writer.append("null"); + } + writer.append(";").softNewLine(); writer.outdent().append("}").newLine(); } private void renderSetStackTrace() throws IOException { + ClassReader cls = classSource.get(SET_STACK_TRACE_METHOD.getClassName()); + boolean supported = cls != null && cls.getMethod(SET_STACK_TRACE_METHOD.getDescriptor()) != null; + writer.append("function $rt_setStack(e,").ws().append("stack)").ws().append("{").indent().softNewLine(); - writer.appendMethodBody(new MethodReference(Throwable.class, "setStackTrace", StackTraceElement[].class, - void.class)); - writer.append("(e,").ws().append("stack);").softNewLine(); + if (supported) { + writer.appendMethodBody(SET_STACK_TRACE_METHOD); + writer.append("(e,").ws().append("stack);").softNewLine(); + } writer.outdent().append("}").newLine(); } } diff --git a/core/src/main/resources/org/teavm/backend/javascript/runtime.js b/core/src/main/resources/org/teavm/backend/javascript/runtime.js index 3dae31179..300fd0657 100644 --- a/core/src/main/resources/org/teavm/backend/javascript/runtime.js +++ b/core/src/main/resources/org/teavm/backend/javascript/runtime.js @@ -231,12 +231,21 @@ function $rt_exception(ex) { if (typeof $rt_decodeStack === "function" && err.stack) { var stack = $rt_decodeStack(err.stack); var javaStack = $rt_createArray($rt_objcls(), stack.length); + var elem; + var noStack = false; for (var i = 0; i < stack.length; ++i) { var element = stack[i]; - javaStack.data[i] = $rt_createStackElement($rt_str(element.className), + elem = $rt_createStackElement($rt_str(element.className), $rt_str(element.methodName), $rt_str(element.fileName), element.lineNumber); + if (elem == null) { + noStack = true; + break; + } + javaStack.data[i] = elem; + } + if (!noStack) { + $rt_setStack(ex, javaStack); } - $rt_setStack(ex, javaStack); } } return err; diff --git a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java index b2315d6c9..7379cca33 100644 --- a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java +++ b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestRunner.java @@ -559,6 +559,7 @@ public class TeaVMTestRunner extends Runner implements Filterable { JavaScriptTarget target = new JavaScriptTarget(); if (decodeStack) { target.setDebugEmitter(debugEmitter); + target.setStackTraceIncluded(true); } return target; };