Fixes dependency checking of arrays

This commit is contained in:
konsoletyper 2014-02-14 16:19:51 +04:00
parent afc85c9780
commit d310409db3
6 changed files with 51 additions and 9 deletions

View File

@ -18,6 +18,7 @@ package org.teavm.dependency;
import java.util.List; import java.util.List;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.instructions.*; import org.teavm.model.instructions.*;
import org.teavm.model.util.ListingBuilder;
/** /**
* *
@ -38,6 +39,10 @@ class DependencyGraphBuilder {
return; return;
} }
program = method.getProgram(); program = method.getProgram();
if (DependencyChecker.shouldLog) {
System.out.println("Method achieved: " + method.getReference());
System.out.println(new ListingBuilder().buildListing(program, " "));
}
resultNode = graph.getResult(); resultNode = graph.getResult();
nodes = graph.getVariables(); nodes = graph.getVariables();
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {

View File

@ -60,6 +60,9 @@ public class DependencyNode implements DependencyValueInformation {
public void connect(DependencyNode node, DependencyTypeFilter filter) { public void connect(DependencyNode node, DependencyTypeFilter filter) {
DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter); DependencyNodeToNodeTransition transition = new DependencyNodeToNodeTransition(this, node, filter);
if (transitions.putIfAbsent(node, transition) == null) { if (transitions.putIfAbsent(node, transition) == null) {
if (DependencyChecker.shouldLog) {
System.out.println("Connecting " + tag + " to " + node.tag);
}
addConsumer(transition); addConsumer(transition);
} }
} }
@ -74,6 +77,9 @@ public class DependencyNode implements DependencyValueInformation {
if (result == null) { if (result == null) {
result = new DependencyNode(dependencyChecker); result = new DependencyNode(dependencyChecker);
if (arrayItemNode.compareAndSet(null, result)) { if (arrayItemNode.compareAndSet(null, result)) {
if (DependencyChecker.shouldLog) {
arrayItemNode.get().tag = tag + "[";
}
arrayItemNodeLatch.countDown(); arrayItemNodeLatch.countDown();
arrayItemNodeLatch = null; arrayItemNodeLatch = null;
} else { } else {

View File

@ -36,12 +36,13 @@ class DependencyNodeToNodeTransition implements DependencyConsumer {
if (filter != null && !filter.match(type)) { if (filter != null && !filter.match(type)) {
return; return;
} }
if (type.startsWith("[")) {
type = "java.lang.Object";
}
if (!destination.hasType(type)) { if (!destination.hasType(type)) {
destination.propagate(type); destination.propagate(type);
if (type.startsWith("[")) { source.getArrayItem().connect(destination.getArrayItem());
source.getArrayItem().connect(destination.getArrayItem()); destination.getArrayItem().connect(source.getArrayItem());
destination.getArrayItem().connect(destination.getArrayItem());
}
} }
} }
} }

View File

@ -29,6 +29,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
@Override @Override
public void started(DependencyChecker dependencyChecker) { public void started(DependencyChecker dependencyChecker) {
allClassesNode = dependencyChecker.createNode(); allClassesNode = dependencyChecker.createNode();
allClassesNode.setTag("JavaScriptBody:global");
} }
@Override @Override
@ -47,6 +48,12 @@ public class JavaScriptBodyDependency implements DependencyListener {
if (graph.getResult() != null) { if (graph.getResult() != null) {
allClassesNode.connect(graph.getResult()); 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()) { if (javacall != null && javacall.getBoolean()) {
String body = annot.getValue("body").getString(); String body = annot.getValue("body").getString();
new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body); new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body);

View File

@ -55,7 +55,7 @@ public class JavaScriptBodyGenerator implements Generator {
writer.append(",").ws(); writer.append(",").ws();
writer.append(context.getParameterName(i + 1)); writer.append(context.getParameterName(i + 1));
} }
writer.append(");"); writer.append(");").softNewLine();
} }
private static class GeneratorJsCallback extends JsCallback { private static class GeneratorJsCallback extends JsCallback {

View File

@ -15,7 +15,7 @@
*/ */
package org.teavm.html4j.test; package org.teavm.html4j.test;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import net.java.html.js.JavaScriptBody; import net.java.html.js.JavaScriptBody;
import org.junit.Test; import org.junit.Test;
@ -29,15 +29,28 @@ public class JavaScriptBodyTests {
assertEquals(23, simpleNativeMethod()); assertEquals(23, simpleNativeMethod());
} }
@JavaScriptBody(args = {}, body = "return 23;")
private native int simpleNativeMethod();
@Test @Test
public void dependencyPropagated() { public void dependencyPropagated() {
A a = (A)returnValuePassed(new AImpl()); A a = (A)returnValuePassed(new AImpl());
assertEquals(23, a.foo()); 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 { private static interface A {
public int foo(); public int foo();
} }
@ -46,6 +59,16 @@ public class JavaScriptBodyTests {
return 23; return 23;
} }
} }
@JavaScriptBody(args = {}, body = "return 23;")
private native int simpleNativeMethod();
@JavaScriptBody(args = { "value" }, body = "return value;") @JavaScriptBody(args = { "value" }, body = "return value;")
private native Object returnValuePassed(Object 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();
} }