6894807: problem with interfaces in C2 type system

Vladimir Kozlov Vladimir.Kozlov at Sun.COM
Mon Oct 26 15:07:20 PDT 2009


John, Tom

I need your help with this.

The original implementation of TypeOopPtr::filter() was done by John
and pushed by Ross for:

6467870: Fixes to monotonically narrow or widen types during igvn

Ross Knippel wrote:
 > This change is from John Rose (I'm just the medium.)
 > It's a piece extracted from his current work.

It did not have the bug's problem since an interface could not be exact.

Then Tom added the klass part for:

6788347: C2Compiler crash 6u7

Which causes the problem since interface klass could be exact (constant,
as in the bug's case) and casting j.l.O klass to interface's ptr
returns incorrectly exact j.l.O klass:

     return ktkp->cast_to_ptr_type(ftkp->ptr());

The fix is either simple return original j.l.o klass:

     return kills;

or cast to ptrs meet:

     return ktkp->cast_to_ptr_type(ktkp->meet_ptr(ftkp->ptr()));

Both of them fixed the problem. But I am not sure since in
both cases we loose the precision of interface klass which
allows more ideal optimizations (for example, for CmpP).

Thanks,
Vladimir

Vladimir Kozlov wrote:
> I am investigating 6894807: No ClassCastException for HashAttributeSet 
> constructors if run with -Xcomp
> 
> Because of Escape Analysis is on by default all constructors are inlined
> in the test case and object scalar replaced. But due to, I think,
> the problem in C2 type system the result is incorrect.
> 
> We should check if interface is exact before replacing
> it with j.l.O in TypeOopPtr::filter() for the case
> (exact interface klass)->filter(j.l.O klass).
> 
> Vladimir
> 
> ----------------------------------------------------------------
> Test code expects ClassCastException exception:
> 
> import javax.print.attribute.Attribute;
> import javax.print.attribute.AttributeSet;
> import javax.print.attribute.DocAttribute;
> import javax.print.attribute.HashAttributeSet;
> import javax.print.attribute.standard.JobState;
> 
>         try {
>             new MyHashAttributeSet(JobState.CANCELED, DocAttribute.class);
>             System.out.println("No ClassCastException in t2!");
>         } catch (ClassCastException _) {
>         }
> 
> EA forces to inline all constructors for MyHashAttributeSet:
> 
> class MyHashAttributeSet extends HashAttributeSet{
>     MyHashAttributeSet(Attribute attribute,
>                            Class interfaceName){
>         super(attribute, interfaceName);
>     }
> 
> then
> 
>     protected HashAttributeSet(Attribute attribute, Class<?> 
> interfaceName) {
>         if (interfaceName == null) {
>             throw new NullPointerException("null interface");
>         }
>         myInterface = interfaceName;
>         add (attribute);
>     }
> 
> add() is inlined also:
> 
>     public boolean add(Attribute attribute) {
>         Object oldAttribute =
>             attrMap.put(attribute.getCategory(),
>                         AttributeSetUtilities.
>                         verifyAttributeValue(attribute, myInterface));
>         return (!attribute.equals(oldAttribute));
>     }
> 
> and verifyAttributeValue(attribute, myInterface) is inlined as well:
> 
>     public static Attribute
>         verifyAttributeValue(Object object, Class<?> interfaceName) {
> 
>         if (object == null) {
>             throw new NullPointerException();
>         }
>         else if (interfaceName.isInstance (object)) {
>             return (Attribute) object;
>         } else {
>             throw new ClassCastException();
>         }
>     }
> 
> object is JobState.CANCELED which is
> 
>     public static final JobState CANCELED = new JobState (7);
> 
> and interfaceName is DocAttribute.class where
> 
> public interface DocAttribute extends Attribute {}
> 
> ----------------------------------------------------------------
> So we end up with
> 
> (DocAttribute.class).isInstance(JobState.CANCELED)
> 
> We have intrinsic for isInstance() for which we generated
> 
>   // Now load the mirror's klass metaobject, and null-check it.
>   // Side-effects region with the control path if the klass is null.
>   Node* kls = load_klass_from_mirror(mirror, never_see_null, nargs,
>                                      region, _prim_path);
> 
>   case vmIntrinsics::_isInstance:
>     // nothing is an instance of a primitive type
>     query_value = gen_instanceof(obj, kls);
> 
> where due to NULL check we have next CastPP for DocAttribute.class:
> [t at 19 l at 19]: print kls->dump(1)
>  390    LoadKlass       === _  7  389  [[ 391  396 ]]  @rawptr:BotPTR, 
> idx=Raw; # *  Klass: * !jvms: 
> AttributeSetUtilities::verifyAttributeValue @ bci:14 
> HashAttributeSet::add @ bci:15 HashAttributeSet::<init> @ bci:36 
> MyHashAttributeSet::<init> @ bci:3 InstanceCheck::t2 @ bci:10
>  395    IfTrue  ===  393  [[ 370  396 ]] #1 !jvms: 
> AttributeSetUtilities::verifyAttributeValue @ bci:14 
> HashAttributeSet::add @ bci:15 HashAttributeSet::<init> @ bci:36 
> MyHashAttributeSet::<init> @ bci:3 InstanceCheck::t2 @ bci:10
>  396    CastPP  ===  395  390  [[ 409  409  413  432  427 ]]  #klass 
> java/lang/Object: 0x0811c7e0 *  Klass:klass java/lang/Object: 0x0811c7e0 
> * !jvms: AttributeSetUtilities::verifyAttributeValue @ bci:14 
> HashAttributeSet::add @ bci:15 HashAttributeSet::<init> @ bci:36 
> MyHashAttributeSet::<init> @ bci:3 InstanceCheck::t2 @ bci:10
> 
> During IGVN LoadKlass(390) transformed to constant klass which is 
> interface:
> 
>  702    ConP    ===  0  [[ 396  391 ]]  #precise klass 
> javax/print/attribute/DocAttribute: 0x08407298:Constant:exact *  
> Interface:precise klass javax/print/attribute/DocAttribute: 
> 0x08407298:Constant:exact *
>  396    CastPP  ===  395  702  [[ 409  409  413  432  427 ]]  #klass 
> java/lang/Object: 0x0811c7e0 *  Klass:klass java/lang/Object: 0x0811c7e0 
> * !jvms: AttributeSetUtilities::verifyAttributeValue @ bci:14 
> HashAttributeSet::add @ bci:15 HashAttributeSet::<init> @ bci:36 
> MyHashAttributeSet::<init> @ bci:3 InstanceCheck::t2 @ bci:10
> 
> ConstraintCastNode::Value() calls TypeOopPtr::filter() method
> which, I think, returns incorrect result:
> 
> [t at 19 l at 19]: print ft->dump()
> precise klass javax/print/attribute/DocAttribute: 
> 0x08407298:Constant:exact *
> 
> [t at 19 l at 19]: print ftkp->klass()->print()
> <ciInstanceKlass name=javax/print/attribute/DocAttribute loader=0x0 
> loaded=true initialized=false finalized=false subklass=false size=9 
> flags=public,interface,abstract mirror=PRESENT ident=655 PERM 
> address=0x8407298>
> 
> [t at 19 l at 19]: print ktkp->klass()->print()
> <ciInstanceKlass name=java/lang/Object loader=0x0 loaded=true 
> initialized=true finalized=false subklass=true size=8 flags=public,super 
> mirror=PRESENT ident=558 PERM address=0x811c7e0>ktkp->klass()->print() = 
> (void)
> 
> because of this code:
> 
>   // If we have an interface-typed Phi or cast and we narrow to a class 
> type,
>   // the join should report back the class.  However, if we have a 
> J/L/Object
>   // class-typed Phi and an interface flows in, it's possible that the 
> meet &
>   // join report an interface back out.  This isn't possible but happens
>   // because the type system doesn't interact well with interfaces.
> 
>   if (ftkp != NULL && ktkp != NULL &&
>       ftkp->is_loaded() &&  ftkp->klass()->is_interface() &&
>       ktkp->is_loaded() && !ktkp->klass()->is_interface()) {
>     // Happens in a CTW of rt.jar, 320-341, no extra flags
>     return ktkp->cast_to_ptr_type(ftkp->ptr());
>   }
> 
> the result is
> 
> precise klass java/lang/Object: 0x0811c7e0:Constant:exact *
> 
> which leads to incorrect result from CmpP node:
> 
>  703    ConP    ===  0  [[ 704  432  704 ]]  #precise klass 
> java/lang/Object: 0x0811c7e0:Constant:exact *  Klass:precise klass 
> java/lang/Object: 0x0811c7e0:Constant:exact *
>  704    CmpP    === _  703  703  [[ 705 ]]  !orig=[413] !jvms: 
> AttributeSetUtilities::verifyAttributeValue @ bci:14 
> HashAttributeSet::add @ bci:15 HashAttributeSet::<init> @ bci:36 
> MyHashAttributeSet::<init> @ bci:3 InstanceCheck::t2 @ bci:10
> 


More information about the hotspot-compiler-dev mailing list