< prev index next >

src/hotspot/share/oops/constantPool.cpp

Print this page
@@ -48,10 +48,11 @@
  #include "memory/resourceArea.hpp"
  #include "memory/universe.hpp"
  #include "oops/array.hpp"
  #include "oops/constantPool.inline.hpp"
  #include "oops/cpCache.inline.hpp"
+ #include "oops/flatArrayKlass.hpp"
  #include "oops/instanceKlass.hpp"
  #include "oops/klass.inline.hpp"
  #include "oops/objArrayKlass.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/oop.inline.hpp"

@@ -244,11 +245,11 @@
        break;
  #ifndef PRODUCT
      case JVM_CONSTANT_Class:
      case JVM_CONSTANT_UnresolvedClass:
      case JVM_CONSTANT_UnresolvedClassInError:
-       // All of these should have been reverted back to ClassIndex before calling
+       // All of these should have been reverted back to Unresolved before calling
        // this function.
        ShouldNotReachHere();
  #endif
      }
    }

@@ -263,10 +264,11 @@
    Klass** adr = resolved_klasses()->adr_at(resolved_klass_index);
    Atomic::release_store(adr, k);
  
    // 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(), "Q-type without JVM_CONSTANT_QDescBit");
    release_tag_at_put(class_index, JVM_CONSTANT_Class);
  }
  
  #if INCLUDE_CDS_JAVA_HEAP
  // Returns the _resolved_reference array after removing unarchivable items from it.

@@ -383,11 +385,14 @@
  
    bool archived = false;
    for (int index = 1; index < length(); index++) { // Index 0 is unused
      switch (tag_at(index).value()) {
      case JVM_CONSTANT_UnresolvedClassInError:
-       tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
+       {
+         jbyte qdesc_bit = tag_at(index).is_Qdescriptor_klass() ? (jbyte) JVM_CONSTANT_QDescBit : 0;
+         tag_at_put(index, JVM_CONSTANT_UnresolvedClass | qdesc_bit);
+       }
        break;
      case JVM_CONSTANT_MethodHandleInError:
        tag_at_put(index, JVM_CONSTANT_MethodHandle);
        break;
      case JVM_CONSTANT_MethodTypeInError:

@@ -439,11 +444,12 @@
    }
  
    // This referenced class cannot be archived. Revert the tag to UnresolvedClass,
    // so that the proper class loading and initialization can happen at runtime.
    resolved_klasses()->at_put(resolved_klass_index, nullptr);
-   tag_at_put(cp_index, JVM_CONSTANT_UnresolvedClass);
+   jbyte qdesc_bit = tag_at(cp_index).is_Qdescriptor_klass() ? (jbyte) JVM_CONSTANT_QDescBit : 0;
+   tag_at_put(cp_index, JVM_CONSTANT_UnresolvedClass | qdesc_bit);
    return false;
  }
  #endif // INCLUDE_CDS
  
  int ConstantPool::cp_to_object_index(int cp_index) {

@@ -485,10 +491,16 @@
                   k->external_name());
      }
    }
  }
  
+ void check_is_inline_type(Klass* k, TRAPS) {
+   if (!k->is_inline_klass()) {
+     THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
+   }
+ }
+ 
  Klass* ConstantPool::klass_at_impl(const constantPoolHandle& this_cp, int which,
                                     TRAPS) {
    JavaThread* javaThread = THREAD;
  
    // A resolved constantPool entry will contain a Klass*, otherwise a Symbol*.

@@ -523,31 +535,59 @@
    }
  
    HandleMark hm(THREAD);
    Handle mirror_handle;
    Symbol* name = this_cp->symbol_at(name_index);
+   bool inline_type_signature = false;
+   if (name->is_Q_signature()) {
+     name = name->fundamental_name(THREAD);
+     inline_type_signature = true;
+   }
    Handle loader (THREAD, this_cp->pool_holder()->class_loader());
    Handle protection_domain (THREAD, this_cp->pool_holder()->protection_domain());
  
    Klass* k;
    {
      // Turn off the single stepping while doing class resolution
      JvmtiHideSingleStepping jhss(javaThread);
      k = SystemDictionary::resolve_or_fail(name, loader, protection_domain, true, THREAD);
    } //  JvmtiHideSingleStepping jhss(javaThread);
+   if (inline_type_signature) {
+     name->decrement_refcount();
+   }
  
    if (!HAS_PENDING_EXCEPTION) {
      // preserve the resolved klass from unloading
      mirror_handle = Handle(THREAD, k->java_mirror());
      // Do access check for klasses
      verify_constant_pool_resolve(this_cp, k, THREAD);
    }
  
