8024930: Re-enable disabled bridging tests

Reviewed-by: psandoz, rfield
This commit is contained in:
Brian Goetz 2013-10-30 14:12:16 -04:00
parent 9d30f46219
commit 6dcdc5b742
4 changed files with 109 additions and 71 deletions

View File

@ -46,7 +46,7 @@ public class Compiler {
USECACHE // Keeps results around for reuse. Only use this is
// you're sure that each compilation name maps to the
// same source code
};
}
private static final AtomicInteger counter = new AtomicInteger();
private static final String targetDir = "gen-separate";
@ -85,7 +85,7 @@ public class Compiler {
}
public void setFlags(Flags ... flags) {
this.flags = new HashSet<Flags>(Arrays.asList(flags));
this.flags = new HashSet<>(Arrays.asList(flags));
}
public void addPostprocessor(ClassFilePreprocessor cfp) {
@ -131,17 +131,10 @@ public class Compiler {
outputDirs.put(type.getName(), outDir);
Class superClass = type.getSuperclass();
if (superClass != null) {
for( Map.Entry<String,File> each : compileHierarchy(superClass).entrySet()) {
outputDirs.put(each.getKey(), each.getValue());
}
}
for (Extends ext : type.getSupertypes()) {
Type iface = ext.getType();
for( Map.Entry<String,File> each : compileHierarchy(iface).entrySet()) {
outputDirs.put(each.getKey(), each.getValue());
}
}
if (superClass != null)
outputDirs.putAll(compileHierarchy(superClass));
for (Extends ext : type.getSupertypes())
outputDirs.putAll(compileHierarchy(ext.getType()));
return outputDirs;
}
@ -157,8 +150,12 @@ public class Compiler {
SourceProcessor accum =
(name, src) -> { files.add(new SourceFile(name, src)); };
for (Type dep : type.typeDependencies()) {
dep.generateAsDependency(accum, type.methodDependencies());
Collection<Type> deps = type.typeDependencies(type.isFullCompilation());
for (Type dep : deps) {
if (type.isFullCompilation())
dep.generate(accum);
else
dep.generateAsDependency(accum, type.methodDependencies());
}
type.generate(accum);
@ -185,7 +182,7 @@ public class Compiler {
StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir));
} catch (IOException e) {
throw new RuntimeException(
"IOException encountered during compilation");
"IOException encountered during compilation", e);
}
Boolean result = ct.call();
if (result == Boolean.FALSE) {

View File

@ -48,7 +48,7 @@ public class SourceModel {
generate(pw);
return sw.toString();
}
};
}
public static class AccessFlag extends Element {
private String flag;
@ -125,6 +125,7 @@ public class SourceModel {
// (and thus will be present in stubs)
private Set<Method> methodDependencies;
private List<Type> typeDependencies;
private boolean fullCompilation;
protected Type(String name,
List<AccessFlag> flags, List<TypeParameter> params,
@ -214,6 +215,14 @@ public class SourceModel {
methodDependencies.add(m);
}
public boolean isFullCompilation() {
return fullCompilation;
}
public void setFullCompilation(boolean fullCompilation) {
this.fullCompilation = fullCompilation;
}
// Convenience method for creating an Extends object using this
// class and specified type arguments.
public Extends with(String ... args) {
@ -255,14 +264,23 @@ public class SourceModel {
pw.println("}");
}
public Collection<Type> typeDependencies() {
public Collection<Type> typeDependencies(boolean recursive) {
HashMap<String,Type> dependencies = new HashMap<>();
Type superclass = getSuperclass();
if (superclass != null) {
dependencies.put(superclass.getName(), superclass);
if (recursive) {
for (Type t : superclass.typeDependencies(true))
dependencies.put(t.getName(), t);
}
}
for (Extends e : getSupertypes())
for (Extends e : getSupertypes()) {
dependencies.put(e.getType().getName(), e.getType());
if (recursive) {
for (Type t : e.getType().typeDependencies(true))
dependencies.put(t.getName(), t);
}
}
// Do these last so that they override
for (Type t : this.typeDependencies)
dependencies.put(t.getName(), t);

View File

@ -198,7 +198,7 @@ public class TestHarness {
assertEquals(res, value);
}
} catch (InvocationTargetException | IllegalAccessException e) {
fail("Unexpected exception thrown: " + e.getCause());
fail("Unexpected exception thrown: " + e.getCause(), e.getCause());
}
}
@ -227,8 +227,7 @@ public class TestHarness {
* a return type of 'int', and no arguments.
*/
public void assertInvokeVirtualEquals(int value, Class target) {
assertInvokeVirtualEquals(
new Integer(value), target, stdCM, "-1");
assertInvokeVirtualEquals(value, target, stdCM, "-1");
}
/**
@ -260,12 +259,31 @@ public class TestHarness {
Compiler compiler = compilerLocal.get();
compiler.setFlags(compilerFlags());
assertInvokeInterfaceEquals(
new Integer(value), target, new Extends(iface), stdAM);
assertInvokeInterfaceEquals(value, target, new Extends(iface), stdAM);
compiler.cleanup();
}
protected void assertInvokeInterfaceThrows(java.lang.Class<? extends Throwable> errorClass,
Class target, Extends iface, AbstractMethod method,
String... args) {
try {
assertInvokeInterfaceEquals(0, target, iface, method, args);
fail("Expected exception: " + errorClass);
}
catch (AssertionError e) {
Throwable cause = e.getCause();
if (cause == null)
throw e;
else if ((errorClass.isAssignableFrom(cause.getClass()))) {
// this is success
return;
}
else
throw e;
}
}
/**
* Creates a class which calls target::method(args) via invokevirtual,
* compiles and loads both the new class and 'target', and then invokes

View File

@ -25,18 +25,22 @@
package org.openjdk.tests.vm;
import java.lang.reflect.*;
import java.util.*;
import java.io.File;
import java.io.IOException;
import org.testng.annotations.Test;
import org.openjdk.tests.separate.*;
import org.openjdk.tests.separate.Compiler;
import org.openjdk.tests.separate.TestHarness;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import static org.openjdk.tests.separate.SourceModel.*;
import static org.openjdk.tests.separate.SourceModel.AbstractMethod;
import static org.openjdk.tests.separate.SourceModel.AccessFlag;
import static org.openjdk.tests.separate.SourceModel.Class;
import static org.openjdk.tests.separate.SourceModel.ConcreteMethod;
import static org.openjdk.tests.separate.SourceModel.DefaultMethod;
import static org.openjdk.tests.separate.SourceModel.Extends;
import static org.openjdk.tests.separate.SourceModel.Interface;
import static org.openjdk.tests.separate.SourceModel.MethodParameter;
import static org.openjdk.tests.separate.SourceModel.TypeParameter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
@Test(groups = "vm")
public class DefaultMethodsTest extends TestHarness {
@ -186,7 +190,7 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: D d = new D(); d.m() == 22;
* TEST: I i = new D(); i.m() == 22;
*/
void testExistingInheritedOverride() {
public void testExistingInheritedOverride() {
Interface I = new Interface("I", DefaultMethod.std("99"));
Class C = new Class("C", I, ConcreteMethod.std("11"));
Class D = new Class("D", C, ConcreteMethod.std("22"));
@ -258,7 +262,6 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: C c = new C(); c.m() throws ICCE
*/
public void testConflict() {
// debugTest();
Interface I = new Interface("I", DefaultMethod.std("99"));
Interface J = new Interface("J", DefaultMethod.std("88"));
Class C = new Class("C", I, J);
@ -390,19 +393,16 @@ public class DefaultMethodsTest extends TestHarness {
/**
* interface I<T> { default int m(T t) { return 99; } }
* Class C implements I<String> { public int m() { return 88; } }
* Class C implements I<String> { public int m(String s) { return 88; } }
*
* TEST: C c = new C(); c.m() == 88;
* TEST: I i = new C(); i.m() == 88;
* TEST: C c = new C(); c.m("string") == 88;
* TEST: I i = new C(); i.m("string") == 88;
*/
@Test(enabled=false)
public void testSelfFill() {
// This test ensures that a concrete method overrides a default method
// that matches at the language-level, but has a different method
// signature due to erasure.
// debugTest();
DefaultMethod dm = new DefaultMethod(
"int", "m", "return 99;", new MethodParameter("T", "t"));
ConcreteMethod cm = new ConcreteMethod(
@ -415,9 +415,11 @@ public class DefaultMethodsTest extends TestHarness {
AbstractMethod pm = new AbstractMethod(
"int", "m", new MethodParameter("T", "t"));
assertInvokeVirtualEquals(new Integer(88), C, cm, "-1", "\"string\"");
assertInvokeInterfaceEquals(
new Integer(88), C, I.with("String"), pm, "\"string\"");
assertInvokeVirtualEquals(88, C, cm, "-1", "\"string\"");
assertInvokeInterfaceEquals(99, C, I.with("String"), pm, "\"string\"");
C.setFullCompilation(true); // Force full bridge generation
assertInvokeInterfaceEquals(88, C, I.with("String"), pm, "\"string\"");
}
/**
@ -485,7 +487,6 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: J<String,String> j = new C(); j.m("A","B","C") == 88;
* TEST: K<String> k = new C(); k.m("A","B","C") == 88;
*/
@Test(enabled=false)
public void testBridges() {
DefaultMethod dm = new DefaultMethod("int", stdMethodName, "return 99;",
new MethodParameter("T", "t"), new MethodParameter("V", "v"),
@ -518,13 +519,17 @@ public class DefaultMethodsTest extends TestHarness {
J.with("String", "T"), pm2);
Class C = new Class("C", K.with("String"), cm);
// First, without compiler bridges
String[] args = new String[] { "\"A\"", "\"B\"", "\"C\"" };
assertInvokeInterfaceEquals(new Integer(88), C,
I.with("String", "String", "String"), pm0, args);
assertInvokeInterfaceEquals(new Integer(88), C,
J.with("String", "String"), pm1, args);
assertInvokeInterfaceEquals(new Integer(88), C,
K.with("String"), pm2, args);
assertInvokeInterfaceEquals(99, C, I.with("String", "String", "String"), pm0, args);
assertInvokeInterfaceThrows(AbstractMethodError.class, C, J.with("String", "String"), pm1, args);
assertInvokeInterfaceThrows(AbstractMethodError.class, C, K.with("String"), pm2, args);
// Then with compiler bridges
C.setFullCompilation(true);
assertInvokeInterfaceEquals(88, C, I.with("String", "String", "String"), pm0, args);
assertInvokeInterfaceEquals(88, C, J.with("String", "String"), pm1, args);
assertInvokeInterfaceEquals(88, C, K.with("String"), pm2, args);
}
/**
@ -536,8 +541,6 @@ public class DefaultMethodsTest extends TestHarness {
* TEST: I i = new C(); i.m() == 88;
*/
public void testSuperBasic() {
// debugTest();
Interface J = new Interface("J", DefaultMethod.std("88"));
Interface I = new Interface("I", J, new DefaultMethod(
"int", stdMethodName, "return J.super.m();"));
@ -559,8 +562,6 @@ public class DefaultMethodsTest extends TestHarness {
* TODO: add case for K k = new C(); k.m() throws ICCE
*/
public void testSuperConflict() {
// debugTest();
Interface K = new Interface("K", DefaultMethod.std("99"));
Interface L = new Interface("L", DefaultMethod.std("101"));
Interface J = new Interface("J", K, L);
@ -635,8 +636,7 @@ public class DefaultMethodsTest extends TestHarness {
AbstractMethod pm = new AbstractMethod("int", stdMethodName,
new MethodParameter("String", "s"));
assertInvokeInterfaceEquals(
new Integer(88), C, new Extends(I), pm, "\"\"");
assertInvokeInterfaceEquals(88, C, new Extends(I), pm, "\"\"");
}
/**
@ -674,7 +674,6 @@ public class DefaultMethodsTest extends TestHarness {
* class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger;
* TEST: S s = new S(); s.foo() == new Integer(99)
*/
@Test(enabled=false)
public void testCovarBridge() {
Interface I = new Interface("I", new DefaultMethod(
"Integer", "m", "return new Integer(88);"));
@ -692,7 +691,8 @@ public class DefaultMethodsTest extends TestHarness {
S.addCompilationDependency(Dstub);
S.addCompilationDependency(DstubMethod);
assertInvokeVirtualEquals(new Integer(99), S, toCall, "null");
// NEGATIVE test for separate compilation -- dispatches to I, not C
assertInvokeVirtualEquals(88, S, toCall, "null");
}
/**
@ -719,7 +719,7 @@ public class DefaultMethodsTest extends TestHarness {
S.addCompilationDependency(Dstub);
S.addCompilationDependency(DstubMethod);
assertInvokeVirtualEquals(new Integer(88), S, toCall, "null");
assertInvokeVirtualEquals(88, S, toCall, "null");
}
/**
@ -757,7 +757,6 @@ public class DefaultMethodsTest extends TestHarness {
* Test that a erased-signature-matching method does not implement
* non-language-level matching methods
*/
@Test(enabled=false)
public void testNonConcreteFill() {
AbstractMethod ipm = new AbstractMethod("int", "m",
new MethodParameter("T", "t"),
@ -781,13 +780,14 @@ public class DefaultMethodsTest extends TestHarness {
new MethodParameter("T", "t"),
new MethodParameter("String", "s"),
new MethodParameter("String", "w"));
DefaultMethod kdm = new DefaultMethod("int", "m", "return 99;",
new MethodParameter("T", "t"),
new MethodParameter("String", "v"),
new MethodParameter("String", "w"));
Interface K = new Interface("K",
new TypeParameter("T"),
J.with("T", "String"),
new DefaultMethod("int", "m", "return 99;",
new MethodParameter("T", "t"),
new MethodParameter("String", "v"),
new MethodParameter("String", "w")));
kdm);
Class C = new Class("C",
K.with("String"),
@ -797,13 +797,18 @@ public class DefaultMethodsTest extends TestHarness {
new MethodParameter("Object", "v"),
new MethodParameter("String", "w")));
// First, without compiler bridges
String a = "\"\"";
assertInvokeInterfaceEquals(99, C,
K.with("String"), kpm, a, a, a);
assertInvokeInterfaceEquals(77, C,
J.with("String", "String"), jpm, a, a, a);
assertInvokeInterfaceEquals(99, C,
I.with("String", "String", "String"), ipm, a, a, a);
assertInvokeInterfaceEquals(99, C, K.with("String"), kpm, a, a, a);
assertInvokeInterfaceEquals(77, C, J.with("String", "String"), jpm, a, a, a);
assertInvokeInterfaceThrows(AbstractMethodError.class, C, I.with("String", "String", "String"), ipm, a, a, a);
// Now, with bridges
J.setFullCompilation(true);
K.setFullCompilation(true);
assertInvokeInterfaceEquals(99, C, K.with("String"), kpm, a, a, a);
assertInvokeInterfaceEquals(77, C, J.with("String", "String"), jpm, a, a, a);
assertInvokeInterfaceEquals(99, C, I.with("String", "String", "String"), ipm, a, a, a);
}
public void testStrictfpDefault() {