Mercurial > hg > graal-compiler
comparison src/share/vm/prims/methodHandleWalk.cpp @ 3371:fabcf26ee72f
6998541: JSR 292 implement missing return-type conversion for OP_RETYPE_RAW
Reviewed-by: jrose, kvn, never
author | twisti |
---|---|
date | Thu, 12 May 2011 14:04:48 -0700 |
parents | e2a92dd0d3d2 |
children | 33ae33516634 |
comparison
equal
deleted
inserted
replaced
3370:2f17eb233d13 | 3371:fabcf26ee72f |
---|---|
29 | 29 |
30 /* | 30 /* |
31 * JSR 292 reference implementation: method handle structure analysis | 31 * JSR 292 reference implementation: method handle structure analysis |
32 */ | 32 */ |
33 | 33 |
34 #ifdef PRODUCT | |
35 #define print_method_handle(mh) {} | |
36 #else //PRODUCT | |
37 extern "C" void print_method_handle(oop mh); | |
38 #endif //PRODUCT | |
34 | 39 |
35 // ----------------------------------------------------------------------------- | 40 // ----------------------------------------------------------------------------- |
36 // MethodHandleChain | 41 // MethodHandleChain |
37 | 42 |
38 void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { | 43 void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { |
204 if (arg_state == NULL | 209 if (arg_state == NULL |
205 && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) { | 210 && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) { |
206 lose("bad argument index", CHECK_(empty)); | 211 lose("bad argument index", CHECK_(empty)); |
207 } | 212 } |
208 | 213 |
214 bool retain_original_args = false; // used by fold/collect logic | |
215 | |
209 // perform the adapter action | 216 // perform the adapter action |
210 switch (chain().adapter_conversion_op()) { | 217 switch (conv_op) { |
211 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: | 218 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: |
212 // No changes to arguments; pass the bits through. | 219 // No changes to arguments; pass the bits through. |
213 break; | 220 break; |
214 | 221 |
215 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: { | 222 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: { |
216 // To keep the verifier happy, emit bitwise ("raw") conversions as needed. | 223 // To keep the verifier happy, emit bitwise ("raw") conversions as needed. |
217 // See MethodHandles::same_basic_type_for_arguments for allowed conversions. | 224 // See MethodHandles::same_basic_type_for_arguments for allowed conversions. |
218 Handle incoming_mtype(THREAD, chain().method_type_oop()); | 225 Handle incoming_mtype(THREAD, chain().method_type_oop()); |
219 oop outgoing_mh_oop = chain().vmtarget_oop(); | 226 Handle outgoing_mtype; |
220 if (!java_lang_invoke_MethodHandle::is_instance(outgoing_mh_oop)) | 227 { |
221 lose("outgoing target not a MethodHandle", CHECK_(empty)); | 228 oop outgoing_mh_oop = chain().vmtarget_oop(); |
222 Handle outgoing_mtype(THREAD, java_lang_invoke_MethodHandle::type(outgoing_mh_oop)); | 229 if (!java_lang_invoke_MethodHandle::is_instance(outgoing_mh_oop)) |
223 outgoing_mh_oop = NULL; // GC safety | 230 lose("outgoing target not a MethodHandle", CHECK_(empty)); |
231 outgoing_mtype = Handle(THREAD, java_lang_invoke_MethodHandle::type(outgoing_mh_oop)); | |
232 } | |
224 | 233 |
225 int nptypes = java_lang_invoke_MethodType::ptype_count(outgoing_mtype()); | 234 int nptypes = java_lang_invoke_MethodType::ptype_count(outgoing_mtype()); |
226 if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype())) | 235 if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype())) |
227 lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); | 236 lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); |
228 | 237 |
238 // Argument types. | |
229 for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { | 239 for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { |
230 SlotState* arg_state = slot_state(slot); | 240 SlotState* arg_state = slot_state(slot); |
231 if (arg_state->_type == T_VOID) continue; | 241 if (arg_state->_type == T_VOID) continue; |
232 ArgToken arg = _outgoing.at(slot)._arg; | 242 |
233 | 243 klassOop src_klass = NULL; |
234 klassOop in_klass = NULL; | 244 klassOop dst_klass = NULL; |
235 klassOop out_klass = NULL; | 245 BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &src_klass); |
236 BasicType inpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &in_klass); | 246 BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &dst_klass); |
237 BasicType outpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &out_klass); | 247 retype_raw_argument_type(src, dst, slot, CHECK_(empty)); |
238 assert(inpbt == arg.basic_type(), "sanity"); | |
239 | |
240 if (inpbt != outpbt) { | |
241 vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(inpbt, outpbt); | |
242 if (iid == vmIntrinsics::_none) { | |
243 lose("no raw conversion method", CHECK_(empty)); | |
244 } | |
245 ArgToken arglist[2]; | |
246 arglist[0] = arg; // outgoing 'this' | |
247 arglist[1] = ArgToken(); // sentinel | |
248 arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); | |
249 change_argument(inpbt, slot, outpbt, arg); | |
250 } | |
251 | |
252 i++; // We need to skip void slots at the top of the loop. | 248 i++; // We need to skip void slots at the top of the loop. |
253 } | 249 } |
254 | 250 |
255 BasicType inrbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(incoming_mtype())); | 251 // Return type. |
256 BasicType outrbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(outgoing_mtype())); | 252 { |
257 if (inrbt != outrbt) { | 253 BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(incoming_mtype())); |
258 if (inrbt == T_INT && outrbt == T_VOID) { | 254 BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(outgoing_mtype())); |
259 // See comments in MethodHandles::same_basic_type_for_arguments. | 255 retype_raw_return_type(src, dst, CHECK_(empty)); |
260 } else { | |
261 assert(false, "IMPLEMENT ME"); | |
262 lose("no raw conversion method", CHECK_(empty)); | |
263 } | |
264 } | 256 } |
265 break; | 257 break; |
266 } | 258 } |
267 | 259 |
268 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: { | 260 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: { |
271 BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); | 263 BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); |
272 assert(dest == T_OBJECT, ""); | 264 assert(dest == T_OBJECT, ""); |
273 assert(dest == arg_state->_type, ""); | 265 assert(dest == arg_state->_type, ""); |
274 ArgToken arg = arg_state->_arg; | 266 ArgToken arg = arg_state->_arg; |
275 ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); | 267 ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); |
276 assert(arg.index() == new_arg.index(), "should be the same index"); | 268 assert(arg.token_type() >= tt_symbolic || arg.index() == new_arg.index(), "should be the same index"); |
277 debug_only(dest_klass = (klassOop)badOop); | 269 debug_only(dest_klass = (klassOop)badOop); |
278 break; | 270 break; |
279 } | 271 } |
280 | 272 |
281 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: { | 273 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: { |
330 lose("no boxing method", CHECK_(empty)); | 322 lose("no boxing method", CHECK_(empty)); |
331 } | 323 } |
332 ArgToken arglist[2]; | 324 ArgToken arglist[2]; |
333 arglist[0] = arg; // outgoing value | 325 arglist[0] = arg; // outgoing value |
334 arglist[1] = ArgToken(); // sentinel | 326 arglist[1] = ArgToken(); // sentinel |
335 arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); | 327 arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); |
336 change_argument(src, arg_slot, T_OBJECT, arg); | 328 change_argument(src, arg_slot, T_OBJECT, arg); |
337 break; | 329 break; |
338 } | 330 } |
339 | 331 |
340 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { | 332 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { |
402 _outgoing.remove_at(arg_slot); | 394 _outgoing.remove_at(arg_slot); |
403 } | 395 } |
404 break; | 396 break; |
405 } | 397 } |
406 | 398 |
407 case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC | 399 case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS: |
408 lose("unimplemented", CHECK_(empty)); | 400 retain_original_args = true; // and fall through: |
409 break; | 401 case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: { |
410 } | 402 // call argument MH recursively |
411 | 403 //{static int x; if (!x++) print_method_handle(chain().method_handle_oop()); --x;} |
412 case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS: { //NYI, may GC | 404 Handle recursive_mh(THREAD, chain().adapter_arg_oop()); |
413 lose("unimplemented", CHECK_(empty)); | 405 if (!java_lang_invoke_MethodHandle::is_instance(recursive_mh())) { |
406 lose("recursive target not a MethodHandle", CHECK_(empty)); | |
407 } | |
408 Handle recursive_mtype(THREAD, java_lang_invoke_MethodHandle::type(recursive_mh())); | |
409 int argc = java_lang_invoke_MethodType::ptype_count(recursive_mtype()); | |
410 int coll_slots = java_lang_invoke_MethodHandle::vmslots(recursive_mh()); | |
411 BasicType rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(recursive_mtype())); | |
412 ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, 1 + argc + 1); // 1+: mh, +1: sentinel | |
413 arglist[0] = make_oop_constant(recursive_mh(), CHECK_(empty)); | |
414 if (arg_slot < 0 || coll_slots < 0 || arg_slot + coll_slots > _outgoing.length()) { | |
415 lose("bad fold/collect arg slot", CHECK_(empty)); | |
416 } | |
417 for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) { | |
418 SlotState* arg_state = slot_state(slot); | |
419 BasicType arg_type = arg_state->_type; | |
420 if (arg_type == T_VOID) continue; | |
421 ArgToken arg = _outgoing.at(slot)._arg; | |
422 if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); } | |
423 arglist[1+i] = arg; | |
424 if (!retain_original_args) | |
425 change_argument(arg_type, slot, T_VOID, ArgToken(tt_void)); | |
426 } | |
427 arglist[1+argc] = ArgToken(); // sentinel | |
428 oop invoker = java_lang_invoke_MethodTypeForm::vmlayout( | |
429 java_lang_invoke_MethodType::form(recursive_mtype()) ); | |
430 if (invoker == NULL || !invoker->is_method()) { | |
431 lose("bad vmlayout slot", CHECK_(empty)); | |
432 } | |
433 // FIXME: consider inlining the invokee at the bytecode level | |
434 ArgToken ret = make_invoke(methodOop(invoker), vmIntrinsics::_none, | |
435 Bytecodes::_invokevirtual, false, 1+argc, &arglist[0], CHECK_(empty)); | |
436 DEBUG_ONLY(invoker = NULL); | |
437 if (rtype == T_OBJECT) { | |
438 klassOop rklass = java_lang_Class::as_klassOop( java_lang_invoke_MethodType::rtype(recursive_mtype()) ); | |
439 if (rklass != SystemDictionary::Object_klass() && | |
440 !Klass::cast(rklass)->is_interface()) { | |
441 // preserve type safety | |
442 ret = make_conversion(T_OBJECT, rklass, Bytecodes::_checkcast, ret, CHECK_(empty)); | |
443 } | |
444 } | |
445 int ret_slot = arg_slot + (retain_original_args ? coll_slots : 0); | |
446 change_argument(T_VOID, ret_slot, rtype, ret); | |
414 break; | 447 break; |
415 } | 448 } |
416 | 449 |
417 case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: { | 450 case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: { |
418 klassOop array_klass_oop = NULL; | 451 klassOop array_klass_oop = NULL; |
502 arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); | 535 arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); |
503 } else { | 536 } else { |
504 lose("bad bound value", CHECK_(empty)); | 537 lose("bad bound value", CHECK_(empty)); |
505 } | 538 } |
506 } | 539 } |
507 debug_only(arg_oop = badOop); | 540 DEBUG_ONLY(arg_oop = badOop); |
508 change_argument(T_VOID, arg_slot, arg_type, arg); | 541 change_argument(T_VOID, arg_slot, arg_type, arg); |
509 } | 542 } |
510 | 543 |
511 // this test must come after the body of the loop | 544 // this test must come after the body of the loop |
512 if (!chain().is_last()) { | 545 if (!chain().is_last()) { |
545 if (argp >= 0) { | 578 if (argp >= 0) { |
546 _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize | 579 _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize |
547 } | 580 } |
548 for (int i = 0; i < nptypes; i++) { | 581 for (int i = 0; i < nptypes; i++) { |
549 klassOop arg_type_klass = NULL; | 582 klassOop arg_type_klass = NULL; |
550 BasicType arg_type = java_lang_Class::as_BasicType( | 583 BasicType arg_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass); |
551 java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass); | |
552 int index = new_local_index(arg_type); | 584 int index = new_local_index(arg_type); |
553 ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); | 585 ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); |
554 debug_only(arg_type_klass = (klassOop) NULL); | 586 DEBUG_ONLY(arg_type_klass = (klassOop) NULL); |
555 _outgoing.at_put(argp, make_state(arg_type, arg)); | 587 _outgoing.at_put(argp, make_state(arg_type, arg)); |
556 if (type2size[arg_type] == 2) { | 588 if (type2size[arg_type] == 2) { |
557 // add the extra slot, so we can model the JVM stack | 589 // add the extra slot, so we can model the JVM stack |
558 _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void))); | 590 _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void))); |
559 } | 591 } |
560 --argp; | 592 --argp; |
561 } | 593 } |
562 // call make_parameter at the end of the list for the return type | 594 // call make_parameter at the end of the list for the return type |
563 klassOop ret_type_klass = NULL; | 595 klassOop ret_type_klass = NULL; |
564 BasicType ret_type = java_lang_Class::as_BasicType( | 596 BasicType ret_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass); |
565 java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass); | |
566 ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); | 597 ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); |
567 // ignore ret; client can catch it if needed | 598 // ignore ret; client can catch it if needed |
568 } | 599 } |
569 | 600 |
570 | 601 |
609 } | 640 } |
610 } | 641 } |
611 return args_seen; | 642 return args_seen; |
612 } | 643 } |
613 #endif | 644 #endif |
645 | |
646 | |
647 // ----------------------------------------------------------------------------- | |
648 // MethodHandleWalker::retype_raw_conversion | |
649 // | |
650 // Do the raw retype conversions for OP_RETYPE_RAW. | |
651 void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS) { | |
652 if (src != dst) { | |
653 if (MethodHandles::same_basic_type_for_returns(src, dst, /*raw*/ true)) { | |
654 if (MethodHandles::is_float_fixed_reinterpretation_cast(src, dst)) { | |
655 if (for_return) Untested("MHW return raw conversion"); // still untested | |
656 vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(src, dst); | |
657 if (iid == vmIntrinsics::_none) { | |
658 lose("no raw conversion method", CHECK); | |
659 } | |
660 ArgToken arglist[2]; | |
661 if (!for_return) { | |
662 // argument type conversion | |
663 ArgToken arg = _outgoing.at(slot)._arg; | |
664 assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity"); | |
665 arglist[0] = arg; // outgoing 'this' | |
666 arglist[1] = ArgToken(); // sentinel | |
667 arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); | |
668 change_argument(src, slot, dst, arg); | |
669 } else { | |
670 // return type conversion | |
671 klassOop arg_klass = NULL; | |
672 arglist[0] = make_parameter(src, arg_klass, -1, CHECK); // return value | |
673 arglist[1] = ArgToken(); // sentinel | |
674 (void) make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); | |
675 } | |
676 } else { | |
677 // Nothing to do. | |
678 } | |
679 } else if (src == T_OBJECT && is_java_primitive(dst)) { | |
680 // ref-to-prim: discard ref, push zero | |
681 lose("requested ref-to-prim conversion not expected", CHECK); | |
682 } else { | |
683 lose("requested raw conversion not allowed", CHECK); | |
684 } | |
685 } | |
686 } | |
614 | 687 |
615 | 688 |
616 // ----------------------------------------------------------------------------- | 689 // ----------------------------------------------------------------------------- |
617 // MethodHandleCompiler | 690 // MethodHandleCompiler |
618 | 691 |
717 case Bytecodes::_dstore_3: | 790 case Bytecodes::_dstore_3: |
718 case Bytecodes::_astore_0: | 791 case Bytecodes::_astore_0: |
719 case Bytecodes::_astore_1: | 792 case Bytecodes::_astore_1: |
720 case Bytecodes::_astore_2: | 793 case Bytecodes::_astore_2: |
721 case Bytecodes::_astore_3: | 794 case Bytecodes::_astore_3: |
795 case Bytecodes::_iand: | |
722 case Bytecodes::_i2l: | 796 case Bytecodes::_i2l: |
723 case Bytecodes::_i2f: | 797 case Bytecodes::_i2f: |
724 case Bytecodes::_i2d: | 798 case Bytecodes::_i2d: |
725 case Bytecodes::_i2b: | 799 case Bytecodes::_i2b: |
726 case Bytecodes::_i2c: | 800 case Bytecodes::_i2c: |
943 emit_bc(op, cpool_klass_put(tk)); | 1017 emit_bc(op, cpool_klass_put(tk)); |
944 emit_store(srctype, index); | 1018 emit_store(srctype, index); |
945 break; | 1019 break; |
946 | 1020 |
947 default: | 1021 default: |
948 ShouldNotReachHere(); | 1022 if (op == Bytecodes::_illegal) |
1023 lose("no such primitive conversion", THREAD); | |
1024 else | |
1025 lose("bad primitive conversion op", THREAD); | |
1026 return make_prim_constant(type, &zero_jvalue, THREAD); | |
949 } | 1027 } |
950 | 1028 |
951 return make_parameter(type, tk, index, THREAD); | 1029 return make_parameter(type, tk, index, THREAD); |
952 } | 1030 } |
953 | 1031 |
954 | 1032 |
955 // ----------------------------------------------------------------------------- | 1033 // ----------------------------------------------------------------------------- |
956 // MethodHandleCompiler | 1034 // MethodHandleCompiler |
957 // | 1035 // |
958 | 1036 |
959 static jvalue zero_jvalue; | 1037 // Values used by the compiler. |
1038 jvalue MethodHandleCompiler::zero_jvalue = { 0 }; | |
1039 jvalue MethodHandleCompiler::one_jvalue = { 1 }; | |
960 | 1040 |
961 // Emit bytecodes for the given invoke instruction. | 1041 // Emit bytecodes for the given invoke instruction. |
962 MethodHandleWalker::ArgToken | 1042 MethodHandleWalker::ArgToken |
963 MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, | 1043 MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, |
964 Bytecodes::Code op, bool tailcall, | 1044 Bytecodes::Code op, bool tailcall, |
965 int argc, MethodHandleWalker::ArgToken* argv, | 1045 int argc, MethodHandleWalker::ArgToken* argv, |
966 TRAPS) { | 1046 TRAPS) { |
1047 ArgToken zero; | |
967 if (m == NULL) { | 1048 if (m == NULL) { |
968 // Get the intrinsic methodOop. | 1049 // Get the intrinsic methodOop. |
969 m = vmIntrinsics::method_for(iid); | 1050 m = vmIntrinsics::method_for(iid); |
970 if (m == NULL) { | 1051 if (m == NULL) { |
971 ArgToken zero; | |
972 lose(vmIntrinsics::name_at(iid), CHECK_(zero)); | 1052 lose(vmIntrinsics::name_at(iid), CHECK_(zero)); |
973 } | 1053 } |
974 } | 1054 } |
975 | 1055 |
976 klassOop klass = m->method_holder(); | 1056 klassOop klass = m->method_holder(); |
977 Symbol* name = m->name(); | 1057 Symbol* name = m->name(); |
978 Symbol* signature = m->signature(); | 1058 Symbol* signature = m->signature(); |
979 | 1059 |
980 if (tailcall) { | 1060 if (tailcall) { |
981 // Actually, in order to make these methods more recognizable, | 1061 // Actually, in order to make these methods more recognizable, |
982 // let's put them in holder class MethodHandle. That way stack | 1062 // let's put them in holder class MethodHandle. That way stack |
983 // walkers and compiler heuristics can recognize them. | 1063 // walkers and compiler heuristics can recognize them. |
1039 ArgToken ret; | 1119 ArgToken ret; |
1040 if (tailcall) { | 1120 if (tailcall) { |
1041 if (rbt != _rtype) { | 1121 if (rbt != _rtype) { |
1042 if (rbt == T_VOID) { | 1122 if (rbt == T_VOID) { |
1043 // push a zero of the right sort | 1123 // push a zero of the right sort |
1044 ArgToken zero; | |
1045 if (_rtype == T_OBJECT) { | 1124 if (_rtype == T_OBJECT) { |
1046 zero = make_oop_constant(NULL, CHECK_(zero)); | 1125 zero = make_oop_constant(NULL, CHECK_(zero)); |
1047 } else { | 1126 } else { |
1048 zero = make_prim_constant(_rtype, &zero_jvalue, CHECK_(zero)); | 1127 zero = make_prim_constant(_rtype, &zero_jvalue, CHECK_(zero)); |
1049 } | 1128 } |
1050 emit_load_constant(zero); | 1129 emit_load_constant(zero); |
1051 } else if (_rtype == T_VOID) { | 1130 } else if (_rtype == T_VOID) { |
1052 // We'll emit a _return with something on the stack. | 1131 // We'll emit a _return with something on the stack. |
1053 // It's OK to ignore what's on the stack. | 1132 // It's OK to ignore what's on the stack. |
1133 } else if (rbt == T_INT && is_subword_type(_rtype)) { | |
1134 // Convert value to match return type. | |
1135 switch (_rtype) { | |
1136 case T_BOOLEAN: { | |
1137 // boolean is treated as a one-bit unsigned integer. | |
1138 // Cf. API documentation: java/lang/invoke/MethodHandles.html#explicitCastArguments | |
1139 ArgToken one = make_prim_constant(T_INT, &one_jvalue, CHECK_(zero)); | |
1140 emit_load_constant(one); | |
1141 emit_bc(Bytecodes::_iand); | |
1142 break; | |
1143 } | |
1144 case T_BYTE: emit_bc(Bytecodes::_i2b); break; | |
1145 case T_CHAR: emit_bc(Bytecodes::_i2c); break; | |
1146 case T_SHORT: emit_bc(Bytecodes::_i2s); break; | |
1147 default: ShouldNotReachHere(); | |
1148 } | |
1149 } else if (is_subword_type(rbt) && (is_subword_type(_rtype) || (_rtype == T_INT))) { | |
1150 // The subword type was returned as an int and will be passed | |
1151 // on as an int. | |
1054 } else { | 1152 } else { |
1055 tty->print_cr("*** rbt=%d != rtype=%d", rbt, _rtype); | 1153 lose("unknown conversion", CHECK_(zero)); |
1056 assert(false, "IMPLEMENT ME"); | |
1057 } | 1154 } |
1058 } | 1155 } |
1059 switch (_rtype) { | 1156 switch (_rtype) { |
1060 case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: | 1157 case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT: |
1061 case T_INT: emit_bc(Bytecodes::_ireturn); break; | 1158 case T_INT: emit_bc(Bytecodes::_ireturn); break; |
1214 m->set_size_of_parameters(_num_params); | 1311 m->set_size_of_parameters(_num_params); |
1215 | 1312 |
1216 typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); | 1313 typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array()); |
1217 m->set_exception_table(exception_handlers()); | 1314 m->set_exception_table(exception_handlers()); |
1218 | 1315 |
1219 // Set the invocation counter's count to the invoke count of the | |
1220 // original call site. | |
1221 InvocationCounter* ic = m->invocation_counter(); | |
1222 ic->set(InvocationCounter::wait_for_compile, _invoke_count); | |
1223 | |
1224 // Rewrite the method and set up the constant pool cache. | 1316 // Rewrite the method and set up the constant pool cache. |
1225 objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty)); | 1317 objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty)); |
1226 objArrayHandle methods(THREAD, m_array); | 1318 objArrayHandle methods(THREAD, m_array); |
1227 methods->obj_at_put(0, m()); | 1319 methods->obj_at_put(0, m()); |
1228 Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(empty)); // Use fake class. | 1320 Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(empty)); // Use fake class. |
1229 | 1321 |
1322 // Set the invocation counter's count to the invoke count of the | |
1323 // original call site. | |
1324 InvocationCounter* ic = m->invocation_counter(); | |
1325 ic->set(InvocationCounter::wait_for_compile, _invoke_count); | |
1326 | |
1230 // Create a new MDO | 1327 // Create a new MDO |
1231 { | 1328 { |
1232 methodDataOop mdo = oopFactory::new_methodData(m, CHECK_(empty)); | 1329 methodDataOop mdo = oopFactory::new_methodData(m, CHECK_(empty)); |
1233 assert(m->method_data() == NULL, "there should not be an MDO yet"); | 1330 assert(m->method_data() == NULL, "there should not be an MDO yet"); |
1234 m->set_method_data(mdo); | 1331 m->set_method_data(mdo); |
1235 | 1332 |
1236 // Iterate over all profile data and set the count of the counter | 1333 // Iterate over all profile data and set the count of the counter |
1237 // data entries to the original call site counter. | 1334 // data entries to the original call site counter. |
1238 for (ProfileData* pd = mdo->first_data(); mdo->is_valid(pd); pd = mdo->next_data(pd)) { | 1335 for (ProfileData* profile_data = mdo->first_data(); |
1239 if (pd->is_CounterData()) { | 1336 mdo->is_valid(profile_data); |
1240 CounterData* cd = pd->as_CounterData(); | 1337 profile_data = mdo->next_data(profile_data)) { |
1241 cd->set_count(_invoke_count); | 1338 if (profile_data->is_CounterData()) { |
1339 CounterData* counter_data = profile_data->as_CounterData(); | |
1340 counter_data->set_count(_invoke_count); | |
1242 } | 1341 } |
1243 } | 1342 } |
1244 } | 1343 } |
1245 | 1344 |
1246 #ifndef PRODUCT | 1345 #ifndef PRODUCT |
1255 } | 1354 } |
1256 | 1355 |
1257 | 1356 |
1258 #ifndef PRODUCT | 1357 #ifndef PRODUCT |
1259 | 1358 |
1260 #if 0 | |
1261 // MH printer for debugging. | 1359 // MH printer for debugging. |
1262 | 1360 |
1263 class MethodHandlePrinter : public MethodHandleWalker { | 1361 class MethodHandlePrinter : public MethodHandleWalker { |
1264 private: | 1362 private: |
1265 outputStream* _out; | 1363 outputStream* _out; |
1266 bool _verbose; | 1364 bool _verbose; |
1267 int _temp_num; | 1365 int _temp_num; |
1366 int _param_state; | |
1268 stringStream _strbuf; | 1367 stringStream _strbuf; |
1269 const char* strbuf() { | 1368 const char* strbuf() { |
1270 const char* s = _strbuf.as_string(); | 1369 const char* s = _strbuf.as_string(); |
1271 _strbuf.reset(); | 1370 _strbuf.reset(); |
1272 return s; | 1371 return s; |
1273 } | 1372 } |
1274 ArgToken token(const char* str) { | 1373 ArgToken token(const char* str) { |
1275 return (ArgToken) str; | 1374 jvalue string_con; |
1375 string_con.j = (intptr_t) str; | |
1376 return ArgToken(tt_symbolic, T_LONG, string_con); | |
1377 } | |
1378 const char* string(ArgToken token) { | |
1379 return (const char*) (intptr_t) token.get_jlong(); | |
1276 } | 1380 } |
1277 void start_params() { | 1381 void start_params() { |
1382 _param_state <<= 1; | |
1278 _out->print("("); | 1383 _out->print("("); |
1279 } | 1384 } |
1280 void end_params() { | 1385 void end_params() { |
1281 if (_verbose) _out->print("\n"); | 1386 if (_verbose) _out->print("\n"); |
1282 _out->print(") => {"); | 1387 _out->print(") => {"); |
1388 _param_state >>= 1; | |
1283 } | 1389 } |
1284 void put_type_name(BasicType type, klassOop tk, outputStream* s) { | 1390 void put_type_name(BasicType type, klassOop tk, outputStream* s) { |
1285 const char* kname = NULL; | 1391 const char* kname = NULL; |
1286 if (tk != NULL) | 1392 if (tk != NULL) |
1287 kname = Klass::cast(tk)->external_name(); | 1393 kname = Klass::cast(tk)->external_name(); |
1297 return token(temp); | 1403 return token(temp); |
1298 } | 1404 } |
1299 | 1405 |
1300 public: | 1406 public: |
1301 MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) | 1407 MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) |
1302 : MethodHandleWalker(root, THREAD), | 1408 : MethodHandleWalker(root, false, THREAD), |
1303 _out(out), | 1409 _out(out), |
1304 _verbose(verbose), | 1410 _verbose(verbose), |
1411 _param_state(0), | |
1305 _temp_num(0) | 1412 _temp_num(0) |
1306 { | 1413 { |
1307 start_params(); | 1414 start_params(); |
1308 } | 1415 } |
1309 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { | 1416 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { |
1310 if (argnum < 0) { | 1417 if (argnum < 0) { |
1311 end_params(); | 1418 end_params(); |
1312 return NULL; | 1419 return token("return"); |
1313 } | 1420 } |
1314 if (argnum == 0) { | 1421 if ((_param_state & 1) == 0) { |
1422 _param_state |= 1; | |
1315 _out->print(_verbose ? "\n " : ""); | 1423 _out->print(_verbose ? "\n " : ""); |
1316 } else { | 1424 } else { |
1317 _out->print(_verbose ? ",\n " : ", "); | 1425 _out->print(_verbose ? ",\n " : ", "); |
1318 } | 1426 } |
1319 if (argnum >= _temp_num) | 1427 if (argnum >= _temp_num) |
1339 } | 1447 } |
1340 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { | 1448 virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { |
1341 java_lang_boxing_object::print(type, con, &_strbuf); | 1449 java_lang_boxing_object::print(type, con, &_strbuf); |
1342 return maybe_make_temp("constant", type, "k"); | 1450 return maybe_make_temp("constant", type, "k"); |
1343 } | 1451 } |
1344 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) { | 1452 void print_bytecode_name(Bytecodes::Code op) { |
1345 _strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src); | 1453 if (Bytecodes::is_defined(op)) |
1454 _strbuf.print("%s", Bytecodes::name(op)); | |
1455 else | |
1456 _strbuf.print("bytecode_%d", (int) op); | |
1457 } | |
1458 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) { | |
1459 print_bytecode_name(op); | |
1460 _strbuf.print("(%s", string(src)); | |
1346 if (tk != NULL) { | 1461 if (tk != NULL) { |
1347 _strbuf.print(", "); | 1462 _strbuf.print(", "); |
1348 put_type_name(type, tk, &_strbuf); | 1463 put_type_name(type, tk, &_strbuf); |
1349 } | 1464 } |
1350 _strbuf.print(")"); | 1465 _strbuf.print(")"); |
1351 return maybe_make_temp("convert", type, "v"); | 1466 return maybe_make_temp("convert", type, "v"); |
1352 } | 1467 } |
1353 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) { | 1468 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) { |
1354 _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset); | 1469 _strbuf.print("%s(%s, %s", Bytecodes::name(op), string(base), string(offset)); |
1355 if (tk != NULL) { | 1470 if (tk != NULL) { |
1356 _strbuf.print(", "); | 1471 _strbuf.print(", "); |
1357 put_type_name(type, tk, &_strbuf); | 1472 put_type_name(type, tk, &_strbuf); |
1358 } | 1473 } |
1359 _strbuf.print(")"); | 1474 _strbuf.print(")"); |
1360 return maybe_make_temp("fetch", type, "x"); | 1475 return maybe_make_temp("fetch", type, "x"); |
1361 } | 1476 } |
1362 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, | 1477 virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, |
1363 Bytecodes::Code op, bool tailcall, | 1478 Bytecodes::Code op, bool tailcall, |
1364 int argc, ArgToken* argv, TRAPS) { | 1479 int argc, ArgToken* argv, TRAPS) { |
1365 Symbol* name, sig; | 1480 Symbol* name; |
1481 Symbol* sig; | |
1366 if (m != NULL) { | 1482 if (m != NULL) { |
1367 name = m->name(); | 1483 name = m->name(); |
1368 sig = m->signature(); | 1484 sig = m->signature(); |
1369 } else { | 1485 } else { |
1370 name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid)); | 1486 name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid)); |
1371 sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid)); | 1487 sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid)); |
1372 } | 1488 } |
1373 _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string()); | 1489 _strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string()); |
1374 for (int i = 0; i < argc; i++) { | 1490 for (int i = 0; i < argc; i++) { |
1375 _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]); | 1491 _strbuf.print("%s%s", (i > 0 ? ", " : ""), string(argv[i])); |
1376 } | 1492 } |
1377 _strbuf.print(")"); | 1493 _strbuf.print(")"); |
1378 if (!tailcall) { | 1494 if (!tailcall) { |
1379 BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1)); | 1495 BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1)); |
1380 if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;' | 1496 if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;' |
1408 if (!HAS_PENDING_EXCEPTION) | 1524 if (!HAS_PENDING_EXCEPTION) |
1409 printer.walk(THREAD); | 1525 printer.walk(THREAD); |
1410 if (HAS_PENDING_EXCEPTION) { | 1526 if (HAS_PENDING_EXCEPTION) { |
1411 oop ex = PENDING_EXCEPTION; | 1527 oop ex = PENDING_EXCEPTION; |
1412 CLEAR_PENDING_EXCEPTION; | 1528 CLEAR_PENDING_EXCEPTION; |
1413 out->print("\n*** "); | 1529 out->print(" *** "); |
1414 if (ex != Universe::virtual_machine_error_instance()) | 1530 if (printer.lose_message() != NULL) out->print("%s ", printer.lose_message()); |
1415 ex->print_on(out); | 1531 out->print("}"); |
1416 else | |
1417 out->print("lose: %s", printer.lose_message()); | |
1418 out->print("\n}\n"); | |
1419 } | 1532 } |
1420 out->print("\n"); | 1533 out->print("\n"); |
1421 } | 1534 } |
1422 }; | 1535 }; |
1423 #endif // 0 | |
1424 | 1536 |
1425 extern "C" | 1537 extern "C" |
1426 void print_method_handle(oop mh) { | 1538 void print_method_handle(oop mh) { |
1427 if (!mh->is_oop()) { | 1539 if (!mh->is_oop()) { |
1428 tty->print_cr("*** not a method handle: "INTPTR_FORMAT, (intptr_t)mh); | 1540 tty->print_cr("*** not a method handle: "PTR_FORMAT, (intptr_t)mh); |
1429 } else if (java_lang_invoke_MethodHandle::is_instance(mh)) { | 1541 } else if (java_lang_invoke_MethodHandle::is_instance(mh)) { |
1430 //MethodHandlePrinter::print(mh); | 1542 MethodHandlePrinter::print(mh); |
1431 } else { | 1543 } else { |
1432 tty->print("*** not a method handle: "); | 1544 tty->print("*** not a method handle: "); |
1433 mh->print(); | 1545 mh->print(); |
1434 } | 1546 } |
1435 } | 1547 } |