--- a/hotspot/src/share/vm/prims/methodHandles.cpp Fri Aug 31 16:39:35 2012 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Sat Sep 01 13:25:18 2012 -0400
@@ -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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
// * 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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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_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 @@
{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 @@
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;