6655638: dynamic languages need method handles

Initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.)

Reviewed-by: kvn, twisti, never
This commit is contained in:
John R Rose 2009-04-08 10:56:49 -07:00
parent 318da3f68c
commit ce0c084720
63 changed files with 5815 additions and 70 deletions

View file

@ -151,6 +151,12 @@ class java_lang_Class : AllStatic {
// Conversion
static klassOop as_klassOop(oop java_class);
static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
static BasicType as_BasicType(oop java_class, KlassHandle* reference_klass) {
klassOop refk_oop = NULL;
BasicType result = as_BasicType(java_class, &refk_oop);
(*reference_klass) = KlassHandle(refk_oop);
return result;
}
static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
static void print_signature(oop java_class, outputStream *st);
// Testing
@ -778,6 +784,284 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
};
// Interface to java.dyn.MethodHandle objects
class MethodHandleEntry;
class java_dyn_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 _vmslots_offset; // OPTIONAL hoisted type.form.vmslots
static void compute_offsets();
public:
// Accessors
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 void init_vmslots(oop mh);
static int compute_vmslots(oop mh);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass());
}
static bool is_instance(oop obj) {
return obj != NULL && is_subclass(obj->klass());
}
// Accessors for code generation:
static int type_offset_in_bytes() { return _type_offset; }
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
static int vmentry_offset_in_bytes() { return _vmentry_offset; }
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
};
class sun_dyn_DirectMethodHandle: public java_dyn_MethodHandle {
friend class JavaClasses;
private:
// _vmtarget_offset; // method or class or interface
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 sun_dyn_BoundMethodHandle: public java_dyn_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 sun_dyn_AdapterMethodHandle: public sun_dyn_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_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument
OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another
OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive
OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI)
OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg)
OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg)
OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS)
OP_DROP_ARGS = 0x8, // remove one or more argument slots
OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI)
OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size)
OP_FLYBY = 0xB, // operate first on reified argument list (NYI)
OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI)
CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
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; }
};
// Interface to sun.dyn.MemberName objects
// (These are a private interface for Java code to query the class hierarchy.)
class sun_dyn_MemberName: AllStatic {
friend class JavaClasses;
private:
// From java.dyn.MemberName:
// private Class<?> clazz; // class in which the method is defined
// private String name; // may be null if not yet materialized
// 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
static int _clazz_offset;
static int _name_offset;
static int _type_offset;
static int _flags_offset;
static int _vmtarget_offset;
static int _vmindex_offset;
static void compute_offsets();
public:
// Accessors
static oop clazz(oop mname);
static void set_clazz(oop mname, oop clazz);
static oop type(oop mname);
static void set_type(oop mname, oop type);
static oop name(oop mname);
static void set_name(oop mname, oop name);
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);
// Testers
static bool is_subclass(klassOop klass) {
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_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 {
MN_IS_METHOD = 0x00010000, // method (not constructor)
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
};
// Accessors for code generation:
static int clazz_offset_in_bytes() { return _clazz_offset; }
static int type_offset_in_bytes() { return _type_offset; }
static int name_offset_in_bytes() { return _name_offset; }
static int flags_offset_in_bytes() { return _flags_offset; }
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
static int vmindex_offset_in_bytes() { return _vmindex_offset; }
};
// Interface to java.dyn.MethodType objects
class java_dyn_MethodType: AllStatic {
friend class JavaClasses;
private:
static int _rtype_offset;
static int _ptypes_offset;
static int _form_offset;
static void compute_offsets();
public:
// Accessors
static oop rtype(oop mt);
static objArrayOop ptypes(oop mt);
static oop form(oop mt);
static oop ptype(oop mt, int index);
static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
static void print_signature(oop mt, outputStream* st);
static bool is_instance(oop obj) {
return obj != NULL && obj->klass() == SystemDictionary::MethodType_klass();
}
// 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; }
};
class java_dyn_MethodTypeForm: AllStatic {
friend class JavaClasses;
private:
static int _vmslots_offset; // number of argument slots needed
static int _erasedType_offset; // erasedType = canonical MethodType
static void compute_offsets();
public:
// Accessors
static int vmslots(oop mtform);
static oop erasedType(oop mtform);
// Accessors for code generation:
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
static int erasedType_offset_in_bytes() { return _erasedType_offset; }
};
// Interface to java.security.AccessControlContext objects
class java_security_AccessControlContext: AllStatic {