< prev index next > src/hotspot/share/oops/constantPool.cpp
Print this page
#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"
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
}
}
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.
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:
}
// 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) {
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*.
}
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");
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);
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:
{
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;
}
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 >