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

src/share/vm/prims/methodHandleWalk.hpp

Print this page




  57   int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
  58 
  59 #ifdef ASSERT
  60   void print_impl(TRAPS);
  61 #endif
  62 
  63 public:
  64   MethodHandleChain(Handle root, TRAPS)
  65     : _root(root)
  66   { set_method_handle(root, THREAD); }
  67 
  68   bool is_adapter()             { return _conversion != -1; }
  69   bool is_bound()               { return _is_bound; }
  70   bool is_last()                { return _is_last; }
  71 
  72   void next(TRAPS) {
  73     assert(!is_last(), "");
  74     set_method_handle(MethodHandle_vmtarget_oop(), THREAD);
  75   }
  76 

  77   Handle method_handle()        { return _method_handle; }
  78   oop    method_handle_oop()    { return _method_handle(); }
  79   oop    method_type_oop()      { return MethodHandle_type_oop(); }
  80   oop    vmtarget_oop()         { return MethodHandle_vmtarget_oop(); }
  81 
  82   jint adapter_conversion()     { assert(is_adapter(), ""); return _conversion; }
  83   int  adapter_conversion_op()  { return MethodHandles::adapter_conversion_op(adapter_conversion()); }
  84   BasicType adapter_conversion_src_type()
  85                                 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); }
  86   BasicType adapter_conversion_dest_type()
  87                                 { return MethodHandles::adapter_conversion_dest_type(adapter_conversion()); }
  88   int  adapter_conversion_stack_move()
  89                                 { return MethodHandles::adapter_conversion_stack_move(adapter_conversion()); }
  90   int  adapter_conversion_stack_pushes()
  91                                 { return adapter_conversion_stack_move() / MethodHandles::stack_move_unit(); }
  92   int  adapter_conversion_vminfo()
  93                                 { return MethodHandles::adapter_conversion_vminfo(adapter_conversion()); }
  94   int adapter_arg_slot()        { assert(is_adapter(), ""); return _arg_slot; }
  95   oop adapter_arg_oop()         { assert(is_adapter(), ""); return BoundMethodHandle_argument_oop(); }
  96 
  97   BasicType bound_arg_type()    { assert(is_bound(), ""); return _arg_type; }
  98   int       bound_arg_slot()    { assert(is_bound(), ""); return _arg_slot; }
  99   oop       bound_arg_oop()     { assert(is_bound(), ""); return BoundMethodHandle_argument_oop(); }
 100 
 101   methodHandle last_method()    { assert(is_last(), ""); return _last_method; }
 102   methodOop last_method_oop()   { assert(is_last(), ""); return _last_method(); }
 103   Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
 104 
 105   void lose(const char* msg, TRAPS);
 106   const char* lose_message()    { return _lose_message; }
 107 
 108 #ifdef ASSERT
 109   // Print a symbolic description of a method handle chain, including
 110   // the signature for each method.  The signatures are printed in
 111   // slot order to make it easier to understand.
 112   void print();
 113   static void print(Handle mh);
 114   static void print(oopDesc* mh);
 115 #endif
 116 };
 117 
 118 
 119 // Structure walker for method handles.
 120 // Does abstract interpretation on top of low-level parsing.
 121 // You supply the tokens shuffled by the abstract interpretation.
 122 class MethodHandleWalker : StackObj {
 123 public:
 124   // Stack values:
 125   enum TokenType {
 126     tt_void,
 127     tt_parameter,
 128     tt_temporary,
 129     tt_constant,
 130     tt_symbolic,
 131     tt_illegal
 132   };
 133 


 260   virtual void set_method_handle(oop mh) { }
 261 
 262   void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
 263   const char* lose_message()        { return chain().lose_message(); }
 264 
 265   ArgToken walk(TRAPS);
 266 };
 267 
 268 
 269 // An abstract interpreter for method handle chains.
 270 // Produces an account of the semantics of a chain, in terms of a static IR.
 271 // The IR happens to be JVM bytecodes.
 272 class MethodHandleCompiler : public MethodHandleWalker {
 273 private:
 274   int          _invoke_count;  // count the original call site has been executed
 275   KlassHandle  _rklass;        // Return type for casting.
 276   BasicType    _rtype;
 277   KlassHandle  _target_klass;
 278   Thread*      _thread;
 279 




 280   // Values used by the compiler.
 281   static jvalue zero_jvalue;
 282   static jvalue one_jvalue;
 283 
 284   // Fake constant pool entry.
 285   class ConstantValue : public ResourceObj {
 286   private:
 287     int       _tag;   // Constant pool tag type.
 288     JavaValue _value;
 289     Handle    _handle;
 290     Symbol*   _sym;
 291     methodHandle _method;  // pre-linkage
 292 
 293   public:
 294     // Constructor for oop types.
 295     ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
 296       assert(tag == JVM_CONSTANT_Class  ||
 297              tag == JVM_CONSTANT_String ||
 298              tag == JVM_CONSTANT_Object, "must be oop type");
 299     }


 355   // Accumulated compiler state:
 356   GrowableArray<unsigned char> _bytecode;
 357 
 358   int _cur_stack;
 359   int _max_stack;
 360   int _num_params;
 361   int _name_index;
 362   int _signature_index;
 363 
 364   void stack_push(BasicType bt) {
 365     _cur_stack += type2size[bt];
 366     if (_cur_stack > _max_stack) _max_stack = _cur_stack;
 367   }
 368   void stack_pop(BasicType bt) {
 369     _cur_stack -= type2size[bt];
 370     assert(_cur_stack >= 0, "sanity");
 371   }
 372 
 373   unsigned char* bytecode()        const { return _bytecode.adr_at(0); }
 374   int            bytecode_length() const { return _bytecode.length(); }

 375 
 376   // Fake constant pool.
 377   int cpool_oop_put(int tag, Handle con) {
 378     if (con.is_null())  return 0;
 379     ConstantValue* cv = new ConstantValue(tag, con);
 380     return _constants.append(cv);
 381   }
 382 
 383   int cpool_symbol_put(int tag, Symbol* con) {
 384     if (con == NULL)  return 0;
 385     ConstantValue* cv = new ConstantValue(tag, con);
 386     con->increment_refcount();
 387     return _constants.append(cv);
 388   }
 389 
 390   int cpool_oop_reference_put(int tag, int first_index, int second_index, methodHandle method) {
 391     if (first_index == 0 && second_index == 0)  return 0;
 392     assert(first_index != 0 && second_index != 0, "no zero indexes");
 393     ConstantValue* cv = new ConstantValue(tag, first_index, second_index);
 394     if (method.not_null())  cv->set_linkage(method);


 419   }
 420 
 421   int cpool_object_put(Handle obj) {
 422     return cpool_oop_put(JVM_CONSTANT_Object, obj);
 423   }
 424   int cpool_symbol_put(Symbol* sym) {
 425     return cpool_symbol_put(JVM_CONSTANT_Utf8, sym);
 426   }
 427   int cpool_klass_put(klassOop klass) {
 428     return cpool_oop_put(JVM_CONSTANT_Class, klass);
 429   }
 430   int cpool_methodref_put(Bytecodes::Code op, int class_index, int name_and_type_index, methodHandle method) {
 431     int tag = (op == Bytecodes::_invokeinterface ? JVM_CONSTANT_InterfaceMethodref : JVM_CONSTANT_Methodref);
 432     return cpool_oop_reference_put(tag, class_index, name_and_type_index, method);
 433   }
 434   int cpool_name_and_type_put(int name_index, int signature_index) {
 435     return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index, methodHandle());
 436   }
 437 
 438   void emit_bc(Bytecodes::Code op, int index = 0, int args_size = -1);


 439   void emit_load(BasicType bt, int index);
 440   void emit_store(BasicType bt, int index);
 441   void emit_load_constant(ArgToken arg);
 442 
 443   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
 444     return ArgToken(tt_parameter, type, argnum);
 445   }
 446   virtual ArgToken make_oop_constant(oop con, TRAPS) {
 447     Handle h(THREAD, con);
 448     return ArgToken(h);
 449   }
 450   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
 451     return ArgToken(type, *con);
 452   }
 453 
 454   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
 455   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
 456   virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
 457 



 458   // Get a real constant pool.
 459   constantPoolHandle get_constant_pool(TRAPS) const;
 460 
 461   // Get a real methodOop.
 462   methodHandle get_method_oop(TRAPS) const;
 463 
 464 public:
 465   MethodHandleCompiler(Handle root, Symbol* name, Symbol* signature, int invoke_count, bool for_invokedynamic, TRAPS);
 466 
 467   // Compile the given MH chain into bytecode.
 468   methodHandle compile(TRAPS);
 469 
 470   // Tests if the given class is a MH adapter holder.
 471   static bool klass_is_method_handle_adapter_holder(klassOop klass) {
 472     return (klass == SystemDictionary::MethodHandle_klass());
 473   }
 474 };
 475 
 476 #endif // SHARE_VM_PRIMS_METHODHANDLEWALK_HPP


  57   int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
  58 
  59 #ifdef ASSERT
  60   void print_impl(TRAPS);
  61 #endif
  62 
  63 public:
  64   MethodHandleChain(Handle root, TRAPS)
  65     : _root(root)
  66   { set_method_handle(root, THREAD); }
  67 
  68   bool is_adapter()             { return _conversion != -1; }
  69   bool is_bound()               { return _is_bound; }
  70   bool is_last()                { return _is_last; }
  71 
  72   void next(TRAPS) {
  73     assert(!is_last(), "");
  74     set_method_handle(MethodHandle_vmtarget_oop(), THREAD);
  75   }
  76 
  77   Handle root()                 { return _root; }
  78   Handle method_handle()        { return _method_handle; }
  79   oop    method_handle_oop()    { return _method_handle(); }
  80   oop    method_type_oop()      { return MethodHandle_type_oop(); }
  81   oop    vmtarget_oop()         { return MethodHandle_vmtarget_oop(); }
  82 
  83   jint adapter_conversion()     { assert(is_adapter(), ""); return _conversion; }
  84   int  adapter_conversion_op()  { return MethodHandles::adapter_conversion_op(adapter_conversion()); }
  85   BasicType adapter_conversion_src_type()
  86                                 { return MethodHandles::adapter_conversion_src_type(adapter_conversion()); }
  87   BasicType adapter_conversion_dest_type()
  88                                 { return MethodHandles::adapter_conversion_dest_type(adapter_conversion()); }
  89   int  adapter_conversion_stack_move()
  90                                 { return MethodHandles::adapter_conversion_stack_move(adapter_conversion()); }
  91   int  adapter_conversion_stack_pushes()
  92                                 { return adapter_conversion_stack_move() / MethodHandles::stack_move_unit(); }
  93   int  adapter_conversion_vminfo()
  94                                 { return MethodHandles::adapter_conversion_vminfo(adapter_conversion()); }
  95   int adapter_arg_slot()        { assert(is_adapter(), ""); return _arg_slot; }
  96   oop adapter_arg_oop()         { assert(is_adapter(), ""); return BoundMethodHandle_argument_oop(); }
  97 
  98   BasicType bound_arg_type()    { assert(is_bound(), ""); return _arg_type; }
  99   int       bound_arg_slot()    { assert(is_bound(), ""); return _arg_slot; }
 100   oop       bound_arg_oop()     { assert(is_bound(), ""); return BoundMethodHandle_argument_oop(); }
 101 
 102   methodHandle last_method()    { assert(is_last(), ""); return _last_method; }
 103   methodOop last_method_oop()   { assert(is_last(), ""); return _last_method(); }
 104   Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
 105 
 106   void lose(const char* msg, TRAPS);
 107   const char* lose_message()    { return _lose_message; }
 108 
 109 #ifdef ASSERT
 110   // Print a symbolic description of a method handle chain, including
 111   // the signature for each method.  The signatures are printed in
 112   // slot order to make it easier to understand.
 113   void print();

 114   static void print(oopDesc* mh);
 115 #endif
 116 };
 117 
 118 
 119 // Structure walker for method handles.
 120 // Does abstract interpretation on top of low-level parsing.
 121 // You supply the tokens shuffled by the abstract interpretation.
 122 class MethodHandleWalker : StackObj {
 123 public:
 124   // Stack values:
 125   enum TokenType {
 126     tt_void,
 127     tt_parameter,
 128     tt_temporary,
 129     tt_constant,
 130     tt_symbolic,
 131     tt_illegal
 132   };
 133 


 260   virtual void set_method_handle(oop mh) { }
 261 
 262   void lose(const char* msg, TRAPS) { chain().lose(msg, THREAD); }
 263   const char* lose_message()        { return chain().lose_message(); }
 264 
 265   ArgToken walk(TRAPS);
 266 };
 267 
 268 
 269 // An abstract interpreter for method handle chains.
 270 // Produces an account of the semantics of a chain, in terms of a static IR.
 271 // The IR happens to be JVM bytecodes.
 272 class MethodHandleCompiler : public MethodHandleWalker {
 273 private:
 274   int          _invoke_count;  // count the original call site has been executed
 275   KlassHandle  _rklass;        // Return type for casting.
 276   BasicType    _rtype;
 277   KlassHandle  _target_klass;
 278   Thread*      _thread;
 279 
 280   int          _selectAlternative_bci; // These are used for capturing profiles from GWTs
 281   int          _taken_count;
 282   int          _not_taken_count;
 283 
 284   // Values used by the compiler.
 285   static jvalue zero_jvalue;
 286   static jvalue one_jvalue;
 287 
 288   // Fake constant pool entry.
 289   class ConstantValue : public ResourceObj {
 290   private:
 291     int       _tag;   // Constant pool tag type.
 292     JavaValue _value;
 293     Handle    _handle;
 294     Symbol*   _sym;
 295     methodHandle _method;  // pre-linkage
 296 
 297   public:
 298     // Constructor for oop types.
 299     ConstantValue(int tag, Handle con) : _tag(tag), _handle(con) {
 300       assert(tag == JVM_CONSTANT_Class  ||
 301              tag == JVM_CONSTANT_String ||
 302              tag == JVM_CONSTANT_Object, "must be oop type");
 303     }


 359   // Accumulated compiler state:
 360   GrowableArray<unsigned char> _bytecode;
 361 
 362   int _cur_stack;
 363   int _max_stack;
 364   int _num_params;
 365   int _name_index;
 366   int _signature_index;
 367 
 368   void stack_push(BasicType bt) {
 369     _cur_stack += type2size[bt];
 370     if (_cur_stack > _max_stack) _max_stack = _cur_stack;
 371   }
 372   void stack_pop(BasicType bt) {
 373     _cur_stack -= type2size[bt];
 374     assert(_cur_stack >= 0, "sanity");
 375   }
 376 
 377   unsigned char* bytecode()        const { return _bytecode.adr_at(0); }
 378   int            bytecode_length() const { return _bytecode.length(); }
 379   int            cur_bci()         const { return _bytecode.length(); }
 380 
 381   // Fake constant pool.
 382   int cpool_oop_put(int tag, Handle con) {
 383     if (con.is_null())  return 0;
 384     ConstantValue* cv = new ConstantValue(tag, con);
 385     return _constants.append(cv);
 386   }
 387 
 388   int cpool_symbol_put(int tag, Symbol* con) {
 389     if (con == NULL)  return 0;
 390     ConstantValue* cv = new ConstantValue(tag, con);
 391     con->increment_refcount();
 392     return _constants.append(cv);
 393   }
 394 
 395   int cpool_oop_reference_put(int tag, int first_index, int second_index, methodHandle method) {
 396     if (first_index == 0 && second_index == 0)  return 0;
 397     assert(first_index != 0 && second_index != 0, "no zero indexes");
 398     ConstantValue* cv = new ConstantValue(tag, first_index, second_index);
 399     if (method.not_null())  cv->set_linkage(method);


 424   }
 425 
 426   int cpool_object_put(Handle obj) {
 427     return cpool_oop_put(JVM_CONSTANT_Object, obj);
 428   }
 429   int cpool_symbol_put(Symbol* sym) {
 430     return cpool_symbol_put(JVM_CONSTANT_Utf8, sym);
 431   }
 432   int cpool_klass_put(klassOop klass) {
 433     return cpool_oop_put(JVM_CONSTANT_Class, klass);
 434   }
 435   int cpool_methodref_put(Bytecodes::Code op, int class_index, int name_and_type_index, methodHandle method) {
 436     int tag = (op == Bytecodes::_invokeinterface ? JVM_CONSTANT_InterfaceMethodref : JVM_CONSTANT_Methodref);
 437     return cpool_oop_reference_put(tag, class_index, name_and_type_index, method);
 438   }
 439   int cpool_name_and_type_put(int name_index, int signature_index) {
 440     return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index, methodHandle());
 441   }
 442 
 443   void emit_bc(Bytecodes::Code op, int index = 0, int args_size = -1);
 444   void update_branch_dest(int src, int dst);
 445   void emit_load(ArgToken arg);
 446   void emit_load(BasicType bt, int index);
 447   void emit_store(BasicType bt, int index);
 448   void emit_load_constant(ArgToken arg);
 449 
 450   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
 451     return ArgToken(tt_parameter, type, argnum);
 452   }
 453   virtual ArgToken make_oop_constant(oop con, TRAPS) {
 454     Handle h(THREAD, con);
 455     return ArgToken(h);
 456   }
 457   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
 458     return ArgToken(type, *con);
 459   }
 460 
 461   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS);
 462   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS);
 463   virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS);
 464 
 465   // Check for profiling information on a GWT and return true if it's found
 466   bool fetch_counts(ArgToken a1, ArgToken a2);
 467 
 468   // Get a real constant pool.
 469   constantPoolHandle get_constant_pool(TRAPS) const;
 470 
 471   // Get a real methodOop.
 472   methodHandle get_method_oop(TRAPS);
 473 
 474 public:
 475   MethodHandleCompiler(Handle root, Symbol* name, Symbol* signature, int invoke_count, bool for_invokedynamic, TRAPS);
 476 
 477   // Compile the given MH chain into bytecode.
 478   methodHandle compile(TRAPS);
 479 
 480   // Tests if the given class is a MH adapter holder.
 481   static bool klass_is_method_handle_adapter_holder(klassOop klass) {
 482     return (klass == SystemDictionary::MethodHandle_klass());
 483   }
 484 };
 485 
 486 #endif // SHARE_VM_PRIMS_METHODHANDLEWALK_HPP
src/share/vm/prims/methodHandleWalk.hpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File