src/share/vm/prims/methodHandleWalk.cpp

changeset 1568
aa62b9388fce
child 1573
dd57230ba8fe
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/prims/methodHandleWalk.cpp	Mon Jan 04 15:52:40 2010 +0100
     1.3 @@ -0,0 +1,805 @@
     1.4 +/*
     1.5 + * Copyright 2008-2010 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +/*
    1.29 + * JSR 292 reference implementation: method handle structure analysis
    1.30 + */
    1.31 +
    1.32 +#include "incls/_precompiled.incl"
    1.33 +#include "incls/_methodHandleWalk.cpp.incl"
    1.34 +
    1.35 +void MethodHandleChain::set_method_handle(Handle mh, TRAPS) {
    1.36 +  if (!java_dyn_MethodHandle::is_instance(mh()))  lose("bad method handle", CHECK);
    1.37 +
    1.38 +  // set current method handle and unpack partially
    1.39 +  _method_handle = mh;
    1.40 +  _is_last       = false;
    1.41 +  _is_bound      = false;
    1.42 +  _arg_slot      = -1;
    1.43 +  _arg_type      = T_VOID;
    1.44 +  _conversion    = -1;
    1.45 +  _last_invoke   = Bytecodes::_nop;  //arbitrary non-garbage
    1.46 +
    1.47 +  if (sun_dyn_DirectMethodHandle::is_instance(mh())) {
    1.48 +    set_last_method(mh(), THREAD);
    1.49 +    return;
    1.50 +  }
    1.51 +  if (sun_dyn_AdapterMethodHandle::is_instance(mh())) {
    1.52 +    _conversion = AdapterMethodHandle_conversion();
    1.53 +    assert(_conversion != -1, "bad conv value");
    1.54 +    assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH");
    1.55 +  }
    1.56 +  if (sun_dyn_BoundMethodHandle::is_instance(mh())) {
    1.57 +    if (!is_adapter())          // keep AMH and BMH separate in this model
    1.58 +      _is_bound = true;
    1.59 +    _arg_slot = BoundMethodHandle_vmargslot();
    1.60 +    oop target = MethodHandle_vmtarget_oop();
    1.61 +    if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) {
    1.62 +      _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK);
    1.63 +    } else if (target != NULL && target->is_method()) {
    1.64 +      _arg_type = compute_bound_arg_type(NULL, (methodOop)target, _arg_slot, CHECK);
    1.65 +      set_last_method(mh(), CHECK);
    1.66 +    } else {
    1.67 +      _is_bound = false;  // lose!
    1.68 +    }
    1.69 +  }
    1.70 +  if (is_bound() && _arg_type == T_VOID) {
    1.71 +    lose("bad vmargslot", CHECK);
    1.72 +  }
    1.73 +  if (!is_bound() && !is_adapter()) {
    1.74 +    lose("unrecognized MH type", CHECK);
    1.75 +  }
    1.76 +}
    1.77 +
    1.78 +void MethodHandleChain::set_last_method(oop target, TRAPS) {
    1.79 +  _is_last = true;
    1.80 +  klassOop receiver_limit_oop = NULL;
    1.81 +  int flags = 0;
    1.82 +  methodOop m = MethodHandles::decode_method(target, receiver_limit_oop, flags);
    1.83 +  _last_method = methodHandle(THREAD, m);
    1.84 +  if ((flags & MethodHandles::_dmf_has_receiver) == 0)
    1.85 +    _last_invoke = Bytecodes::_invokestatic;
    1.86 +  else if ((flags & MethodHandles::_dmf_does_dispatch) == 0)
    1.87 +    _last_invoke = Bytecodes::_invokespecial;
    1.88 +  else if ((flags & MethodHandles::_dmf_from_interface) != 0)
    1.89 +    _last_invoke = Bytecodes::_invokeinterface;
    1.90 +  else
    1.91 +    _last_invoke = Bytecodes::_invokevirtual;
    1.92 +}
    1.93 +
    1.94 +BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) {
    1.95 +  // There is no direct indication of whether the argument is primitive or not.
    1.96 +  // It is implied by the _vmentry code, and by the MethodType of the target.
    1.97 +  // FIXME: Make it explicit MethodHandleImpl refactors out from MethodHandle
    1.98 +  BasicType arg_type = T_VOID;
    1.99 +  if (target != NULL) {
   1.100 +    oop mtype = java_dyn_MethodHandle::type(target);
   1.101 +    int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot);
   1.102 +    if (arg_num >= 0) {
   1.103 +      oop ptype = java_dyn_MethodType::ptype(mtype, arg_num);
   1.104 +      arg_type = java_lang_Class::as_BasicType(ptype);
   1.105 +    }
   1.106 +  } else if (m != NULL) {
   1.107 +    // figure out the argument type from the slot
   1.108 +    // FIXME: make this explicit in the MH
   1.109 +    int cur_slot = m->size_of_parameters();
   1.110 +    if (arg_slot >= cur_slot)
   1.111 +      return T_VOID;
   1.112 +    if (!m->is_static()) {
   1.113 +      cur_slot -= type2size[T_OBJECT];
   1.114 +      if (cur_slot == arg_slot)
   1.115 +        return T_OBJECT;
   1.116 +    }
   1.117 +    for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) {
   1.118 +      BasicType bt = ss.type();
   1.119 +      cur_slot -= type2size[bt];
   1.120 +      if (cur_slot <= arg_slot) {
   1.121 +        if (cur_slot == arg_slot)
   1.122 +          arg_type = bt;
   1.123 +        break;
   1.124 +      }
   1.125 +    }
   1.126 +  }
   1.127 +  if (arg_type == T_ARRAY)
   1.128 +    arg_type = T_OBJECT;
   1.129 +  return arg_type;
   1.130 +}
   1.131 +
   1.132 +void MethodHandleChain::lose(const char* msg, TRAPS) {
   1.133 +  _lose_message = msg;
   1.134 +  if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
   1.135 +    // throw a preallocated exception
   1.136 +    THROW_OOP(Universe::virtual_machine_error_instance());
   1.137 +  }
   1.138 +  THROW_MSG(vmSymbols::java_lang_InternalError(), msg);
   1.139 +}
   1.140 +
   1.141 +Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) {
   1.142 +  if (is_subword_type(src)) {
   1.143 +    src = T_INT;          // all subword src types act like int
   1.144 +  }
   1.145 +  if (src == dest) {
   1.146 +    return Bytecodes::_nop;
   1.147 +  }
   1.148 +
   1.149 +#define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d))
   1.150 +  switch (SRC_DEST(src, dest)) {
   1.151 +  case SRC_DEST(T_INT, T_LONG):           return Bytecodes::_i2l;
   1.152 +  case SRC_DEST(T_INT, T_FLOAT):          return Bytecodes::_i2f;
   1.153 +  case SRC_DEST(T_INT, T_DOUBLE):         return Bytecodes::_i2d;
   1.154 +  case SRC_DEST(T_INT, T_BYTE):           return Bytecodes::_i2b;
   1.155 +  case SRC_DEST(T_INT, T_CHAR):           return Bytecodes::_i2c;
   1.156 +  case SRC_DEST(T_INT, T_SHORT):          return Bytecodes::_i2s;
   1.157 +
   1.158 +  case SRC_DEST(T_LONG, T_INT):           return Bytecodes::_l2i;
   1.159 +  case SRC_DEST(T_LONG, T_FLOAT):         return Bytecodes::_l2f;
   1.160 +  case SRC_DEST(T_LONG, T_DOUBLE):        return Bytecodes::_l2d;
   1.161 +
   1.162 +  case SRC_DEST(T_FLOAT, T_INT):          return Bytecodes::_f2i;
   1.163 +  case SRC_DEST(T_FLOAT, T_LONG):         return Bytecodes::_f2l;
   1.164 +  case SRC_DEST(T_FLOAT, T_DOUBLE):       return Bytecodes::_f2d;
   1.165 +
   1.166 +  case SRC_DEST(T_DOUBLE, T_INT):         return Bytecodes::_d2i;
   1.167 +  case SRC_DEST(T_DOUBLE, T_LONG):        return Bytecodes::_d2l;
   1.168 +  case SRC_DEST(T_DOUBLE, T_FLOAT):       return Bytecodes::_d2f;
   1.169 +  }
   1.170 +#undef SRC_DEST
   1.171 +
   1.172 +  // cannot do it in one step, or at all
   1.173 +  return Bytecodes::_illegal;
   1.174 +}
   1.175 +
   1.176 +MethodHandleWalker::ArgToken
   1.177 +MethodHandleWalker::walk(TRAPS) {
   1.178 +  walk_incoming_state(CHECK_NULL);
   1.179 +
   1.180 +  for (;;) {
   1.181 +    set_method_handle(chain().method_handle_oop());
   1.182 +
   1.183 +    assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
   1.184 +
   1.185 +    if (chain().is_adapter()) {
   1.186 +      int conv_op = chain().adapter_conversion_op();
   1.187 +      int arg_slot = chain().adapter_arg_slot();
   1.188 +      SlotState* arg_state = slot_state(arg_slot);
   1.189 +      if (arg_state == NULL
   1.190 +          && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) {
   1.191 +        lose("bad argument index", CHECK_NULL);
   1.192 +      }
   1.193 +
   1.194 +      // perform the adapter action
   1.195 +      switch (chain().adapter_conversion_op()) {
   1.196 +      case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY:
   1.197 +      case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW:
   1.198 +        // No changes to arguments; pass the bits through.
   1.199 +        // The only difference between the two ops is that the "only" version
   1.200 +        // is fully compatible with the verifier, while the "raw" version
   1.201 +        // performs a few extra bitwise conversions (like long <-> double).
   1.202 +        break;
   1.203 +
   1.204 +      case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: {
   1.205 +        // checkcast the Nth outgoing argument in place
   1.206 +        klassOop dest_klass = NULL;
   1.207 +        BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass);
   1.208 +        assert(dest == T_OBJECT, "");
   1.209 +        assert(dest == arg_state->_type, "");
   1.210 +        arg_state->_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg_state->_arg, CHECK_NULL);
   1.211 +        debug_only(dest_klass = (klassOop)badOop);
   1.212 +        break;
   1.213 +      }
   1.214 +
   1.215 +      case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: {
   1.216 +        // i2l, etc., on the Nth outgoing argument in place
   1.217 +        BasicType src = chain().adapter_conversion_src_type(),
   1.218 +                  dest = chain().adapter_conversion_dest_type();
   1.219 +        Bytecodes::Code bc = conversion_code(src, dest);
   1.220 +        ArgToken arg = arg_state->_arg;
   1.221 +        if (bc == Bytecodes::_nop) {
   1.222 +          break;
   1.223 +        } else if (bc != Bytecodes::_illegal) {
   1.224 +          arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL);
   1.225 +        } else if (is_subword_type(dest)) {
   1.226 +          bc = conversion_code(src, T_INT);
   1.227 +          if (bc != Bytecodes::_illegal) {
   1.228 +            arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL);
   1.229 +            bc = conversion_code(T_INT, dest);
   1.230 +            arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL);
   1.231 +          }
   1.232 +        }
   1.233 +        if (bc == Bytecodes::_illegal) {
   1.234 +          lose("bad primitive conversion", CHECK_NULL);
   1.235 +        }
   1.236 +        change_argument(src, arg_slot, dest, arg);
   1.237 +        break;
   1.238 +      }
   1.239 +
   1.240 +      case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: {
   1.241 +        // checkcast to wrapper type & call intValue, etc.
   1.242 +        BasicType dest = chain().adapter_conversion_dest_type();
   1.243 +        ArgToken arg = arg_state->_arg;
   1.244 +        arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest),
   1.245 +                              Bytecodes::_checkcast, arg, CHECK_NULL);
   1.246 +        vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest);
   1.247 +        if (unboxer == vmIntrinsics::_none) {
   1.248 +          lose("no unboxing method", CHECK_NULL);
   1.249 +        }
   1.250 +        ArgToken arglist[2];
   1.251 +        arglist[0] = arg;       // outgoing 'this'
   1.252 +        arglist[1] = NULL;      // sentinel
   1.253 +        arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL);
   1.254 +        change_argument(T_OBJECT, arg_slot, dest, arg);
   1.255 +        break;
   1.256 +      }
   1.257 +
   1.258 +      case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: {
   1.259 +        // call wrapper type.valueOf
   1.260 +        BasicType src = chain().adapter_conversion_src_type();
   1.261 +        ArgToken arg = arg_state->_arg;
   1.262 +        vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src);
   1.263 +        if (boxer == vmIntrinsics::_none) {
   1.264 +          lose("no boxing method", CHECK_NULL);
   1.265 +        }
   1.266 +        ArgToken arglist[2];
   1.267 +        arglist[0] = arg;       // outgoing value
   1.268 +        arglist[1] = NULL;      // sentinel
   1.269 +        arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL);
   1.270 +        change_argument(src, arg_slot, T_OBJECT, arg);
   1.271 +        break;
   1.272 +      }
   1.273 +
   1.274 +      case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: {
   1.275 +        int dest_arg_slot = chain().adapter_conversion_vminfo();
   1.276 +        if (!slot_has_argument(dest_arg_slot)) {
   1.277 +          lose("bad swap index", CHECK_NULL);
   1.278 +        }
   1.279 +        // a simple swap between two arguments
   1.280 +        SlotState* dest_arg_state = slot_state(dest_arg_slot);
   1.281 +        SlotState temp = (*dest_arg_state);
   1.282 +        (*dest_arg_state) = (*arg_state);
   1.283 +        (*arg_state) = temp;
   1.284 +        break;
   1.285 +      }
   1.286 +
   1.287 +      case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: {
   1.288 +        int dest_arg_slot = chain().adapter_conversion_vminfo();
   1.289 +        if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
   1.290 +          lose("bad rotate index", CHECK_NULL);
   1.291 +        }
   1.292 +        SlotState* dest_arg_state = slot_state(dest_arg_slot);
   1.293 +        // Rotate the source argument (plus following N slots) into the
   1.294 +        // position occupied by the dest argument (plus following N slots).
   1.295 +        int rotate_count = type2size[dest_arg_state->_type];
   1.296 +        // (no other rotate counts are currently supported)
   1.297 +        if (arg_slot < dest_arg_slot) {
   1.298 +          for (int i = 0; i < rotate_count; i++) {
   1.299 +            SlotState temp = _outgoing.at(arg_slot);
   1.300 +            _outgoing.remove_at(arg_slot);
   1.301 +            _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp);
   1.302 +          }
   1.303 +        } else { // arg_slot > dest_arg_slot
   1.304 +          for (int i = 0; i < rotate_count; i++) {
   1.305 +            SlotState temp = _outgoing.at(arg_slot + rotate_count - 1);
   1.306 +            _outgoing.remove_at(arg_slot + rotate_count - 1);
   1.307 +            _outgoing.insert_before(dest_arg_slot, temp);
   1.308 +          }
   1.309 +        }
   1.310 +        break;
   1.311 +      }
   1.312 +
   1.313 +      case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: {
   1.314 +        int dup_slots = chain().adapter_conversion_stack_pushes();
   1.315 +        if (dup_slots <= 0) {
   1.316 +          lose("bad dup count", CHECK_NULL);
   1.317 +        }
   1.318 +        for (int i = 0; i < dup_slots; i++) {
   1.319 +          SlotState* dup = slot_state(arg_slot + 2*i);
   1.320 +          if (dup == NULL)              break;  // safety net
   1.321 +          if (dup->_type != T_VOID)     _outgoing_argc += 1;
   1.322 +          _outgoing.insert_before(i, (*dup));
   1.323 +        }
   1.324 +        break;
   1.325 +      }
   1.326 +
   1.327 +      case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: {
   1.328 +        int drop_slots = -chain().adapter_conversion_stack_pushes();
   1.329 +        if (drop_slots <= 0) {
   1.330 +          lose("bad drop count", CHECK_NULL);
   1.331 +        }
   1.332 +        for (int i = 0; i < drop_slots; i++) {
   1.333 +          SlotState* drop = slot_state(arg_slot);
   1.334 +          if (drop == NULL)             break;  // safety net
   1.335 +          if (drop->_type != T_VOID)    _outgoing_argc -= 1;
   1.336 +          _outgoing.remove_at(arg_slot);
   1.337 +        }
   1.338 +        break;
   1.339 +      }
   1.340 +
   1.341 +      case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC
   1.342 +        lose("unimplemented", CHECK_NULL);
   1.343 +        break;
   1.344 +      }
   1.345 +
   1.346 +      case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: {
   1.347 +        klassOop array_klass_oop = NULL;
   1.348 +        BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(),
   1.349 +                                                             &array_klass_oop);
   1.350 +        assert(array_type == T_OBJECT, "");
   1.351 +        assert(Klass::cast(array_klass_oop)->oop_is_array(), "");
   1.352 +        arrayKlassHandle array_klass(THREAD, array_klass_oop);
   1.353 +        debug_only(array_klass_oop = (klassOop)badOop);
   1.354 +
   1.355 +        klassOop element_klass_oop = NULL;
   1.356 +        BasicType element_type = java_lang_Class::as_BasicType(array_klass->component_mirror(),
   1.357 +                                                               &element_klass_oop);
   1.358 +        KlassHandle element_klass(THREAD, element_klass_oop);
   1.359 +        debug_only(element_klass_oop = (klassOop)badOop);
   1.360 +
   1.361 +        // Fetch the argument, which we will cast to the required array type.
   1.362 +        assert(arg_state->_type == T_OBJECT, "");
   1.363 +        ArgToken array_arg = arg_state->_arg;
   1.364 +        array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_NULL);
   1.365 +        change_argument(T_OBJECT, arg_slot, T_VOID, NULL);
   1.366 +
   1.367 +        // Check the required length.
   1.368 +        int spread_slots = 1 + chain().adapter_conversion_stack_pushes();
   1.369 +        int spread_length = spread_slots;
   1.370 +        if (type2size[element_type] == 2) {
   1.371 +          if (spread_slots % 2 != 0)  spread_slots = -1;  // force error
   1.372 +          spread_length = spread_slots / 2;
   1.373 +        }
   1.374 +        if (spread_slots < 0) {
   1.375 +          lose("bad spread length", CHECK_NULL);
   1.376 +        }
   1.377 +
   1.378 +        jvalue   length_jvalue;  length_jvalue.i = spread_length;
   1.379 +        ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_NULL);
   1.380 +        // Call a built-in method known to the JVM to validate the length.
   1.381 +        ArgToken arglist[3];
   1.382 +        arglist[0] = array_arg;  // value to check
   1.383 +        arglist[1] = length_arg; // length to check
   1.384 +        arglist[2] = NULL;       // sentinel
   1.385 +        make_invoke(NULL, vmIntrinsics::_checkSpreadArgument,
   1.386 +                    Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_NULL);
   1.387 +
   1.388 +        // Spread out the array elements.
   1.389 +        Bytecodes::Code aload_op = Bytecodes::_aaload;
   1.390 +        if (element_type != T_OBJECT) {
   1.391 +          lose("primitive array NYI", CHECK_NULL);
   1.392 +        }
   1.393 +        int ap = arg_slot;
   1.394 +        for (int i = 0; i < spread_length; i++) {
   1.395 +          jvalue   offset_jvalue;  offset_jvalue.i = i;
   1.396 +          ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_NULL);
   1.397 +          ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_NULL);
   1.398 +          change_argument(T_VOID, ap, element_type, element_arg);
   1.399 +          ap += type2size[element_type];
   1.400 +        }
   1.401 +        break;
   1.402 +      }
   1.403 +
   1.404 +      case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code
   1.405 +      case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code
   1.406 +        lose("unimplemented", CHECK_NULL);
   1.407 +        break;
   1.408 +
   1.409 +      default:
   1.410 +        lose("bad adapter conversion", CHECK_NULL);
   1.411 +        break;
   1.412 +      }
   1.413 +    }
   1.414 +
   1.415 +    if (chain().is_bound()) {
   1.416 +      // push a new argument
   1.417 +      BasicType arg_type  = chain().bound_arg_type();
   1.418 +      jint      arg_slot  = chain().bound_arg_slot();
   1.419 +      oop       arg_oop   = chain().bound_arg_oop();
   1.420 +      ArgToken  arg       = NULL;
   1.421 +      if (arg_type == T_OBJECT) {
   1.422 +        arg = make_oop_constant(arg_oop, CHECK_NULL);
   1.423 +      } else {
   1.424 +        jvalue arg_value;
   1.425 +        BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value);
   1.426 +        if (bt == arg_type) {
   1.427 +          arg = make_prim_constant(arg_type, &arg_value, CHECK_NULL);
   1.428 +        } else {
   1.429 +          lose("bad bound value", CHECK_NULL);
   1.430 +        }
   1.431 +      }
   1.432 +      debug_only(arg_oop = badOop);
   1.433 +      change_argument(T_VOID, arg_slot, arg_type, arg);
   1.434 +    }
   1.435 +
   1.436 +    // this test must come after the body of the loop
   1.437 +    if (!chain().is_last()) {
   1.438 +      chain().next(CHECK_NULL);
   1.439 +    } else {
   1.440 +      break;
   1.441 +    }
   1.442 +  }
   1.443 +
   1.444 +  // finish the sequence with a tail-call to the ultimate target
   1.445 +  // parameters are passed in logical order (recv 1st), not slot order
   1.446 +  ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1);
   1.447 +  int ap = 0;
   1.448 +  for (int i = _outgoing.length() - 1; i >= 0; i--) {
   1.449 +    SlotState* arg_state = slot_state(i);
   1.450 +    if (arg_state->_type == T_VOID)  continue;
   1.451 +    arglist[ap++] = _outgoing.at(i)._arg;
   1.452 +  }
   1.453 +  assert(ap == _outgoing_argc, "");
   1.454 +  arglist[ap] = NULL; // add a sentinel, for the sake of asserts
   1.455 +  return make_invoke(chain().last_method_oop(),
   1.456 +                     vmIntrinsics::_none,
   1.457 +                     chain().last_invoke_code(), true,
   1.458 +                     ap, arglist, THREAD);
   1.459 +}
   1.460 +
   1.461 +void MethodHandleWalker::walk_incoming_state(TRAPS) {
   1.462 +  Handle mtype(THREAD, chain().method_type_oop());
   1.463 +  int nptypes = java_dyn_MethodType::ptype_count(mtype());
   1.464 +  _outgoing_argc = nptypes;
   1.465 +  int argp = nptypes - 1;
   1.466 +  if (argp >= 0) {
   1.467 +    _outgoing.at_grow(argp, make_state(T_VOID, NULL)); // presize
   1.468 +  }
   1.469 +  for (int i = 0; i < nptypes; i++) {
   1.470 +    klassOop  arg_type_klass = NULL;
   1.471 +    BasicType arg_type = java_lang_Class::as_BasicType(
   1.472 +                java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass);
   1.473 +    ArgToken  arg = make_parameter(arg_type, arg_type_klass, i, CHECK);
   1.474 +    debug_only(arg_type_klass = (klassOop)NULL);
   1.475 +    _outgoing.at_put(argp, make_state(arg_type, arg));
   1.476 +    if (type2size[arg_type] == 2) {
   1.477 +      // add the extra slot, so we can model the JVM stack
   1.478 +      _outgoing.insert_before(argp+1, make_state(T_VOID, NULL));
   1.479 +    }
   1.480 +    --argp;
   1.481 +  }
   1.482 +  // call make_parameter at the end of the list for the return type
   1.483 +  klassOop  ret_type_klass = NULL;
   1.484 +  BasicType ret_type = java_lang_Class::as_BasicType(
   1.485 +              java_dyn_MethodType::rtype(mtype()), &ret_type_klass);
   1.486 +  ArgToken  ret = make_parameter(ret_type, ret_type_klass, -1, CHECK);
   1.487 +  // ignore ret; client can catch it if needed
   1.488 +}
   1.489 +
   1.490 +// this is messy because some kinds of arguments are paired with
   1.491 +// companion slots containing an empty value
   1.492 +void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type,
   1.493 +                                         MethodHandleWalker::ArgToken new_arg) {
   1.494 +  int old_size = type2size[old_type];
   1.495 +  int new_size = type2size[new_type];
   1.496 +  if (old_size == new_size) {
   1.497 +    // simple case first
   1.498 +    _outgoing.at_put(slot, make_state(new_type, new_arg));
   1.499 +  } else if (old_size > new_size) {
   1.500 +    for (int i = old_size-1; i >= new_size; i++) {
   1.501 +      assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), "");
   1.502 +      _outgoing.remove_at(slot + i);
   1.503 +    }
   1.504 +    if (new_size > 0)
   1.505 +      _outgoing.at_put(slot, make_state(new_type, new_arg));
   1.506 +    else
   1.507 +      _outgoing_argc -= 1;      // deleted a real argument
   1.508 +  } else {
   1.509 +    for (int i = old_size; i < new_size; i++) {
   1.510 +      _outgoing.insert_before(slot+i, make_state(T_VOID, NULL));
   1.511 +    }
   1.512 +    _outgoing.at_put(slot, make_state(new_type, new_arg));
   1.513 +    if (old_size == 0)
   1.514 +      _outgoing_argc += 1;      // inserted a real argument
   1.515 +  }
   1.516 +}
   1.517 +
   1.518 +
   1.519 +#ifdef ASSERT
   1.520 +int MethodHandleWalker::argument_count_slow() {
   1.521 +  int args_seen = 0;
   1.522 +  for (int i = _outgoing.length() - 1; i >= 0; i--) {
   1.523 +    if (_outgoing.at(i)._type != T_VOID) {
   1.524 +      ++args_seen;
   1.525 +    }
   1.526 +  }
   1.527 +  return args_seen;
   1.528 +}
   1.529 +#endif
   1.530 +
   1.531 +
   1.532 +void MethodHandleCompiler::compile(TRAPS) {
   1.533 +  assert(_thread == THREAD, "must be same thread");
   1.534 +
   1.535 +  _constant_oops.append(Handle());  // element zero is always the null constant
   1.536 +  _constant_prims.append(NULL);
   1.537 +  {
   1.538 +    symbolOop sig
   1.539 +      = java_dyn_MethodType::as_signature(chain().method_type_oop(), true, CHECK);
   1.540 +    _signature_index = find_oop_constant(sig);
   1.541 +    assert(signature() == sig, "");
   1.542 +  }
   1.543 +
   1.544 +  walk(CHECK);
   1.545 +}
   1.546 +
   1.547 +MethodHandleWalker::ArgToken
   1.548 +MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Code op,
   1.549 +                                      MethodHandleWalker::ArgToken src, TRAPS) {
   1.550 +  Unimplemented();
   1.551 +  return NULL;
   1.552 +}
   1.553 +
   1.554 +MethodHandleWalker::ArgToken
   1.555 +MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
   1.556 +                                  Bytecodes::Code op, bool tailcall,
   1.557 +                                  int argc, MethodHandleWalker::ArgToken* argv,
   1.558 +                                  TRAPS) {
   1.559 +  // If tailcall, we have walked all the way to a direct method handle.
   1.560 +  // Otherwise, make a recursive call to some helper routine.
   1.561 +#ifdef ASSERT
   1.562 +  switch (op) {
   1.563 +  case Bytecodes::_invokevirtual:
   1.564 +  case Bytecodes::_invokespecial:
   1.565 +  case Bytecodes::_invokestatic:
   1.566 +  case Bytecodes::_invokeinterface:
   1.567 +    break;
   1.568 +  default:
   1.569 +    ShouldNotReachHere();
   1.570 +  }
   1.571 +#endif //ASSERT
   1.572 +  _bytes.put((char) op);
   1.573 +
   1.574 +  Unimplemented();
   1.575 +  return NULL;
   1.576 +}
   1.577 +
   1.578 +MethodHandleWalker::ArgToken
   1.579 +MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op,
   1.580 +                                 MethodHandleWalker::ArgToken base,
   1.581 +                                 MethodHandleWalker::ArgToken offset,
   1.582 +                                 TRAPS) {
   1.583 +  Unimplemented();
   1.584 +  return NULL;
   1.585 +}
   1.586 +
   1.587 +int MethodHandleCompiler::find_oop_constant(oop con) {
   1.588 +  if (con == NULL)  return 0;
   1.589 +  for (int i = 1, imax = _constant_oops.length(); i < imax; i++) {
   1.590 +    if (_constant_oops.at(i) == con)
   1.591 +      return i;
   1.592 +  }
   1.593 +  _constant_prims.append(NULL);
   1.594 +  return _constant_oops.append(con);
   1.595 +}
   1.596 +
   1.597 +int MethodHandleCompiler::find_prim_constant(BasicType bt, jvalue* con) {
   1.598 +  jvalue con_copy;
   1.599 +  assert(bt < T_OBJECT, "");
   1.600 +  if (type2aelembytes(bt) < jintSize) {
   1.601 +    // widen to int
   1.602 +    con_copy = (*con);
   1.603 +    con = &con_copy;
   1.604 +    switch (bt) {
   1.605 +    case T_BOOLEAN: con->i = (con->z ? 1 : 0); break;
   1.606 +    case T_BYTE:    con->i = con->b;           break;
   1.607 +    case T_CHAR:    con->i = con->c;           break;
   1.608 +    case T_SHORT:   con->i = con->s;           break;
   1.609 +    default: ShouldNotReachHere();
   1.610 +    }
   1.611 +    bt = T_INT;
   1.612 +  }
   1.613 +  for (int i = 1, imax = _constant_prims.length(); i < imax; i++) {
   1.614 +    PrimCon* pcon = _constant_prims.at(i);
   1.615 +    if (pcon != NULL && pcon->_type == bt) {
   1.616 +      bool match = false;
   1.617 +      switch (type2size[bt]) {
   1.618 +      case 1:  if (pcon->_value.i == con->i)  match = true;  break;
   1.619 +      case 2:  if (pcon->_value.j == con->j)  match = true;  break;
   1.620 +      }
   1.621 +      if (match)
   1.622 +        return i;
   1.623 +    }
   1.624 +  }
   1.625 +  PrimCon* pcon = new PrimCon();
   1.626 +  pcon->_type = bt;
   1.627 +  pcon->_value = (*con);
   1.628 +  _constant_oops.append(Handle());
   1.629 +  return _constant_prims.append(pcon);
   1.630 +}
   1.631 +
   1.632 +
   1.633 +#ifndef PRODUCT
   1.634 +
   1.635 +// MH printer for debugging.
   1.636 +
   1.637 +class MethodHandlePrinter : public MethodHandleWalker {
   1.638 +private:
   1.639 +  outputStream* _out;
   1.640 +  bool          _verbose;
   1.641 +  int           _temp_num;
   1.642 +  stringStream  _strbuf;
   1.643 +  const char* strbuf() {
   1.644 +    const char* s = _strbuf.as_string();
   1.645 +    _strbuf.reset();
   1.646 +    return s;
   1.647 +  }
   1.648 +  ArgToken token(const char* str) {
   1.649 +    return (ArgToken) str;
   1.650 +  }
   1.651 +  void start_params() {
   1.652 +    _out->print("(");
   1.653 +  }
   1.654 +  void end_params() {
   1.655 +    if (_verbose)  _out->print("\n");
   1.656 +    _out->print(") => {");
   1.657 +  }
   1.658 +  void put_type_name(BasicType type, klassOop tk, outputStream* s) {
   1.659 +    const char* kname = NULL;
   1.660 +    if (tk != NULL)
   1.661 +      kname = Klass::cast(tk)->external_name();
   1.662 +    s->print("%s", (kname != NULL) ? kname : type2name(type));
   1.663 +  }
   1.664 +  ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) {
   1.665 +    const char* value = strbuf();
   1.666 +    if (!_verbose)  return token(value);
   1.667 +    // make an explicit binding for each separate value
   1.668 +    _strbuf.print("%s%d", temp_name, ++_temp_num);
   1.669 +    const char* temp = strbuf();
   1.670 +    _out->print("\n  %s %s %s = %s;", statement_op, type2name(type), temp, value);
   1.671 +    return token(temp);
   1.672 +  }
   1.673 +
   1.674 +public:
   1.675 +  MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS)
   1.676 +    : MethodHandleWalker(root, THREAD),
   1.677 +      _out(out),
   1.678 +      _verbose(verbose),
   1.679 +      _temp_num(0)
   1.680 +  {
   1.681 +    start_params();
   1.682 +  }
   1.683 +  virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
   1.684 +    if (argnum < 0) {
   1.685 +      end_params();
   1.686 +      return NULL;
   1.687 +    }
   1.688 +    if (argnum == 0) {
   1.689 +      _out->print(_verbose ? "\n  " : "");
   1.690 +    } else {
   1.691 +      _out->print(_verbose ? ",\n  " : ", ");
   1.692 +    }
   1.693 +    if (argnum >= _temp_num)
   1.694 +      _temp_num = argnum;
   1.695 +    // generate an argument name
   1.696 +    _strbuf.print("a%d", argnum);
   1.697 +    const char* arg = strbuf();
   1.698 +    put_type_name(type, tk, _out);
   1.699 +    _out->print(" %s", arg);
   1.700 +    return token(arg);
   1.701 +  }
   1.702 +  virtual ArgToken make_oop_constant(oop con, TRAPS) {
   1.703 +    if (con == NULL)
   1.704 +      _strbuf.print("null");
   1.705 +    else
   1.706 +      con->print_value_on(&_strbuf);
   1.707 +    if (_strbuf.size() == 0) {  // yuck
   1.708 +      _strbuf.print("(a ");
   1.709 +      put_type_name(T_OBJECT, con->klass(), &_strbuf);
   1.710 +      _strbuf.print(")");
   1.711 +    }
   1.712 +    return maybe_make_temp("constant", T_OBJECT, "k");
   1.713 +  }
   1.714 +  virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
   1.715 +    java_lang_boxing_object::print(type, con, &_strbuf);
   1.716 +    return maybe_make_temp("constant", type, "k");
   1.717 +  }
   1.718 +  virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) {
   1.719 +    _strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src);
   1.720 +    if (tk != NULL) {
   1.721 +      _strbuf.print(", ");
   1.722 +      put_type_name(type, tk, &_strbuf);
   1.723 +    }
   1.724 +    _strbuf.print(")");
   1.725 +    return maybe_make_temp("convert", type, "v");
   1.726 +  }
   1.727 +  virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) {
   1.728 +    _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset);
   1.729 +    if (tk != NULL) {
   1.730 +      _strbuf.print(", ");
   1.731 +      put_type_name(type, tk, &_strbuf);
   1.732 +    }
   1.733 +    _strbuf.print(")");
   1.734 +    return maybe_make_temp("fetch", type, "x");
   1.735 +  }
   1.736 +  virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid,
   1.737 +                               Bytecodes::Code op, bool tailcall,
   1.738 +                               int argc, ArgToken* argv, TRAPS) {
   1.739 +    symbolOop name, sig;
   1.740 +    if (m != NULL) {
   1.741 +      name = m->name();
   1.742 +      sig  = m->signature();
   1.743 +    } else {
   1.744 +      name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid));
   1.745 +      sig  = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid));
   1.746 +    }
   1.747 +    _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string());
   1.748 +    for (int i = 0; i < argc; i++) {
   1.749 +      _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]);
   1.750 +    }
   1.751 +    _strbuf.print(")");
   1.752 +    if (!tailcall) {
   1.753 +      BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1));
   1.754 +      if (rt == T_ILLEGAL)  rt = T_OBJECT;  // ';' at the end of '(...)L...;'
   1.755 +      return maybe_make_temp("invoke", rt, "x");
   1.756 +    } else {
   1.757 +      const char* ret = strbuf();
   1.758 +      _out->print(_verbose ? "\n  return " : " ");
   1.759 +      _out->print("%s", ret);
   1.760 +      _out->print(_verbose ? "\n}\n" : " }");
   1.761 +    }
   1.762 +    return ArgToken();
   1.763 +  }
   1.764 +
   1.765 +  virtual void set_method_handle(oop mh) {
   1.766 +    if (WizardMode && Verbose) {
   1.767 +      tty->print("\n--- next target: ");
   1.768 +      mh->print();
   1.769 +    }
   1.770 +  }
   1.771 +
   1.772 +  static void print(Handle root, bool verbose, outputStream* out, TRAPS) {
   1.773 +    ResourceMark rm;
   1.774 +    MethodHandlePrinter printer(root, verbose, out, CHECK);
   1.775 +    printer.walk(CHECK);
   1.776 +    out->print("\n");
   1.777 +  }
   1.778 +  static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) {
   1.779 +    EXCEPTION_MARK;
   1.780 +    ResourceMark rm;
   1.781 +    MethodHandlePrinter printer(root, verbose, out, THREAD);
   1.782 +    if (!HAS_PENDING_EXCEPTION)
   1.783 +      printer.walk(THREAD);
   1.784 +    if (HAS_PENDING_EXCEPTION) {
   1.785 +      oop ex = PENDING_EXCEPTION;
   1.786 +      CLEAR_PENDING_EXCEPTION;
   1.787 +      out->print("\n*** ");
   1.788 +      if (ex != Universe::virtual_machine_error_instance())
   1.789 +        ex->print_on(out);
   1.790 +      else
   1.791 +        out->print("lose: %s", printer.lose_message());
   1.792 +      out->print("\n}\n");
   1.793 +    }
   1.794 +    out->print("\n");
   1.795 +  }
   1.796 +};
   1.797 +
   1.798 +extern "C"
   1.799 +void print_method_handle(oop mh) {
   1.800 +  if (java_dyn_MethodHandle::is_instance(mh)) {
   1.801 +    MethodHandlePrinter::print(mh);
   1.802 +  } else {
   1.803 +    tty->print("*** not a method handle: ");
   1.804 +    mh->print();
   1.805 +  }
   1.806 +}
   1.807 +
   1.808 +#endif // PRODUCT

mercurial