changeset 55117:aabb0a86787a lworld

8223017: [lworld] checkcast/instance broken for LW2 arrays Reviewed-by: fparain
author dsimms
date Fri, 10 May 2019 10:25:57 +0200
parents ac891b47cc41
children baa7d191cc28
files src/hotspot/cpu/x86/templateTable_x86.cpp src/hotspot/share/classfile/classFileParser.cpp src/hotspot/share/interpreter/interpreterRuntime.cpp src/hotspot/share/oops/constantPool.cpp src/hotspot/share/oops/constantPool.hpp src/hotspot/share/oops/objArrayKlass.cpp src/hotspot/share/oops/valueArrayKlass.cpp src/hotspot/share/oops/valueArrayKlass.hpp src/hotspot/share/utilities/constantTag.cpp src/hotspot/share/utilities/constantTag.hpp test/hotspot/jtreg/runtime/valhalla/valuetypes/ValueTypeArray.java test/langtools/tools/javac/valhalla/lworld-values/ArrayRelationsTest.java
diffstat 12 files changed, 66 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp	Fri May 10 10:25:57 2019 +0200
@@ -370,7 +370,7 @@
 
   // get type
   __ movzbl(rdx, Address(rax, rbx, Address::times_1, tags_offset));
-  __ andl(rdx, ~JVM_CONSTANT_QDESC_BIT);
+  __ andl(rdx, ~JVM_CONSTANT_QDescBit);
 
   // unresolved class - get the resolved class
   __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass);
@@ -4469,7 +4469,7 @@
   __ movzbl(rdx, Address(rdx, rbx,
       Address::times_1,
       Array<u1>::base_offset_in_bytes()));
-  __ andl (rdx, ~JVM_CONSTANT_QDESC_BIT);
+  __ andl (rdx, ~JVM_CONSTANT_QDescBit);
   __ cmpl(rdx, JVM_CONSTANT_Class);
   __ jcc(Assembler::equal, quicked);
   __ push(atos); // save receiver for result, and for GC
@@ -4525,8 +4525,8 @@
     __ movzbl(rcx, Address(rdx, rbx,
         Address::times_1,
         Array<u1>::base_offset_in_bytes()));
-    __ andl (rcx, JVM_CONSTANT_QDESC_BIT);
-    __ cmpl(rcx, JVM_CONSTANT_QDESC_BIT);
+    __ andl (rcx, JVM_CONSTANT_QDescBit);
+    __ cmpl(rcx, JVM_CONSTANT_QDescBit);
     __ jcc(Assembler::notEqual, done);
     __ jump(ExternalAddress(Interpreter::_throw_NullPointerException_entry));
   }
@@ -4547,7 +4547,7 @@
   __ movzbl(rdx, Address(rdx, rbx,
         Address::times_1,
         Array<u1>::base_offset_in_bytes()));
-  __ andl (rdx, ~JVM_CONSTANT_QDESC_BIT);
+  __ andl (rdx, ~JVM_CONSTANT_QDescBit);
   __ cmpl(rdx, JVM_CONSTANT_Class);
   __ jcc(Assembler::equal, quicked);
 
--- a/src/hotspot/share/classfile/classFileParser.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Fri May 10 10:25:57 2019 +0200
@@ -501,7 +501,7 @@
 
         Symbol* const name = cp->symbol_at(class_index);
         const unsigned int name_len = name->utf8_length();
