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