dependencies bug

Tom Rodriguez tom.rodriguez at oracle.com
Mon Oct 24 16:48:32 PDT 2011


While testing the metadata compiler changes in CTW I hit an assertion failure in dependencies, so this is probably a question for John.  We have the following classes:

public interface javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface01901i{
    public abstract int f1(int, float);
}

public class javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface019c extends java.lang.Object implements javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface01901i{
    public int f1(int, float);
    public javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface019c();
}

public class javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface019d extends javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface019c{
    public static int f1(int, float);
    public javasoft.sqe.tests.vm.invokeinterface.invokeinterface019.invokeinterface01901.invokeinterface019d();
}

Note that the subclass has a static method with the same name and signature as the super.  javac would never allow this but it's a legal class file.  We've got a piece of code roughly like this:

invokeinterface019c  i = new invokeinterface019d();
i.f1(0, 0);

We head down into CHA to bind the method f1 and call check_method_context, where it looks up the method in invokeinterface019d using just the name and signature, which returns the static method.  We then assert because the methods aren't the same.  check_method_context appears to be slightly sloppy about it's checking so I'm assuming it should have a guard like this:

diff -r 8d6869d5ef1a src/share/vm/code/dependencies.cpp                                                                                                
--- a/src/share/vm/code/dependencies.cpp                                                                                                                
+++ b/src/share/vm/code/dependencies.cpp                                                                                                                
@@ -795,6 +795,9 @@
       if (!(lm->is_public() || lm->is_protected()))                                                                                                    
         // Method is [package-]private, so the override story is complex.                                                                              
         return true;  // Must punt the assertion to true.                                                                                              
+      if (lm->is_static())                                                                                                                            
+        // Static doesn't override non-static                                                                                                          
+        return true;  // Punt                                                                                                                          
       if (   !Dependencies::is_concrete_method(lm)                                                                                                    
&& !Dependencies::is_concrete_method(m)                                                                                                      
           && Klass::cast(lm->method_holder())->is_subtype_of(m->method_holder()))

The other interesting bit is that the reason this showed up in the metadata repo is because separation of oops and metadata exposed this mistake, which was fixed:

diff -r 42783d1414b2 src/share/vm/oops/constantPoolKlass.cpp                                                                                            
--- a/src/share/vm/oops/constantPoolKlass.cpp                                                                                                          
+++ b/src/share/vm/oops/constantPoolKlass.cpp                                                                                                          
@@ -532,7 +532,7 @@
     if (cp->tag_at(i).is_unresolved_klass()) {                                                                                                        
       // This will force loading of the class                                                                                                          
       klassOop klass = cp->klass_at(i, CHECK);                                                                                                        
-      if (klass->is_instance()) {                                                                                                                      
+      if (klass->klass_part()->oop_is_instance()) {                                                                                                    
         // Force initialization of class                                                                                                              
instanceKlass::cast(klass)->initialize(CHECK);                                                                                                
       }

The previous code would never succeed because a klass is never an instance, so we weren't actually preloading any classes in the constant pool.

tom


More information about the hotspot-compiler-dev mailing list