hotspot/src/share/vm/prims/methodHandleWalk.hpp
changeset 9963 4a783069663c
parent 9946 b3d5b50e2289
child 9976 6fef34e63df1
equal deleted inserted replaced
9961:5d84243241ac 9963:4a783069663c
    54   int DirectMethodHandle_vmindex()     { return java_lang_invoke_DirectMethodHandle::vmindex(method_handle_oop()); }
    54   int DirectMethodHandle_vmindex()     { return java_lang_invoke_DirectMethodHandle::vmindex(method_handle_oop()); }
    55   oop BoundMethodHandle_argument_oop() { return java_lang_invoke_BoundMethodHandle::argument(method_handle_oop()); }
    55   oop BoundMethodHandle_argument_oop() { return java_lang_invoke_BoundMethodHandle::argument(method_handle_oop()); }
    56   int BoundMethodHandle_vmargslot()    { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); }
    56   int BoundMethodHandle_vmargslot()    { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); }
    57   int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
    57   int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
    58 
    58 
       
    59 #ifdef ASSERT
       
    60   void print_impl(TRAPS);
       
    61 #endif
       
    62 
    59 public:
    63 public:
    60   MethodHandleChain(Handle root, TRAPS)
    64   MethodHandleChain(Handle root, TRAPS)
    61     : _root(root)
    65     : _root(root)
    62   { set_method_handle(root, THREAD); }
    66   { set_method_handle(root, THREAD); }
    63 
    67 
    97   methodOop last_method_oop()   { assert(is_last(), ""); return _last_method(); }
   101   methodOop last_method_oop()   { assert(is_last(), ""); return _last_method(); }
    98   Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
   102   Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; }
    99 
   103 
   100   void lose(const char* msg, TRAPS);
   104   void lose(const char* msg, TRAPS);
   101   const char* lose_message()    { return _lose_message; }
   105   const char* lose_message()    { return _lose_message; }
       
   106 
       
   107 #ifdef ASSERT
       
   108   // Print a symbolic description of a method handle chain, including
       
   109   // the signature for each method.  The signatures are printed in
       
   110   // slot order to make it easier to understand.
       
   111   void print();
       
   112   static void print(Handle mh);
       
   113 #endif
   102 };
   114 };
   103 
   115 
   104 
   116 
   105 // Structure walker for method handles.
   117 // Structure walker for method handles.
   106 // Does abstract interpretation on top of low-level parsing.
   118 // Does abstract interpretation on top of low-level parsing.
   124     BasicType _bt;
   136     BasicType _bt;
   125     jvalue    _value;
   137     jvalue    _value;
   126     Handle    _handle;
   138     Handle    _handle;
   127 
   139 
   128   public:
   140   public:
   129     ArgToken(TokenType tt = tt_illegal) : _tt(tt) {
   141     ArgToken(TokenType tt = tt_illegal) : _tt(tt), _bt(tt == tt_void ? T_VOID : T_ILLEGAL) {
   130       assert(tt == tt_illegal || tt == tt_void, "invalid token type");
   142       assert(tt == tt_illegal || tt == tt_void, "invalid token type");
   131     }
   143     }
   132 
   144 
   133     ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
   145     ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
   134       assert(_tt == tt_parameter || _tt == tt_temporary, "must have index");
   146       assert(_tt == tt_parameter || _tt == tt_temporary, "must have index");
   135       _value.i = index;
   147       _value.i = index;
   136     }
   148     }
   137 
   149 
   138     ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {}
   150     ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) { assert(_bt != T_OBJECT, "wrong constructor"); }
   139     ArgToken(BasicType bt, Handle value) : _tt(tt_constant), _bt(bt), _handle(value) {}
   151     ArgToken(Handle handle) : _tt(tt_constant), _bt(T_OBJECT), _handle(handle) {}
   140 
   152 
   141 
   153 
   142     ArgToken(const char* str) : _tt(tt_symbolic), _bt(T_LONG) {
   154     ArgToken(const char* str, BasicType type) : _tt(tt_symbolic), _bt(type) {
   143       _value.j = (intptr_t)str;
   155       _value.j = (intptr_t)str;
   144     }
   156     }
   145 
   157 
   146     TokenType token_type()  const { return _tt; }
   158     TokenType token_type()  const { return _tt; }
   147     BasicType basic_type()  const { return _bt; }
   159     BasicType basic_type()  const { return _bt; }
   148     bool      has_index()   const { return _tt == tt_parameter || _tt == tt_temporary; }
   160     bool      has_index()   const { return _tt == tt_parameter || _tt == tt_temporary; }
   149     int       index()       const { assert(has_index(), "must have index");; return _value.i; }
   161     int       index()       const { assert(has_index(), "must have index");; return _value.i; }
   150     Handle    object()      const { assert(_tt == tt_constant, "value type"); return _handle; }
   162     Handle    object()      const { assert(_bt == T_OBJECT, "wrong accessor"); assert(_tt == tt_constant, "value type"); return _handle; }
   151     const char* str()       const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; }
   163     const char* str()       const { assert(_tt == tt_symbolic, "string type"); return (const char*)(intptr_t)_value.j; }
   152 
   164 
   153     jint      get_jint()    const { assert(_tt == tt_constant, "value types"); return _value.i; }
   165     jint      get_jint()    const { assert(_bt == T_INT || is_subword_type(_bt), "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.i; }
   154     jlong     get_jlong()   const { assert(_tt == tt_constant, "value types"); return _value.j; }
   166     jlong     get_jlong()   const { assert(_bt == T_LONG, "wrong accessor");   assert(_tt == tt_constant, "value types"); return _value.j; }
   155     jfloat    get_jfloat()  const { assert(_tt == tt_constant, "value types"); return _value.f; }
   167     jfloat    get_jfloat()  const { assert(_bt == T_FLOAT, "wrong accessor");  assert(_tt == tt_constant, "value types"); return _value.f; }
   156     jdouble   get_jdouble() const { assert(_tt == tt_constant, "value types"); return _value.d; }
   168     jdouble   get_jdouble() const { assert(_bt == T_DOUBLE, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.d; }
   157   };
   169   };
   158 
       
   159   // Abstract interpretation state:
       
   160   struct SlotState {
       
   161     BasicType _type;
       
   162     ArgToken  _arg;
       
   163     SlotState() : _type(), _arg() {}
       
   164   };
       
   165   static SlotState make_state(BasicType type, ArgToken arg) {
       
   166     SlotState ss;
       
   167     ss._type = type; ss._arg = arg;
       
   168     return ss;
       
   169   }
       
   170 
   170 
   171 private:
   171 private:
   172   MethodHandleChain _chain;
   172   MethodHandleChain _chain;
   173   bool              _for_invokedynamic;
   173   bool              _for_invokedynamic;
   174   int               _local_index;
   174   int               _local_index;
   175 
   175 
   176   // This array is kept in an unusual order, indexed by low-level "slot number".
   176   // This array is kept in an unusual order, indexed by low-level "slot number".
   177   // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
   177   // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
   178   // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
   178   // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
   179   // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
   179   // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
   180   GrowableArray<SlotState> _outgoing;       // current outgoing parameter slots
   180   GrowableArray<ArgToken>  _outgoing;       // current outgoing parameter slots
   181   int                      _outgoing_argc;  // # non-empty outgoing slots
   181   int                      _outgoing_argc;  // # non-empty outgoing slots
   182 
   182 
   183   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
   183   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
   184   // If old_type != T_VOID, remove the old argument at that point.
   184   // If old_type != T_VOID, remove the old argument at that point.
   185   // If new_type != T_VOID, insert the new argument at that point.
   185   // If new_type != T_VOID, insert the new argument at that point.
   186   // Insert or delete a second empty slot as needed.
   186   // Insert or delete a second empty slot as needed.
   187   void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
   187   void change_argument(BasicType old_type, int slot, const ArgToken& new_arg);
       
   188   void change_argument(BasicType old_type, int slot, BasicType type, const ArgToken& new_arg) {
       
   189     assert(type == new_arg.basic_type(), "must agree");
       
   190     change_argument(old_type, slot, new_arg);
       
   191   }
   188 
   192 
   189   // Raw retype conversions for OP_RAW_RETYPE.
   193   // Raw retype conversions for OP_RAW_RETYPE.
   190   void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
   194   void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
   191   void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
   195   void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
   192   void retype_raw_return_type(  BasicType src, BasicType dst,           TRAPS) { retype_raw_conversion(src, dst, true,  -1,   CHECK); }
   196   void retype_raw_return_type(  BasicType src, BasicType dst,           TRAPS) { retype_raw_conversion(src, dst, true,  -1,   CHECK); }
   193 
   197 
   194   SlotState* slot_state(int slot) {
   198   BasicType arg_type(int slot) {
   195     if (slot < 0 || slot >= _outgoing.length())
   199     return _outgoing.at(slot).basic_type();
   196       return NULL;
   200   }
   197     return _outgoing.adr_at(slot);
   201   bool has_argument(int slot) {
   198   }
   202     return arg_type(slot) < T_VOID;
   199   BasicType slot_type(int slot) {
       
   200     SlotState* ss = slot_state(slot);
       
   201     if (ss == NULL)
       
   202       return T_ILLEGAL;
       
   203     return ss->_type;
       
   204   }
       
   205   bool slot_has_argument(int slot) {
       
   206     return slot_type(slot) < T_VOID;
       
   207   }
   203   }
   208 
   204 
   209 #ifdef ASSERT
   205 #ifdef ASSERT
   210   int argument_count_slow();
   206   int argument_count_slow();
   211 #endif
   207 #endif
   212 
   208 
   213   // Return a bytecode for converting src to dest, if one exists.
   209   // Return a bytecode for converting src to dest, if one exists.
   214   Bytecodes::Code conversion_code(BasicType src, BasicType dest);
   210   Bytecodes::Code conversion_code(BasicType src, BasicType dest);
   215 
   211 
   216   void walk_incoming_state(TRAPS);
   212   void walk_incoming_state(TRAPS);
       
   213 
       
   214   void verify_args_and_signature(TRAPS) NOT_DEBUG_RETURN;
   217 
   215 
   218 public:
   216 public:
   219   MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
   217   MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
   220     : _chain(root, THREAD),
   218     : _chain(root, THREAD),
   221       _for_invokedynamic(for_invokedynamic),
   219       _for_invokedynamic(for_invokedynamic),
   419   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
   417   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
   420     return ArgToken(tt_parameter, type, argnum);
   418     return ArgToken(tt_parameter, type, argnum);
   421   }
   419   }
   422   virtual ArgToken make_oop_constant(oop con, TRAPS) {
   420   virtual ArgToken make_oop_constant(oop con, TRAPS) {
   423     Handle h(THREAD, con);
   421     Handle h(THREAD, con);
   424     return ArgToken(T_OBJECT, h);
   422     return ArgToken(h);
   425   }
   423   }
   426   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
   424   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
   427     return ArgToken(type, *con);
   425     return ArgToken(type, *con);
   428   }
   426   }
   429 
   427