-        if (name->is_Q_signature() || name->is_Q_array_signature()) {
+        if (name->is_Q_signature()) {
           cp->unresolved_qdescriptor_at_put(index, class_index, num_klasses++);
         } else {
           cp->unresolved_klass_at_put(index, class_index, num_klasses++);
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp	Fri May 10 10:25:57 2019 +0200
@@ -482,7 +482,7 @@
   ConstantPool* constants = last_frame.method()->constants();
   int i = last_frame.get_index_u2(Bytecodes::_multianewarray);
   Klass* klass = constants->klass_at(i, CHECK);
-  bool is_qtype = constants->tag_at(i).is_Qdescriptor_klass();
+  bool is_qtype = klass->name()->is_Q_array_signature();
   int   nof_dims = last_frame.number_of_dimensions();
   assert(klass->is_klass(), "not a class");
   assert(nof_dims >= 1, "multianewarray rank must be nonzero");
--- a/src/hotspot/share/oops/constantPool.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/oops/constantPool.cpp	Fri May 10 10:25:57 2019 +0200
@@ -235,7 +235,7 @@
 
   // The interpreter assumes when the tag is stored, the klass is resolved
   // and the Klass* non-NULL, so we need hardware store ordering here.
-  jbyte qdesc_bit = (name->is_Q_signature() || name->is_Q_array_signature()) ? (jbyte)JVM_CONSTANT_QDESC_BIT : 0;
+  jbyte qdesc_bit = (name->is_Q_signature()) ? (jbyte) JVM_CONSTANT_QDescBit : 0;
   if (k != NULL) {
     release_tag_at_put(class_index, JVM_CONSTANT_Class | qdesc_bit);
   } else {
@@ -253,7 +253,7 @@
 
   // The interpreter assumes when the tag is stored, the klass is resolved
   // and the Klass* non-NULL, so we need hardware store ordering here.
-  assert(!(k->name()->is_Q_signature() || k->name()->is_Q_array_signature()), "Q-type without JVM_CONSTANT_QDESC_BIT");
+  assert(!k->name()->is_Q_signature(), "Q-type without JVM_CONSTANT_QDescBit");
   release_tag_at_put(class_index, JVM_CONSTANT_Class);
 }
 
@@ -551,7 +551,7 @@
   // hardware store ordering here.
   jbyte tag = JVM_CONSTANT_Class;
   if (this_cp->tag_at(which).is_Qdescriptor_klass()) {
-    tag |= JVM_CONSTANT_QDESC_BIT;
+    tag |= JVM_CONSTANT_QDescBit;
   }
   this_cp->release_tag_at_put(which, tag);
   return k;
@@ -1989,7 +1989,7 @@
         ent_size = 2;
         break;
       }
-      case (JVM_CONSTANT_Class | JVM_CONSTANT_QDESC_BIT): {
+      case (JVM_CONSTANT_Class | JVM_CONSTANT_QDescBit): {
         idx1 = Bytes::get_Java_u2(bytes);
         printf("qclass        #%03d", idx1);
         ent_size = 2;
@@ -2037,7 +2037,7 @@
         printf("UnresolvedClass: %s", WARN_MSG);
         break;
       }
-      case (JVM_CONSTANT_UnresolvedClass | JVM_CONSTANT_QDESC_BIT): {
+      case (JVM_CONSTANT_UnresolvedClass | JVM_CONSTANT_QDescBit): {
         printf("UnresolvedQClass: %s", WARN_MSG);
         break;
       }
--- a/src/hotspot/share/oops/constantPool.hpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/oops/constantPool.hpp	Fri May 10 10:25:57 2019 +0200
@@ -282,7 +282,7 @@
   void klass_at_put(int class_index, Klass* k);
 
   void unresolved_qdescriptor_at_put(int which, int name_index, int resolved_klass_index) {
-      release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass | (jbyte)JVM_CONSTANT_QDESC_BIT);
+      release_tag_at_put(which, JVM_CONSTANT_UnresolvedClass | (jbyte) JVM_CONSTANT_QDescBit);
 
       assert((name_index & 0xffff0000) == 0, "must be");
       assert((resolved_klass_index & 0xffff0000) == 0, "must be");
--- a/src/hotspot/share/oops/objArrayKlass.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/oops/objArrayKlass.cpp	Fri May 10 10:25:57 2019 +0200
@@ -59,7 +59,17 @@
                                               int n, Klass* element_klass, TRAPS) {
   // Eagerly allocate the direct array supertype.
   Klass* super_klass = NULL;
-  if (!Universe::is_bootstrapping() || SystemDictionary::Object_klass_loaded()) {
+  if (storage_props.is_null_free()) {
+    assert(!Universe::is_bootstrapping(), "Need bootstrap");
+    // Arrange null ok as direct super
+    super_klass = element_klass->array_klass_or_null(ArrayStorageProperties::empty, n);
+    if (super_klass == NULL) { // allocate super...need to drop the lock
+      MutexUnlocker mu(MultiArray_lock);
+      element_klass->array_klass(ArrayStorageProperties::empty, n, CHECK_NULL);
+      // retry, start from the beginning since lock dropped...
+      return element_klass->array_klass(storage_props, n, CHECK_NULL);
+    }
+  } else if (!Universe::is_bootstrapping() || SystemDictionary::Object_klass_loaded()) {
     Klass* element_super = element_klass->super();
     if (element_super != NULL) {
       // The element type has a direct super.  E.g., String[] has direct super of Object[].
--- a/src/hotspot/share/oops/valueArrayKlass.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/oops/valueArrayKlass.cpp	Fri May 10 10:25:57 2019 +0200
@@ -81,9 +81,7 @@
   _element_klass = k;
 }
 
-ValueArrayKlass* ValueArrayKlass::allocate_klass(Klass*  element_klass,
-                                                 Symbol* name,
-                                                 TRAPS) {
+ValueArrayKlass* ValueArrayKlass::allocate_klass(Klass* element_klass, TRAPS) {
   assert(ValueArrayFlatten, "Flatten array required");
   assert(ValueKlass::cast(element_klass)->is_atomic() || (!ValueArrayAtomicAccess), "Atomic by-default");
 
@@ -93,45 +91,18 @@
    *  TODO refactor any remaining commonality
    */
 
-  // Eagerly allocate the direct array supertype.
-  Klass* super_klass = NULL;
-  if (!Universe::is_bootstrapping() || SystemDictionary::Object_klass_loaded()) {
-    Klass* element_super = element_klass->super();
-    if (element_super != NULL) {
-      // The element type has a direct super.  E.g., String[] has direct super of Object[].
-      super_klass = element_super->array_klass_or_null(ArrayStorageProperties::empty);
-      bool supers_exist = super_klass != NULL;
-      // Also, see if the element has secondary supertypes.
-      // We need an array type for each.
-      Array<Klass*>* element_supers = element_klass->secondary_supers();
-      for( int i = element_supers->length()-1; i >= 0; i-- ) {
-        Klass* elem_super = element_supers->at(i);
-        if (elem_super->array_klass_or_null(ArrayStorageProperties::empty) == NULL) {
-          supers_exist = false;
-          break;
-        }
-      }
-      if (!supers_exist) {
-        // Oops.  Not allocated yet.  Back out, allocate it, and retry.
-        Klass* ek = NULL;
-        {
-          MutexUnlocker mu(MultiArray_lock);
-          super_klass = element_super->array_klass(CHECK_0);
-          for( int i = element_supers->length()-1; i >= 0; i-- ) {
-            Klass* elem_super = element_supers->at(i);
-            elem_super->array_klass(CHECK_0);
-          }
-          // Now retry from the beginning
-          ek = element_klass->array_klass(ArrayStorageProperties::flattened_and_null_free, 1, CHECK_0);
-        }  // re-lock
-        return ValueArrayKlass::cast(ek);
-      }
-    } else {
-      ShouldNotReachHere(); // Value array klass cannot be the object array klass
-    }
+  // Eagerly allocate the direct array supertype, which would be "[L<vt>;" for this "[Q<vt>;"
+  Klass* super_klass = element_klass->array_klass_or_null(ArrayStorageProperties::empty);
+  if (super_klass == NULL) {
+    MutexUnlocker mu(MultiArray_lock);
+    // allocate super...need to drop the lock
+    element_klass->array_klass(ArrayStorageProperties::empty, 1, CHECK_NULL);
+    // retry, start from the beginning since lock dropped...
+    Klass* ak = element_klass->array_klass(ArrayStorageProperties::flattened_and_null_free, 1, CHECK_NULL);
+    return ValueArrayKlass::cast(ak);
   }
 
-
+  Symbol* name = ArrayKlass::create_element_klass_array_name(true, element_klass, CHECK_NULL);
   ClassLoaderData* loader_data = element_klass->class_loader_data();
   int size = ArrayKlass::static_size(ValueArrayKlass::header_size());
   ValueArrayKlass* vak = new (loader_data, size, THREAD) ValueArrayKlass(element_klass, name);
@@ -145,8 +116,7 @@
 
 ValueArrayKlass* ValueArrayKlass::allocate_klass(ArrayStorageProperties storage_props, Klass* element_klass, TRAPS) {
   assert(storage_props.is_flattened(), "Expected flat storage");
-  Symbol* name = ArrayKlass::create_element_klass_array_name(true, element_klass, CHECK_NULL);
-  return allocate_klass(element_klass, name, THREAD);
+  return allocate_klass(element_klass, THREAD);
 }
 
 void ValueArrayKlass::initialize(TRAPS) {
--- a/src/hotspot/share/oops/valueArrayKlass.hpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/oops/valueArrayKlass.hpp	Fri May 10 10:25:57 2019 +0200
@@ -43,7 +43,7 @@
   // Constructor
   ValueArrayKlass(Klass* element_klass, Symbol* name);
 
-  static ValueArrayKlass* allocate_klass(Klass* element_klass, Symbol* name, TRAPS);
+  static ValueArrayKlass* allocate_klass(Klass* element_klass, TRAPS);
  protected:
   // Returns the ArrayKlass for n'th dimension.
   Klass* array_klass_impl(ArrayStorageProperties storage_props, bool or_null, int n, TRAPS);
--- a/src/hotspot/share/utilities/constantTag.cpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/utilities/constantTag.cpp	Fri May 10 10:25:57 2019 +0200
@@ -106,7 +106,7 @@
       return "Invalid index";
     case JVM_CONSTANT_Class :
       return "Class";
-    case (JVM_CONSTANT_Class | (jbyte)JVM_CONSTANT_QDESC_BIT):
+    case (JVM_CONSTANT_Class | (jbyte)JVM_CONSTANT_QDescBit):
       return "Q-Descriptor";
     case JVM_CONSTANT_Fieldref :
       return "Field";
--- a/src/hotspot/share/utilities/constantTag.hpp	Mon May 06 11:46:27 2019 +0200
+++ b/src/hotspot/share/utilities/constantTag.hpp	Fri May 10 10:25:57 2019 +0200
@@ -46,11 +46,11 @@
   JVM_CONSTANT_MethodHandleInError      = 104,  // Error tag due to resolution error
   JVM_CONSTANT_MethodTypeInError        = 105,  // Error tag due to resolution error
   JVM_CONSTANT_DynamicInError           = 106,  // Error tag due to resolution error
-  JVM_CONSTANT_InternalMax              = 106   // Last implementation tag
+  JVM_CONSTANT_InternalMax              = 106,  // Last implementation tag
+  // internal constant tag flags
+  JVM_CONSTANT_QDescBit                 = (1 << 7) // Separate bit, encode Q type descriptors
 };
 
-#define JVM_CONSTANT_QDESC_BIT (1 << 7)
-
 class constantTag {
  private:
   jbyte _tag;
@@ -78,7 +78,7 @@
   }
 
   bool is_Qdescriptor_klass() const {
-    return (_tag & JVM_CONSTANT_QDESC_BIT) != 0;
+    return (_tag & JVM_CONSTANT_QDescBit) != 0;
   }
 
   bool is_method_handle_in_error() const {
@@ -121,11 +121,11 @@
     _tag = JVM_CONSTANT_Invalid;
   }
   constantTag(jbyte tag) {
-    jbyte entry_tag = tag & ~JVM_CONSTANT_QDESC_BIT;
-    assert((((tag & JVM_CONSTANT_QDESC_BIT) == 0) && (entry_tag >= 0 && entry_tag <= JVM_CONSTANT_NameAndType) ||
+    jbyte entry_tag = tag & ~JVM_CONSTANT_QDescBit;
+    assert((((tag & JVM_CONSTANT_QDescBit) == 0) && (entry_tag >= 0 && entry_tag <= JVM_CONSTANT_NameAndType) ||
            (entry_tag >= JVM_CONSTANT_MethodHandle && entry_tag <= JVM_CONSTANT_InvokeDynamic) ||
            (entry_tag >= JVM_CONSTANT_InternalMin && entry_tag <= JVM_CONSTANT_InternalMax))
-           || (((tag & JVM_CONSTANT_QDESC_BIT) != 0) && (entry_tag == JVM_CONSTANT_Class ||
+           || (((tag & JVM_CONSTANT_QDescBit) != 0) && (entry_tag == JVM_CONSTANT_Class ||
                entry_tag == JVM_CONSTANT_UnresolvedClass || entry_tag == JVM_CONSTANT_UnresolvedClassInError
                || entry_tag == JVM_CONSTANT_ClassIndex))
                , "Invalid constant tag");
@@ -146,7 +146,7 @@
     return constantTag();
   }
 
-  jbyte value() const                { return _tag & ~JVM_CONSTANT_QDESC_BIT; }
+  jbyte value() const                { return _tag & ~JVM_CONSTANT_QDescBit; }
   jbyte tag() const                  { return _tag; }
   jbyte error_value() const;
   jbyte non_error_value() const;
--- a/test/hotspot/jtreg/runtime/valhalla/valuetypes/ValueTypeArray.java	Mon May 06 11:46:27 2019 +0200
+++ b/test/hotspot/jtreg/runtime/valhalla/valuetypes/ValueTypeArray.java	Fri May 10 10:25:57 2019 +0200
@@ -253,6 +253,7 @@
         MyInt[] myInts = new MyInt[1];
         assertTrue(myInts instanceof Object[]);
         assertTrue(myInts instanceof Comparable[]);
+        assertTrue(myInts instanceof MyInt?[]);
 
         Class<?> cls = MyInt.class.asValueType();
         assertTrue(cls.isValue());
@@ -271,15 +272,30 @@
         MyOtherInt[][] matrix = new MyOtherInt[1][1];
         assertTrue(matrix[0] instanceof MyOtherInt[]);
         assertTrue(matrix[0] instanceof SomeSecondaryType[]);
+        assertTrue(matrix[0] instanceof MyOtherInt?[]);
 
         // Box types vs Inline...
         MyInt?[] myValueRefs = new MyInt?[1];
-        // JDK-8222974
-        //assertTrue(myValueRefs instanceof MyInt?[]);
-        assertFalse(myValueRefs instanceof MyInt[]);
+        assertTrue(myValueRefs instanceof MyInt?[]);
         assertTrue(myValueRefs instanceof Object[]);
         assertTrue(myValueRefs instanceof Comparable[]);
         assertFalse(myValueRefs instanceof MyInt[]);
+
+        MyInt?[][] myMdValueRefs = new MyInt?[1][1];
+        assertTrue(myMdValueRefs[0] instanceof MyInt?[]);
+        assertTrue(myMdValueRefs[0] instanceof Object[]);
+        assertTrue(myMdValueRefs[0] instanceof Comparable[]);
+        assertFalse(myMdValueRefs[0] instanceof MyInt[]);
+
+        // Did we break checkcast...
+        MyInt?[]     va1 = (MyInt?[])null;
+        MyInt?[]     va2 = null;
+        MyInt?[][]   va3 = (MyInt?[][])null;
+        MyInt?[][][] va4 = (MyInt?[][][])null;
+        MyInt[]      va5 = null;
+        MyInt[]      va6 = (MyInt[])null;
+        MyInt[][]    va7 = (MyInt[][])null;
+        MyInt[][][]  va8 = (MyInt[][][])null;
     }
 
 
--- a/test/langtools/tools/javac/valhalla/lworld-values/ArrayRelationsTest.java	Mon May 06 11:46:27 2019 +0200
+++ b/test/langtools/tools/javac/valhalla/lworld-values/ArrayRelationsTest.java	Fri May 10 10:25:57 2019 +0200
@@ -86,15 +86,13 @@
 
         la = new ArrayRelationsTest? [10];
 
-        // NOTE: The following line should trigger a CCE, but doesn't ATM - this will
-        // start failing when the VM is fixed. Flip the condition then.
         cce = false;
         try {
             qa = (ArrayRelationsTest[]) la;
         } catch (ClassCastException c) {
             cce = true;
         }
-        if (cce) {  // <----- Flip this condition.
+        if (!cce) {
             throw new AssertionError("Unexpected CCE behavior");
         }
     }