< prev index next >

src/hotspot/share/oops/constantPool.cpp

Print this page
@@ -43,10 +43,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"

@@ -226,11 +227,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
      }
    }

@@ -245,10 +246,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
  // Archive the resolved references

@@ -388,12 +390,13 @@
      resolved_references() != NULL ? resolved_references()->length() : 0);
    set_resolved_references(OopHandle());
  
    int num_klasses = 0;
    for (int index = 1; index < length(); index++) { // Index 0 is unused
+     jbyte qdesc_bit = tag_at(index).is_Qdescriptor_klass() ? (jbyte) JVM_CONSTANT_QDescBit : 0;
      if (tag_at(index).is_unresolved_klass_in_error()) {
-       tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
+       tag_at_put(index, JVM_CONSTANT_UnresolvedClass | qdesc_bit);
      } else if (tag_at(index).is_method_handle_in_error()) {
        tag_at_put(index, JVM_CONSTANT_MethodHandle);
      } else if (tag_at(index).is_method_type_in_error()) {
        tag_at_put(index, JVM_CONSTANT_MethodType);
      } else if (tag_at(index).is_dynamic_constant_in_error()) {

@@ -414,11 +417,11 @@
          CPKlassSlot kslot = klass_slot_at(index);
          int resolved_klass_index = kslot.resolved_klass_index();
          int name_index = kslot.name_index();
          assert(tag_at(name_index).is_symbol(), "sanity");
          resolved_klasses()->at_put(resolved_klass_index, NULL);
-         tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
+         tag_at_put(index, JVM_CONSTANT_UnresolvedClass | qdesc_bit);
          assert(klass_name_at(index) == symbol_at(name_index), "sanity");
        }
      }
    }
    if (cache() != NULL) {

@@ -464,10 +467,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*.

@@ -501,31 +510,59 @@
      ShouldNotReachHere();
    }
  
    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 = NULL;
+     if (k->is_objArray_klass()) {
+       bottom_klass = ObjArrayKlass::cast(k)->bottom_klass();
+       assert(bottom_klass != NULL, "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 != NULL, "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 != NULL, "must be resolved if exception was cleared");

@@ -540,15 +577,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, NULL);

@@ -980,11 +1021,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:
      {

@@ -1898,10 +1941,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;

@@ -1940,10 +1989,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: {

@@ -2111,10 +2164,11 @@
          break;
        }
        case JVM_CONSTANT_Class:
        case JVM_CONSTANT_UnresolvedClass:
        case JVM_CONSTANT_UnresolvedClassInError: {
+         assert(!tag_at(idx).is_Qdescriptor_klass(), "Failed to encode QDesc");
          *bytes = JVM_CONSTANT_Class;
          Symbol* sym = klass_name_at(idx);
          idx1 = tbl->symbol_to_value(sym);
          assert(idx1 != 0, "Have not found a hashtable entry");
          Bytes::put_Java_u2((address) (bytes+1), idx1);
< prev index next >