mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
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:
parent
893817c28d
commit
12901d0e5b
181 changed files with 5760 additions and 14402 deletions
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue