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

View File

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

View File

@ -198,7 +198,7 @@ public class TestHarness {
assertEquals(res, value); assertEquals(res, value);
} }
} catch (InvocationTargetException | IllegalAccessException e) { } 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. * a return type of 'int', and no arguments.
*/ */
public void assertInvokeVirtualEquals(int value, Class target) { public void assertInvokeVirtualEquals(int value, Class target) {
assertInvokeVirtualEquals( assertInvokeVirtualEquals(value, target, stdCM, "-1");
new Integer(value), target, stdCM, "-1");
} }
/** /**
@ -260,12 +259,31 @@ public class TestHarness {
Compiler compiler = compilerLocal.get(); Compiler compiler = compilerLocal.get();
compiler.setFlags(compilerFlags()); compiler.setFlags(compilerFlags());
assertInvokeInterfaceEquals( assertInvokeInterfaceEquals(value, target, new Extends(iface), stdAM);
new Integer(value), target, new Extends(iface), stdAM);
compiler.cleanup(); 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, * Creates a class which calls target::method(args) via invokevirtual,
* compiles and loads both the new class and 'target', and then invokes * compiles and loads both the new class and 'target', and then invokes

View File

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