Skip to content
Permalink
Browse files
8267948: [lword] Core reflection and method handles support for L/Q m…
…odel

Reviewed-by: fparain, rriggs
  • Loading branch information
Mandy Chung committed Jun 7, 2021
1 parent 477ecf5 commit d9d96e8c8df1546a9930fba89a081c10b1a52349
Showing with 631 additions and 337 deletions.
  1. +69 −12 src/hotspot/share/classfile/javaClasses.cpp
  2. +12 −0 src/hotspot/share/classfile/javaClasses.hpp
  3. +18 −0 src/hotspot/share/classfile/javaClasses.inline.hpp
  4. +2 −0 src/hotspot/share/classfile/vmSymbols.hpp
  5. +3 −1 src/hotspot/share/interpreter/interpreterRuntime.cpp
  6. +3 −1 src/hotspot/share/oops/constantPool.cpp
  7. +12 −0 src/hotspot/share/oops/inlineKlass.hpp
  8. +5 −1 src/hotspot/share/oops/instanceKlass.cpp
  9. +1 −0 src/hotspot/share/oops/instanceKlass.hpp
  10. +0 −2 src/hotspot/share/oops/klass.hpp
  11. +13 −2 src/hotspot/share/prims/jni.cpp
  12. +7 −3 src/hotspot/share/runtime/reflection.cpp
  13. +2 −1 src/hotspot/share/runtime/signature.cpp
  14. +77 −138 src/java.base/share/classes/java/lang/Class.java
  15. +6 −9 src/java.base/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
  16. +2 −1 src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
  17. +3 −2 src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java
  18. +4 −3 src/java.base/share/classes/java/lang/invoke/MemberName.java
  19. +8 −10 src/java.base/share/classes/java/lang/invoke/MethodHandles.java
  20. +10 −2 src/java.base/share/classes/java/lang/invoke/MethodType.java
  21. +35 −22 src/java.base/share/classes/java/lang/invoke/ValueBootstrapMethods.java
  22. +6 −0 src/java.base/share/classes/java/lang/invoke/VarHandle.java
  23. +1 −1 src/java.base/share/classes/java/lang/invoke/VarHandles.java
  24. +4 −4 src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template
  25. +3 −2 src/java.base/share/classes/java/lang/reflect/Constructor.java
  26. +8 −0 src/java.base/share/classes/java/lang/reflect/Executable.java
  27. +12 −3 src/java.base/share/classes/java/lang/reflect/Field.java
  28. +4 −3 src/java.base/share/classes/java/lang/reflect/Method.java
  29. +1 −1 src/java.base/share/classes/java/lang/reflect/Proxy.java
  30. +7 −2 src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
  31. +2 −2 src/java.base/share/classes/jdk/internal/misc/Unsafe.java
  32. +6 −2 src/java.base/share/classes/jdk/internal/reflect/UnsafeFieldAccessorImpl.java
  33. +2 −1 src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java
  34. +5 −5 src/java.base/share/classes/sun/invoke/util/VerifyAccess.java
  35. +9 −9 test/hotspot/jtreg/runtime/valhalla/inlinetypes/EmptyInlineTest.java
  36. +2 −2 test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java
  37. +1 −1 test/hotspot/jtreg/runtime/valhalla/inlinetypes/ObjectMethods.java
  38. +4 −3 test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java
  39. +193 −0 test/jdk/valhalla/valuetypes/BasicTest.java
  40. +3 −3 test/jdk/valhalla/valuetypes/InlineConstructorTest.java
  41. +12 −9 test/jdk/valhalla/valuetypes/MethodHandleTest.java
  42. +4 −3 test/jdk/valhalla/valuetypes/ObjectMethods.java
  43. +13 −15 test/jdk/valhalla/valuetypes/QTypeDescriptorTest.java
  44. +28 −47 test/jdk/valhalla/valuetypes/Reflection.java
  45. +1 −1 test/jdk/valhalla/valuetypes/StaticInitFactoryTest.java
  46. +5 −5 test/jdk/valhalla/valuetypes/ValueArray.java
  47. +3 −3 test/langtools/tools/javac/valhalla/lworld-values/SplitPrimitiveClassNestHostTest.java
@@ -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() {

0 comments on commit d9d96e8

Please sign in to comment.