< prev index next >

src/hotspot/share/classfile/verificationType.cpp

Print this page
@@ -62,19 +62,22 @@
      if (log_is_enabled(Debug, class, resolve)) {
        Verifier::trace_class_resolution(this_class, klass);
      }
    }
  
+   if (this_class->access_flags().is_inline_type()) return false;
    if (this_class->is_interface() && (!from_field_is_protected ||
        from_name != vmSymbols::java_lang_Object())) {
      // If we are not trying to access a protected field or method in
      // java.lang.Object then, for arrays, we only allow assignability
-     // to interfaces java.lang.Cloneable and java.io.Serializable.
+     // to interfaces java.lang.Cloneable, java.io.Serializable,
+     // and java.lang.IdentityObject.
      // Otherwise, we treat interfaces as java.lang.Object.
      return !from_is_array ||
        this_class == vmClasses::Cloneable_klass() ||
-       this_class == vmClasses::Serializable_klass();
+       this_class == vmClasses::Serializable_klass() ||
+       this_class == vmClasses::IdentityObject_klass();
    } else if (from_is_object) {
      Klass* from_class;
      if (klass->is_hidden() && klass->name() == from_name) {
        from_class = klass;
      } else {

@@ -122,18 +125,86 @@
      return resolve_and_check_assignability(klass, name(), from.name(),
            from_field_is_protected, from.is_array(), from.is_object(), THREAD);
    } else if (is_array() && from.is_array()) {
      VerificationType comp_this = get_component(context);
      VerificationType comp_from = from.get_component(context);
+ 
+ /*
+     // This code implements non-covariance between inline type arrays and both
+     // arrays of objects and arrays of interface types.  If covariance is
+     // supported for inline type arrays then this code should be removed.
+     if (comp_from.is_inline_type() && !comp_this.is_null() && comp_this.is_reference()) {
+       // An array of inline types is not assignable to an array of java.lang.Objects.
+       if (comp_this.name() == vmSymbols::java_lang_Object()) {
+         return false;
+       }
+ 
+       // Need to load 'comp_this' to see if it is an interface.
+       InstanceKlass* klass = context->current_class();
+       {
+         HandleMark hm(THREAD);
+         Klass* comp_this_class = SystemDictionary::resolve_or_fail(
+             comp_this.name(), Handle(THREAD, klass->class_loader()),
+             Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+         klass->class_loader_data()->record_dependency(comp_this_class);
+         if (log_is_enabled(Debug, class, resolve)) {
+           Verifier::trace_class_resolution(comp_this_class, klass);
+         }
+         // An array of inline types is not assignable to an array of interface types.
+         if (comp_this_class->is_interface()) {
+           return false;
+         }
+       }
+     }
+ */
      if (!comp_this.is_bogus() && !comp_from.is_bogus()) {
        return comp_this.is_component_assignable_from(comp_from, context,
                                                      from_field_is_protected, THREAD);
      }
    }
    return false;
  }
  
+ bool VerificationType::is_inline_type_assignable_from(const VerificationType& from) const {
+   // Check that 'from' is not null, is an inline type, and is the same inline type.
+   assert(is_inline_type(), "called with a non-inline type");
+   assert(!is_null(), "inline type is not null");
+   return (!from.is_null() && from.is_inline_type() && name() == from.name());
+ }
+ 
+ bool VerificationType::is_ref_assignable_from_inline_type(const VerificationType& from, ClassVerifier* context, TRAPS) const {
+   assert(!from.is_null(), "Inline type should not be null");
+   if (!is_null() && (name()->is_same_fundamental_type(from.name()) ||
+       name() == vmSymbols::java_lang_Object())) {
+     return true;
+   }
+ 
+   // Need to load 'this' to see if it is an interface or supertype.
+   InstanceKlass* klass = context->current_class();
+   {
+     HandleMark hm(THREAD);
+     Klass* this_class = SystemDictionary::resolve_or_fail(
+         name(), Handle(THREAD, klass->class_loader()),
+         Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+     klass->class_loader_data()->record_dependency(this_class);
+     if (log_is_enabled(Debug, class, resolve)) {
+       Verifier::trace_class_resolution(this_class, klass);
+     }
+     if (this_class->is_interface()) {
+       return true;
+     } else {
+       Klass* from_class = SystemDictionary::resolve_or_fail(
+         from.name(), Handle(THREAD, klass->class_loader()),
+         Handle(THREAD, klass->protection_domain()), true, CHECK_false);
+       if (log_is_enabled(Debug, class, resolve)) {
+         Verifier::trace_class_resolution(from_class, klass);
+       }
+       return from_class->is_subclass_of(this_class);
+     }
+   }
+ }
+ 
  VerificationType VerificationType::get_component(ClassVerifier *context) const {
    assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array");
    SignatureStream ss(name(), false);
    ss.skip_array_prefix(1);
    switch (ss.type()) {

@@ -144,17 +215,20 @@
      case T_INT:     return VerificationType(Integer);
      case T_LONG:    return VerificationType(Long);
      case T_FLOAT:   return VerificationType(Float);
      case T_DOUBLE:  return VerificationType(Double);
      case T_ARRAY:
-     case T_OBJECT: {
+     case T_OBJECT:
+     case T_INLINE_TYPE: {
        guarantee(ss.is_reference(), "unchecked verifier input?");
        Symbol* component = ss.as_symbol();
        // Create another symbol to save as signature stream unreferences this symbol.
        Symbol* component_copy = context->create_temporary_symbol(component);
        assert(component_copy == component, "symbols don't match");
-       return VerificationType::reference_type(component_copy);
+       return (ss.type() == T_INLINE_TYPE) ?
+         VerificationType::inline_type(component_copy) :
+         VerificationType::reference_type(component_copy);
     }
     default:
       // Met an invalid type signature, e.g. [X
       return VerificationType::bogus_type();
    }

@@ -176,18 +250,22 @@
      case Double:           st->print("double"); break;
      case Long_2nd:         st->print("long_2nd"); break;
      case Double_2nd:       st->print("double_2nd"); break;
      case Null:             st->print("null"); break;
      case ReferenceQuery:   st->print("reference type"); break;
+     case InlineTypeQuery:  st->print("inline type"); break;
+     case NonScalarQuery:   st->print("reference or inline type"); break;
      case Category1Query:   st->print("category1 type"); break;
      case Category2Query:   st->print("category2 type"); break;
      case Category2_2ndQuery: st->print("category2_2nd type"); break;
      default:
        if (is_uninitialized_this()) {
          st->print("uninitializedThis");
        } else if (is_uninitialized()) {
          st->print("uninitialized %d", bci());
+       } else if (is_inline_type()) {
+         name()->print_Qvalue_on(st);
        } else {
          if (name() != NULL) {
            name()->print_value_on(st);
          } else {
            st->print_cr("NULL");
< prev index next >