src/share/vm/prims/methodHandleWalk.hpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6998541 Sdiff src/share/vm/prims

src/share/vm/prims/methodHandleWalk.hpp

Print this page




  96 
  97   methodOop last_method_oop()   { assert(is_last(), ""); return _last_method(); }
  98   Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
  99 
 100   void lose(const char* msg, TRAPS);
 101   const char* lose_message()    { return _lose_message; }
 102 };
 103 
 104 
 105 // Structure walker for method handles.
 106 // Does abstract interpretation on top of low-level parsing.
 107 // You supply the tokens shuffled by the abstract interpretation.
 108 class MethodHandleWalker : StackObj {
 109 public:
 110   // Stack values:
 111   enum TokenType {
 112     tt_void,
 113     tt_parameter,
 114     tt_temporary,
 115     tt_constant,

 116     tt_illegal
 117   };
 118 
 119   // Argument token:
 120   class ArgToken {
 121   private:
 122     TokenType _tt;
 123     BasicType _bt;
 124     jvalue    _value;
 125     Handle    _handle;
 126 
 127   public:
 128     ArgToken(TokenType tt = tt_illegal) : _tt(tt) {}
 129     ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {}
 130 
 131     ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
 132       _value.i = index;
 133     }
 134 
 135     ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) {


 147     jdouble   get_jdouble() const { return _value.d; }
 148   };
 149 
 150   // Abstract interpretation state:
 151   struct SlotState {
 152     BasicType _type;
 153     ArgToken  _arg;
 154     SlotState() : _type(), _arg() {}
 155   };
 156   static SlotState make_state(BasicType type, ArgToken arg) {
 157     SlotState ss;
 158     ss._type = type; ss._arg = arg;
 159     return ss;
 160   }
 161 
 162 private:
 163   MethodHandleChain _chain;
 164   bool              _for_invokedynamic;
 165   int               _local_index;
 166 




 167   GrowableArray<SlotState> _outgoing;       // current outgoing parameter slots
 168   int                      _outgoing_argc;  // # non-empty outgoing slots
 169 
 170   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
 171   // If old_type != T_VOID, remove the old argument at that point.
 172   // If new_type != T_VOID, insert the new argument at that point.
 173   // Insert or delete a second empty slot as needed.
 174   void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
 175 





 176   SlotState* slot_state(int slot) {
 177     if (slot < 0 || slot >= _outgoing.length())
 178       return NULL;
 179     return _outgoing.adr_at(slot);
 180   }
 181   BasicType slot_type(int slot) {
 182     SlotState* ss = slot_state(slot);
 183     if (ss == NULL)
 184       return T_ILLEGAL;
 185     return ss->_type;
 186   }
 187   bool slot_has_argument(int slot) {
 188     return slot_type(slot) < T_VOID;
 189   }
 190 
 191 #ifdef ASSERT
 192   int argument_count_slow();
 193 #endif
 194 
 195   // Return a bytecode for converting src to dest, if one exists.


 204       _outgoing(THREAD, 10),
 205       _outgoing_argc(0)
 206   {
 207     _local_index = for_invokedynamic ? 0 : 1;
 208   }
 209 
 210   MethodHandleChain& chain() { return _chain; }
 211 
 212   bool for_invokedynamic() const { return _for_invokedynamic; }
 213 
 214   int new_local_index(BasicType bt) {
 215     //int index = _for_invokedynamic ? _local_index : _local_index - 1;
 216     int index = _local_index;
 217     _local_index += type2size[bt];
 218     return index;
 219   }
 220 
 221   int max_locals() const { return _local_index; }
 222 
 223   // plug-in abstract interpretation steps:
 224   virtual ArgToken make_parameter( BasicType type, klassOop tk, int argnum, TRAPS ) = 0;
 225   virtual ArgToken make_prim_constant( BasicType type, jvalue* con, TRAPS ) = 0;
 226   virtual ArgToken make_oop_constant( oop con, TRAPS ) = 0;
 227   virtual ArgToken make_conversion( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS ) = 0;
 228   virtual ArgToken make_fetch( BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS ) = 0;
 229   virtual ArgToken make_invoke( methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS ) = 0;
 230 
 231   // For make_invoke, the methodOop can be NULL if the intrinsic ID
 232   // is something other than vmIntrinsics::_none.
 233 
 234   // and in case anyone cares to related the previous actions to the chain:
 235   virtual void set_method_handle(oop mh) { }
 236 
 237   void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
 238   const char* lose_message()        { return chain().lose_message(); }
 239 
 240   ArgToken walk(TRAPS);
 241 };
 242 
 243 
 244 // An abstract interpreter for method handle chains.
 245 // Produces an account of the semantics of a chain, in terms of a static IR.
 246 // The IR happens to be JVM bytecodes.
 247 class MethodHandleCompiler : public MethodHandleWalker {
 248 private:
 249   methodHandle _callee;
 250   int          _invoke_count;  // count the original call site has been executed
 251   KlassHandle  _rklass;        // Return type for casting.
 252   BasicType    _rtype;
 253   KlassHandle  _target_klass;
 254   Thread*      _thread;
 255 




 256   // Fake constant pool entry.
 257   class ConstantValue {
 258   private:
 259     int       _tag;   // Constant pool tag type.
 260     JavaValue _value;
 261     Handle    _handle;
 262     Symbol*   _sym;
 263 
 264   public:
 265     // Constructor for oop types.
 266     ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
 267       assert(tag == JVM_CONSTANT_Class  ||
 268              tag == JVM_CONSTANT_String ||
 269              tag == JVM_CONSTANT_Object, "must be oop type");
 270     }
 271 
 272     ConstantValue(int tag, Symbol* con) : _tag(tag), _sym(con) {
 273       assert(tag == JVM_CONSTANT_Utf8, "must be symbol type");
 274     }
 275 


 400   }
 401   virtual ArgToken make_oop_constant(oop con, TRAPS) {
 402     Handle h(THREAD, con);
 403     return ArgToken(tt_constant, T_OBJECT, h);
 404   }
 405   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
 406     return ArgToken(tt_constant, type, *con);
 407   }
 408 
 409   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
 410   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
 411   virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
 412 
 413   // Get a real constant pool.
 414   constantPoolHandle get_constant_pool(TRAPS) const;
 415 
 416   // Get a real methodOop.
 417   methodHandle get_method_oop(TRAPS) const;
 418 
 419 public:
 420   MethodHandleCompiler(Handle root, methodHandle call_method, int invoke_count, bool for_invokedynamic, TRAPS);
 421 
 422   // Compile the given MH chain into bytecode.
 423   methodHandle compile(TRAPS);
 424 
 425   // Tests if the given class is a MH adapter holder.
 426   static bool klass_is_method_handle_adapter_holder(klassOop klass) {
 427     return (klass == SystemDictionary::MethodHandle_klass());
 428   }
 429 };
 430 
 431 #endif // SHARE_VM_PRIMS_METHODHANDLEWALK_HPP


  96 
  97   methodOop last_method_oop()   { assert(is_last(), ""); return _last_method(); }
  98   Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
  99 
 100   void lose(const char* msg, TRAPS);
 101   const char* lose_message()    { return _lose_message; }
 102 };
 103 
 104 
 105 // Structure walker for method handles.
 106 // Does abstract interpretation on top of low-level parsing.
 107 // You supply the tokens shuffled by the abstract interpretation.
 108 class MethodHandleWalker : StackObj {
 109 public:
 110   // Stack values:
 111   enum TokenType {
 112     tt_void,
 113     tt_parameter,
 114     tt_temporary,
 115     tt_constant,
 116     tt_symbolic,
 117     tt_illegal
 118   };
 119 
 120   // Argument token:
 121   class ArgToken {
 122   private:
 123     TokenType _tt;
 124     BasicType _bt;
 125     jvalue    _value;
 126     Handle    _handle;
 127 
 128   public:
 129     ArgToken(TokenType tt = tt_illegal) : _tt(tt) {}
 130     ArgToken(TokenType tt, BasicType bt, jvalue value) : _tt(tt), _bt(bt), _value(value) {}
 131 
 132     ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
 133       _value.i = index;
 134     }
 135 
 136     ArgToken(TokenType tt, BasicType bt, Handle value) : _tt(tt), _bt(bt) {


 148     jdouble   get_jdouble() const { return _value.d; }
 149   };
 150 
 151   // Abstract interpretation state:
 152   struct SlotState {
 153     BasicType _type;
 154     ArgToken  _arg;
 155     SlotState() : _type(), _arg() {}
 156   };
 157   static SlotState make_state(BasicType type, ArgToken arg) {
 158     SlotState ss;
 159     ss._type = type; ss._arg = arg;
 160     return ss;
 161   }
 162 
 163 private:
 164   MethodHandleChain _chain;
 165   bool              _for_invokedynamic;
 166   int               _local_index;
 167 
 168   // This array is kept in an unusual order, indexed by low-level "slot number".
 169   // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
 170   // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
 171   // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
 172   GrowableArray<SlotState> _outgoing;       // current outgoing parameter slots
 173   int                      _outgoing_argc;  // # non-empty outgoing slots
 174 
 175   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
 176   // If old_type != T_VOID, remove the old argument at that point.
 177   // If new_type != T_VOID, insert the new argument at that point.
 178   // Insert or delete a second empty slot as needed.
 179   void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
 180 
 181   // Raw retype conversions for OP_RAW_RETYPE.
 182   void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
 183   void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
 184   void retype_raw_return_type(  BasicType src, BasicType dst,           TRAPS) { retype_raw_conversion(src, dst, true,  -1,   CHECK); }
 185 
 186   SlotState* slot_state(int slot) {
 187     if (slot < 0 || slot >= _outgoing.length())
 188       return NULL;
 189     return _outgoing.adr_at(slot);
 190   }
 191   BasicType slot_type(int slot) {
 192     SlotState* ss = slot_state(slot);
 193     if (ss == NULL)
 194       return T_ILLEGAL;
 195     return ss->_type;
 196   }
 197   bool slot_has_argument(int slot) {
 198     return slot_type(slot) < T_VOID;
 199   }
 200 
 201 #ifdef ASSERT
 202   int argument_count_slow();
 203 #endif
 204 
 205   // Return a bytecode for converting src to dest, if one exists.


 214       _outgoing(THREAD, 10),
 215       _outgoing_argc(0)
 216   {
 217     _local_index = for_invokedynamic ? 0 : 1;
 218   }
 219 
 220   MethodHandleChain& chain() { return _chain; }
 221 
 222   bool for_invokedynamic() const { return _for_invokedynamic; }
 223 
 224   int new_local_index(BasicType bt) {
 225     //int index = _for_invokedynamic ? _local_index : _local_index - 1;
 226     int index = _local_index;
 227     _local_index += type2size[bt];
 228     return index;
 229   }
 230 
 231   int max_locals() const { return _local_index; }
 232 
 233   // plug-in abstract interpretation steps:
 234   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) = 0;
 235   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) = 0;
 236   virtual ArgToken make_oop_constant(oop con, TRAPS) = 0;
 237   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) = 0;
 238   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) = 0;
 239   virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS) = 0;
 240 
 241   // For make_invoke, the methodOop can be NULL if the intrinsic ID
 242   // is something other than vmIntrinsics::_none.
 243 
 244   // and in case anyone cares to related the previous actions to the chain:
 245   virtual void set_method_handle(oop mh) { }
 246 
 247   void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
 248   const char* lose_message()        { return chain().lose_message(); }
 249 
 250   ArgToken walk(TRAPS);
 251 };
 252 
 253 
 254 // An abstract interpreter for method handle chains.
 255 // Produces an account of the semantics of a chain, in terms of a static IR.
 256 // The IR happens to be JVM bytecodes.
 257 class MethodHandleCompiler : public MethodHandleWalker {
 258 private:
 259   methodHandle _callee;
 260   int          _invoke_count;  // count the original call site has been executed
 261   KlassHandle  _rklass;        // Return type for casting.
 262   BasicType    _rtype;
 263   KlassHandle  _target_klass;
 264   Thread*      _thread;
 265 
 266   // Values used by the compiler.
 267   static jvalue zero_jvalue;
 268   static jvalue one_jvalue;
 269 
 270   // Fake constant pool entry.
 271   class ConstantValue {
 272   private:
 273     int       _tag;   // Constant pool tag type.
 274     JavaValue _value;
 275     Handle    _handle;
 276     Symbol*   _sym;
 277 
 278   public:
 279     // Constructor for oop types.
 280     ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
 281       assert(tag == JVM_CONSTANT_Class  ||
 282              tag == JVM_CONSTANT_String ||
 283              tag == JVM_CONSTANT_Object, "must be oop type");
 284     }
 285 
 286     ConstantValue(int tag, Symbol* con) : _tag(tag), _sym(con) {
 287       assert(tag == JVM_CONSTANT_Utf8, "must be symbol type");
 288     }
 289 


 414   }
 415   virtual ArgToken make_oop_constant(oop con, TRAPS) {
 416     Handle h(THREAD, con);
 417     return ArgToken(tt_constant, T_OBJECT, h);
 418   }
 419   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
 420     return ArgToken(tt_constant, type, *con);
 421   }
 422 
 423   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
 424   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
 425   virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
 426 
 427   // Get a real constant pool.
 428   constantPoolHandle get_constant_pool(TRAPS) const;
 429 
 430   // Get a real methodOop.
 431   methodHandle get_method_oop(TRAPS) const;
 432 
 433 public:
 434   MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool for_invokedynamic, TRAPS);
 435 
 436   // Compile the given MH chain into bytecode.
 437   methodHandle compile(TRAPS);
 438 
 439   // Tests if the given class is a MH adapter holder.
 440   static bool klass_is_method_handle_adapter_holder(klassOop klass) {
 441     return (klass == SystemDictionary::MethodHandle_klass());
 442   }
 443 };
 444 
 445 #endif // SHARE_VM_PRIMS_METHODHANDLEWALK_HPP
src/share/vm/prims/methodHandleWalk.hpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File