Print this page
rev 1080 : [mq]: meth.walker.patch
rev 1083 : [mq]: indy.compiler.inline.patch

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