hotspot/src/share/vm/prims/methodHandleWalk.hpp
changeset 13391 30245956af37
parent 13309 50c604cb0d5f
child 13392 1ef07ae0723d
equal deleted inserted replaced
13309:50c604cb0d5f 13391:30245956af37
     1 /*
       
     2  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #ifndef SHARE_VM_PRIMS_METHODHANDLEWALK_HPP
       
    26 #define SHARE_VM_PRIMS_METHODHANDLEWALK_HPP
       
    27 
       
    28 #include "prims/methodHandles.hpp"
       
    29 
       
    30 // Low-level parser for method handle chains.
       
    31 class MethodHandleChain : StackObj {
       
    32 public:
       
    33   typedef MethodHandles::EntryKind EntryKind;
       
    34 
       
    35 private:
       
    36   Handle        _root;          // original target
       
    37   Handle        _method_handle; // current target
       
    38   bool          _is_last;       // final guy in chain
       
    39   bool          _is_bound;      // has a bound argument
       
    40   BasicType     _arg_type;      // if is_bound, the bound argument type
       
    41   int           _arg_slot;      // if is_bound or is_adapter, affected argument slot
       
    42   jint          _conversion;    // conversion field of AMH or -1
       
    43   methodHandle  _last_method;   // if is_last, which method we target
       
    44   Bytecodes::Code _last_invoke; // if is_last, type of invoke
       
    45   const char*   _lose_message;  // saved argument to lose()
       
    46 
       
    47   void set_method_handle(Handle target, TRAPS);
       
    48   void set_last_method(oop target, TRAPS);
       
    49   static BasicType compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS);
       
    50 
       
    51   oop MethodHandle_type_oop()          { return java_lang_invoke_MethodHandle::type(method_handle_oop()); }
       
    52   oop MethodHandle_vmtarget_oop()      { return java_lang_invoke_MethodHandle::vmtarget(method_handle_oop()); }
       
    53   int MethodHandle_vmslots()           { return java_lang_invoke_MethodHandle::vmslots(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()); }
       
    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()); }
       
    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 
       
   134   // Argument token:
       
   135   class ArgToken {
       
   136   private:
       
   137     TokenType _tt;
       
   138     BasicType _bt;
       
   139     jvalue    _value;
       
   140     Handle    _handle;
       
   141 
       
   142   public:
       
   143     ArgToken(TokenType tt = tt_illegal) : _tt(tt), _bt(tt == tt_void ? T_VOID : T_ILLEGAL) {
       
   144       assert(tt == tt_illegal || tt == tt_void, "invalid token type");
       
   145     }
       
   146 
       
   147     ArgToken(TokenType tt, BasicType bt, int index) : _tt(tt), _bt(bt) {
       
   148       assert(_tt == tt_parameter || _tt == tt_temporary, "must have index");
       
   149       _value.i = index;
       
   150     }
       
   151 
       
   152     ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) { assert(_bt != T_OBJECT, "wrong constructor"); }
       
   153     ArgToken(Handle handle) : _tt(tt_constant), _bt(T_OBJECT), _handle(handle) {}
       
   154 
       
   155 
       
   156     ArgToken(const char* str, BasicType type) : _tt(tt_symbolic), _bt(type) {
       
   157       _value.j = (intptr_t)str;
       
   158     }
       
   159 
       
   160     TokenType token_type()  const { return _tt; }
       
   161     BasicType basic_type()  const { return _bt; }
       
   162     bool      has_index()   const { return _tt == tt_parameter || _tt == tt_temporary; }
       
   163     int       index()       const { assert(has_index(), "must have index");; return _value.i; }
       
   164     Handle    object()      const { assert(_bt == T_OBJECT, "wrong accessor"); assert(_tt == tt_constant, "value type"); return _handle; }
       
   165     const char* str()       const { assert(_tt == tt_symbolic, "string type"); return (const char*)(intptr_t)_value.j; }
       
   166 
       
   167     jint      get_jint()    const { assert(_bt == T_INT || is_subword_type(_bt), "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.i; }
       
   168     jlong     get_jlong()   const { assert(_bt == T_LONG, "wrong accessor");   assert(_tt == tt_constant, "value types"); return _value.j; }
       
   169     jfloat    get_jfloat()  const { assert(_bt == T_FLOAT, "wrong accessor");  assert(_tt == tt_constant, "value types"); return _value.f; }
       
   170     jdouble   get_jdouble() const { assert(_bt == T_DOUBLE, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.d; }
       
   171   };
       
   172 
       
   173 private:
       
   174   MethodHandleChain _chain;
       
   175   bool              _for_invokedynamic;
       
   176   int               _local_index;
       
   177 
       
   178   // This array is kept in an unusual order, indexed by low-level "slot number".
       
   179   // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
       
   180   // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
       
   181   // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
       
   182   GrowableArray<ArgToken>  _outgoing;       // current outgoing parameter slots
       
   183   int                      _outgoing_argc;  // # non-empty outgoing slots
       
   184 
       
   185   vmIntrinsics::ID _return_conv;            // Return conversion required by raw retypes.
       
   186 
       
   187   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
       
   188   // If old_type != T_VOID, remove the old argument at that point.
       
   189   // If new_type != T_VOID, insert the new argument at that point.
       
   190   // Insert or delete a second empty slot as needed.
       
   191   void change_argument(BasicType old_type, int slot, const ArgToken& new_arg);
       
   192   void change_argument(BasicType old_type, int slot, BasicType type, const ArgToken& new_arg) {
       
   193     assert(type == new_arg.basic_type(), "must agree");
       
   194     change_argument(old_type, slot, new_arg);
       
   195   }
       
   196 
       
   197   // Raw retype conversions for OP_RAW_RETYPE.
       
   198   void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
       
   199   void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
       
   200   void retype_raw_return_type(  BasicType src, BasicType dst,           TRAPS) { retype_raw_conversion(src, dst, true,  -1,   CHECK); }
       
   201 
       
   202   BasicType arg_type(int slot) {
       
   203     return _outgoing.at(slot).basic_type();
       
   204   }
       
   205   bool has_argument(int slot) {
       
   206     return arg_type(slot) < T_VOID;
       
   207   }
       
   208 
       
   209 #ifdef ASSERT
       
   210   int argument_count_slow();
       
   211 #endif
       
   212 
       
   213   // Return a bytecode for converting src to dest, if one exists.
       
   214   Bytecodes::Code conversion_code(BasicType src, BasicType dest);
       
   215 
       
   216   void walk_incoming_state(TRAPS);
       
   217 
       
   218   void verify_args_and_signature(TRAPS) NOT_DEBUG_RETURN;
       
   219 
       
   220 public:
       
   221   MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
       
   222     : _chain(root, THREAD),
       
   223       _for_invokedynamic(for_invokedynamic),
       
   224       _outgoing(THREAD, 10),
       
   225       _outgoing_argc(0),
       
   226       _return_conv(vmIntrinsics::_none)
       
   227   {
       
   228     _local_index = for_invokedynamic ? 0 : 1;
       
   229   }
       
   230 
       
   231   MethodHandleChain& chain() { return _chain; }
       
   232 
       
   233   bool for_invokedynamic() const { return _for_invokedynamic; }
       
   234 
       
   235   vmIntrinsics::ID return_conv() const { return _return_conv; }
       
   236   void set_return_conv(vmIntrinsics::ID c) { _return_conv = c; }
       
   237   static vmIntrinsics::ID zero_return_conv() { return vmIntrinsics::_min; }
       
   238 
       
   239   int new_local_index(BasicType bt) {
       
   240     //int index = _for_invokedynamic ? _local_index : _local_index - 1;
       
   241     int index = _local_index;
       
   242     _local_index += type2size[bt];
       
   243     return index;
       
   244   }
       
   245 
       
   246   int max_locals() const { return _local_index; }
       
   247 
       
   248   // plug-in abstract interpretation steps:
       
   249   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) = 0;
       
   250   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) = 0;
       
   251   virtual ArgToken make_oop_constant(oop con, TRAPS) = 0;
       
   252   virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) = 0;
       
   253   virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) = 0;
       
   254   virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS) = 0;
       
   255 
       
   256   // For make_invoke, the methodHandle can be NULL if the intrinsic ID
       
   257   // is something other than vmIntrinsics::_none.
       
   258 
       
   259   // and in case anyone cares to related the previous actions to the chain:
       
   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     }
       
   304 
       
   305     ConstantValue(int tag, Symbol* con) : _tag(tag), _sym(con) {
       
   306       assert(tag == JVM_CONSTANT_Utf8, "must be symbol type");
       
   307     }
       
   308 
       
   309     // Constructor for oop reference types.
       
   310     ConstantValue(int tag, int index) : _tag(tag) {
       
   311       assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
       
   312       _value.set_jint(index);
       
   313     }
       
   314     ConstantValue(int tag, int first_index, int second_index) : _tag(tag) {
       
   315       assert(JVM_CONSTANT_Fieldref <= tag && tag <= JVM_CONSTANT_NameAndType, "must be ref type");
       
   316       _value.set_jint(first_index << 16 | second_index);
       
   317     }
       
   318 
       
   319     // Constructor for primitive types.
       
   320     ConstantValue(BasicType bt, jvalue con) {
       
   321       _value.set_type(bt);
       
   322       switch (bt) {
       
   323       case T_INT:    _tag = JVM_CONSTANT_Integer; _value.set_jint(   con.i); break;
       
   324       case T_LONG:   _tag = JVM_CONSTANT_Long;    _value.set_jlong(  con.j); break;
       
   325       case T_FLOAT:  _tag = JVM_CONSTANT_Float;   _value.set_jfloat( con.f); break;
       
   326       case T_DOUBLE: _tag = JVM_CONSTANT_Double;  _value.set_jdouble(con.d); break;
       
   327       default: ShouldNotReachHere();
       
   328       }
       
   329     }
       
   330 
       
   331     int       tag()          const { return _tag; }
       
   332     Symbol*   symbol()       const { return _sym; }
       
   333     klassOop  klass_oop()    const { return (klassOop)  _handle(); }
       
   334     oop       object_oop()   const { return _handle(); }
       
   335     int       index()        const { return _value.get_jint(); }
       
   336     int       first_index()  const { return _value.get_jint() >> 16; }
       
   337     int       second_index() const { return _value.get_jint() & 0x0000FFFF; }
       
   338 
       
   339     bool      is_primitive() const { return is_java_primitive(_value.get_type()); }
       
   340     jint      get_jint()     const { return _value.get_jint();    }
       
   341     jlong     get_jlong()    const { return _value.get_jlong();   }
       
   342     jfloat    get_jfloat()   const { return _value.get_jfloat();  }
       
   343     jdouble   get_jdouble()  const { return _value.get_jdouble(); }
       
   344 
       
   345     void set_linkage(methodHandle method) {
       
   346       assert(_method.is_null(), "");
       
   347       _method = method;
       
   348     }
       
   349     bool     has_linkage()   const { return _method.not_null(); }
       
   350     methodHandle linkage()   const { return _method; }
       
   351   };
       
   352 
       
   353   // Fake constant pool.
       
   354   GrowableArray<ConstantValue*> _constants;
       
   355 
       
   356   // Non-BCP classes that appear in associated MethodTypes (require special handling).
       
   357   GrowableArray<KlassHandle> _non_bcp_klasses;
       
   358 
       
   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);
       
   400     return _constants.append(cv);
       
   401   }
       
   402 
       
   403   int cpool_primitive_put(BasicType type, jvalue* con);
       
   404 
       
   405   bool check_non_bcp_klasses(Handle method_type, TRAPS);
       
   406   bool check_non_bcp_klass(klassOop klass, TRAPS);
       
   407   void record_non_bcp_klasses();
       
   408 
       
   409   int cpool_int_put(jint value) {
       
   410     jvalue con; con.i = value;
       
   411     return cpool_primitive_put(T_INT, &con);
       
   412   }
       
   413   int cpool_long_put(jlong value) {
       
   414     jvalue con; con.j = value;
       
   415     return cpool_primitive_put(T_LONG, &con);
       
   416   }
       
   417   int cpool_float_put(jfloat value) {
       
   418     jvalue con; con.f = value;
       
   419     return cpool_primitive_put(T_FLOAT, &con);
       
   420   }
       
   421   int cpool_double_put(jdouble value) {
       
   422     jvalue con; con.d = value;
       
   423     return cpool_primitive_put(T_DOUBLE, &con);
       
   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