1 /* 2 * Copyright 2008-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 /* 26 * JSR 292 reference implementation: method handle structure analysis 27 */ 28 29 #include "incls/_precompiled.incl" 30 #include "incls/_methodHandleWalk.cpp.incl" 31 32 void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { 33 if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); 34 35 // set current method handle and unpack partially 36 _method_handle = mh; 37 _is_last = false; 38 _is_bound = false; 39 _arg_slot = -1; 40 _arg_type = T_VOID; 41 _conversion = -1; 42 _last_invoke = Bytecodes::_nop; //arbitrary non-garbage 43 44 if (sun_dyn_DirectMethodHandle::is_instance(mh())) { 45 set_last_method(mh(), THREAD); 46 return; 47 } 48 if (sun_dyn_AdapterMethodHandle::is_instance(mh())) { 49 _conversion = AdapterMethodHandle_conversion(); 50 assert(_conversion != -1, "bad conv value"); 51 assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH"); 52 } 53 if (sun_dyn_BoundMethodHandle::is_instance(mh())) { 54 if (!is_adapter()) // keep AMH and BMH separate in this model 55 _is_bound = true; 56 _arg_slot = BoundMethodHandle_vmargslot(); 57 oop target = MethodHandle_vmtarget_oop(); 58 if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) { 59 _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); 60 } else if (target != NULL && target->is_method()) { 61 _arg_type = compute_bound_arg_type(NULL, (methodOop)target, _arg_slot, CHECK); 62 set_last_method(mh(), CHECK); 63 } else { 64 _is_bound = false; // lose! 65 } 66 } 67 if (is_bound() && _arg_type == T_VOID) { 68 lose("bad vmargslot", CHECK); 69 } 70 if (!is_bound() && !is_adapter()) { 71 lose("unrecognized MH type", CHECK); 72 } 73 } 74 75 void MethodHandleChain::set_last_method(oop target, TRAPS) { 76 _is_last = true; 77 klassOop receiver_limit_oop = NULL; 78 int flags = 0; 79 methodOop m = MethodHandles::decode_method(target, receiver_limit_oop, flags); 80 _last_method = methodHandle(THREAD, m); 81 if ((flags & MethodHandles::_dmf_has_receiver) == 0) 82 _last_invoke = Bytecodes::_invokestatic; 83 else if ((flags & MethodHandles::_dmf_does_dispatch) == 0) 84 _last_invoke = Bytecodes::_invokespecial; 85 else if ((flags & MethodHandles::_dmf_from_interface) != 0) 86 _last_invoke = Bytecodes::_invokeinterface; 87 else 88 _last_invoke = Bytecodes::_invokevirtual; 89 } 90 91 BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { 92 // There is no direct indication of whether the argument is primitive or not. 93 // It is implied by the _vmentry code, and by the MethodType of the target. 94 // FIXME: Make it explicit MethodHandleImpl refactors out from MethodHandle 95 BasicType arg_type = T_VOID; 96 if (target != NULL) { 97 oop mtype = java_dyn_MethodHandle::type(target); 98 int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot); 99 if (arg_num >= 0) { 100 oop ptype = java_dyn_MethodType::ptype(mtype, arg_num); 101 arg_type = java_lang_Class::as_BasicType(ptype); 102 } 103 } else if (m != NULL) { 104 // figure out the argument type from the slot 105 // FIXME: make this explicit in the MH 106 int cur_slot = m->size_of_parameters(); 107 if (arg_slot >= cur_slot) 108 return T_VOID; 109 if (!m->is_static()) { 110 cur_slot -= type2size[T_OBJECT]; 111 if (cur_slot == arg_slot) 112 return T_OBJECT; 113 } 114 for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { 115 BasicType bt = ss.type(); 116 cur_slot -= type2size[bt]; 117 if (cur_slot <= arg_slot) { 118 if (cur_slot == arg_slot) 119 arg_type = bt; 120 break; 121 } 122 } 123 } 124 if (arg_type == T_ARRAY) 125 arg_type = T_OBJECT; 126 return arg_type; 127 } 128 129 void MethodHandleChain::lose(const char* msg, TRAPS) { 130 _lose_message = msg; 131 if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { 132 // throw a preallocated exception 133 THROW_OOP(Universe::virtual_machine_error_instance()); 134 } 135 THROW_MSG(vmSymbols::java_lang_InternalError(), msg); 136 } 137 138 Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) { 139 if (is_subword_type(src)) { 140 src = T_INT; // all subword src types act like int 141 } 142 if (src == dest) { 143 return Bytecodes::_nop; 144 } 145 146 #define SRC_DEST(s,d) (((int)(s) << 4) + (int)(d)) 147 switch (SRC_DEST(src, dest)) { 148 case SRC_DEST(T_INT, T_LONG): return Bytecodes::_i2l; 149 case SRC_DEST(T_INT, T_FLOAT): return Bytecodes::_i2f; 150 case SRC_DEST(T_INT, T_DOUBLE): return Bytecodes::_i2d; 151 case SRC_DEST(T_INT, T_BYTE): return Bytecodes::_i2b; 152 case SRC_DEST(T_INT, T_CHAR): return Bytecodes::_i2c; 153 case SRC_DEST(T_INT, T_SHORT): return Bytecodes::_i2s; 154 155 case SRC_DEST(T_LONG, T_INT): return Bytecodes::_l2i; 156 case SRC_DEST(T_LONG, T_FLOAT): return Bytecodes::_l2f; 157 case SRC_DEST(T_LONG, T_DOUBLE): return Bytecodes::_l2d; 158 159 case SRC_DEST(T_FLOAT, T_INT): return Bytecodes::_f2i; 160 case SRC_DEST(T_FLOAT, T_LONG): return Bytecodes::_f2l; 161 case SRC_DEST(T_FLOAT, T_DOUBLE): return Bytecodes::_f2d; 162 163 case SRC_DEST(T_DOUBLE, T_INT): return Bytecodes::_d2i; 164 case SRC_DEST(T_DOUBLE, T_LONG): return Bytecodes::_d2l; 165 case SRC_DEST(T_DOUBLE, T_FLOAT): return Bytecodes::_d2f; 166 } 167 #undef SRC_DEST 168 169 // cannot do it in one step, or at all 170 return Bytecodes::_illegal; 171 } 172 173 MethodHandleWalker::ArgToken 174 MethodHandleWalker::walk(TRAPS) { 175 walk_incoming_state(CHECK_NULL); 176 177 for (;;) { 178 set_method_handle(chain().method_handle_oop()); 179 180 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); 181 182 if (chain().is_adapter()) { 183 int conv_op = chain().adapter_conversion_op(); 184 int arg_slot = chain().adapter_arg_slot(); 185 SlotState* arg_state = slot_state(arg_slot); 186 if (arg_state == NULL 187 && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) { 188 lose("bad argument index", CHECK_NULL); 189 } 190 191 // perform the adapter action 192 switch (chain().adapter_conversion_op()) { 193 case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY: 194 case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: 195 // No changes to arguments; pass the bits through. 196 // The only difference between the two ops is that the "only" version 197 // is fully compatible with the verifier, while the "raw" version 198 // performs a few extra bitwise conversions (like long <-> double). 199 break; 200 201 case sun_dyn_AdapterMethodHandle::OP_CHECK_CAST: { 202 // checkcast the Nth outgoing argument in place 203 klassOop dest_klass = NULL; 204 BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); 205 assert(dest == T_OBJECT, ""); 206 assert(dest == arg_state->_type, ""); 207 arg_state->_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg_state->_arg, CHECK_NULL); 208 debug_only(dest_klass = (klassOop)badOop); 209 break; 210 } 211 212 case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: { 213 // i2l, etc., on the Nth outgoing argument in place 214 BasicType src = chain().adapter_conversion_src_type(), 215 dest = chain().adapter_conversion_dest_type(); 216 Bytecodes::Code bc = conversion_code(src, dest); 217 ArgToken arg = arg_state->_arg; 218 if (bc == Bytecodes::_nop) { 219 break; 220 } else if (bc != Bytecodes::_illegal) { 221 arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); 222 } else if (is_subword_type(dest)) { 223 bc = conversion_code(src, T_INT); 224 if (bc != Bytecodes::_illegal) { 225 arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); 226 bc = conversion_code(T_INT, dest); 227 arg = make_conversion(dest, NULL, bc, arg, CHECK_NULL); 228 } 229 } 230 if (bc == Bytecodes::_illegal) { 231 lose("bad primitive conversion", CHECK_NULL); 232 } 233 change_argument(src, arg_slot, dest, arg); 234 break; 235 } 236 237 case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: { 238 // checkcast to wrapper type & call intValue, etc. 239 BasicType dest = chain().adapter_conversion_dest_type(); 240 ArgToken arg = arg_state->_arg; 241 arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), 242 Bytecodes::_checkcast, arg, CHECK_NULL); 243 vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); 244 if (unboxer == vmIntrinsics::_none) { 245 lose("no unboxing method", CHECK_NULL); 246 } 247 ArgToken arglist[2]; 248 arglist[0] = arg; // outgoing 'this' 249 arglist[1] = NULL; // sentinel 250 arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL); 251 change_argument(T_OBJECT, arg_slot, dest, arg); 252 break; 253 } 254 255 case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: { 256 // call wrapper type.valueOf 257 BasicType src = chain().adapter_conversion_src_type(); 258 ArgToken arg = arg_state->_arg; 259 vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); 260 if (boxer == vmIntrinsics::_none) { 261 lose("no boxing method", CHECK_NULL); 262 } 263 ArgToken arglist[2]; 264 arglist[0] = arg; // outgoing value 265 arglist[1] = NULL; // sentinel 266 arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_NULL); 267 change_argument(src, arg_slot, T_OBJECT, arg); 268 break; 269 } 270 271 case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: { 272 int dest_arg_slot = chain().adapter_conversion_vminfo(); 273 if (!slot_has_argument(dest_arg_slot)) { 274 lose("bad swap index", CHECK_NULL); 275 } 276 // a simple swap between two arguments 277 SlotState* dest_arg_state = slot_state(dest_arg_slot); 278 SlotState temp = (*dest_arg_state); 279 (*dest_arg_state) = (*arg_state); 280 (*arg_state) = temp; 281 break; 282 } 283 284 case sun_dyn_AdapterMethodHandle::OP_ROT_ARGS: { 285 int dest_arg_slot = chain().adapter_conversion_vminfo(); 286 if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { 287 lose("bad rotate index", CHECK_NULL); 288 } 289 SlotState* dest_arg_state = slot_state(dest_arg_slot); 290 // Rotate the source argument (plus following N slots) into the 291 // position occupied by the dest argument (plus following N slots). 292 int rotate_count = type2size[dest_arg_state->_type]; 293 // (no other rotate counts are currently supported) 294 if (arg_slot < dest_arg_slot) { 295 for (int i = 0; i < rotate_count; i++) { 296 SlotState temp = _outgoing.at(arg_slot); 297 _outgoing.remove_at(arg_slot); 298 _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); 299 } 300 } else { // arg_slot > dest_arg_slot 301 for (int i = 0; i < rotate_count; i++) { 302 SlotState temp = _outgoing.at(arg_slot + rotate_count - 1); 303 _outgoing.remove_at(arg_slot + rotate_count - 1); 304 _outgoing.insert_before(dest_arg_slot, temp); 305 } 306 } 307 break; 308 } 309 310 case sun_dyn_AdapterMethodHandle::OP_DUP_ARGS: { 311 int dup_slots = chain().adapter_conversion_stack_pushes(); 312 if (dup_slots <= 0) { 313 lose("bad dup count", CHECK_NULL); 314 } 315 for (int i = 0; i < dup_slots; i++) { 316 SlotState* dup = slot_state(arg_slot + 2*i); 317 if (dup == NULL) break; // safety net 318 if (dup->_type != T_VOID) _outgoing_argc += 1; 319 _outgoing.insert_before(i, (*dup)); 320 } 321 break; 322 } 323 324 case sun_dyn_AdapterMethodHandle::OP_DROP_ARGS: { 325 int drop_slots = -chain().adapter_conversion_stack_pushes(); 326 if (drop_slots <= 0) { 327 lose("bad drop count", CHECK_NULL); 328 } 329 for (int i = 0; i < drop_slots; i++) { 330 SlotState* drop = slot_state(arg_slot); 331 if (drop == NULL) break; // safety net 332 if (drop->_type != T_VOID) _outgoing_argc -= 1; 333 _outgoing.remove_at(arg_slot); 334 } 335 break; 336 } 337 338 case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC 339 lose("unimplemented", CHECK_NULL); 340 break; 341 } 342 343 case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: { 344 klassOop array_klass_oop = NULL; 345 BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), 346 &array_klass_oop); 347 assert(array_type == T_OBJECT, ""); 348 assert(Klass::cast(array_klass_oop)->oop_is_array(), ""); 349 arrayKlassHandle array_klass(THREAD, array_klass_oop); 350 debug_only(array_klass_oop = (klassOop)badOop); 351 352 klassOop element_klass_oop = NULL; 353 BasicType element_type = java_lang_Class::as_BasicType(array_klass->component_mirror(), 354 &element_klass_oop); 355 KlassHandle element_klass(THREAD, element_klass_oop); 356 debug_only(element_klass_oop = (klassOop)badOop); 357 358 // Fetch the argument, which we will cast to the required array type. 359 assert(arg_state->_type == T_OBJECT, ""); 360 ArgToken array_arg = arg_state->_arg; 361 array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_NULL); 362 change_argument(T_OBJECT, arg_slot, T_VOID, NULL); 363 364 // Check the required length. 365 int spread_slots = 1 + chain().adapter_conversion_stack_pushes(); 366 int spread_length = spread_slots; 367 if (type2size[element_type] == 2) { 368 if (spread_slots % 2 != 0) spread_slots = -1; // force error 369 spread_length = spread_slots / 2; 370 } 371 if (spread_slots < 0) { 372 lose("bad spread length", CHECK_NULL); 373 } 374 375 jvalue length_jvalue; length_jvalue.i = spread_length; 376 ArgToken length_arg = make_prim_constant(T_INT, &length_jvalue, CHECK_NULL); 377 // Call a built-in method known to the JVM to validate the length. 378 ArgToken arglist[3]; 379 arglist[0] = array_arg; // value to check 380 arglist[1] = length_arg; // length to check 381 arglist[2] = NULL; // sentinel 382 make_invoke(NULL, vmIntrinsics::_checkSpreadArgument, 383 Bytecodes::_invokestatic, false, 3, &arglist[0], CHECK_NULL); 384 385 // Spread out the array elements. 386 Bytecodes::Code aload_op = Bytecodes::_aaload; 387 if (element_type != T_OBJECT) { 388 lose("primitive array NYI", CHECK_NULL); 389 } 390 int ap = arg_slot; 391 for (int i = 0; i < spread_length; i++) { 392 jvalue offset_jvalue; offset_jvalue.i = i; 393 ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_NULL); 394 ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_NULL); 395 change_argument(T_VOID, ap, element_type, element_arg); 396 ap += type2size[element_type]; 397 } 398 break; 399 } 400 401 case sun_dyn_AdapterMethodHandle::OP_FLYBY: //NYI, runs Java code 402 case sun_dyn_AdapterMethodHandle::OP_RICOCHET: //NYI, runs Java code 403 lose("unimplemented", CHECK_NULL); 404 break; 405 406 default: 407 lose("bad adapter conversion", CHECK_NULL); 408 break; 409 } 410 } 411 412 if (chain().is_bound()) { 413 // push a new argument 414 BasicType arg_type = chain().bound_arg_type(); 415 jint arg_slot = chain().bound_arg_slot(); 416 oop arg_oop = chain().bound_arg_oop(); 417 ArgToken arg = NULL; 418 if (arg_type == T_OBJECT) { 419 arg = make_oop_constant(arg_oop, CHECK_NULL); 420 } else { 421 jvalue arg_value; 422 BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); 423 if (bt == arg_type) { 424 arg = make_prim_constant(arg_type, &arg_value, CHECK_NULL); 425 } else { 426 lose("bad bound value", CHECK_NULL); 427 } 428 } 429 debug_only(arg_oop = badOop); 430 change_argument(T_VOID, arg_slot, arg_type, arg); 431 } 432 433 // this test must come after the body of the loop 434 if (!chain().is_last()) { 435 chain().next(CHECK_NULL); 436 } else { 437 break; 438 } 439 } 440 441 // finish the sequence with a tail-call to the ultimate target 442 // parameters are passed in logical order (recv 1st), not slot order 443 ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1); 444 int ap = 0; 445 for (int i = _outgoing.length() - 1; i >= 0; i--) { 446 SlotState* arg_state = slot_state(i); 447 if (arg_state->_type == T_VOID) continue; 448 arglist[ap++] = _outgoing.at(i)._arg; 449 } 450 assert(ap == _outgoing_argc, ""); 451 arglist[ap] = NULL; // add a sentinel, for the sake of asserts 452 return make_invoke(chain().last_method_oop(), 453 vmIntrinsics::_none, 454 chain().last_invoke_code(), true, 455 ap, arglist, THREAD); 456 } 457 458 void MethodHandleWalker::walk_incoming_state(TRAPS) { 459 Handle mtype(THREAD, chain().method_type_oop()); 460 int nptypes = java_dyn_MethodType::ptype_count(mtype()); 461 _outgoing_argc = nptypes; 462 int argp = nptypes - 1; 463 if (argp >= 0) { 464 _outgoing.at_grow(argp, make_state(T_VOID, NULL)); // presize 465 } 466 for (int i = 0; i < nptypes; i++) { 467 klassOop arg_type_klass = NULL; 468 BasicType arg_type = java_lang_Class::as_BasicType( 469 java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass); 470 ArgToken arg = make_parameter(arg_type, arg_type_klass, i, CHECK); 471 debug_only(arg_type_klass = (klassOop)NULL); 472 _outgoing.at_put(argp, make_state(arg_type, arg)); 473 if (type2size[arg_type] == 2) { 474 // add the extra slot, so we can model the JVM stack 475 _outgoing.insert_before(argp+1, make_state(T_VOID, NULL)); 476 } 477 --argp; 478 } 479 // call make_parameter at the end of the list for the return type 480 klassOop ret_type_klass = NULL; 481 BasicType ret_type = java_lang_Class::as_BasicType( 482 java_dyn_MethodType::rtype(mtype()), &ret_type_klass); 483 ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); 484 // ignore ret; client can catch it if needed 485 } 486 487 // this is messy because some kinds of arguments are paired with 488 // companion slots containing an empty value 489 void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type, 490 MethodHandleWalker::ArgToken new_arg) { 491 int old_size = type2size[old_type]; 492 int new_size = type2size[new_type]; 493 if (old_size == new_size) { 494 // simple case first 495 _outgoing.at_put(slot, make_state(new_type, new_arg)); 496 } else if (old_size > new_size) { 497 for (int i = old_size-1; i >= new_size; i++) { 498 assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), ""); 499 _outgoing.remove_at(slot + i); 500 } 501 if (new_size > 0) 502 _outgoing.at_put(slot, make_state(new_type, new_arg)); 503 else 504 _outgoing_argc -= 1; // deleted a real argument 505 } else { 506 for (int i = old_size; i < new_size; i++) { 507 _outgoing.insert_before(slot+i, make_state(T_VOID, NULL)); 508 } 509 _outgoing.at_put(slot, make_state(new_type, new_arg)); 510 if (old_size == 0) 511 _outgoing_argc += 1; // inserted a real argument 512 } 513 } 514 515 516 #ifdef ASSERT 517 int MethodHandleWalker::argument_count_slow() { 518 int args_seen = 0; 519 for (int i = _outgoing.length() - 1; i >= 0; i--) { 520 if (_outgoing.at(i)._type != T_VOID) { 521 ++args_seen; 522 } 523 } 524 return args_seen; 525 } 526 #endif 527 528 529 void MethodHandleCompiler::compile(TRAPS) { 530 assert(_thread == THREAD, "must be same thread"); 531 532 _constant_oops.append(Handle()); // element zero is always the null constant 533 _constant_prims.append(NULL); 534 { 535 symbolOop sig 536 = java_dyn_MethodType::as_signature(chain().method_type_oop(), true, CHECK); 537 _signature_index = find_oop_constant(sig); 538 assert(signature() == sig, ""); 539 } 540 541 walk(CHECK); 542 } 543 544 MethodHandleWalker::ArgToken 545 MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, 546 MethodHandleWalker::ArgToken src, TRAPS) { 547 Unimplemented(); 548 return NULL; 549 } 550 551 MethodHandleWalker::ArgToken 552 MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, 553 Bytecodes::Code op, bool tailcall, 554 int argc, MethodHandleWalker::ArgToken* argv, 555 TRAPS) { 556 // If tailcall, we have walked all the way to a direct method handle. 557 // Otherwise, make a recursive call to some helper routine. 558 #ifdef ASSERT 559 switch (op) { 560 case Bytecodes::_invokevirtual: 561 case Bytecodes::_invokespecial: 562 case Bytecodes::_invokestatic: 563 case Bytecodes::_invokeinterface: 564 break; 565 default: 566 ShouldNotReachHere(); 567 } 568 #endif //ASSERT 569 _bytes.put((char) op); 570 571 Unimplemented(); 572 return NULL; 573 } 574 575 MethodHandleWalker::ArgToken 576 MethodHandleCompiler::make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, 577 MethodHandleWalker::ArgToken base, 578 MethodHandleWalker::ArgToken offset, 579 TRAPS) { 580 Unimplemented(); 581 return NULL; 582 } 583 584 int MethodHandleCompiler::find_oop_constant(oop con) { 585 if (con == NULL) return 0; 586 for (int i = 1, imax = _constant_oops.length(); i < imax; i++) { 587 if (_constant_oops.at(i) == con) 588 return i; 589 } 590 _constant_prims.append(NULL); 591 return _constant_oops.append(con); 592 } 593 594 int MethodHandleCompiler::find_prim_constant(BasicType bt, jvalue* con) { 595 jvalue con_copy; 596 assert(bt < T_OBJECT, ""); 597 if (type2aelembytes(bt) < jintSize) { 598 // widen to int 599 con_copy = (*con); 600 con = &con_copy; 601 switch (bt) { 602 case T_BOOLEAN: con->i = (con->z ? 1 : 0); break; 603 case T_BYTE: con->i = con->b; break; 604 case T_CHAR: con->i = con->c; break; 605 case T_SHORT: con->i = con->s; break; 606 default: ShouldNotReachHere(); 607 } 608 bt = T_INT; 609 } 610 for (int i = 1, imax = _constant_prims.length(); i < imax; i++) { 611 PrimCon* pcon = _constant_prims.at(i); 612 if (pcon != NULL && pcon->_type == bt) { 613 bool match = false; 614 switch (type2size[bt]) { 615 case 1: if (pcon->_value.i == con->i) match = true; break; 616 case 2: if (pcon->_value.j == con->j) match = true; break; 617 } 618 if (match) 619 return i; 620 } 621 } 622 PrimCon* pcon = new PrimCon(); 623 pcon->_type = bt; 624 pcon->_value = (*con); 625 _constant_oops.append(Handle()); 626 return _constant_prims.append(pcon); 627 } 628 629 630 #ifndef PRODUCT 631 632 // MH printer for debugging. 633 634 class MethodHandlePrinter : public MethodHandleWalker { 635 private: 636 outputStream* _out; 637 bool _verbose; 638 int _temp_num; 639 stringStream _strbuf; 640 const char* strbuf() { 641 const char* s = _strbuf.as_string(); 642 _strbuf.reset(); 643 return s; 644 } 645 ArgToken token(const char* str) { 646 return (ArgToken) str; 647 } 648 void start_params() { 649 _out->print("("); 650 } 651 void end_params() { 652 if (_verbose) _out->print("\n"); 653 _out->print(") => {"); 654 } 655 void put_type_name(BasicType type, klassOop tk, outputStream* s) { 656 const char* kname = NULL; 657 if (tk != NULL) 658 kname = Klass::cast(tk)->external_name(); 659 s->print("%s", (kname != NULL) ? kname : type2name(type)); 660 } 661 ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) { 662 const char* value = strbuf(); 663 if (!_verbose) return token(value); 664 // make an explicit binding for each separate value 665 _strbuf.print("%s%d", temp_name, ++_temp_num); 666 const char* temp = strbuf(); 667 _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value); 668 return token(temp); 669 } 670 671 public: 672 MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) 673 : MethodHandleWalker(root, THREAD), 674 _out(out), 675 _verbose(verbose), 676 _temp_num(0) 677 { 678 start_params(); 679 } 680 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { 681 if (argnum < 0) { 682 end_params(); 683 return NULL; 684 } 685 if (argnum == 0) { 686 _out->print(_verbose ? "\n " : ""); 687 } else { 688 _out->print(_verbose ? ",\n " : ", "); 689 } 690 if (argnum >= _temp_num) 691 _temp_num = argnum; 692 // generate an argument name 693 _strbuf.print("a%d", argnum); 694 const char* arg = strbuf(); 695 put_type_name(type, tk, _out); 696 _out->print(" %s", arg); 697 return token(arg); 698 } 699 virtual ArgToken make_oop_constant(oop con, TRAPS) { 700 if (con == NULL) 701 _strbuf.print("null"); 702 else 703 con->print_value_on(&_strbuf); 704 if (_strbuf.size() == 0) { // yuck 705 _strbuf.print("(a "); 706 put_type_name(T_OBJECT, con->klass(), &_strbuf); 707 _strbuf.print(")"); 708 } 709 return maybe_make_temp("constant", T_OBJECT, "k"); 710 } 711 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { 712 java_lang_boxing_object::print(type, con, &_strbuf); 713 return maybe_make_temp("constant", type, "k"); 714 } 715 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) { 716 _strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src); 717 if (tk != NULL) { 718 _strbuf.print(", "); 719 put_type_name(type, tk, &_strbuf); 720 } 721 _strbuf.print(")"); 722 return maybe_make_temp("convert", type, "v"); 723 } 724 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) { 725 _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset); 726 if (tk != NULL) { 727 _strbuf.print(", "); 728 put_type_name(type, tk, &_strbuf); 729 } 730 _strbuf.print(")"); 731 return maybe_make_temp("fetch", type, "x"); 732 } 733 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, 734 Bytecodes::Code op, bool tailcall, 735 int argc, ArgToken* argv, TRAPS) { 736 symbolOop name, sig; 737 if (m != NULL) { 738 name = m->name(); 739 sig = m->signature(); 740 } else { 741 name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid)); 742 sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid)); 743 } 744 _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string()); 745 for (int i = 0; i < argc; i++) { 746 _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]); 747 } 748 _strbuf.print(")"); 749 if (!tailcall) { 750 BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1)); 751 if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;' 752 return maybe_make_temp("invoke", rt, "x"); 753 } else { 754 const char* ret = strbuf(); 755 _out->print(_verbose ? "\n return " : " "); 756 _out->print("%s", ret); 757 _out->print(_verbose ? "\n}\n" : " }"); 758 } 759 } 760 761 virtual void set_method_handle(oop mh) { 762 if (WizardMode && Verbose) { 763 tty->print("\n--- next target: "); 764 mh->print(); 765 } 766 } 767 768 static void print(Handle root, bool verbose, outputStream* out, TRAPS) { 769 ResourceMark rm; 770 MethodHandlePrinter printer(root, verbose, out, CHECK); 771 printer.walk(CHECK); 772 out->print("\n"); 773 } 774 static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) { 775 EXCEPTION_MARK; 776 ResourceMark rm; 777 MethodHandlePrinter printer(root, verbose, out, THREAD); 778 if (!HAS_PENDING_EXCEPTION) 779 printer.walk(THREAD); 780 if (HAS_PENDING_EXCEPTION) { 781 oop ex = PENDING_EXCEPTION; 782 CLEAR_PENDING_EXCEPTION; 783 out->print("\n*** "); 784 if (ex != Universe::virtual_machine_error_instance()) 785 ex->print_on(out); 786 else 787 out->print("lose: %s", printer.lose_message()); 788 out->print("\n}\n"); 789 } 790 out->print("\n"); 791 } 792 }; 793 794 extern "C" 795 void print_method_handle(oopDesc* mh) { 796 if (java_dyn_MethodHandle::is_instance(mh)) { 797 MethodHandlePrinter::print(mh); 798 } else { 799 tty->print("*** not a method handle: "); 800 mh->print(); 801 } 802 } 803 804 #endif // PRODUCT