< prev index next >

src/hotspot/share/classfile/verificationType.cpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -52,10 +52,11 @@
       Handle(THREAD, klass->protection_domain()), true, CHECK_false);
   if (log_is_enabled(Debug, class, resolve)) {
     Verifier::trace_class_resolution(this_class, klass);
   }
 
+  if (this_class->access_flags().is_value_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.

@@ -105,18 +106,77 @@
     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, CHECK_false);
     VerificationType comp_from = from.get_component(context, CHECK_false);
+
+/*
+    // This code implements non-covariance between value type arrays and both
+    // arrays of objects and arrays of interface types.  If covariance is
+    // supported for value type arrays then this code should be removed.
+    if (comp_from.is_valuetype() && !comp_this.is_null() && comp_this.is_reference()) {
+      // An array of value 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 value 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_valuetype_assignable_from(const VerificationType& from) const {
+  // Check that 'from' is not null, is a value type, and is the same value type.
+  assert(is_valuetype(), "called with a non-valuetype type");
+  assert(!is_null(), "valuetype is not null");
+  assert(name() != vmSymbols::java_lang_Object(), "java.lang.Object is a value type?");
+  return (!from.is_null() && from.is_valuetype() && name() == from.name());
+}
+
+bool VerificationType::is_ref_assignable_from_value_type(const VerificationType& from, ClassVerifier* context, TRAPS) const {
+  assert(!from.is_null(), "Value 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.
+  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);
+    }
+    return (this_class->is_interface());
+  }
+}
+
 VerificationType VerificationType::get_component(ClassVerifier *context, TRAPS) const {
   assert(is_array() && name()->utf8_length() >= 2, "Must be a valid array");
   Symbol* component;
   switch (name()->char_at(1)) {
     case 'Z': return VerificationType(Boolean);

@@ -135,10 +195,15 @@
     case 'L':
       component = context->create_temporary_symbol(
         name(), 2, name()->utf8_length() - 1,
         CHECK_(VerificationType::bogus_type()));
       return VerificationType::reference_type(component);
+    case 'Q':
+      component = context->create_temporary_symbol(
+        name(), 2, name()->utf8_length() - 1,
+        CHECK_(VerificationType::bogus_type()));
+      return VerificationType::valuetype_type(component);
     default:
       // Met an invalid type signature, e.g. [X
       return VerificationType::bogus_type();
   }
 }

@@ -159,18 +224,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 ValueTypeQuery:   st->print("value type"); break;
+    case NonScalarQuery:   st->print("reference or value 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_valuetype()) {
+        name()->print_Qvalue_on(st);
       } else {
         if (name() != NULL) {
           name()->print_value_on(st);
         } else {
           st->print_cr("NULL");
< prev index next >