Le 21/09/2010 21:48, Tom Rodriguez a écrit :
Thanks for the test case. The reason it works well for C1 is that we have an
explicit check for single implementor interfaces and insert an extra checkcast
to confirm that the type really is the type we expect. The extra check is
needed since interface types aren't actually checked by the verifier. In your
example the extra check isn't actually needed since all array stores are
actually type checked so any type loaded from the array must actually implement
the interface. C2 generally relies on type profiling to get cases like this
but since type profiling is tracking the type of the receiver instead of the
actual method being invoked it doesn't handle this case that well. It's not
hard to do something better for this case. I filed 6986483 for this.
tom
Thanks Tom,
I know since a long time that the verifier doesn't check interface but
I have discovered recently the runtime implication.
I wonder if the fix can improve performance of benchmarks that use
java.util collection,
because this API uses a similar class hierarchy scheme.
Rémi
On Sep 18, 2010, at 11:25 AM, Rémi Forax wrote:
I take a little time to create a simple test case to reproduce a bug
found by Charles Nutter with c2.
see
http://groups.google.com/group/jvm-languages/browse_thread/thread/6c9e05ecd28fdcd4#
Here is the test case,
There is 3 classes A, B, C that inherit from AbstractFoo that implements Foo.
The method test do a virtual call to check() and because
check() is implemented in AbstractFoo we expect that this call should be
de-virtualized then inlined.
c2 fails, foo.check() is compiled as a virtual call :(
With c1, there is no problem, CHA works correctly.
Rémi
------------------------------------------------------------------------------------------------
public class InlineTest {
interface Foo {
public boolean check(int generation);
}
static class AbstractFoo implements Foo {
private final int value;
protected AbstractFoo(int value) {
this.value = value;
}
public boolean check(int generation) {
return this.getClass().hashCode() - value == generation;
}
}
static class A extends AbstractFoo {
public A(int value) {
super(value);
}
}
static class B extends AbstractFoo {
public B(int value) {
super(value);
}
}
static class C extends AbstractFoo {
public C(int value) {
super(value);
}
}
private static final int CONST = A.class.hashCode();
private static int count;
private static void test(Foo foo) {
if (foo.check(0)) {
count += 2;
//System.out.println("foo");
} else {
count += 1;
//System.out.println("bar");
}
}
public static void main(String[] args) {
Foo[] array = new Foo[100000];
int threshold = 20000;
for(int i=0; i<threshold; i++) {
array[i] = new A(CONST);
}
for(int i=threshold; i<array.length; i++) {
array[i] = (i%2 == 0)? new B(0): new C(CONST);
}
for(int i=0; i<array.length; i++) {
test(array[i]);
}
System.out.println(count);
}
}
--
You received this message because you are subscribed to the Google Groups "JVM
Languages" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/jvm-languages?hl=en.