Navigation Menu

Skip to content

Commit

Permalink
8267948: [lword] Core reflection and method handles support for L/Q m…
Browse files Browse the repository at this point in the history
…odel
  • Loading branch information
mlchung committed Jun 3, 2021
1 parent 477ecf5 commit be0b5c2
Show file tree
Hide file tree
Showing 47 changed files with 631 additions and 337 deletions.
81 changes: 69 additions & 12 deletions src/hotspot/share/classfile/javaClasses.cpp
Expand Up @@ -816,6 +816,8 @@ int java_lang_Class::_class_loader_offset;
int java_lang_Class::_module_offset;
int java_lang_Class::_protection_domain_offset;
int java_lang_Class::_component_mirror_offset;
int java_lang_Class::_primary_mirror_offset;
int java_lang_Class::_secondary_mirror_offset;
int java_lang_Class::_init_lock_offset;
int java_lang_Class::_signers_offset;
int java_lang_Class::_name_offset;
Expand Down Expand Up @@ -1052,16 +1054,21 @@ void java_lang_Class::create_mirror(Klass* k, Handle class_loader,
if (k->is_flatArray_klass()) {
Klass* element_klass = (Klass*) FlatArrayKlass::cast(k)->element_klass();
assert(element_klass->is_inline_klass(), "Must be inline type component");
InlineKlass* vk = InlineKlass::cast(InstanceKlass::cast(element_klass));
comp_mirror = Handle(THREAD, vk->java_mirror());
InlineKlass* vk = InlineKlass::cast(element_klass);
comp_mirror = Handle(THREAD, vk->val_mirror());
} else if (k->is_typeArray_klass()) {
BasicType type = TypeArrayKlass::cast(k)->element_type();
comp_mirror = Handle(THREAD, Universe::java_mirror(type));
} else {
assert(k->is_objArray_klass(), "Must be");
Klass* element_klass = ObjArrayKlass::cast(k)->element_klass();
assert(element_klass != NULL, "Must have an element klass");
comp_mirror = Handle(THREAD, element_klass->java_mirror());
oop comp_oop = element_klass->java_mirror();
if (element_klass->is_inline_klass()) {
InlineKlass* ik = InlineKlass::cast(element_klass);
comp_oop = k->name()->is_Q_array_signature() ? ik->val_mirror() : ik->ref_mirror();
}
comp_mirror = Handle(THREAD, comp_oop);
}
assert(comp_mirror() != NULL, "must have a mirror");

Expand Down Expand Up @@ -1101,11 +1108,38 @@ void java_lang_Class::create_mirror(Klass* k, Handle class_loader,
// concurrently doesn't expect a k to have a null java_mirror.
release_set_array_klass(comp_mirror(), k);
}

if (k->is_inline_klass()) {
oop secondary_mirror = create_secondary_mirror(k, mirror, CHECK);
set_primary_mirror(mirror(), mirror());
set_secondary_mirror(mirror(), secondary_mirror);
}
} else {
assert(fixup_mirror_list() != NULL, "fixup_mirror_list not initialized");
fixup_mirror_list()->push(k);
}
}
// Create the secondary mirror for inline class. Sets all the fields of this java.lang.Class
// instance with the same value as the primary mirror
oop java_lang_Class::create_secondary_mirror(Klass* k, Handle mirror, TRAPS) {
assert(k->is_inline_klass(), "primitive class");
// Allocate mirror (java.lang.Class instance)
oop mirror_oop = InstanceMirrorKlass::cast(vmClasses::Class_klass())->allocate_instance(k, CHECK_0);
Handle secondary_mirror(THREAD, mirror_oop);

java_lang_Class::set_klass(secondary_mirror(), k);
java_lang_Class::set_static_oop_field_count(secondary_mirror(), static_oop_field_count(mirror()));
// ## do we need to set init lock?
java_lang_Class::set_init_lock(secondary_mirror(), init_lock(mirror()));

set_protection_domain(secondary_mirror(), protection_domain(mirror()));
set_class_loader(secondary_mirror(), class_loader(mirror()));
// ## handle if java.base is not yet defined
set_module(secondary_mirror(), module(mirror()));
set_primary_mirror(secondary_mirror(), mirror());
set_secondary_mirror(secondary_mirror(), secondary_mirror());
return secondary_mirror();
}

#if INCLUDE_CDS_JAVA_HEAP
// Clears mirror fields. Static final fields with initial values are reloaded
Expand Down Expand Up @@ -1252,7 +1286,7 @@ oop java_lang_Class::archive_mirror(Klass* k) {
}

if (k->is_inline_klass()) {
// Inline types have a val type mirror and a ref type mirror. Don't handle this for now. TODO:CDS
// Inline types have a primary mirror and a secondary mirror. Don't handle this for now. TODO:CDS
k->clear_java_mirror_handle();
return NULL;
}
Expand Down Expand Up @@ -1472,6 +1506,26 @@ oop java_lang_Class::component_mirror(oop java_class) {
return java_class->obj_field(_component_mirror_offset);
}

oop java_lang_Class::primary_mirror(oop java_class) {
assert(_primary_mirror_offset != 0, "must be set");
return java_class->obj_field(_primary_mirror_offset);
}

void java_lang_Class::set_primary_mirror(oop java_class, oop mirror) {
assert(_primary_mirror_offset != 0, "must be set");
java_class->obj_field_put(_primary_mirror_offset, mirror);
}

oop java_lang_Class::secondary_mirror(oop java_class) {
assert(_secondary_mirror_offset != 0, "must be set");
return java_class->obj_field(_secondary_mirror_offset);
}

void java_lang_Class::set_secondary_mirror(oop java_class, oop mirror) {
assert(_secondary_mirror_offset != 0, "must be set");
java_class->obj_field_put(_secondary_mirror_offset, mirror);
}

oop java_lang_Class::init_lock(oop java_class) {
assert(_init_lock_offset != 0, "must be set");
return java_class->obj_field(_init_lock_offset);
Expand Down Expand Up @@ -1575,25 +1629,21 @@ void java_lang_Class::print_signature(oop java_class, outputStream* st) {
assert(java_lang_Class::is_instance(java_class), "must be a Class object");
Symbol* name = NULL;
bool is_instance = false;
bool is_value = false;
bool is_Q_descriptor = false;
if (is_primitive(java_class)) {
name = vmSymbols::type_signature(primitive_type(java_class));
} else {
Klass* k = as_Klass(java_class);
is_instance = k->is_instance_klass();
is_value = k->is_inline_klass();
is_Q_descriptor = k->is_inline_klass() && is_secondary_mirror(java_class);
name = k->name();
}
if (name == NULL) {
st->print("<null>");
return;
}
if (is_instance) {
if (is_value) {
st->print("Q");
} else {
st->print("L");
}
st->print(is_Q_descriptor ? "Q" : "L");
}
st->write((char*) name->base(), (int) name->utf8_length());
if (is_instance) st->print(";");
Expand All @@ -1615,7 +1665,12 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found)
name->increment_refcount();
} else {
ResourceMark rm;
const char* sigstr = k->signature_name();
const char* sigstr;
if (k->is_inline_klass() && is_secondary_mirror(java_class)) {
sigstr = InlineKlass::cast(k)->val_signature_name();
} else {
sigstr = k->signature_name();
}
int siglen = (int) strlen(sigstr);
if (!intern_if_not_found) {
name = SymbolTable::probe(sigstr, siglen);
Expand Down Expand Up @@ -1696,6 +1751,8 @@ oop java_lang_Class::primitive_mirror(BasicType t) {
macro(_classRedefinedCount_offset, k, "classRedefinedCount", int_signature, false); \
macro(_class_loader_offset, k, "classLoader", classloader_signature, false); \
macro(_component_mirror_offset, k, "componentType", class_signature, false); \
macro(_primary_mirror_offset, k, "primaryType", class_signature, false); \
macro(_secondary_mirror_offset, k, "secondaryType", class_signature, false); \
macro(_module_offset, k, "module", module_signature, false); \
macro(_name_offset, k, "name", string_signature, false); \
macro(_classData_offset, k, "classData", object_signature, false);
Expand Down
12 changes: 12 additions & 0 deletions src/hotspot/share/classfile/javaClasses.hpp
Expand Up @@ -245,6 +245,9 @@ class java_lang_Class : AllStatic {
static int _class_loader_offset;
static int _module_offset;
static int _component_mirror_offset;
static int _primary_mirror_offset;
static int _secondary_mirror_offset;

static int _name_offset;
static int _source_file_offset;
static int _classData_offset;
Expand All @@ -259,6 +262,9 @@ class java_lang_Class : AllStatic {
static void set_protection_domain(oop java_class, oop protection_domain);
static void set_class_loader(oop java_class, oop class_loader);
static void set_component_mirror(oop java_class, oop comp_mirror);
static void set_primary_mirror(oop java_class, oop comp_mirror);
static void set_secondary_mirror(oop java_class, oop comp_mirror);

static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain,
Handle classData, TRAPS);
static void set_mirror_module_field(JavaThread* current, Klass* K, Handle mirror, Handle module);
Expand All @@ -271,6 +277,7 @@ class java_lang_Class : AllStatic {
Handle protection_domain, Handle classData, TRAPS);
static void fixup_mirror(Klass* k, TRAPS);
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
static oop create_secondary_mirror(Klass* k, Handle mirror, TRAPS);
static void update_archived_primitive_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN;
static void update_archived_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN;

Expand Down Expand Up @@ -318,6 +325,11 @@ class java_lang_Class : AllStatic {
set_init_lock(java_class, NULL);
}
static oop component_mirror(oop java_class);
static oop primary_mirror(oop java_class);
static oop secondary_mirror(oop java_class);
static bool is_primary_mirror(oop java_class);
static bool is_secondary_mirror(oop java_class);

static objArrayOop signers(oop java_class);
static void set_signers(oop java_class, objArrayOop signers);
static oop class_data(oop java_class);
Expand Down
18 changes: 18 additions & 0 deletions src/hotspot/share/classfile/javaClasses.inline.hpp
Expand Up @@ -234,6 +234,24 @@ inline bool java_lang_Class::is_primitive(oop java_class) {
return is_primitive;
}

inline bool java_lang_Class::is_primary_mirror(oop java_class) {
Klass* k = as_Klass(java_class);
if (k->is_inline_klass()) {
return java_class == primary_mirror(java_class);
} else {
return true;
}
}

inline bool java_lang_Class::is_secondary_mirror(oop java_class) {
Klass* k = as_Klass(java_class);
if (k->is_inline_klass()) {
return java_class == secondary_mirror(java_class);
} else {
return false;
}
}

inline int java_lang_Class::oop_size_raw(oop java_class) {
assert(_oop_size_offset != 0, "must be set");
int size = java_class->int_field_raw(_oop_size_offset);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/classfile/vmSymbols.hpp
Expand Up @@ -687,6 +687,8 @@
template(classRedefinedCount_name, "classRedefinedCount") \
template(classLoader_name, "classLoader") \
template(componentType_name, "componentType") \
template(primaryType_name, "primaryType") \
template(secondaryType_name, "secondaryType") \
\
/* forEachRemaining support */ \
template(java_util_stream_StreamsRangeIntSpliterator, "java/util/stream/Streams$RangeIntSpliterator") \
Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/share/interpreter/interpreterRuntime.cpp
Expand Up @@ -160,7 +160,9 @@ JRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* current, bool wide))

assert (tag.is_unresolved_klass() || tag.is_klass(), "wrong ldc call");
Klass* klass = pool->klass_at(index, CHECK);
oop java_class = klass->java_mirror();
oop java_class = tag.is_Qdescriptor_klass()
? InlineKlass::cast(klass)->val_mirror()
: klass->java_mirror();
current->set_vm_result(java_class);
JRT_END

Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/share/oops/constantPool.cpp
Expand Up @@ -1046,7 +1046,9 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
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;
}

Expand Down
12 changes: 12 additions & 0 deletions src/hotspot/share/oops/inlineKlass.hpp
Expand Up @@ -142,6 +142,18 @@ class InlineKlass: public InstanceKlass {
// Type testing
bool is_inline_klass_slow() const { return true; }

// ref and val mirror
oop ref_mirror() const { return java_mirror(); }
oop val_mirror() const { return java_lang_Class::secondary_mirror(java_mirror()); }

// naming
const char* ref_signature_name() const {
return InstanceKlass::signature_name_of_carrier(JVM_SIGNATURE_CLASS);
}
const char* val_signature_name() const {
return InstanceKlass::signature_name_of_carrier(JVM_SIGNATURE_INLINE_TYPE);
}

// Iterators
virtual void array_klasses_do(void f(Klass* k));
virtual void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
Expand Down
6 changes: 5 additions & 1 deletion src/hotspot/share/oops/instanceKlass.cpp
Expand Up @@ -2874,6 +2874,10 @@ void InstanceKlass::set_source_debug_extension(const char* array, int length) {
}

const char* InstanceKlass::signature_name() const {
return signature_name_of_carrier(JVM_SIGNATURE_CLASS);
}

const char* InstanceKlass::signature_name_of_carrier(char c) const {
int hash_len = 0;
char hash_buf[40];

Expand All @@ -2892,7 +2896,7 @@ const char* InstanceKlass::signature_name() const {

// Add L or Q as type indicator
int dest_index = 0;
dest[dest_index++] = JVM_SIGNATURE_CLASS;
dest[dest_index++] = c;

// Add the actual class name
for (int src_index = 0; src_index < src_length; ) {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/oops/instanceKlass.hpp
Expand Up @@ -1261,6 +1261,7 @@ class InstanceKlass: public Klass {

// Naming
const char* signature_name() const;
const char* signature_name_of_carrier(char c) const;

// Oop fields (and metadata) iterators
//
Expand Down
2 changes: 0 additions & 2 deletions src/hotspot/share/oops/klass.hpp
Expand Up @@ -591,8 +591,6 @@ class Klass : public Metadata {
// For arrays, this returns the name of the element with a leading '['.
// For classes, this returns the name with a leading 'L' and a trailing ';'
// and the package separators as '/'.
// For value classes, this returns the name with a leading 'Q' and a trailing ';'
// and the package separators as '/'.
virtual const char* signature_name() const;

const char* joint_in_module_of_loader(const Klass* class2, bool include_parent_loader = false) const;
Expand Down
15 changes: 13 additions & 2 deletions src/hotspot/share/prims/jni.cpp
Expand Up @@ -26,6 +26,7 @@

#include "precompiled.hpp"
#include "jni.h"
#include "jni.h"
#include "jvm.h"
#include "ci/ciReplay.hpp"
#include "classfile/altHashing.hpp"
Expand Down Expand Up @@ -498,8 +499,18 @@ JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jc
Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
jboolean ret = sub_klass->is_subtype_of(super_klass) ?
JNI_TRUE : JNI_FALSE;
jboolean ret;
if (sub_klass == super_klass && sub_klass->is_inline_klass()) {
// val type is a subtype of ref type
InlineKlass* ik = InlineKlass::cast(sub_klass);
if (sub_mirror == super_mirror || (ik->val_mirror() == sub_mirror && ik->ref_mirror() == super_mirror)) {
ret = JNI_TRUE;
} else {
ret = JNI_FALSE;
}
} else {
ret = sub_klass->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE;
}
HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
return ret;
JNI_END
Expand Down
10 changes: 7 additions & 3 deletions src/hotspot/share/runtime/reflection.cpp
Expand Up @@ -349,7 +349,7 @@ arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
if (k->is_array_klass() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
if (k->is_inline_klass()) {
if (k->is_inline_klass() && java_lang_Class::is_secondary_mirror(element_mirror)) {
return oopFactory::new_flatArray(k, length, THREAD);
} else {
return oopFactory::new_objArray(k, length, THREAD);
Expand Down Expand Up @@ -394,7 +394,11 @@ arrayOop Reflection::reflect_new_multi_array(oop element_mirror, typeArrayOop di
dim += k_dim;
}
}
klass = klass->array_klass(dim, CHECK_NULL);
if (klass->is_inline_klass() && java_lang_Class::is_secondary_mirror(element_mirror)) {
klass = InlineKlass::cast(klass)->null_free_inline_array_klass(dim, CHECK_NULL);
} else {
klass = klass->array_klass(dim, CHECK_NULL);
}
oop obj = ArrayKlass::cast(klass)->multi_allocate(len, dimensions, CHECK_NULL);
assert(obj->is_array(), "just checking");
return arrayOop(obj);
Expand Down Expand Up @@ -1185,7 +1189,7 @@ oop Reflection::invoke_method(oop method_mirror, Handle receiver, objArrayHandle
if (java_lang_Class::is_primitive(return_type_mirror)) {
rtype = basic_type_mirror_to_basic_type(return_type_mirror);
} else if (java_lang_Class::as_Klass(return_type_mirror)->is_inline_klass()) {
rtype = T_INLINE_TYPE;
rtype = java_lang_Class::is_primary_mirror(return_type_mirror) ? T_OBJECT : T_INLINE_TYPE;
} else {
rtype = T_OBJECT;
}
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/runtime/signature.cpp
Expand Up @@ -436,7 +436,8 @@ oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domai
if (klass == NULL) {
return NULL;
}
return klass->java_mirror();
return has_Q_descriptor() ? InlineKlass::cast(klass)->val_mirror()
: klass->java_mirror();
}

void SignatureStream::skip_to_return_type() {
Expand Down

0 comments on commit be0b5c2

Please sign in to comment.