hotspot/src/share/vm/prims/methodHandleWalk.hpp
changeset 4567 7fc02fbe5c7a
parent 4562 5d93cb2d2090
child 4581 e89fbd1bcb3d
equal deleted inserted replaced
4566:b363f6ef4068 4567:7fc02fbe5c7a
    66   }
    66   }
    67 
    67 
    68   Handle method_handle()        { return _method_handle; }
    68   Handle method_handle()        { return _method_handle; }
    69   oop    method_handle_oop()    { return _method_handle(); }
    69   oop    method_handle_oop()    { return _method_handle(); }
    70   oop    method_type_oop()      { return MethodHandle_type_oop(); }
    70   oop    method_type_oop()      { return MethodHandle_type_oop(); }
       
    71   oop    vmtarget_oop()         { return MethodHandle_vmtarget_oop(); }
    71 
    72 
    72   jint adapter_conversion()     { assert(is_adapter(), ""); return _conversion; }
    73   jint adapter_conversion()     { assert(is_adapter(), ""); return _conversion; }
    73   int  adapter_conversion_op()  { return MethodHandles::adapter_conversion_op(adapter_conversion()); }
    74   int  adapter_conversion_op()  { return MethodHandles::adapter_conversion_op(adapter_conversion()); }
    74   BasicType adapter_conversion_src_type()
    75   BasicType adapter_conversion_src_type()
    75                                 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); }
    76                                 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); }
    99 // Structure walker for method handles.
   100 // Structure walker for method handles.
   100 // Does abstract interpretation on top of low-level parsing.
   101 // Does abstract interpretation on top of low-level parsing.
   101 // You supply the tokens shuffled by the abstract interpretation.
   102 // You supply the tokens shuffled by the abstract interpretation.
   102 class MethodHandleWalker : StackObj {
   103 class MethodHandleWalker : StackObj {
   103 public:
   104 public:
   104   struct _ArgToken { };  // dummy struct
   105   // Stack values:
   105   typedef _ArgToken* ArgToken;
   106   enum TokenType {
       
   107     tt_void,
       
   108     tt_parameter,
       
   109     tt_temporary,
       
   110     tt_constant,
       
   111     tt_illegal
       
   112   };
       
   113 
       
   114   // Argument token:
       
   115   class ArgToken {
       
   116   private:
       
   117     TokenType _tt;
       
   118     BasicType _bt;
       
   119     jvalue    _value;
       
   120     Handle    _handle;
       
   121 
       
   122   public:
       
   123     ArgToken(TokenType tt = tt_illegal) : _tt(tt) {}
       
   124     ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {}
       
   125 
       
   126     ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
       
   127       _value.i = index;
       
   128     }
       
   129 
       
   130     ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) {
       
   131       _handle = value;
       
   132     }
       
   133 
       
   134     TokenType token_type()  const { return _tt; }
       
   135     BasicType basic_type()  const { return _bt; }
       
   136     int       index()       const { return _value.i; }
       
   137     Handle    object()      const { return _handle; }
       
   138 
       
   139     jint      get_jint()    const { return _value.i; }
       
   140     jlong     get_jlong()   const { return _value.j; }
       
   141     jfloat    get_jfloat()  const { return _value.f; }
       
   142     jdouble   get_jdouble() const { return _value.d; }
       
   143   };
   106 
   144 
   107   // Abstract interpretation state:
   145   // Abstract interpretation state:
   108   struct SlotState {
   146   struct SlotState {
   109     BasicType _type;
   147     BasicType _type;
   110     ArgToken  _arg;
   148     ArgToken  _arg;
   116     return ss;
   154     return ss;
   117   }
   155   }
   118 
   156 
   119 private:
   157 private:
   120   MethodHandleChain _chain;
   158   MethodHandleChain _chain;
   121 
   159   bool              _for_invokedynamic;
   122   GrowableArray<SlotState> _outgoing;  // current outgoing parameter slots
   160   int               _local_index;
       
   161 
       
   162   GrowableArray<SlotState> _outgoing;       // current outgoing parameter slots
   123   int                      _outgoing_argc;  // # non-empty outgoing slots
   163   int                      _outgoing_argc;  // # non-empty outgoing slots
   124 
   164 
   125   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
   165   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
   126   // If old_type != T_VOID, remove the old argument at that point.
   166   // If old_type != T_VOID, remove the old argument at that point.
   127   // If new_type != T_VOID, insert the new argument at that point.
   167   // If new_type != T_VOID, insert the new argument at that point.
   128   // Insert or delete a second empty slot as needed.
   168   // Insert or delete a second empty slot as needed.
   129   void change_argument(BasicType old_type, int slot, BasicType new_type, ArgToken new_arg);
   169   void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
   130 
   170 
   131   SlotState* slot_state(int slot) {
   171   SlotState* slot_state(int slot) {
   132     if (slot < 0 || slot >= _outgoing.length())
   172     if (slot < 0 || slot >= _outgoing.length())
   133       return NULL;
   173       return NULL;
   134     return _outgoing.adr_at(slot);
   174     return _outgoing.adr_at(slot);
   151   Bytecodes::Code conversion_code(BasicType src, BasicType dest);
   191   Bytecodes::Code conversion_code(BasicType src, BasicType dest);
   152 
   192 
   153   void walk_incoming_state(TRAPS);
   193   void walk_incoming_state(TRAPS);
   154 
   194 
   155 public:
   195 public:
   156   MethodHandleWalker(Handle root, TRAPS)
   196   MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
   157     : _chain(root, THREAD),
   197     : _chain(root, THREAD),
       
   198       _for_invokedynamic(for_invokedynamic),
   158       _outgoing(THREAD, 10),
   199       _outgoing(THREAD, 10),
   159       _outgoing_argc(0)
   200       _outgoing_argc(0)
   160   { }
   201   {
       
   202     _local_index = for_invokedynamic ? 0 : 1;
       
   203   }
   161 
   204 
   162   MethodHandleChain& chain() { return _chain; }
   205   MethodHandleChain& chain() { return _chain; }
       
   206 
       
   207   bool for_invokedynamic() const { return _for_invokedynamic; }
       
   208 
       
   209   int new_local_index(BasicType bt) {
       
   210     //int index = _for_invokedynamic ? _local_index : _local_index - 1;
       
   211     int index = _local_index;
       
   212     _local_index += type2size[bt];
       
   213     return index;
       
   214   }
       
   215 
       
   216   int max_locals() const { return _local_index; }
   163 
   217 
   164   // plug-in abstract interpretation steps:
   218   // plug-in abstract interpretation steps:
   165   virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0;
   219   virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0;
   166   virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0;
   220   virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0;
   167   virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0;
   221   virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0;
   168   virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS ) = 0;
   222   virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0;
   169   virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS ) = 0;
   223   virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0;
   170   virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0;
   224   virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0;
   171 
   225 
   172   // For make_invoke, the methodOop can be NULL if the intrinsic ID
   226   // For make_invoke, the methodOop can be NULL if the intrinsic ID
   173   // is something other than vmIntrinsics::_none.
   227   // is something other than vmIntrinsics::_none.
   174 
   228 
   185 // An abstract interpreter for method handle chains.
   239 // An abstract interpreter for method handle chains.
   186 // Produces an account of the semantics of a chain, in terms of a static IR.
   240 // Produces an account of the semantics of a chain, in terms of a static IR.
   187 // The IR happens to be JVM bytecodes.
   241 // The IR happens to be JVM bytecodes.
   188 class MethodHandleCompiler : public MethodHandleWalker {
   242 class MethodHandleCompiler : public MethodHandleWalker {
   189 private:
   243 private:
   190   Thread* _thread;
   244   methodHandle _callee;
   191 
   245   KlassHandle  _rklass;        // Return type for casting.
   192   struct PrimCon {
   246   BasicType    _rtype;
   193     BasicType _type;
   247   KlassHandle  _target_klass;
   194     jvalue    _value;
   248   Thread*      _thread;
       
   249 
       
   250   // Fake constant pool entry.
       
   251   class ConstantValue {
       
   252   private:
       
   253     int       _tag;   // Constant pool tag type.
       
   254     JavaValue _value;
       
   255     Handle    _handle;
       
   256 
       
   257   public:
       
   258     // Constructor for oop types.
       
   259     ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
       
   260       assert(tag == JVM_CONSTANT_Utf8   ||
       
   261              tag == JVM_CONSTANT_Class  ||
       
   262              tag == JVM_CONSTANT_String ||
       
   263              tag == JVM_CONSTANT_Object, "must be oop type");
       
   264     }
       
   265 
       
   266     // Constructor for oop reference types.
       
   267     ConstantValue(int tag, int index) : _tag(tag) {
       
   268       assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
       
   269       _value.set_jint(index);
       
   270     }
       
   271     ConstantValue(int tag, int first_index, int second_index) : _tag(tag) {
       
   272       assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
       
   273       _value.set_jint(first_index << 16 | second_index);
       
   274     }
       
   275 
       
   276     // Constructor for primitive types.
       
   277     ConstantValue(BasicType bt, jvalue con) {
       
   278       _value.set_type(bt);
       
   279       switch (bt) {
       
   280       case T_INT:    _tag = JVM_CONSTANT_Integer; _value.set_jint(   con.i); break;
       
   281       case T_LONG:   _tag = JVM_CONSTANT_Long;    _value.set_jlong(  con.j); break;
       
   282       case T_FLOAT:  _tag = JVM_CONSTANT_Float;   _value.set_jfloat( con.f); break;
       
   283       case T_DOUBLE: _tag = JVM_CONSTANT_Double;  _value.set_jdouble(con.d); break;
       
   284       default: ShouldNotReachHere();
       
   285       }
       
   286     }
       
   287 
       
   288     int       tag()          const { return _tag; }
       
   289     symbolOop symbol_oop()   const { return (symbolOop) _handle(); }
       
   290     klassOop  klass_oop()    const { return (klassOop)  _handle(); }
       
   291     oop       object_oop()   const { return _handle(); }
       
   292     int       index()        const { return _value.get_jint(); }
       
   293     int       first_index()  const { return _value.get_jint() >> 16; }
       
   294     int       second_index() const { return _value.get_jint() & 0x0000FFFF; }
       
   295 
       
   296     bool      is_primitive() const { return is_java_primitive(_value.get_type()); }
       
   297     jint      get_jint()     const { return _value.get_jint();    }
       
   298     jlong     get_jlong()    const { return _value.get_jlong();   }
       
   299     jfloat    get_jfloat()   const { return _value.get_jfloat();  }
       
   300     jdouble   get_jdouble()  const { return _value.get_jdouble(); }
   195   };
   301   };
   196 
   302 
       
   303   // Fake constant pool.
       
   304   GrowableArray<ConstantValue*> _constants;
       
   305 
   197   // Accumulated compiler state:
   306   // Accumulated compiler state:
   198   stringStream _bytes;
   307   GrowableArray<unsigned char> _bytecode;
   199   GrowableArray<Handle>   _constant_oops;
   308 
   200   GrowableArray<PrimCon*> _constant_prims;
   309   int _cur_stack;
   201   int _max_stack;
   310   int _max_stack;
   202   int _num_params;
   311   int _num_params;
   203   int _max_locals;
       
   204   int _name_index;
   312   int _name_index;
   205   int _signature_index;
   313   int _signature_index;
   206 
   314 
   207   // Stack values:
   315   void stack_push(BasicType bt) {
   208   enum TokenType {
   316     _cur_stack += type2size[bt];
   209     tt_void,
   317     if (_cur_stack > _max_stack) _max_stack = _cur_stack;
   210     tt_parameter,
   318   }
   211     tt_temporary,
   319   void stack_pop(BasicType bt) {
   212     tt_constant
   320     _cur_stack -= type2size[bt];
   213   };
   321     assert(_cur_stack >= 0, "sanity");
   214 
   322   }
   215   ArgToken make_stack_value(TokenType tt, BasicType type, int id) {
   323 
   216     return ArgToken( ((intptr_t)id << 8) | ((intptr_t)type << 4) | (intptr_t)tt );
   324   unsigned char* bytecode()        const { return _bytecode.adr_at(0); }
   217   }
   325   int            bytecode_length() const { return _bytecode.length(); }
       
   326 
       
   327   // Fake constant pool.
       
   328   int cpool_oop_put(int tag, Handle con) {
       
   329     if (con.is_null())  return 0;
       
   330     ConstantValue* cv = new ConstantValue(tag, con);
       
   331     return _constants.append(cv);
       
   332   }
       
   333 
       
   334   int cpool_oop_reference_put(int tag, int first_index, int second_index) {
       
   335     if (first_index == 0 && second_index == 0)  return 0;
       
   336     assert(first_index != 0 && second_index != 0, "no zero indexes");
       
   337     ConstantValue* cv = new ConstantValue(tag, first_index, second_index);
       
   338     return _constants.append(cv);
       
   339   }
       
   340 
       
   341   int cpool_primitive_put(BasicType type, jvalue* con);
       
   342 
       
   343   int cpool_int_put(jint value) {
       
   344     jvalue con; con.i = value;
       
   345     return cpool_primitive_put(T_INT, &con);
       
   346   }
       
   347   int cpool_long_put(jlong value) {
       
   348     jvalue con; con.j = value;
       
   349     return cpool_primitive_put(T_LONG, &con);
       
   350   }
       
   351   int cpool_float_put(jfloat value) {
       
   352     jvalue con; con.f = value;
       
   353     return cpool_primitive_put(T_FLOAT, &con);
       
   354   }
       
   355   int cpool_double_put(jdouble value) {
       
   356     jvalue con; con.d = value;
       
   357     return cpool_primitive_put(T_DOUBLE, &con);
       
   358   }
       
   359 
       
   360   int cpool_object_put(Handle obj) {
       
   361     return cpool_oop_put(JVM_CONSTANT_Object, obj);
       
   362   }
       
   363   int cpool_symbol_put(symbolOop sym) {
       
   364     return cpool_oop_put(JVM_CONSTANT_Utf8, sym);
       
   365   }
       
   366   int cpool_klass_put(klassOop klass) {
       
   367     return cpool_oop_put(JVM_CONSTANT_Class, klass);
       
   368   }
       
   369   int cpool_methodref_put(int class_index, int name_and_type_index) {
       
   370     return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index);
       
   371   }
       
   372   int cpool_name_and_type_put(int name_index, int signature_index) {
       
   373     return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index);
       
   374   }
       
   375 
       
   376   void emit_bc(Bytecodes::Code op, int index = 0);
       
   377   void emit_load(BasicType bt, int index);
       
   378   void emit_store(BasicType bt, int index);
       
   379   void emit_load_constant(ArgToken arg);
       
   380 
       
   381   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
       
   382     return ArgToken(tt_parameter, type, argnum);
       
   383   }
       
   384   virtual ArgToken make_oop_constant(oop con, TRAPS) {
       
   385     Handle h(THREAD, con);
       
   386     return ArgToken(tt_constant, T_OBJECT, h);
       
   387   }
       
   388   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
       
   389     return ArgToken(tt_constant, type, *con);
       
   390   }
       
   391 
       
   392   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
       
   393   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
       
   394   virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
       
   395 
       
   396   // Get a real constant pool.
       
   397   constantPoolHandle get_constant_pool(TRAPS) const;
       
   398 
       
   399   // Get a real methodOop.
       
   400   methodHandle get_method_oop(TRAPS) const;
   218 
   401 
   219 public:
   402 public:
   220   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
   403   MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS);
   221     return make_stack_value(tt_parameter, type, argnum);
       
   222   }
       
   223   virtual ArgToken make_oop_constant(oop con, TRAPS) {
       
   224     return make_stack_value(tt_constant, T_OBJECT, find_oop_constant(con));
       
   225   }
       
   226   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
       
   227     return make_stack_value(tt_constant, type, find_prim_constant(type, con));
       
   228   }
       
   229   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS);
       
   230   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS);
       
   231   virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
       
   232 
       
   233   int find_oop_constant(oop con);
       
   234   int find_prim_constant(BasicType type, jvalue* con);
       
   235 
       
   236 public:
       
   237   MethodHandleCompiler(Handle root, TRAPS)
       
   238     : MethodHandleWalker(root, THREAD),
       
   239       _thread(THREAD),
       
   240       _bytes(50),
       
   241       _constant_oops(THREAD, 10),
       
   242       _constant_prims(THREAD, 10),
       
   243       _max_stack(0), _max_locals(0),
       
   244       _name_index(0), _signature_index(0)
       
   245   { }
       
   246   const char* bytes()         { return _bytes.as_string(); }
       
   247   int constant_length()       { return _constant_oops.length(); }
       
   248   int max_stack()             { return _max_stack; }
       
   249   int max_locals()            { return _max_locals; }
       
   250   int name_index()            { return _name_index; }
       
   251   int signature_index()       { return _signature_index; }
       
   252   symbolHandle name()         { return symbolHandle(_thread, (symbolOop)constant_oop_at(_name_index)()); }
       
   253   symbolHandle signature()    { return symbolHandle(_thread, (symbolOop)constant_oop_at(_signature_index)()); }
       
   254 
       
   255   bool constant_is_oop_at(int i) {
       
   256     return (_constant_prims.at(i) == NULL);
       
   257   }
       
   258   Handle constant_oop_at(int i) {
       
   259     assert(constant_is_oop_at(i), "");
       
   260     return _constant_oops.at(i);
       
   261   }
       
   262   PrimCon* constant_prim_at(int i) {
       
   263     assert(!constant_is_oop_at(i), "");
       
   264     return _constant_prims.at(i);
       
   265   }
       
   266 
   404 
   267   // Compile the given MH chain into bytecode.
   405   // Compile the given MH chain into bytecode.
   268   void compile(TRAPS);
   406   methodHandle compile(TRAPS);
   269 };
   407 };