From d310409db3c610f56e6f98b99e4f565211140c13 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Fri, 14 Feb 2014 16:19:51 +0400 Subject: [PATCH] Fixes dependency checking of arrays --- .../dependency/DependencyGraphBuilder.java | 5 +++ .../org/teavm/dependency/DependencyNode.java | 6 ++++ .../DependencyNodeToNodeTransition.java | 9 +++--- .../html4j/JavaScriptBodyDependency.java | 7 +++++ .../teavm/html4j/JavaScriptBodyGenerator.java | 2 +- .../html4j/test/JavaScriptBodyTests.java | 31 ++++++++++++++++--- 6 files changed, 51 insertions(+), 9 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index 734a66835..a45b913de 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -18,6 +18,7 @@ package org.teavm.dependency; import java.util.List; import org.teavm.model.*; import org.teavm.model.instructions.*; +import org.teavm.model.util.ListingBuilder; /** * @@ -38,6 +39,10 @@ class DependencyGraphBuilder { return; } program = method.getProgram(); + if (DependencyChecker.shouldLog) { + System.out.println("Method achieved: " + method.getReference()); + System.out.println(new ListingBuilder().buildListing(program, " ")); + } resultNode = graph.getResult(); nodes = graph.getVariables(); for (int i = 0; i < program.basicBlockCount(); ++i) { diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java index 5aa734dc4..a7ac48779 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyNode.java @@ -60,6 +60,9 @@ public class DependencyNode implements DependencyValueInformation { public void connect(DependencyNode node, DependencyTypeFilter filter) { DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter); if (transitions.putIfAbsent(node, transition) == null) { + if (DependencyChecker.shouldLog) { + System.out.println("Connecting " + tag + " to " + node.tag); + } addConsumer(transition); } } @@ -74,6 +77,9 @@ public class DependencyNode implements DependencyValueInformation { if (result == null) { result = new DependencyNode(dependencyChecker); if (arrayItemNode.compareAndSet(null, result)) { + if (DependencyChecker.shouldLog) { + arrayItemNode.get().tag = tag + "["; + } arrayItemNodeLatch.countDown(); arrayItemNodeLatch = null; } else { diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java index 07b24320e..b13d1a467 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java @@ -36,12 +36,13 @@ class DependencyNodeToNodeTransition implements DependencyConsumer { if (filter != null && !filter.match(type)) { return; } + if (type.startsWith("[")) { + type = "java.lang.Object"; + } if (!destination.hasType(type)) { destination.propagate(type); - if (type.startsWith("[")) { - source.getArrayItem().connect(destination.getArrayItem()); - destination.getArrayItem().connect(destination.getArrayItem()); - } + source.getArrayItem().connect(destination.getArrayItem()); + destination.getArrayItem().connect(source.getArrayItem()); } } } diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java index d3b9b1d50..2006a3ff6 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java @@ -29,6 +29,7 @@ public class JavaScriptBodyDependency implements DependencyListener { @Override public void started(DependencyChecker dependencyChecker) { allClassesNode = dependencyChecker.createNode(); + allClassesNode.setTag("JavaScriptBody:global"); } @Override @@ -47,6 +48,12 @@ public class JavaScriptBodyDependency implements DependencyListener { if (graph.getResult() != null) { allClassesNode.connect(graph.getResult()); } + for (int i = 0; i < graph.getParameterCount(); ++i) { + graph.getVariable(i).connect(allClassesNode); + allClassesNode.getArrayItem().connect(graph.getVariable(i).getArrayItem()); + allClassesNode.getArrayItem().getArrayItem().connect(graph.getVariable(i) + .getArrayItem().getArrayItem()); + } if (javacall != null && javacall.getBoolean()) { String body = annot.getValue("body").getString(); new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body); diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java index 7af09efcc..6def41382 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java @@ -55,7 +55,7 @@ public class JavaScriptBodyGenerator implements Generator { writer.append(",").ws(); writer.append(context.getParameterName(i + 1)); } - writer.append(");"); + writer.append(");").softNewLine(); } private static class GeneratorJsCallback extends JsCallback { diff --git a/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java b/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java index dae072957..318546c63 100644 --- a/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java +++ b/teavm-html4j/src/test/java/org/teavm/html4j/test/JavaScriptBodyTests.java @@ -15,7 +15,7 @@ */ package org.teavm.html4j.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import net.java.html.js.JavaScriptBody; import org.junit.Test; @@ -29,15 +29,28 @@ public class JavaScriptBodyTests { assertEquals(23, simpleNativeMethod()); } - @JavaScriptBody(args = {}, body = "return 23;") - private native int simpleNativeMethod(); - @Test public void dependencyPropagated() { A a = (A)returnValuePassed(new AImpl()); assertEquals(23, a.foo()); } + @Test + public void dependencyPropagatedThroughProperty() { + storeObject(new AImpl()); + A a = (A)retrieveObject(); + assertEquals(23, a.foo()); + } + + @Test + public void dependencyPropagatedThroughArray() { + A[] first = new A[1]; + storeObject(first); + Object[] second = (Object[])retrieveObject(); + second[0] = new AImpl(); + assertEquals(23, first[0].foo()); + } + private static interface A { public int foo(); } @@ -46,6 +59,16 @@ public class JavaScriptBodyTests { return 23; } } + + @JavaScriptBody(args = {}, body = "return 23;") + private native int simpleNativeMethod(); + @JavaScriptBody(args = { "value" }, body = "return value;") private native Object returnValuePassed(Object value); + + @JavaScriptBody(args = { "obj" }, body = "window._global_ = obj;") + private native void storeObject(Object obj); + + @JavaScriptBody(args = {}, body = "return window._global_;") + private native Object retrieveObject(); }