+   if (!HAS_PENDING_EXCEPTION && inline_type_signature) {
+     check_is_inline_type(k, THREAD);
+   }
+ 
+   if (!HAS_PENDING_EXCEPTION) {
+     Klass* bottom_klass = nullptr;
+     if (k->is_objArray_klass()) {
+       bottom_klass = ObjArrayKlass::cast(k)->bottom_klass();
+       assert(bottom_klass != nullptr, "Should be set");
+       assert(bottom_klass->is_instance_klass() || bottom_klass->is_typeArray_klass(), "Sanity check");
+     } else if (k->is_flatArray_klass()) {
+       bottom_klass = FlatArrayKlass::cast(k)->element_klass();
+       assert(bottom_klass != nullptr, "Should be set");
+     }
+   }
+ 
    // Failed to resolve class. We must record the errors so that subsequent attempts
    // to resolve this constant pool entry fail with the same error (JVMS 5.4.3).
    if (HAS_PENDING_EXCEPTION) {
-     save_and_throw_exception(this_cp, which, constantTag(JVM_CONSTANT_UnresolvedClass), CHECK_NULL);
+     jbyte tag = JVM_CONSTANT_UnresolvedClass;
+     if (this_cp->tag_at(which).is_Qdescriptor_klass()) {
+       tag |= JVM_CONSTANT_QDescBit;
+     }
+     save_and_throw_exception(this_cp, which, constantTag(tag), CHECK_NULL);
      // If CHECK_NULL above doesn't return the exception, that means that
      // some other thread has beaten us and has resolved the class.
      // To preserve old behavior, we return the resolved class.
      Klass* klass = this_cp->resolved_klasses()->at(resolved_klass_index);
      assert(klass != nullptr, "must be resolved if exception was cleared");

@@ -562,15 +602,19 @@
    Klass** adr = this_cp->resolved_klasses()->adr_at(resolved_klass_index);
    Atomic::release_store(adr, k);
    // The interpreter assumes when the tag is stored, the klass is resolved
    // and the Klass* stored in _resolved_klasses is non-null, so we need
    // hardware store ordering here.
+   jbyte tag = JVM_CONSTANT_Class;
+   if (this_cp->tag_at(which).is_Qdescriptor_klass()) {
+     tag |= JVM_CONSTANT_QDescBit;
+   }
    // We also need to CAS to not overwrite an error from a racing thread.
  
    jbyte old_tag = Atomic::cmpxchg((jbyte*)this_cp->tag_addr_at(which),
                                    (jbyte)JVM_CONSTANT_UnresolvedClass,
-                                   (jbyte)JVM_CONSTANT_Class);
+                                   tag);
  
    // We need to recheck exceptions from racing thread and return the same.
    if (old_tag == JVM_CONSTANT_UnresolvedClassInError) {
      // Remove klass.
      this_cp->resolved_klasses()->at_put(resolved_klass_index, nullptr);

@@ -1011,11 +1055,13 @@
    case JVM_CONSTANT_Class:
      {
        assert(cache_index == _no_index_sentinel, "should not have been set");
        Klass* resolved = klass_at_impl(this_cp, index, CHECK_NULL);
        // ldc wants the java mirror.
-       result_oop = resolved->java_mirror();
+       result_oop = tag.is_Qdescriptor_klass()
+                       ? InlineKlass::cast(resolved)->val_mirror()
+                       : resolved->java_mirror();
        break;
      }
  
    case JVM_CONSTANT_Dynamic:
      {

@@ -1930,10 +1976,16 @@
          idx1 = Bytes::get_Java_u2(bytes);
          printf("class        #%03d", idx1);
          ent_size = 2;
          break;
        }
+       case (JVM_CONSTANT_Class | JVM_CONSTANT_QDescBit): {
+         idx1 = Bytes::get_Java_u2(bytes);
+         printf("qclass        #%03d", idx1);
+         ent_size = 2;
+         break;
+       }
        case JVM_CONSTANT_String: {
          idx1 = Bytes::get_Java_u2(bytes);
          printf("String       #%03d", idx1);
          ent_size = 2;
          break;

@@ -1972,10 +2024,14 @@
        }
        case JVM_CONSTANT_UnresolvedClass: {
          printf("UnresolvedClass: %s", WARN_MSG);
          break;
        }
+       case (JVM_CONSTANT_UnresolvedClass | JVM_CONSTANT_QDescBit): {
+         printf("UnresolvedQClass: %s", WARN_MSG);
+         break;
+       }
        case JVM_CONSTANT_UnresolvedClassInError: {
          printf("UnresolvedClassInErr: %s", WARN_MSG);
          break;
        }
        case JVM_CONSTANT_StringIndex: {
< prev index next >