diff src/share/vm/classfile/javaClasses.hpp @ 710:e5b0439ef4ae

6655638: dynamic languages need method handles Summary: initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.) Reviewed-by: kvn, twisti, never
author jrose
date Wed, 08 Apr 2009 10:56:49 -0700
parents c89f86385056
children be93aad57795
line wrap: on
line diff
--- a/src/share/vm/classfile/javaClasses.hpp	Wed Apr 08 00:12:59 2009 -0700
+++ b/src/share/vm/classfile/javaClasses.hpp	Wed Apr 08 10:56:49 2009 -0700
@@ -151,6 +151,12 @@
   // 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 @@
 };
 
 
+// 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 {