Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8267948: [lword] Core reflection and method handles support for L/Q model #436

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -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;
@@ -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");

@@ -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
@@ -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;
}
@@ -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);
@@ -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(";");
@@ -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);
@@ -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);
@@ -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;
@@ -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);
@@ -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;

@@ -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);
@@ -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);
@@ -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") \
@@ -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

@@ -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;
}

@@ -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);
@@ -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];

@@ -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; ) {
@@ -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
//
@@ -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;
@@ -26,6 +26,7 @@

#include "precompiled.hpp"
#include "jni.h"
#include "jni.h"
#include "jvm.h"
#include "ci/ciReplay.hpp"
#include "classfile/altHashing.hpp"
@@ -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
@@ -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);
@@ -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);
@@ -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;
}
@@ -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() {