mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
6964458: Reimplement class meta-data storage to use native memory
Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes Co-authored-by: Stefan Karlsson <stefan.karlsson@oracle.com> Co-authored-by: Mikael Gerdin <mikael.gerdin@oracle.com> Co-authored-by: Tom Rodriguez <tom.rodriguez@oracle.com> Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
This commit is contained in:
parent
36eee7c8c8
commit
5c58d27aac
853 changed files with 26124 additions and 82956 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -124,49 +124,49 @@ Handle MethodHandles::new_MemberName(TRAPS) {
|
|||
}
|
||||
|
||||
oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
|
||||
klassOop target_klass = target_oop->klass();
|
||||
Klass* target_klass = target_oop->klass();
|
||||
if (target_klass == SystemDictionary::reflect_Field_klass()) {
|
||||
oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
|
||||
int slot = java_lang_reflect_Field::slot(target_oop); // fd.index()
|
||||
int mods = java_lang_reflect_Field::modifiers(target_oop);
|
||||
oop type = java_lang_reflect_Field::type(target_oop);
|
||||
oop name = java_lang_reflect_Field::name(target_oop);
|
||||
klassOop k = java_lang_Class::as_klassOop(clazz);
|
||||
intptr_t offset = instanceKlass::cast(k)->field_offset(slot);
|
||||
Klass* k = java_lang_Class::as_Klass(clazz);
|
||||
intptr_t offset = InstanceKlass::cast(k)->field_offset(slot);
|
||||
return init_field_MemberName(mname_oop, k, accessFlags_from(mods), type, name, offset);
|
||||
} else if (target_klass == SystemDictionary::reflect_Method_klass()) {
|
||||
oop clazz = java_lang_reflect_Method::clazz(target_oop);
|
||||
int slot = java_lang_reflect_Method::slot(target_oop);
|
||||
klassOop k = java_lang_Class::as_klassOop(clazz);
|
||||
Klass* k = java_lang_Class::as_Klass(clazz);
|
||||
if (k != NULL && Klass::cast(k)->oop_is_instance()) {
|
||||
methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
|
||||
Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
|
||||
return init_method_MemberName(mname_oop, m, true, k);
|
||||
}
|
||||
} else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
|
||||
oop clazz = java_lang_reflect_Constructor::clazz(target_oop);
|
||||
int slot = java_lang_reflect_Constructor::slot(target_oop);
|
||||
klassOop k = java_lang_Class::as_klassOop(clazz);
|
||||
Klass* k = java_lang_Class::as_Klass(clazz);
|
||||
if (k != NULL && Klass::cast(k)->oop_is_instance()) {
|
||||
methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
|
||||
Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
|
||||
return init_method_MemberName(mname_oop, m, false, k);
|
||||
}
|
||||
} else if (target_klass == SystemDictionary::MemberName_klass()) {
|
||||
// Note: This only works if the MemberName has already been resolved.
|
||||
oop clazz = java_lang_invoke_MemberName::clazz(target_oop);
|
||||
int flags = java_lang_invoke_MemberName::flags(target_oop);
|
||||
oop vmtarget = java_lang_invoke_MemberName::vmtarget(target_oop);
|
||||
Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop);
|
||||
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop);
|
||||
klassOop k = java_lang_Class::as_klassOop(clazz);
|
||||
Klass* k = java_lang_Class::as_Klass(clazz);
|
||||
int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
|
||||
if (vmtarget == NULL) return NULL; // not resolved
|
||||
if ((flags & IS_FIELD) != 0) {
|
||||
assert(vmtarget->is_klass(), "field vmtarget is klassOop");
|
||||
assert(vmtarget->is_klass(), "field vmtarget is Klass*");
|
||||
int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0);
|
||||
// FIXME: how does k (receiver_limit) contribute?
|
||||
return init_field_MemberName(mname_oop, klassOop(vmtarget), accessFlags_from(basic_mods), NULL, NULL, vmindex);
|
||||
return init_field_MemberName(mname_oop, (Klass*)vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex);
|
||||
} else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
|
||||
assert(vmtarget->is_method(), "method or constructor vmtarget is methodOop");
|
||||
return init_method_MemberName(mname_oop, methodOop(vmtarget), ref_kind_does_dispatch(ref_kind), k);
|
||||
assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
|
||||
return init_method_MemberName(mname_oop, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -174,12 +174,12 @@ oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch,
|
||||
klassOop receiver_limit) {
|
||||
oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch,
|
||||
Klass* receiver_limit) {
|
||||
AccessFlags mods = m->access_flags();
|
||||
int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
|
||||
int vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch
|
||||
klassOop mklass = m->method_holder();
|
||||
int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch
|
||||
Klass* mklass = m->method_holder();
|
||||
if (receiver_limit == NULL)
|
||||
receiver_limit = mklass;
|
||||
if (m->is_initializer()) {
|
||||
|
@ -198,7 +198,7 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_di
|
|||
flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
|
||||
// it is a miranda method, so m->vtable_index is not what we want
|
||||
ResourceMark rm;
|
||||
klassVtable* vt = instanceKlass::cast(receiver_limit)->vtable();
|
||||
klassVtable* vt = InstanceKlass::cast(receiver_limit)->vtable();
|
||||
vmindex = vt->index_of_miranda(m->name(), m->signature());
|
||||
} else if (!do_dispatch || m->can_be_statically_bound()) {
|
||||
flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
|
||||
|
@ -214,7 +214,7 @@ oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_di
|
|||
// Note: name and type can be lazily computed by resolve_MemberName,
|
||||
// if Java code needs them as resolved String and MethodType objects.
|
||||
// The clazz must be eagerly stored, because it provides a GC
|
||||
// root to help keep alive the methodOop.
|
||||
// root to help keep alive the Method*.
|
||||
// If relevant, the vtable or itable value is stored as vmindex.
|
||||
// This is done eagerly, since it is readily available without
|
||||
// constructing any new objects.
|
||||
|
@ -238,7 +238,7 @@ Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAP
|
|||
vmindex = klassItable::compute_itable_index(m());
|
||||
} else if (m->can_be_statically_bound()) {
|
||||
// LinkResolver reports vtable index even for final methods!
|
||||
vmindex = methodOopDesc::nonvirtual_vtable_index;
|
||||
vmindex = Method::nonvirtual_vtable_index;
|
||||
} else {
|
||||
vmindex = info.vtable_index();
|
||||
}
|
||||
|
@ -247,13 +247,13 @@ Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAP
|
|||
return Handle(THREAD, res);
|
||||
}
|
||||
|
||||
oop MethodHandles::init_field_MemberName(oop mname_oop, klassOop field_holder,
|
||||
oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder,
|
||||
AccessFlags mods, oop type, oop name,
|
||||
intptr_t offset, bool is_setter) {
|
||||
int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
|
||||
flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
|
||||
if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
|
||||
oop vmtarget = field_holder;
|
||||
Metadata* vmtarget = field_holder;
|
||||
int vmindex = offset; // determines the field uniquely when combined with static bit
|
||||
java_lang_invoke_MemberName::set_flags(mname_oop, flags);
|
||||
java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
|
||||
|
@ -276,7 +276,7 @@ oop MethodHandles::init_field_MemberName(oop mname_oop, klassOop field_holder,
|
|||
|
||||
Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS) {
|
||||
return Handle();
|
||||
#if 0
|
||||
#if 0 // FIXME
|
||||
KlassHandle field_holder = info.klass();
|
||||
intptr_t field_offset = info.field_offset();
|
||||
return init_field_MemberName(mname_oop, field_holder(),
|
||||
|
@ -293,7 +293,7 @@ Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info
|
|||
// * It has a single formal parameter of type Object[].
|
||||
// * It has a return type of Object.
|
||||
// * It has the ACC_VARARGS and ACC_NATIVE flags set.
|
||||
bool MethodHandles::is_method_handle_invoke_name(klassOop klass, Symbol* name) {
|
||||
bool MethodHandles::is_method_handle_invoke_name(Klass* klass, Symbol* name) {
|
||||
if (klass == NULL)
|
||||
return false;
|
||||
// The following test will fail spuriously during bootstrap of MethodHandle itself:
|
||||
|
@ -302,7 +302,7 @@ bool MethodHandles::is_method_handle_invoke_name(klassOop klass, Symbol* name) {
|
|||
if (Klass::cast(klass)->name() != vmSymbols::java_lang_invoke_MethodHandle())
|
||||
return false;
|
||||
Symbol* poly_sig = vmSymbols::object_array_object_signature();
|
||||
methodOop m = instanceKlass::cast(klass)->find_method(name, poly_sig);
|
||||
Method* m = InstanceKlass::cast(klass)->find_method(name, poly_sig);
|
||||
if (m == NULL) return false;
|
||||
int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS;
|
||||
int flags = m->access_flags().as_int();
|
||||
|
@ -351,7 +351,7 @@ vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Symbol* name) {
|
|||
}
|
||||
|
||||
// Cover the case of invokeExact and any future variants of invokeFoo.
|
||||
klassOop mh_klass = SystemDictionary::well_known_klass(
|
||||
Klass* mh_klass = SystemDictionary::well_known_klass(
|
||||
SystemDictionary::WK_KLASS_ENUM_NAME(MethodHandle_klass) );
|
||||
if (mh_klass != NULL && is_method_handle_invoke_name(mh_klass, name))
|
||||
return vmIntrinsics::_invokeGeneric;
|
||||
|
@ -361,7 +361,7 @@ vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Symbol* name) {
|
|||
return vmIntrinsics::_none;
|
||||
}
|
||||
|
||||
vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(klassOop klass, Symbol* name) {
|
||||
vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Klass* klass, Symbol* name) {
|
||||
if (klass != NULL &&
|
||||
Klass::cast(klass)->name() == vmSymbols::java_lang_invoke_MethodHandle()) {
|
||||
vmIntrinsics::ID iid = signature_polymorphic_name_id(name);
|
||||
|
@ -568,7 +568,7 @@ static oop field_signature_type_or_null(Symbol* s) {
|
|||
if (s->byte_at(0) == 'L' && s->byte_at(len-1) == ';') {
|
||||
TempNewSymbol cname = SymbolTable::probe((const char*)&s->bytes()[1], len-2);
|
||||
if (cname == NULL) return NULL;
|
||||
klassOop wkk = SystemDictionary::find_well_known_klass(cname);
|
||||
Klass* wkk = SystemDictionary::find_well_known_klass(cname);
|
||||
if (wkk == NULL) return NULL;
|
||||
return Klass::cast(wkk)->java_mirror();
|
||||
}
|
||||
|
@ -577,9 +577,10 @@ static oop field_signature_type_or_null(Symbol* s) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// An unresolved member name is a mere symbolic reference.
|
||||
// Resolving it plants a vmtarget/vmindex in it,
|
||||
// which refers dirctly to JVM internals.
|
||||
// which refers directly to JVM internals.
|
||||
Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
||||
Handle empty;
|
||||
assert(java_lang_invoke_MemberName::is_instance(mname()), "");
|
||||
|
@ -587,7 +588,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||
if (java_lang_invoke_MemberName::vmtarget(mname()) != NULL) {
|
||||
// Already resolved.
|
||||
DEBUG_ONLY(int vmindex = java_lang_invoke_MemberName::vmindex(mname()));
|
||||
assert(vmindex >= methodOopDesc::nonvirtual_vtable_index, "");
|
||||
assert(vmindex >= Method::nonvirtual_vtable_index, "");
|
||||
return mname;
|
||||
}
|
||||
|
||||
|
@ -609,13 +610,13 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||
|
||||
instanceKlassHandle defc;
|
||||
{
|
||||
klassOop defc_klassOop = java_lang_Class::as_klassOop(defc_oop());
|
||||
if (defc_klassOop == NULL) return empty; // a primitive; no resolution possible
|
||||
if (!Klass::cast(defc_klassOop)->oop_is_instance()) {
|
||||
if (!Klass::cast(defc_klassOop)->oop_is_array()) return empty;
|
||||
defc_klassOop = SystemDictionary::Object_klass();
|
||||
Klass* defc_klass = java_lang_Class::as_Klass(defc_oop());
|
||||
if (defc_klass == NULL) return empty; // a primitive; no resolution possible
|
||||
if (!Klass::cast(defc_klass)->oop_is_instance()) {
|
||||
if (!Klass::cast(defc_klass)->oop_is_array()) return empty;
|
||||
defc_klass = SystemDictionary::Object_klass();
|
||||
}
|
||||
defc = instanceKlassHandle(THREAD, defc_klassOop);
|
||||
defc = instanceKlassHandle(THREAD, defc_klass);
|
||||
}
|
||||
if (defc.is_null()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_InternalError(), "primitive class", empty);
|
||||
|
@ -705,14 +706,14 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||
{
|
||||
// This is taken from LinkResolver::resolve_field, sans access checks.
|
||||
fieldDescriptor fd; // find_field initializes fd if found
|
||||
KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name, type, &fd));
|
||||
KlassHandle sel_klass(THREAD, InstanceKlass::cast(defc())->find_field(name, type, &fd));
|
||||
// check if field exists; i.e., if a klass containing the field def has been selected
|
||||
if (sel_klass.is_null()) return empty; // should not happen
|
||||
oop type = field_signature_type_or_null(fd.signature());
|
||||
oop name = field_name_or_null(fd.name());
|
||||
bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind));
|
||||
mname = Handle(THREAD,
|
||||
init_field_MemberName(mname(), sel_klass->as_klassOop(),
|
||||
init_field_MemberName(mname(), sel_klass(),
|
||||
fd.access_flags(), type, name, fd.offset(), is_setter));
|
||||
return mname;
|
||||
}
|
||||
|
@ -729,7 +730,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
|
|||
// which refers directly to JVM internals.
|
||||
void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
|
||||
assert(java_lang_invoke_MemberName::is_instance(mname()), "");
|
||||
oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
|
||||
Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
|
||||
int vmindex = java_lang_invoke_MemberName::vmindex(mname());
|
||||
if (vmtarget == NULL) {
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand");
|
||||
|
@ -752,12 +753,12 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
|
|||
case IS_METHOD:
|
||||
case IS_CONSTRUCTOR:
|
||||
{
|
||||
assert(vmtarget->is_method(), "method or constructor vmtarget is methodOop");
|
||||
methodHandle m(THREAD, methodOop(vmtarget));
|
||||
assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
|
||||
methodHandle m(THREAD, (Method*)vmtarget);
|
||||
DEBUG_ONLY(vmtarget = NULL); // safety
|
||||
if (m.is_null()) break;
|
||||
if (!have_defc) {
|
||||
klassOop defc = m->method_holder();
|
||||
Klass* defc = m->method_holder();
|
||||
java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror());
|
||||
}
|
||||
if (!have_name) {
|
||||
|
@ -774,9 +775,9 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
|
|||
case IS_FIELD:
|
||||
{
|
||||
// This is taken from LinkResolver::resolve_field, sans access checks.
|
||||
assert(vmtarget->is_klass(), "field vmtarget is klassOop");
|
||||
if (!Klass::cast((klassOop) vmtarget)->oop_is_instance()) break;
|
||||
instanceKlassHandle defc(THREAD, (klassOop) vmtarget);
|
||||
assert(vmtarget->is_klass(), "field vmtarget is Klass*");
|
||||
if (!Klass::cast((Klass*) vmtarget)->oop_is_instance()) break;
|
||||
instanceKlassHandle defc(THREAD, (Klass*) vmtarget);
|
||||
DEBUG_ONLY(vmtarget = NULL); // safety
|
||||
bool is_static = ((flags & JVM_ACC_STATIC) != 0);
|
||||
fieldDescriptor fd; // find_field initializes fd if found
|
||||
|
@ -804,9 +805,9 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
|
|||
THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format");
|
||||
}
|
||||
|
||||
int MethodHandles::find_MemberNames(klassOop k,
|
||||
int MethodHandles::find_MemberNames(Klass* k,
|
||||
Symbol* name, Symbol* sig,
|
||||
int mflags, klassOop caller,
|
||||
int mflags, Klass* caller,
|
||||
int skip, objArrayOop results) {
|
||||
DEBUG_ONLY(No_Safepoint_Verifier nsv);
|
||||
// this code contains no safepoints!
|
||||
|
@ -855,7 +856,7 @@ int MethodHandles::find_MemberNames(klassOop k,
|
|||
return -99; // caller bug!
|
||||
oop type = field_signature_type_or_null(st.signature());
|
||||
oop name = field_name_or_null(st.name());
|
||||
oop saved = MethodHandles::init_field_MemberName(result, st.klass()->as_klassOop(),
|
||||
oop saved = MethodHandles::init_field_MemberName(result, st.klass()(),
|
||||
st.access_flags(), type, name,
|
||||
st.offset());
|
||||
if (saved != result)
|
||||
|
@ -892,7 +893,7 @@ int MethodHandles::find_MemberNames(klassOop k,
|
|||
// caller will accept either sort; no need to adjust name
|
||||
}
|
||||
for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) {
|
||||
methodOop m = st.method();
|
||||
Method* m = st.method();
|
||||
Symbol* m_name = m->name();
|
||||
if (m_name == clinit_name)
|
||||
continue;
|
||||
|
@ -919,7 +920,6 @@ int MethodHandles::find_MemberNames(klassOop k,
|
|||
// return number of elements we at leasted wanted to initialize
|
||||
return rfill + overflow;
|
||||
}
|
||||
|
||||
//
|
||||
// Here are the native methods in java.lang.invoke.MethodHandleNatives
|
||||
// They are the private interface between this JVM and the HotSpot-specific
|
||||
|
@ -928,6 +928,7 @@ int MethodHandles::find_MemberNames(klassOop k,
|
|||
// Note: We use a JVM_ENTRY macro to define each of these, for this is the way
|
||||
// that intrinsic (non-JNI) native methods are defined in HotSpot.
|
||||
//
|
||||
|
||||
JVM_ENTRY(jint, MHN_getConstant(JNIEnv *env, jobject igcls, jint which)) {
|
||||
switch (which) {
|
||||
case MethodHandles::GC_COUNT_GWT:
|
||||
|
@ -1033,10 +1034,10 @@ JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh,
|
|||
// access checks on behalf of the given caller. But, we can verify this.
|
||||
if (VerifyMethodHandles && caller_jh != NULL &&
|
||||
java_lang_invoke_MemberName::clazz(mname()) != NULL) {
|
||||
klassOop reference_klass = java_lang_Class::as_klassOop(java_lang_invoke_MemberName::clazz(mname()));
|
||||
Klass* reference_klass = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
|
||||
if (reference_klass != NULL) {
|
||||
// Emulate LinkResolver::check_klass_accessability.
|
||||
klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh));
|
||||
Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
|
||||
if (!Reflection::verify_class_access(caller,
|
||||
reference_klass,
|
||||
true)) {
|
||||
|
@ -1107,22 +1108,19 @@ JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname
|
|||
if (mname_jh == NULL) return NULL;
|
||||
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
|
||||
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(mname());
|
||||
Handle vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
|
||||
Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
|
||||
objArrayHandle result = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL);
|
||||
jvalue vmindex_value; vmindex_value.j = (long)vmindex;
|
||||
oop x = java_lang_boxing_object::create(T_LONG, &vmindex_value, CHECK_NULL);
|
||||
result->obj_at_put(0, x);
|
||||
x = NULL;
|
||||
if (vmtarget.is_null() || vmtarget->is_instance()) {
|
||||
x = vmtarget();
|
||||
if (vmtarget == NULL) {
|
||||
x = NULL;
|
||||
} else if (vmtarget->is_klass()) {
|
||||
x = Klass::cast((klassOop) vmtarget())->java_mirror();
|
||||
} else {
|
||||
x = Klass::cast((Klass*) vmtarget)->java_mirror();
|
||||
} else if (vmtarget->is_method()) {
|
||||
Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
|
||||
if (vmtarget->is_method())
|
||||
x = MethodHandles::init_method_MemberName(mname2(), methodOop(vmtarget()), false, NULL);
|
||||
else
|
||||
x = MethodHandles::init_MemberName(mname2(), vmtarget());
|
||||
x = MethodHandles::init_method_MemberName(mname2(), (Method*)vmtarget, false, NULL);
|
||||
}
|
||||
result->obj_at_put(1, x);
|
||||
return JNIHandles::make_local(env, result());
|
||||
|
@ -1137,7 +1135,7 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls,
|
|||
jclass clazz_jh, jstring name_jh, jstring sig_jh,
|
||||
int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) {
|
||||
if (clazz_jh == NULL || results_jh == NULL) return -1;
|
||||
KlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz_jh)));
|
||||
KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz_jh)));
|
||||
|
||||
objArrayHandle results(THREAD, (objArrayOop) JNIHandles::resolve(results_jh));
|
||||
if (results.is_null() || !results->is_objArray()) return -1;
|
||||
|
@ -1157,7 +1155,7 @@ JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls,
|
|||
if (caller_jh != NULL) {
|
||||
oop caller_oop = JNIHandles::resolve_non_null(caller_jh);
|
||||
if (!java_lang_Class::is_instance(caller_oop)) return -1;
|
||||
caller = KlassHandle(THREAD, java_lang_Class::as_klassOop(caller_oop));
|
||||
caller = KlassHandle(THREAD, java_lang_Class::as_Klass(caller_oop));
|
||||
}
|
||||
|
||||
if (name != NULL && sig != NULL && results.not_null()) {
|
||||
|
@ -1196,6 +1194,20 @@ JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobjec
|
|||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(jobject, MH_invoke_UOE(JNIEnv *env, jobject igmh, jobjectArray igargs)) {
|
||||
TempNewSymbol UOE_name = SymbolTable::new_symbol("java/lang/UnsupportedOperationException", CHECK_NULL);
|
||||
THROW_MSG_NULL(UOE_name, "MethodHandle.invoke cannot be invoked reflectively");
|
||||
return NULL;
|
||||
}
|
||||
JVM_END
|
||||
|
||||
JVM_ENTRY(jobject, MH_invokeExact_UOE(JNIEnv *env, jobject igmh, jobjectArray igargs)) {
|
||||
TempNewSymbol UOE_name = SymbolTable::new_symbol("java/lang/UnsupportedOperationException", CHECK_NULL);
|
||||
THROW_MSG_NULL(UOE_name, "MethodHandle.invokeExact cannot be invoked reflectively");
|
||||
return NULL;
|
||||
}
|
||||
JVM_END
|
||||
|
||||
/// JVM_RegisterMethodHandleMethods
|
||||
|
||||
#undef CS // Solaris builds complain
|
||||
|
@ -1233,6 +1245,11 @@ static JNINativeMethod required_methods_JDK8[] = {
|
|||
{CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)}
|
||||
};
|
||||
|
||||
static JNINativeMethod invoke_methods[] = {
|
||||
{CC"invoke", CC"(["OBJ")"OBJ, FN_PTR(MH_invoke_UOE)},
|
||||
{CC"invokeExact", CC"(["OBJ")"OBJ, FN_PTR(MH_invokeExact_UOE)}
|
||||
};
|
||||
|
||||
// This one function is exported, used by NativeLookup.
|
||||
|
||||
JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
|
||||
|
@ -1258,6 +1275,9 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
|
|||
ThreadToNativeFromVM ttnfv(thread);
|
||||
|
||||
status = env->RegisterNatives(MHN_class, required_methods_JDK8, sizeof(required_methods_JDK8)/sizeof(JNINativeMethod));
|
||||
if (status == JNI_OK && !env->ExceptionOccurred()) {
|
||||
status = env->RegisterNatives(MH_class, invoke_methods, sizeof(invoke_methods)/sizeof(JNINativeMethod));
|
||||
}
|
||||
if (status != JNI_OK || env->ExceptionOccurred()) {
|
||||
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
|
||||
enable_MH = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue