34 |
34 |
35 // ----------------------------------------------------------------------------- |
35 // ----------------------------------------------------------------------------- |
36 // MethodHandleChain |
36 // MethodHandleChain |
37 |
37 |
38 void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { |
38 void MethodHandleChain::set_method_handle(Handle mh, TRAPS) { |
39 if (!java_dyn_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); |
39 if (!java_lang_invoke_MethodHandle::is_instance(mh())) lose("bad method handle", CHECK); |
40 |
40 |
41 // set current method handle and unpack partially |
41 // set current method handle and unpack partially |
42 _method_handle = mh; |
42 _method_handle = mh; |
43 _is_last = false; |
43 _is_last = false; |
44 _is_bound = false; |
44 _is_bound = false; |
45 _arg_slot = -1; |
45 _arg_slot = -1; |
46 _arg_type = T_VOID; |
46 _arg_type = T_VOID; |
47 _conversion = -1; |
47 _conversion = -1; |
48 _last_invoke = Bytecodes::_nop; //arbitrary non-garbage |
48 _last_invoke = Bytecodes::_nop; //arbitrary non-garbage |
49 |
49 |
50 if (sun_dyn_DirectMethodHandle::is_instance(mh())) { |
50 if (java_lang_invoke_DirectMethodHandle::is_instance(mh())) { |
51 set_last_method(mh(), THREAD); |
51 set_last_method(mh(), THREAD); |
52 return; |
52 return; |
53 } |
53 } |
54 if (sun_dyn_AdapterMethodHandle::is_instance(mh())) { |
54 if (java_lang_invoke_AdapterMethodHandle::is_instance(mh())) { |
55 _conversion = AdapterMethodHandle_conversion(); |
55 _conversion = AdapterMethodHandle_conversion(); |
56 assert(_conversion != -1, "bad conv value"); |
56 assert(_conversion != -1, "bad conv value"); |
57 assert(sun_dyn_BoundMethodHandle::is_instance(mh()), "also BMH"); |
57 assert(java_lang_invoke_BoundMethodHandle::is_instance(mh()), "also BMH"); |
58 } |
58 } |
59 if (sun_dyn_BoundMethodHandle::is_instance(mh())) { |
59 if (java_lang_invoke_BoundMethodHandle::is_instance(mh())) { |
60 if (!is_adapter()) // keep AMH and BMH separate in this model |
60 if (!is_adapter()) // keep AMH and BMH separate in this model |
61 _is_bound = true; |
61 _is_bound = true; |
62 _arg_slot = BoundMethodHandle_vmargslot(); |
62 _arg_slot = BoundMethodHandle_vmargslot(); |
63 oop target = MethodHandle_vmtarget_oop(); |
63 oop target = MethodHandle_vmtarget_oop(); |
64 if (!is_bound() || java_dyn_MethodHandle::is_instance(target)) { |
64 if (!is_bound() || java_lang_invoke_MethodHandle::is_instance(target)) { |
65 _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); |
65 _arg_type = compute_bound_arg_type(target, NULL, _arg_slot, CHECK); |
66 } else if (target != NULL && target->is_method()) { |
66 } else if (target != NULL && target->is_method()) { |
67 methodOop m = (methodOop) target; |
67 methodOop m = (methodOop) target; |
68 _arg_type = compute_bound_arg_type(NULL, m, _arg_slot, CHECK); |
68 _arg_type = compute_bound_arg_type(NULL, m, _arg_slot, CHECK); |
69 set_last_method(mh(), CHECK); |
69 set_last_method(mh(), CHECK); |
100 BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { |
100 BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int arg_slot, TRAPS) { |
101 // There is no direct indication of whether the argument is primitive or not. |
101 // There is no direct indication of whether the argument is primitive or not. |
102 // It is implied by the _vmentry code, and by the MethodType of the target. |
102 // It is implied by the _vmentry code, and by the MethodType of the target. |
103 BasicType arg_type = T_VOID; |
103 BasicType arg_type = T_VOID; |
104 if (target != NULL) { |
104 if (target != NULL) { |
105 oop mtype = java_dyn_MethodHandle::type(target); |
105 oop mtype = java_lang_invoke_MethodHandle::type(target); |
106 int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot); |
106 int arg_num = MethodHandles::argument_slot_to_argnum(mtype, arg_slot); |
107 if (arg_num >= 0) { |
107 if (arg_num >= 0) { |
108 oop ptype = java_dyn_MethodType::ptype(mtype, arg_num); |
108 oop ptype = java_lang_invoke_MethodType::ptype(mtype, arg_num); |
109 arg_type = java_lang_Class::as_BasicType(ptype); |
109 arg_type = java_lang_Class::as_BasicType(ptype); |
110 } |
110 } |
111 } else if (m != NULL) { |
111 } else if (m != NULL) { |
112 // figure out the argument type from the slot |
112 // figure out the argument type from the slot |
113 // FIXME: make this explicit in the MH |
113 // FIXME: make this explicit in the MH |
202 if (chain().is_adapter()) { |
202 if (chain().is_adapter()) { |
203 int conv_op = chain().adapter_conversion_op(); |
203 int conv_op = chain().adapter_conversion_op(); |
204 int arg_slot = chain().adapter_arg_slot(); |
204 int arg_slot = chain().adapter_arg_slot(); |
205 SlotState* arg_state = slot_state(arg_slot); |
205 SlotState* arg_state = slot_state(arg_slot); |
206 if (arg_state == NULL |
206 if (arg_state == NULL |
207 && conv_op > sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) { |
207 && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) { |
208 lose("bad argument index", CHECK_(empty)); |
208 lose("bad argument index", CHECK_(empty)); |
209 } |
209 } |
210 |
210 |
211 // perform the adapter action |
211 // perform the adapter action |
212 switch (chain().adapter_conversion_op()) { |
212 switch (chain().adapter_conversion_op()) { |
213 case sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY: |
213 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: |
214 // No changes to arguments; pass the bits through. |
214 // No changes to arguments; pass the bits through. |
215 break; |
215 break; |
216 |
216 |
217 case sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW: { |
217 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: { |
218 // To keep the verifier happy, emit bitwise ("raw") conversions as needed. |
218 // To keep the verifier happy, emit bitwise ("raw") conversions as needed. |
219 // See MethodHandles::same_basic_type_for_arguments for allowed conversions. |
219 // See MethodHandles::same_basic_type_for_arguments for allowed conversions. |
220 Handle incoming_mtype(THREAD, chain().method_type_oop()); |
220 Handle incoming_mtype(THREAD, chain().method_type_oop()); |
221 oop outgoing_mh_oop = chain().vmtarget_oop(); |
221 oop outgoing_mh_oop = chain().vmtarget_oop(); |
222 if (!java_dyn_MethodHandle::is_instance(outgoing_mh_oop)) |
222 if (!java_lang_invoke_MethodHandle::is_instance(outgoing_mh_oop)) |
223 lose("outgoing target not a MethodHandle", CHECK_(empty)); |
223 lose("outgoing target not a MethodHandle", CHECK_(empty)); |
224 Handle outgoing_mtype(THREAD, java_dyn_MethodHandle::type(outgoing_mh_oop)); |
224 Handle outgoing_mtype(THREAD, java_lang_invoke_MethodHandle::type(outgoing_mh_oop)); |
225 outgoing_mh_oop = NULL; // GC safety |
225 outgoing_mh_oop = NULL; // GC safety |
226 |
226 |
227 int nptypes = java_dyn_MethodType::ptype_count(outgoing_mtype()); |
227 int nptypes = java_lang_invoke_MethodType::ptype_count(outgoing_mtype()); |
228 if (nptypes != java_dyn_MethodType::ptype_count(incoming_mtype())) |
228 if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype())) |
229 lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); |
229 lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); |
230 |
230 |
231 for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { |
231 for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { |
232 SlotState* arg_state = slot_state(slot); |
232 SlotState* arg_state = slot_state(slot); |
233 if (arg_state->_type == T_VOID) continue; |
233 if (arg_state->_type == T_VOID) continue; |
234 ArgToken arg = _outgoing.at(slot)._arg; |
234 ArgToken arg = _outgoing.at(slot)._arg; |
235 |
235 |
236 klassOop in_klass = NULL; |
236 klassOop in_klass = NULL; |
237 klassOop out_klass = NULL; |
237 klassOop out_klass = NULL; |
238 BasicType inpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(incoming_mtype(), i), &in_klass); |
238 BasicType inpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &in_klass); |
239 BasicType outpbt = java_lang_Class::as_BasicType(java_dyn_MethodType::ptype(outgoing_mtype(), i), &out_klass); |
239 BasicType outpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &out_klass); |
240 assert(inpbt == arg.basic_type(), "sanity"); |
240 assert(inpbt == arg.basic_type(), "sanity"); |
241 |
241 |
242 if (inpbt != outpbt) { |
242 if (inpbt != outpbt) { |
243 vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(inpbt, outpbt); |
243 vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(inpbt, outpbt); |
244 if (iid == vmIntrinsics::_none) { |
244 if (iid == vmIntrinsics::_none) { |
278 assert(arg.index() == new_arg.index(), "should be the same index"); |
278 assert(arg.index() == new_arg.index(), "should be the same index"); |
279 debug_only(dest_klass = (klassOop)badOop); |
279 debug_only(dest_klass = (klassOop)badOop); |
280 break; |
280 break; |
281 } |
281 } |
282 |
282 |
283 case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM: { |
283 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: { |
284 // i2l, etc., on the Nth outgoing argument in place |
284 // i2l, etc., on the Nth outgoing argument in place |
285 BasicType src = chain().adapter_conversion_src_type(), |
285 BasicType src = chain().adapter_conversion_src_type(), |
286 dest = chain().adapter_conversion_dest_type(); |
286 dest = chain().adapter_conversion_dest_type(); |
287 Bytecodes::Code bc = conversion_code(src, dest); |
287 Bytecodes::Code bc = conversion_code(src, dest); |
288 ArgToken arg = arg_state->_arg; |
288 ArgToken arg = arg_state->_arg; |
303 } |
303 } |
304 change_argument(src, arg_slot, dest, arg); |
304 change_argument(src, arg_slot, dest, arg); |
305 break; |
305 break; |
306 } |
306 } |
307 |
307 |
308 case sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM: { |
308 case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: { |
309 // checkcast to wrapper type & call intValue, etc. |
309 // checkcast to wrapper type & call intValue, etc. |
310 BasicType dest = chain().adapter_conversion_dest_type(); |
310 BasicType dest = chain().adapter_conversion_dest_type(); |
311 ArgToken arg = arg_state->_arg; |
311 ArgToken arg = arg_state->_arg; |
312 arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), |
312 arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), |
313 Bytecodes::_checkcast, arg, CHECK_(empty)); |
313 Bytecodes::_checkcast, arg, CHECK_(empty)); |
321 arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); |
321 arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); |
322 change_argument(T_OBJECT, arg_slot, dest, arg); |
322 change_argument(T_OBJECT, arg_slot, dest, arg); |
323 break; |
323 break; |
324 } |
324 } |
325 |
325 |
326 case sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF: { |
326 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: { |
327 // call wrapper type.valueOf |
327 // call wrapper type.valueOf |
328 BasicType src = chain().adapter_conversion_src_type(); |
328 BasicType src = chain().adapter_conversion_src_type(); |
329 ArgToken arg = arg_state->_arg; |
329 ArgToken arg = arg_state->_arg; |
330 vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); |
330 vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); |
331 if (boxer == vmIntrinsics::_none) { |
331 if (boxer == vmIntrinsics::_none) { |
337 arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); |
337 arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); |
338 change_argument(src, arg_slot, T_OBJECT, arg); |
338 change_argument(src, arg_slot, T_OBJECT, arg); |
339 break; |
339 break; |
340 } |
340 } |
341 |
341 |
342 case sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS: { |
342 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { |
343 int dest_arg_slot = chain().adapter_conversion_vminfo(); |
343 int dest_arg_slot = chain().adapter_conversion_vminfo(); |
344 if (!slot_has_argument(dest_arg_slot)) { |
344 if (!slot_has_argument(dest_arg_slot)) { |
345 lose("bad swap index", CHECK_(empty)); |
345 lose("bad swap index", CHECK_(empty)); |
346 } |
346 } |
347 // a simple swap between two arguments |
347 // a simple swap between two arguments |
404 _outgoing.remove_at(arg_slot); |
404 _outgoing.remove_at(arg_slot); |
405 } |
405 } |
406 break; |
406 break; |
407 } |
407 } |
408 |
408 |
409 case sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC |
409 case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC |
410 lose("unimplemented", CHECK_(empty)); |
410 lose("unimplemented", CHECK_(empty)); |
411 break; |
411 break; |
412 } |
412 } |
413 |
413 |
414 case sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS: { |
414 case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: { |
415 klassOop array_klass_oop = NULL; |
415 klassOop array_klass_oop = NULL; |
416 BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), |
416 BasicType array_type = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), |
417 &array_klass_oop); |
417 &array_klass_oop); |
418 assert(array_type == T_OBJECT, ""); |
418 assert(array_type == T_OBJECT, ""); |
419 assert(Klass::cast(array_klass_oop)->oop_is_array(), ""); |
419 assert(Klass::cast(array_klass_oop)->oop_is_array(), ""); |
530 // ----------------------------------------------------------------------------- |
530 // ----------------------------------------------------------------------------- |
531 // MethodHandleWalker::walk_incoming_state |
531 // MethodHandleWalker::walk_incoming_state |
532 // |
532 // |
533 void MethodHandleWalker::walk_incoming_state(TRAPS) { |
533 void MethodHandleWalker::walk_incoming_state(TRAPS) { |
534 Handle mtype(THREAD, chain().method_type_oop()); |
534 Handle mtype(THREAD, chain().method_type_oop()); |
535 int nptypes = java_dyn_MethodType::ptype_count(mtype()); |
535 int nptypes = java_lang_invoke_MethodType::ptype_count(mtype()); |
536 _outgoing_argc = nptypes; |
536 _outgoing_argc = nptypes; |
537 int argp = nptypes - 1; |
537 int argp = nptypes - 1; |
538 if (argp >= 0) { |
538 if (argp >= 0) { |
539 _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize |
539 _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize |
540 } |
540 } |
541 for (int i = 0; i < nptypes; i++) { |
541 for (int i = 0; i < nptypes; i++) { |
542 klassOop arg_type_klass = NULL; |
542 klassOop arg_type_klass = NULL; |
543 BasicType arg_type = java_lang_Class::as_BasicType( |
543 BasicType arg_type = java_lang_Class::as_BasicType( |
544 java_dyn_MethodType::ptype(mtype(), i), &arg_type_klass); |
544 java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass); |
545 int index = new_local_index(arg_type); |
545 int index = new_local_index(arg_type); |
546 ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); |
546 ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); |
547 debug_only(arg_type_klass = (klassOop) NULL); |
547 debug_only(arg_type_klass = (klassOop) NULL); |
548 _outgoing.at_put(argp, make_state(arg_type, arg)); |
548 _outgoing.at_put(argp, make_state(arg_type, arg)); |
549 if (type2size[arg_type] == 2) { |
549 if (type2size[arg_type] == 2) { |
628 _signature_index = cpool_symbol_put(_callee->signature()); |
628 _signature_index = cpool_symbol_put(_callee->signature()); |
629 |
629 |
630 // Get return type klass. |
630 // Get return type klass. |
631 Handle first_mtype(THREAD, chain().method_type_oop()); |
631 Handle first_mtype(THREAD, chain().method_type_oop()); |
632 // _rklass is NULL for primitives. |
632 // _rklass is NULL for primitives. |
633 _rtype = java_lang_Class::as_BasicType(java_dyn_MethodType::rtype(first_mtype()), &_rklass); |
633 _rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(first_mtype()), &_rklass); |
634 if (_rtype == T_ARRAY) _rtype = T_OBJECT; |
634 if (_rtype == T_ARRAY) _rtype = T_OBJECT; |
635 |
635 |
636 int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. |
636 int params = _callee->size_of_parameters(); // Incoming arguments plus receiver. |
637 _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static? |
637 _num_params = for_invokedynamic() ? params - 1 : params; // XXX Check if callee is static? |
638 } |
638 } |