7023639: JSR 292 method handle invocation needs a fast path for compiled code

6984705: JSR 292 method handle creation should not go through JNI

Remove assembly code for JDK 7 chained method handles

Co-authored-by: John Rose <john.r.rose@oracle.com>
Co-authored-by: Michael Haupt <michael.haupt@oracle.com>
Reviewed-by: jrose, twisti, kvn, mhaupt
This commit is contained in:
Christian Thalinger 2012-07-24 10:51:00 -07:00
parent 893817c28d
commit 12901d0e5b
181 changed files with 5760 additions and 14402 deletions

View file

@ -883,19 +883,14 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
// Interface to java.lang.invoke.MethodHandle objects
#define METHODHANDLE_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MethodHandle, vmentry, intptr_signature, false) \
macro(java_lang_invoke_MethodHandle, vmtarget, object_signature, true)
class MethodHandleEntry;
class java_lang_invoke_MethodHandle: AllStatic {
friend class JavaClasses;
private:
static int _vmentry_offset; // assembly code trampoline for MH
static int _vmtarget_offset; // class-specific target reference
static int _type_offset; // the MethodType of this MH
static int _type_offset; // the MethodType of this MH
static int _form_offset; // the LambdaForm of this MH
static void compute_offsets();
@ -904,13 +899,8 @@ class java_lang_invoke_MethodHandle: AllStatic {
static oop type(oop mh);
static void set_type(oop mh, oop mtype);
static oop vmtarget(oop mh);
static void set_vmtarget(oop mh, oop target);
static MethodHandleEntry* vmentry(oop mh);
static void set_vmentry(oop mh, MethodHandleEntry* data);
static int vmslots(oop mh);
static oop form(oop mh);
static void set_form(oop mh, oop lform);
// Testers
static bool is_subclass(klassOop klass) {
@ -922,149 +912,45 @@ class java_lang_invoke_MethodHandle: AllStatic {
// Accessors for code generation:
static int type_offset_in_bytes() { return _type_offset; }
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
static int form_offset_in_bytes() { return _form_offset; }
};
// Interface to java.lang.invoke.LambdaForm objects
// (These are a private interface for managing adapter code generation.)
class java_lang_invoke_LambdaForm: AllStatic {
friend class JavaClasses;
private:
static int _vmentry_offset; // type is MemberName
static void compute_offsets();
public:
// Accessors
static oop vmentry(oop lform);
static void set_vmentry(oop lform, oop invoker);
// Testers
static bool is_subclass(klassOop klass) {
return SystemDictionary::LambdaForm_klass() != NULL &&
Klass::cast(klass)->is_subclass_of(SystemDictionary::LambdaForm_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
// Accessors for code generation:
static int vmentry_offset_in_bytes() { return _vmentry_offset; }
};
#define DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_DirectMethodHandle, vmindex, int_signature, true)
class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle {
friend class JavaClasses;
private:
static int _vmindex_offset; // negative or vtable idx or itable idx
static void compute_offsets();
public:
// Accessors
static int vmindex(oop mh);
static void set_vmindex(oop mh, int index);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
// Accessors for code generation:
static int vmindex_offset_in_bytes() { return _vmindex_offset; }
};
class java_lang_invoke_BoundMethodHandle: public java_lang_invoke_MethodHandle {
friend class JavaClasses;
private:
static int _argument_offset; // argument value bound into this MH
static int _vmargslot_offset; // relevant argument slot (<= vmslots)
static void compute_offsets();
public:
static oop argument(oop mh);
static void set_argument(oop mh, oop ref);
static jint vmargslot(oop mh);
static void set_vmargslot(oop mh, jint slot);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::BoundMethodHandle_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
static int argument_offset_in_bytes() { return _argument_offset; }
static int vmargslot_offset_in_bytes() { return _vmargslot_offset; }
};
class java_lang_invoke_AdapterMethodHandle: public java_lang_invoke_BoundMethodHandle {
friend class JavaClasses;
private:
static int _conversion_offset; // type of conversion to apply
static void compute_offsets();
public:
static int conversion(oop mh);
static void set_conversion(oop mh, int conv);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::AdapterMethodHandle_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
enum {
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T)
OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper
OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
OP_DROP_ARGS = 0x9, // remove one or more argument slots
OP_COLLECT_ARGS = 0xA, // combine arguments using an auxiliary function
OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
OP_FOLD_ARGS = 0xC, // combine but do not remove arguments; prepend result
//OP_UNUSED_13 = 0xD, // unused code, perhaps for reified argument lists
CONV_OP_LIMIT = 0xE, // limit of CONV_OP enumeration
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
CONV_TYPE_MASK = 0x0F, // fits T_ADDRESS and below
CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1
};
static int conversion_offset_in_bytes() { return _conversion_offset; }
};
// A simple class that maintains an invocation count
class java_lang_invoke_CountingMethodHandle: public java_lang_invoke_MethodHandle {
friend class JavaClasses;
private:
static int _vmcount_offset;
static void compute_offsets();
public:
// Accessors
static int vmcount(oop mh);
static void set_vmcount(oop mh, int count);
// Testers
static bool is_subclass(klassOop klass) {
return SystemDictionary::CountingMethodHandle_klass() != NULL &&
Klass::cast(klass)->is_subclass_of(SystemDictionary::CountingMethodHandle_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
// Accessors for code generation:
static int vmcount_offset_in_bytes() { return _vmcount_offset; }
};
// Interface to java.lang.invoke.MemberName objects
// (These are a private interface for Java code to query the class hierarchy.)
#define MEMBERNAME_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MemberName, vmtarget, object_signature, true)
#define MEMBERNAME_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MemberName, vmindex, intptr_signature, false) \
macro(java_lang_invoke_MemberName, vmtarget, object_signature, false)
class java_lang_invoke_MemberName: AllStatic {
friend class JavaClasses;
@ -1076,7 +962,7 @@ class java_lang_invoke_MemberName: AllStatic {
// private Object type; // may be null if not yet materialized
// private int flags; // modifier bits; see reflect.Modifier
// private Object vmtarget; // VM-specific target value
// private int vmindex; // method index within class or interface
// private intptr_t vmindex; // member index within class or interface
static int _clazz_offset;
static int _name_offset;
static int _type_offset;
@ -1100,15 +986,11 @@ class java_lang_invoke_MemberName: AllStatic {
static int flags(oop mname);
static void set_flags(oop mname, int flags);
static int modifiers(oop mname) { return (u2) flags(mname); }
static void set_modifiers(oop mname, int mods)
{ set_flags(mname, (flags(mname) &~ (u2)-1) | (u2)mods); }
static oop vmtarget(oop mname);
static void set_vmtarget(oop mname, oop target);
static int vmindex(oop mname);
static void set_vmindex(oop mname, int index);
static intptr_t vmindex(oop mname);
static void set_vmindex(oop mname, intptr_t index);
// Testers
static bool is_subclass(klassOop klass) {
@ -1124,9 +1006,11 @@ class java_lang_invoke_MemberName: AllStatic {
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
MN_IS_FIELD = 0x00040000, // field
MN_IS_TYPE = 0x00080000, // nested type
MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
VM_INDEX_UNINITIALIZED = -99
MN_REFERENCE_KIND_SHIFT = 24, // refKind
MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
// The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
MN_SEARCH_SUPERCLASSES = 0x00100000, // walk super classes
MN_SEARCH_INTERFACES = 0x00200000 // walk implemented interfaces
};
// Accessors for code generation:
@ -1147,7 +1031,6 @@ class java_lang_invoke_MethodType: AllStatic {
private:
static int _rtype_offset;
static int _ptypes_offset;
static int _form_offset;
static void compute_offsets();
@ -1155,11 +1038,13 @@ class java_lang_invoke_MethodType: AllStatic {
// Accessors
static oop rtype(oop mt);
static objArrayOop ptypes(oop mt);
static oop form(oop mt);
static oop ptype(oop mt, int index);
static int ptype_count(oop mt);
static int ptype_slot_count(oop mt); // extra counts for long/double
static int rtype_slot_count(oop mt); // extra counts for long/double
static Symbol* as_signature(oop mt, bool intern_if_not_found, TRAPS);
static void print_signature(oop mt, outputStream* st);
@ -1172,40 +1057,6 @@ class java_lang_invoke_MethodType: AllStatic {
// Accessors for code generation:
static int rtype_offset_in_bytes() { return _rtype_offset; }
static int ptypes_offset_in_bytes() { return _ptypes_offset; }
static int form_offset_in_bytes() { return _form_offset; }
};
#define METHODTYPEFORM_INJECTED_FIELDS(macro) \
macro(java_lang_invoke_MethodTypeForm, vmslots, int_signature, true) \
macro(java_lang_invoke_MethodTypeForm, vmlayout, object_signature, true)
class java_lang_invoke_MethodTypeForm: AllStatic {
friend class JavaClasses;
private:
static int _vmslots_offset; // number of argument slots needed
static int _vmlayout_offset; // object describing internal calling sequence
static int _erasedType_offset; // erasedType = canonical MethodType
static int _genericInvoker_offset; // genericInvoker = adapter for invokeGeneric
static void compute_offsets();
public:
// Accessors
static int vmslots(oop mtform);
static void set_vmslots(oop mtform, int vmslots);
static oop erasedType(oop mtform);
static oop genericInvoker(oop mtform);
static oop vmlayout(oop mtform);
static oop init_vmlayout(oop mtform, oop cookie);
// Accessors for code generation:
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
static int vmlayout_offset_in_bytes() { return _vmlayout_offset; }
static int erasedType_offset_in_bytes() { return _erasedType_offset; }
static int genericInvoker_offset_in_bytes() { return _genericInvoker_offset; }
};
@ -1275,6 +1126,7 @@ class java_lang_ClassLoader : AllStatic {
public:
static oop parent(oop loader);
static bool isAncestor(oop loader, oop cl);
// Support for parallelCapable field
static bool parallelCapable(oop the_class_mirror);
@ -1284,6 +1136,14 @@ class java_lang_ClassLoader : AllStatic {
// Fix for 4474172
static oop non_reflection_class_loader(oop loader);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::ClassLoader_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
// Debugging
friend class JavaClasses;
};
@ -1425,10 +1285,7 @@ class InjectedField {
#define ALL_INJECTED_FIELDS(macro) \
CLASS_INJECTED_FIELDS(macro) \
METHODHANDLE_INJECTED_FIELDS(macro) \
DIRECTMETHODHANDLE_INJECTED_FIELDS(macro) \
MEMBERNAME_INJECTED_FIELDS(macro) \
METHODTYPEFORM_INJECTED_FIELDS(macro)
MEMBERNAME_INJECTED_FIELDS(macro)
// Interface to hard-coded offset checking