Mercurial > hg > truffle
comparison src/share/vm/prims/methodHandleWalk.cpp @ 3740:5ac411b3b8fc
7047961: JSR 292 MethodHandleWalk swap args doesn't handle T_LONG and T_DOUBLE properly
Reviewed-by: kvn, jrose
author | never |
---|---|
date | Thu, 26 May 2011 14:44:41 -0700 |
parents | a80577f854f9 |
children | 96c891ebe56a cba7b5c2d53f |
comparison
equal
deleted
inserted
replaced
3738:c7c81f18c834 | 3740:5ac411b3b8fc |
---|---|
139 } | 139 } |
140 | 140 |
141 | 141 |
142 void MethodHandleChain::lose(const char* msg, TRAPS) { | 142 void MethodHandleChain::lose(const char* msg, TRAPS) { |
143 _lose_message = msg; | 143 _lose_message = msg; |
144 #ifdef ASSERT | |
145 if (Verbose) { | |
146 tty->print_cr(INTPTR_FORMAT " lose: %s", _method_handle(), msg); | |
147 print(); | |
148 } | |
149 #endif | |
144 if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { | 150 if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { |
145 // throw a preallocated exception | 151 // throw a preallocated exception |
146 THROW_OOP(Universe::virtual_machine_error_instance()); | 152 THROW_OOP(Universe::virtual_machine_error_instance()); |
147 } | 153 } |
148 THROW_MSG(vmSymbols::java_lang_InternalError(), msg); | 154 THROW_MSG(vmSymbols::java_lang_InternalError(), msg); |
149 } | 155 } |
156 | |
157 | |
158 #ifdef ASSERT | |
159 static const char* adapter_ops[] = { | |
160 "retype_only" , | |
161 "retype_raw" , | |
162 "check_cast" , | |
163 "prim_to_prim" , | |
164 "ref_to_prim" , | |
165 "prim_to_ref" , | |
166 "swap_args" , | |
167 "rot_args" , | |
168 "dup_args" , | |
169 "drop_args" , | |
170 "collect_args" , | |
171 "spread_args" , | |
172 "fold_args" | |
173 }; | |
174 | |
175 static const char* adapter_op_to_string(int op) { | |
176 if (op >= 0 && op < (int)ARRAY_SIZE(adapter_ops)) | |
177 return adapter_ops[op]; | |
178 return "unknown_op"; | |
179 } | |
180 | |
181 | |
182 void MethodHandleChain::print(Handle mh) { | |
183 EXCEPTION_MARK; | |
184 MethodHandleChain mhc(mh, THREAD); | |
185 if (HAS_PENDING_EXCEPTION) { | |
186 oop ex = THREAD->pending_exception(); | |
187 CLEAR_PENDING_EXCEPTION; | |
188 ex->print(); | |
189 return; | |
190 } | |
191 mhc.print(); | |
192 } | |
193 | |
194 | |
195 void MethodHandleChain::print() { | |
196 EXCEPTION_MARK; | |
197 print_impl(THREAD); | |
198 if (HAS_PENDING_EXCEPTION) { | |
199 oop ex = THREAD->pending_exception(); | |
200 CLEAR_PENDING_EXCEPTION; | |
201 ex->print(); | |
202 } | |
203 } | |
204 | |
205 void MethodHandleChain::print_impl(TRAPS) { | |
206 ResourceMark rm; | |
207 | |
208 MethodHandleChain chain(_root, CHECK); | |
209 for (;;) { | |
210 tty->print(INTPTR_FORMAT ": ", chain.method_handle()()); | |
211 if (chain.is_bound()) { | |
212 tty->print("bound: arg_type %s arg_slot %d", | |
213 type2name(chain.bound_arg_type()), | |
214 chain.bound_arg_slot()); | |
215 oop o = chain.bound_arg_oop(); | |
216 if (o != NULL) { | |
217 if (o->is_instance()) { | |
218 tty->print(" instance %s", o->klass()->klass_part()->internal_name()); | |
219 } else { | |
220 o->print(); | |
221 } | |
222 } | |
223 } else if (chain.is_adapter()) { | |
224 tty->print("adapter: arg_slot %d conversion op %s", | |
225 chain.adapter_arg_slot(), | |
226 adapter_op_to_string(chain.adapter_conversion_op())); | |
227 switch (chain.adapter_conversion_op()) { | |
228 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY: | |
229 case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: | |
230 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: | |
231 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: | |
232 case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: | |
233 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: | |
234 break; | |
235 | |
236 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: | |
237 case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { | |
238 int dest_arg_slot = chain.adapter_conversion_vminfo(); | |
239 tty->print(" dest_arg_slot %d type %s", dest_arg_slot, type2name(chain.adapter_conversion_src_type())); | |
240 break; | |
241 } | |
242 | |
243 case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS: | |
244 case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: { | |
245 int dup_slots = chain.adapter_conversion_stack_pushes(); | |
246 tty->print(" pushes %d", dup_slots); | |
247 break; | |
248 } | |
249 | |
250 case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS: | |
251 case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: { | |
252 int coll_slots = chain.MethodHandle_vmslots(); | |
253 tty->print(" coll_slots %d", coll_slots); | |
254 break; | |
255 } | |
256 | |
257 case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: { | |
258 // Check the required length. | |
259 int spread_slots = 1 + chain.adapter_conversion_stack_pushes(); | |
260 tty->print(" spread_slots %d", spread_slots); | |
261 break; | |
262 } | |
263 | |
264 default: | |
265 tty->print_cr("bad adapter conversion"); | |
266 break; | |
267 } | |
268 } else { | |
269 // DMH | |
270 tty->print("direct: "); | |
271 chain.last_method_oop()->print_short_name(tty); | |
272 } | |
273 | |
274 tty->print(" ("); | |
275 objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(chain.method_type_oop()); | |
276 for (int i = ptypes->length() - 1; i >= 0; i--) { | |
277 BasicType t = java_lang_Class::as_BasicType(ptypes->obj_at(i)); | |
278 if (t == T_ARRAY) t = T_OBJECT; | |
279 tty->print("%c", type2char(t)); | |
280 if (t == T_LONG || t == T_DOUBLE) tty->print("_"); | |
281 } | |
282 tty->print(")"); | |
283 BasicType rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(chain.method_type_oop())); | |
284 if (rtype == T_ARRAY) rtype = T_OBJECT; | |
285 tty->print("%c", type2char(rtype)); | |
286 tty->cr(); | |
287 if (!chain.is_last()) { | |
288 chain.next(CHECK); | |
289 } else { | |
290 break; | |
291 } | |
292 } | |
293 } | |
294 #endif | |
150 | 295 |
151 | 296 |
152 // ----------------------------------------------------------------------------- | 297 // ----------------------------------------------------------------------------- |
153 // MethodHandleWalker | 298 // MethodHandleWalker |
154 | 299 |
203 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); | 348 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); |
204 | 349 |
205 if (chain().is_adapter()) { | 350 if (chain().is_adapter()) { |
206 int conv_op = chain().adapter_conversion_op(); | 351 int conv_op = chain().adapter_conversion_op(); |
207 int arg_slot = chain().adapter_arg_slot(); | 352 int arg_slot = chain().adapter_arg_slot(); |
208 SlotState* arg_state = slot_state(arg_slot); | 353 |
209 if (arg_state == NULL | 354 // Check that the arg_slot is valid. In most cases it must be |
210 && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) { | 355 // within range of the current arguments but there are some |
211 lose("bad argument index", CHECK_(empty)); | 356 // exceptions. Those are sanity checked in their implemention |
357 // below. | |
358 if ((arg_slot < 0 || arg_slot >= _outgoing.length()) && | |
359 conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW && | |
360 conv_op != java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS && | |
361 conv_op != java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS) { | |
362 lose(err_msg("bad argument index %d", arg_slot), CHECK_(empty)); | |
212 } | 363 } |
213 | 364 |
214 bool retain_original_args = false; // used by fold/collect logic | 365 bool retain_original_args = false; // used by fold/collect logic |
215 | 366 |
216 // perform the adapter action | 367 // perform the adapter action |
235 if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype())) | 386 if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype())) |
236 lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); | 387 lose("incoming and outgoing parameter count do not agree", CHECK_(empty)); |
237 | 388 |
238 // Argument types. | 389 // Argument types. |
239 for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { | 390 for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { |
240 SlotState* arg_state = slot_state(slot); | 391 if (arg_type(slot) == T_VOID) continue; |
241 if (arg_state->_type == T_VOID) continue; | |
242 | 392 |
243 klassOop src_klass = NULL; | 393 klassOop src_klass = NULL; |
244 klassOop dst_klass = NULL; | 394 klassOop dst_klass = NULL; |
245 BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &src_klass); | 395 BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &src_klass); |
246 BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &dst_klass); | 396 BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &dst_klass); |
260 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: { | 410 case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: { |
261 // checkcast the Nth outgoing argument in place | 411 // checkcast the Nth outgoing argument in place |
262 klassOop dest_klass = NULL; | 412 klassOop dest_klass = NULL; |
263 BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); | 413 BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); |
264 assert(dest == T_OBJECT, ""); | 414 assert(dest == T_OBJECT, ""); |
265 assert(dest == arg_state->_type, ""); | 415 ArgToken arg = _outgoing.at(arg_slot); |
266 ArgToken arg = arg_state->_arg; | 416 assert(dest == arg.basic_type(), ""); |
267 ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); | 417 ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); |
268 assert(!arg.has_index() || arg.index() == new_arg.index(), "should be the same index"); | 418 assert(!arg.has_index() || arg.index() == new_arg.index(), "should be the same index"); |
269 debug_only(dest_klass = (klassOop)badOop); | 419 debug_only(dest_klass = (klassOop)badOop); |
270 break; | 420 break; |
271 } | 421 } |
272 | 422 |
273 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: { | 423 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: { |
274 // i2l, etc., on the Nth outgoing argument in place | 424 // i2l, etc., on the Nth outgoing argument in place |
275 BasicType src = chain().adapter_conversion_src_type(), | 425 BasicType src = chain().adapter_conversion_src_type(), |
276 dest = chain().adapter_conversion_dest_type(); | 426 dest = chain().adapter_conversion_dest_type(); |
427 ArgToken arg = _outgoing.at(arg_slot); | |
277 Bytecodes::Code bc = conversion_code(src, dest); | 428 Bytecodes::Code bc = conversion_code(src, dest); |
278 ArgToken arg = arg_state->_arg; | |
279 if (bc == Bytecodes::_nop) { | 429 if (bc == Bytecodes::_nop) { |
280 break; | 430 break; |
281 } else if (bc != Bytecodes::_illegal) { | 431 } else if (bc != Bytecodes::_illegal) { |
282 arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); | 432 arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); |
283 } else if (is_subword_type(dest)) { | 433 } else if (is_subword_type(dest)) { |
287 bc = conversion_code(T_INT, dest); | 437 bc = conversion_code(T_INT, dest); |
288 arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); | 438 arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty)); |
289 } | 439 } |
290 } | 440 } |
291 if (bc == Bytecodes::_illegal) { | 441 if (bc == Bytecodes::_illegal) { |
292 lose("bad primitive conversion", CHECK_(empty)); | 442 lose(err_msg("bad primitive conversion for %s -> %s", type2name(src), type2name(dest)), CHECK_(empty)); |
293 } | 443 } |
294 change_argument(src, arg_slot, dest, arg); | 444 change_argument(src, arg_slot, dest, arg); |
295 break; | 445 break; |
296 } | 446 } |
297 | 447 |
298 case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: { | 448 case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: { |
299 // checkcast to wrapper type & call intValue, etc. | 449 // checkcast to wrapper type & call intValue, etc. |
300 BasicType dest = chain().adapter_conversion_dest_type(); | 450 BasicType dest = chain().adapter_conversion_dest_type(); |
301 ArgToken arg = arg_state->_arg; | 451 ArgToken arg = _outgoing.at(arg_slot); |
302 arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), | 452 arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), |
303 Bytecodes::_checkcast, arg, CHECK_(empty)); | 453 Bytecodes::_checkcast, arg, CHECK_(empty)); |
304 vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); | 454 vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); |
305 if (unboxer == vmIntrinsics::_none) { | 455 if (unboxer == vmIntrinsics::_none) { |
306 lose("no unboxing method", CHECK_(empty)); | 456 lose("no unboxing method", CHECK_(empty)); |
314 } | 464 } |
315 | 465 |
316 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: { | 466 case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: { |
317 // call wrapper type.valueOf | 467 // call wrapper type.valueOf |
318 BasicType src = chain().adapter_conversion_src_type(); | 468 BasicType src = chain().adapter_conversion_src_type(); |
319 ArgToken arg = arg_state->_arg; | |
320 vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); | 469 vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); |
321 if (boxer == vmIntrinsics::_none) { | 470 if (boxer == vmIntrinsics::_none) { |
322 lose("no boxing method", CHECK_(empty)); | 471 lose("no boxing method", CHECK_(empty)); |
323 } | 472 } |
473 ArgToken arg = _outgoing.at(arg_slot); | |
324 ArgToken arglist[2]; | 474 ArgToken arglist[2]; |
325 arglist[0] = arg; // outgoing value | 475 arglist[0] = arg; // outgoing value |
326 arglist[1] = ArgToken(); // sentinel | 476 arglist[1] = ArgToken(); // sentinel |
327 arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); | 477 arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); |
328 change_argument(src, arg_slot, T_OBJECT, arg); | 478 change_argument(src, arg_slot, T_OBJECT, arg); |
329 break; | 479 break; |
330 } | 480 } |
331 | 481 |
332 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { | 482 case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { |
333 int dest_arg_slot = chain().adapter_conversion_vminfo(); | 483 int dest_arg_slot = chain().adapter_conversion_vminfo(); |
334 if (!slot_has_argument(dest_arg_slot)) { | 484 if (!has_argument(dest_arg_slot)) { |
335 lose("bad swap index", CHECK_(empty)); | 485 lose("bad swap index", CHECK_(empty)); |
336 } | 486 } |
337 // a simple swap between two arguments | 487 // a simple swap between two arguments |
338 SlotState* dest_arg_state = slot_state(dest_arg_slot); | 488 if (arg_slot > dest_arg_slot) { |
339 SlotState temp = (*dest_arg_state); | 489 int tmp = arg_slot; |
340 (*dest_arg_state) = (*arg_state); | 490 arg_slot = dest_arg_slot; |
341 (*arg_state) = temp; | 491 dest_arg_slot = tmp; |
492 } | |
493 ArgToken a1 = _outgoing.at(arg_slot); | |
494 ArgToken a2 = _outgoing.at(dest_arg_slot); | |
495 change_argument(a2.basic_type(), dest_arg_slot, a1); | |
496 change_argument(a1.basic_type(), arg_slot, a2); | |
342 break; | 497 break; |
343 } | 498 } |
344 | 499 |
345 case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { | 500 case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { |
346 int dest_arg_slot = chain().adapter_conversion_vminfo(); | 501 int dest_arg_slot = chain().adapter_conversion_vminfo(); |
347 if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { | 502 if (!has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { |
348 lose("bad rotate index", CHECK_(empty)); | 503 lose("bad rotate index", CHECK_(empty)); |
349 } | 504 } |
350 SlotState* dest_arg_state = slot_state(dest_arg_slot); | |
351 // Rotate the source argument (plus following N slots) into the | 505 // Rotate the source argument (plus following N slots) into the |
352 // position occupied by the dest argument (plus following N slots). | 506 // position occupied by the dest argument (plus following N slots). |
353 int rotate_count = type2size[dest_arg_state->_type]; | 507 int rotate_count = type2size[chain().adapter_conversion_src_type()]; |
354 // (no other rotate counts are currently supported) | 508 // (no other rotate counts are currently supported) |
355 if (arg_slot < dest_arg_slot) { | 509 if (arg_slot < dest_arg_slot) { |
356 for (int i = 0; i < rotate_count; i++) { | 510 for (int i = 0; i < rotate_count; i++) { |
357 SlotState temp = _outgoing.at(arg_slot); | 511 ArgToken temp = _outgoing.at(arg_slot); |
358 _outgoing.remove_at(arg_slot); | 512 _outgoing.remove_at(arg_slot); |
359 _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); | 513 _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); |
360 } | 514 } |
361 } else { // arg_slot > dest_arg_slot | 515 } else { // arg_slot > dest_arg_slot |
362 for (int i = 0; i < rotate_count; i++) { | 516 for (int i = 0; i < rotate_count; i++) { |
363 SlotState temp = _outgoing.at(arg_slot + rotate_count - 1); | 517 ArgToken temp = _outgoing.at(arg_slot + rotate_count - 1); |
364 _outgoing.remove_at(arg_slot + rotate_count - 1); | 518 _outgoing.remove_at(arg_slot + rotate_count - 1); |
365 _outgoing.insert_before(dest_arg_slot, temp); | 519 _outgoing.insert_before(dest_arg_slot, temp); |
366 } | 520 } |
367 } | 521 } |
522 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); | |
368 break; | 523 break; |
369 } | 524 } |
370 | 525 |
371 case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS: { | 526 case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS: { |
372 int dup_slots = chain().adapter_conversion_stack_pushes(); | 527 int dup_slots = chain().adapter_conversion_stack_pushes(); |
373 if (dup_slots <= 0) { | 528 if (dup_slots <= 0) { |
374 lose("bad dup count", CHECK_(empty)); | 529 lose("bad dup count", CHECK_(empty)); |
375 } | 530 } |
376 for (int i = 0; i < dup_slots; i++) { | 531 for (int i = 0; i < dup_slots; i++) { |
377 SlotState* dup = slot_state(arg_slot + 2*i); | 532 ArgToken dup = _outgoing.at(arg_slot + 2*i); |
378 if (dup == NULL) break; // safety net | 533 if (dup.basic_type() != T_VOID) _outgoing_argc += 1; |
379 if (dup->_type != T_VOID) _outgoing_argc += 1; | 534 _outgoing.insert_before(i, dup); |
380 _outgoing.insert_before(i, (*dup)); | 535 } |
381 } | 536 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); |
382 break; | 537 break; |
383 } | 538 } |
384 | 539 |
385 case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: { | 540 case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: { |
386 int drop_slots = -chain().adapter_conversion_stack_pushes(); | 541 int drop_slots = -chain().adapter_conversion_stack_pushes(); |
387 if (drop_slots <= 0) { | 542 if (drop_slots <= 0) { |
388 lose("bad drop count", CHECK_(empty)); | 543 lose("bad drop count", CHECK_(empty)); |
389 } | 544 } |
390 for (int i = 0; i < drop_slots; i++) { | 545 for (int i = 0; i < drop_slots; i++) { |
391 SlotState* drop = slot_state(arg_slot); | 546 ArgToken drop = _outgoing.at(arg_slot); |
392 if (drop == NULL) break; // safety net | 547 if (drop.basic_type() != T_VOID) _outgoing_argc -= 1; |
393 if (drop->_type != T_VOID) _outgoing_argc -= 1; | |
394 _outgoing.remove_at(arg_slot); | 548 _outgoing.remove_at(arg_slot); |
395 } | 549 } |
550 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); | |
396 break; | 551 break; |
397 } | 552 } |
398 | 553 |
399 case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS: | 554 case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS: |
400 retain_original_args = true; // and fall through: | 555 retain_original_args = true; // and fall through: |
413 arglist[0] = make_oop_constant(recursive_mh(), CHECK_(empty)); | 568 arglist[0] = make_oop_constant(recursive_mh(), CHECK_(empty)); |
414 if (arg_slot < 0 || coll_slots < 0 || arg_slot + coll_slots > _outgoing.length()) { | 569 if (arg_slot < 0 || coll_slots < 0 || arg_slot + coll_slots > _outgoing.length()) { |
415 lose("bad fold/collect arg slot", CHECK_(empty)); | 570 lose("bad fold/collect arg slot", CHECK_(empty)); |
416 } | 571 } |
417 for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) { | 572 for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) { |
418 SlotState* arg_state = slot_state(slot); | 573 ArgToken arg_state = _outgoing.at(slot); |
419 BasicType arg_type = arg_state->_type; | 574 BasicType arg_type = arg_state.basic_type(); |
420 if (arg_type == T_VOID) continue; | 575 if (arg_type == T_VOID) continue; |
421 ArgToken arg = _outgoing.at(slot)._arg; | 576 ArgToken arg = _outgoing.at(slot); |
422 if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); } | 577 if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); } |
423 arglist[1+i] = arg; | 578 arglist[1+i] = arg; |
424 if (!retain_original_args) | 579 if (!retain_original_args) |
425 change_argument(arg_type, slot, T_VOID, ArgToken(tt_void)); | 580 change_argument(arg_type, slot, T_VOID, ArgToken(tt_void)); |
426 i++; | 581 i++; |
464 &element_klass_oop); | 619 &element_klass_oop); |
465 KlassHandle element_klass(THREAD, element_klass_oop); | 620 KlassHandle element_klass(THREAD, element_klass_oop); |
466 debug_only(element_klass_oop = (klassOop)badOop); | 621 debug_only(element_klass_oop = (klassOop)badOop); |
467 | 622 |
468 // Fetch the argument, which we will cast to the required array type. | 623 // Fetch the argument, which we will cast to the required array type. |
469 assert(arg_state->_type == T_OBJECT, ""); | 624 ArgToken arg = _outgoing.at(arg_slot); |
470 ArgToken array_arg = arg_state->_arg; | 625 assert(arg.basic_type() == T_OBJECT, ""); |
626 ArgToken array_arg = arg; | |
471 array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty)); | 627 array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty)); |
472 change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void)); | 628 change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void)); |
473 | 629 |
474 // Check the required length. | 630 // Check the required length. |
475 int spread_slots = 1 + chain().adapter_conversion_stack_pushes(); | 631 int spread_slots = 1 + chain().adapter_conversion_stack_pushes(); |
532 if (arg_type == T_OBJECT) { | 688 if (arg_type == T_OBJECT) { |
533 arg = make_oop_constant(arg_oop, CHECK_(empty)); | 689 arg = make_oop_constant(arg_oop, CHECK_(empty)); |
534 } else { | 690 } else { |
535 jvalue arg_value; | 691 jvalue arg_value; |
536 BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); | 692 BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); |
537 if (bt == arg_type) { | 693 if (bt == arg_type || (bt == T_INT && is_subword_type(arg_type))) { |
538 arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); | 694 arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); |
539 } else { | 695 } else { |
540 lose("bad bound value", CHECK_(empty)); | 696 lose(err_msg("bad bound value: arg_type %s boxing %s", type2name(arg_type), type2name(bt)), CHECK_(empty)); |
541 } | 697 } |
542 } | 698 } |
543 DEBUG_ONLY(arg_oop = badOop); | 699 DEBUG_ONLY(arg_oop = badOop); |
544 change_argument(T_VOID, arg_slot, arg_type, arg); | 700 change_argument(T_VOID, arg_slot, arg_type, arg); |
545 } | 701 } |
555 // finish the sequence with a tail-call to the ultimate target | 711 // finish the sequence with a tail-call to the ultimate target |
556 // parameters are passed in logical order (recv 1st), not slot order | 712 // parameters are passed in logical order (recv 1st), not slot order |
557 ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1); | 713 ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1); |
558 int ap = 0; | 714 int ap = 0; |
559 for (int i = _outgoing.length() - 1; i >= 0; i--) { | 715 for (int i = _outgoing.length() - 1; i >= 0; i--) { |
560 SlotState* arg_state = slot_state(i); | 716 ArgToken arg_state = _outgoing.at(i); |
561 if (arg_state->_type == T_VOID) continue; | 717 if (arg_state.basic_type() == T_VOID) continue; |
562 arglist[ap++] = _outgoing.at(i)._arg; | 718 arglist[ap++] = _outgoing.at(i); |
563 } | 719 } |
564 assert(ap == _outgoing_argc, ""); | 720 assert(ap == _outgoing_argc, ""); |
565 arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts | 721 arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts |
566 return make_invoke(chain().last_method_oop(), | 722 return make_invoke(chain().last_method_oop(), |
567 vmIntrinsics::_none, | 723 vmIntrinsics::_none, |
577 Handle mtype(THREAD, chain().method_type_oop()); | 733 Handle mtype(THREAD, chain().method_type_oop()); |
578 int nptypes = java_lang_invoke_MethodType::ptype_count(mtype()); | 734 int nptypes = java_lang_invoke_MethodType::ptype_count(mtype()); |
579 _outgoing_argc = nptypes; | 735 _outgoing_argc = nptypes; |
580 int argp = nptypes - 1; | 736 int argp = nptypes - 1; |
581 if (argp >= 0) { | 737 if (argp >= 0) { |
582 _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize | 738 _outgoing.at_grow(argp, ArgToken(tt_void)); // presize |
583 } | 739 } |
584 for (int i = 0; i < nptypes; i++) { | 740 for (int i = 0; i < nptypes; i++) { |
585 klassOop arg_type_klass = NULL; | 741 klassOop arg_type_klass = NULL; |
586 BasicType arg_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass); | 742 BasicType arg_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass); |
587 int index = new_local_index(arg_type); | 743 int index = new_local_index(arg_type); |
588 ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); | 744 ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); |
589 DEBUG_ONLY(arg_type_klass = (klassOop) NULL); | 745 DEBUG_ONLY(arg_type_klass = (klassOop) NULL); |
590 _outgoing.at_put(argp, make_state(arg_type, arg)); | 746 _outgoing.at_put(argp, arg); |
591 if (type2size[arg_type] == 2) { | 747 if (type2size[arg_type] == 2) { |
592 // add the extra slot, so we can model the JVM stack | 748 // add the extra slot, so we can model the JVM stack |
593 _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void))); | 749 _outgoing.insert_before(argp+1, ArgToken(tt_void)); |
594 } | 750 } |
595 --argp; | 751 --argp; |
596 } | 752 } |
597 // call make_parameter at the end of the list for the return type | 753 // call make_parameter at the end of the list for the return type |
598 klassOop ret_type_klass = NULL; | 754 klassOop ret_type_klass = NULL; |
599 BasicType ret_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass); | 755 BasicType ret_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass); |
600 ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); | 756 ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); |
601 // ignore ret; client can catch it if needed | 757 // ignore ret; client can catch it if needed |
602 } | 758 |
759 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); | |
760 | |
761 verify_args_and_signature(CHECK); | |
762 } | |
763 | |
764 | |
765 #ifdef ASSERT | |
766 void MethodHandleWalker::verify_args_and_signature(TRAPS) { | |
767 int index = _outgoing.length() - 1; | |
768 objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(chain().method_type_oop()); | |
769 for (int i = 0, limit = ptypes->length(); i < limit; i++) { | |
770 BasicType t = java_lang_Class::as_BasicType(ptypes->obj_at(i)); | |
771 if (t == T_ARRAY) t = T_OBJECT; | |
772 if (t == T_LONG || t == T_DOUBLE) { | |
773 assert(T_VOID == _outgoing.at(index).basic_type(), "types must match"); | |
774 index--; | |
775 } | |
776 assert(t == _outgoing.at(index).basic_type(), "types must match"); | |
777 index--; | |
778 } | |
779 } | |
780 #endif | |
603 | 781 |
604 | 782 |
605 // ----------------------------------------------------------------------------- | 783 // ----------------------------------------------------------------------------- |
606 // MethodHandleWalker::change_argument | 784 // MethodHandleWalker::change_argument |
607 // | 785 // |
608 // This is messy because some kinds of arguments are paired with | 786 // This is messy because some kinds of arguments are paired with |
609 // companion slots containing an empty value. | 787 // companion slots containing an empty value. |
610 void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type, | 788 void MethodHandleWalker::change_argument(BasicType old_type, int slot, const ArgToken& new_arg) { |
611 const ArgToken& new_arg) { | 789 BasicType new_type = new_arg.basic_type(); |
612 int old_size = type2size[old_type]; | 790 int old_size = type2size[old_type]; |
613 int new_size = type2size[new_type]; | 791 int new_size = type2size[new_type]; |
614 if (old_size == new_size) { | 792 if (old_size == new_size) { |
615 // simple case first | 793 // simple case first |
616 _outgoing.at_put(slot, make_state(new_type, new_arg)); | 794 _outgoing.at_put(slot, new_arg); |
617 } else if (old_size > new_size) { | 795 } else if (old_size > new_size) { |
618 for (int i = old_size - 1; i >= new_size; i--) { | 796 for (int i = old_size - 1; i >= new_size; i--) { |
619 assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), ""); | 797 assert((i != 0) == (_outgoing.at(slot + i).basic_type() == T_VOID), ""); |
620 _outgoing.remove_at(slot + i); | 798 _outgoing.remove_at(slot + i); |
621 } | 799 } |
622 if (new_size > 0) | 800 if (new_size > 0) |
623 _outgoing.at_put(slot, make_state(new_type, new_arg)); | 801 _outgoing.at_put(slot, new_arg); |
624 else | 802 else |
625 _outgoing_argc -= 1; // deleted a real argument | 803 _outgoing_argc -= 1; // deleted a real argument |
626 } else { | 804 } else { |
627 for (int i = old_size; i < new_size; i++) { | 805 for (int i = old_size; i < new_size; i++) { |
628 _outgoing.insert_before(slot + i, make_state(T_VOID, ArgToken(tt_void))); | 806 _outgoing.insert_before(slot + i, ArgToken(tt_void)); |
629 } | 807 } |
630 _outgoing.at_put(slot, make_state(new_type, new_arg)); | 808 _outgoing.at_put(slot, new_arg); |
631 if (old_size == 0) | 809 if (old_size == 0) |
632 _outgoing_argc += 1; // inserted a real argument | 810 _outgoing_argc += 1; // inserted a real argument |
633 } | 811 } |
812 assert(_outgoing_argc == argument_count_slow(), "empty slots under control"); | |
634 } | 813 } |
635 | 814 |
636 | 815 |
637 #ifdef ASSERT | 816 #ifdef ASSERT |
638 int MethodHandleWalker::argument_count_slow() { | 817 int MethodHandleWalker::argument_count_slow() { |
639 int args_seen = 0; | 818 int args_seen = 0; |
640 for (int i = _outgoing.length() - 1; i >= 0; i--) { | 819 for (int i = _outgoing.length() - 1; i >= 0; i--) { |
641 if (_outgoing.at(i)._type != T_VOID) { | 820 if (_outgoing.at(i).basic_type() != T_VOID) { |
642 ++args_seen; | 821 ++args_seen; |
822 if (_outgoing.at(i).basic_type() == T_LONG || | |
823 _outgoing.at(i).basic_type() == T_DOUBLE) { | |
824 assert(_outgoing.at(i + 1).basic_type() == T_VOID, "should only follow two word"); | |
825 } | |
826 } else { | |
827 assert(_outgoing.at(i - 1).basic_type() == T_LONG || | |
828 _outgoing.at(i - 1).basic_type() == T_DOUBLE, "should only follow two word"); | |
643 } | 829 } |
644 } | 830 } |
645 return args_seen; | 831 return args_seen; |
646 } | 832 } |
647 #endif | 833 #endif |
661 lose("no raw conversion method", CHECK); | 847 lose("no raw conversion method", CHECK); |
662 } | 848 } |
663 ArgToken arglist[2]; | 849 ArgToken arglist[2]; |
664 if (!for_return) { | 850 if (!for_return) { |
665 // argument type conversion | 851 // argument type conversion |
666 ArgToken arg = _outgoing.at(slot)._arg; | 852 ArgToken arg = _outgoing.at(slot); |
667 assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity"); | 853 assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity"); |
668 arglist[0] = arg; // outgoing 'this' | 854 arglist[0] = arg; // outgoing 'this' |
669 arglist[1] = ArgToken(); // sentinel | 855 arglist[1] = ArgToken(); // sentinel |
670 arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); | 856 arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); |
671 change_argument(src, slot, dst, arg); | 857 change_argument(src, slot, dst, arg); |
681 } | 867 } |
682 } else if (src == T_OBJECT && is_java_primitive(dst)) { | 868 } else if (src == T_OBJECT && is_java_primitive(dst)) { |
683 // ref-to-prim: discard ref, push zero | 869 // ref-to-prim: discard ref, push zero |
684 lose("requested ref-to-prim conversion not expected", CHECK); | 870 lose("requested ref-to-prim conversion not expected", CHECK); |
685 } else { | 871 } else { |
686 lose("requested raw conversion not allowed", CHECK); | 872 lose(err_msg("requested raw conversion not allowed: %s -> %s", type2name(src), type2name(dst)), CHECK); |
687 } | 873 } |
688 } | 874 } |
689 } | 875 } |
690 | 876 |
691 | 877 |
961 } | 1147 } |
962 | 1148 |
963 | 1149 |
964 void MethodHandleCompiler::emit_load_constant(ArgToken arg) { | 1150 void MethodHandleCompiler::emit_load_constant(ArgToken arg) { |
965 BasicType bt = arg.basic_type(); | 1151 BasicType bt = arg.basic_type(); |
1152 if (is_subword_type(bt)) bt = T_INT; | |
966 switch (bt) { | 1153 switch (bt) { |
967 case T_INT: { | 1154 case T_INT: { |
968 jint value = arg.get_jint(); | 1155 jint value = arg.get_jint(); |
969 if (-1 <= value && value <= 5) | 1156 if (-1 <= value && value <= 5) |
970 emit_bc(Bytecodes::cast(Bytecodes::_iconst_0 + value)); | 1157 emit_bc(Bytecodes::cast(Bytecodes::_iconst_0 + value)); |
1064 if (index == -1) | 1251 if (index == -1) |
1065 index = new_local_index(type); | 1252 index = new_local_index(type); |
1066 emit_store(srctype, index); | 1253 emit_store(srctype, index); |
1067 break; | 1254 break; |
1068 | 1255 |
1256 case Bytecodes::_nop: | |
1257 // nothing to do | |
1258 return src; | |
1259 | |
1069 default: | 1260 default: |
1070 if (op == Bytecodes::_illegal) | 1261 if (op == Bytecodes::_illegal) |
1071 lose("no such primitive conversion", THREAD); | 1262 lose(err_msg("no such primitive conversion: %s -> %s", type2name(src.basic_type()), type2name(type)), THREAD); |
1072 else | 1263 else |
1073 lose("bad primitive conversion op", THREAD); | 1264 lose(err_msg("bad primitive conversion op: %s", Bytecodes::name(op)), THREAD); |
1074 return make_prim_constant(type, &zero_jvalue, THREAD); | 1265 return make_prim_constant(type, &zero_jvalue, THREAD); |
1075 } | 1266 } |
1076 | 1267 |
1077 return make_parameter(type, tk, index, THREAD); | 1268 return make_parameter(type, tk, index, THREAD); |
1078 } | 1269 } |
1298 bt = T_INT; | 1489 bt = T_INT; |
1299 } | 1490 } |
1300 | 1491 |
1301 // for (int i = 1, imax = _constants.length(); i < imax; i++) { | 1492 // for (int i = 1, imax = _constants.length(); i < imax; i++) { |
1302 // ConstantValue* con = _constants.at(i); | 1493 // ConstantValue* con = _constants.at(i); |
1303 // if (con != NULL && con->is_primitive() && con->_type == bt) { | 1494 // if (con != NULL && con->is_primitive() && con.basic_type() == bt) { |
1304 // bool match = false; | 1495 // bool match = false; |
1305 // switch (type2size[bt]) { | 1496 // switch (type2size[bt]) { |
1306 // case 1: if (pcon->_value.i == con->i) match = true; break; | 1497 // case 1: if (pcon->_value.i == con->i) match = true; break; |
1307 // case 2: if (pcon->_value.j == con->j) match = true; break; | 1498 // case 2: if (pcon->_value.j == con->j) match = true; break; |
1308 // } | 1499 // } |
1449 const char* strbuf() { | 1640 const char* strbuf() { |
1450 const char* s = _strbuf.as_string(); | 1641 const char* s = _strbuf.as_string(); |
1451 _strbuf.reset(); | 1642 _strbuf.reset(); |
1452 return s; | 1643 return s; |
1453 } | 1644 } |
1454 ArgToken token(const char* str) { | 1645 ArgToken token(const char* str, BasicType type) { |
1455 return ArgToken(str); | 1646 return ArgToken(str, type); |
1456 } | 1647 } |
1457 const char* string(ArgToken token) { | 1648 const char* string(ArgToken token) { |
1458 return token.str(); | 1649 return token.str(); |
1459 } | 1650 } |
1460 void start_params() { | 1651 void start_params() { |
1472 kname = Klass::cast(tk)->external_name(); | 1663 kname = Klass::cast(tk)->external_name(); |
1473 s->print("%s", (kname != NULL) ? kname : type2name(type)); | 1664 s->print("%s", (kname != NULL) ? kname : type2name(type)); |
1474 } | 1665 } |
1475 ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) { | 1666 ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) { |
1476 const char* value = strbuf(); | 1667 const char* value = strbuf(); |
1477 if (!_verbose) return token(value); | 1668 if (!_verbose) return token(value, type); |
1478 // make an explicit binding for each separate value | 1669 // make an explicit binding for each separate value |
1479 _strbuf.print("%s%d", temp_name, ++_temp_num); | 1670 _strbuf.print("%s%d", temp_name, ++_temp_num); |
1480 const char* temp = strbuf(); | 1671 const char* temp = strbuf(); |
1481 _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value); | 1672 _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value); |
1482 return token(temp); | 1673 return token(temp, type); |
1483 } | 1674 } |
1484 | 1675 |
1485 public: | 1676 public: |
1486 MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) | 1677 MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS) |
1487 : MethodHandleWalker(root, false, THREAD), | 1678 : MethodHandleWalker(root, false, THREAD), |
1493 start_params(); | 1684 start_params(); |
1494 } | 1685 } |
1495 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { | 1686 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { |
1496 if (argnum < 0) { | 1687 if (argnum < 0) { |
1497 end_params(); | 1688 end_params(); |
1498 return token("return"); | 1689 return token("return", type); |
1499 } | 1690 } |
1500 if ((_param_state & 1) == 0) { | 1691 if ((_param_state & 1) == 0) { |
1501 _param_state |= 1; | 1692 _param_state |= 1; |
1502 _out->print(_verbose ? "\n " : ""); | 1693 _out->print(_verbose ? "\n " : ""); |
1503 } else { | 1694 } else { |
1508 // generate an argument name | 1699 // generate an argument name |
1509 _strbuf.print("a%d", argnum); | 1700 _strbuf.print("a%d", argnum); |
1510 const char* arg = strbuf(); | 1701 const char* arg = strbuf(); |
1511 put_type_name(type, tk, _out); | 1702 put_type_name(type, tk, _out); |
1512 _out->print(" %s", arg); | 1703 _out->print(" %s", arg); |
1513 return token(arg); | 1704 return token(arg, type); |
1514 } | 1705 } |
1515 virtual ArgToken make_oop_constant(oop con, TRAPS) { | 1706 virtual ArgToken make_oop_constant(oop con, TRAPS) { |
1516 if (con == NULL) | 1707 if (con == NULL) |
1517 _strbuf.print("null"); | 1708 _strbuf.print("null"); |
1518 else | 1709 else |
1595 MethodHandlePrinter printer(root, verbose, out, CHECK); | 1786 MethodHandlePrinter printer(root, verbose, out, CHECK); |
1596 printer.walk(CHECK); | 1787 printer.walk(CHECK); |
1597 out->print("\n"); | 1788 out->print("\n"); |
1598 } | 1789 } |
1599 static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) { | 1790 static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) { |
1600 EXCEPTION_MARK; | 1791 Thread* THREAD = Thread::current(); |
1601 ResourceMark rm; | 1792 ResourceMark rm; |
1602 MethodHandlePrinter printer(root, verbose, out, THREAD); | 1793 MethodHandlePrinter printer(root, verbose, out, THREAD); |
1603 if (!HAS_PENDING_EXCEPTION) | 1794 if (!HAS_PENDING_EXCEPTION) |
1604 printer.walk(THREAD); | 1795 printer.walk(THREAD); |
1605 if (HAS_PENDING_EXCEPTION) { | 1796 if (HAS_PENDING_EXCEPTION) { |