Mercurial > hg > graal-compiler
comparison src/cpu/x86/vm/methodHandles_x86.cpp @ 1039:987e948ebbc8
6815692: method handle code needs some cleanup (post-6655638)
Summary: correctly raise exceptions, support safe bitwise "raw" conversions, fix bugs revealed by VerifyMethodHandles, remove dead code, improve debugging support
Reviewed-by: never, twisti
author | jrose |
---|---|
date | Sat, 17 Oct 2009 19:51:05 -0700 |
parents | df6caf649ff7 |
children | 85f13cdfbc1d |
comparison
equal
deleted
inserted
replaced
1038:71fdc5052e49 | 1039:987e948ebbc8 |
---|---|
269 | 269 |
270 #ifndef PRODUCT | 270 #ifndef PRODUCT |
271 void trace_method_handle_stub(const char* adaptername, | 271 void trace_method_handle_stub(const char* adaptername, |
272 oopDesc* mh, | 272 oopDesc* mh, |
273 intptr_t* entry_sp, | 273 intptr_t* entry_sp, |
274 intptr_t* saved_sp) { | 274 intptr_t* saved_sp, |
275 intptr_t* saved_bp) { | |
275 // called as a leaf from native code: do not block the JVM! | 276 // called as a leaf from native code: do not block the JVM! |
276 printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp); | 277 intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; |
278 intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; | |
279 printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n", | |
280 adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); | |
281 if (last_sp != saved_sp) | |
282 printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp); | |
277 } | 283 } |
278 #endif //PRODUCT | 284 #endif //PRODUCT |
279 | 285 |
280 // Generate an "entry" field for a method handle. | 286 // Generate an "entry" field for a method handle. |
281 // This determines how the method handle will respond to calls. | 287 // This determines how the method handle will respond to calls. |
291 Register rcx_recv = rcx; | 297 Register rcx_recv = rcx; |
292 Register rax_argslot = rax; | 298 Register rax_argslot = rax; |
293 Register rbx_temp = rbx; | 299 Register rbx_temp = rbx; |
294 Register rdx_temp = rdx; | 300 Register rdx_temp = rdx; |
295 | 301 |
302 // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) | |
303 // and gen_c2i_adapter (from compiled calls): | |
304 Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); | |
305 | |
296 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); | 306 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); |
297 | 307 |
298 // some handy addresses | 308 // some handy addresses |
299 Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); | 309 Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); |
300 | 310 |
312 int tag_offset = -1; | 322 int tag_offset = -1; |
313 if (TaggedStackInterpreter) { | 323 if (TaggedStackInterpreter) { |
314 tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); | 324 tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); |
315 assert(tag_offset = wordSize, "stack grows as expected"); | 325 assert(tag_offset = wordSize, "stack grows as expected"); |
316 } | 326 } |
327 | |
328 const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); | |
317 | 329 |
318 if (have_entry(ek)) { | 330 if (have_entry(ek)) { |
319 __ nop(); // empty stubs make SG sick | 331 __ nop(); // empty stubs make SG sick |
320 return; | 332 return; |
321 } | 333 } |
326 #ifndef PRODUCT | 338 #ifndef PRODUCT |
327 if (TraceMethodHandles) { | 339 if (TraceMethodHandles) { |
328 __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi); | 340 __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi); |
329 __ lea(rax, Address(rsp, wordSize*6)); // entry_sp | 341 __ lea(rax, Address(rsp, wordSize*6)); // entry_sp |
330 // arguments: | 342 // arguments: |
343 __ push(rbp); // interpreter frame pointer | |
331 __ push(rsi); // saved_sp | 344 __ push(rsi); // saved_sp |
332 __ push(rax); // entry_sp | 345 __ push(rax); // entry_sp |
333 __ push(rcx); // mh | 346 __ push(rcx); // mh |
334 __ push(rcx); | 347 __ push(rcx); |
335 __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek)); | 348 __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek)); |
336 __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4); | 349 __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5); |
337 __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax); | 350 __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax); |
338 } | 351 } |
339 #endif //PRODUCT | 352 #endif //PRODUCT |
340 | 353 |
341 switch ((int) ek) { | 354 switch ((int) ek) { |
342 case _check_mtype: | 355 case _raise_exception: |
343 { | 356 { |
344 // this stub is special, because it requires a live mtype argument | 357 // Not a real MH entry, but rather shared code for raising an exception. |
345 Register rax_mtype = rax; | 358 // Extra local arguments are pushed on stack, as required type at TOS+8, |
346 | 359 // failing object (or NULL) at TOS+4, failing bytecode type at TOS. |
347 // emit WrongMethodType path first, to enable jccb back-branch | 360 // Beyond those local arguments are the PC, of course. |
348 Label wrong_method_type; | 361 Register rdx_code = rdx_temp; |
349 __ bind(wrong_method_type); | 362 Register rcx_fail = rcx_recv; |
350 __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type])); | 363 Register rax_want = rax_argslot; |
351 __ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); | 364 Register rdi_pc = rdi; |
352 __ hlt(); | 365 __ pop(rdx_code); // TOS+0 |
353 | 366 __ pop(rcx_fail); // TOS+4 |
354 interp_entry = __ pc(); | 367 __ pop(rax_want); // TOS+8 |
355 __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type); | 368 __ pop(rdi_pc); // caller PC |
356 // now rax_mtype is dead; subsequent stubs will use it as a temp | 369 |
357 | 370 __ mov(rsp, rsi); // cut the stack back to where the caller started |
358 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 371 |
359 } | 372 // Repush the arguments as if coming from the interpreter. |
360 break; | 373 if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT)); |
361 | 374 __ push(rdx_code); |
362 case _wrong_method_type: | 375 if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); |
363 { | 376 __ push(rcx_fail); |
364 // this stub is special, because it requires a live mtype argument | 377 if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT)); |
365 Register rax_mtype = rax; | 378 __ push(rax_want); |
366 | 379 |
367 interp_entry = __ pc(); | 380 Register rbx_method = rbx_temp; |
368 __ push(rax_mtype); // required mtype | 381 Label no_method; |
369 __ push(rcx_recv); // random mh (1st stacked argument) | 382 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method |
383 __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); | |
384 __ testptr(rbx_method, rbx_method); | |
385 __ jcc(Assembler::zero, no_method); | |
386 int jobject_oop_offset = 0; | |
387 __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject | |
388 __ testptr(rbx_method, rbx_method); | |
389 __ jcc(Assembler::zero, no_method); | |
390 __ verify_oop(rbx_method); | |
391 __ push(rdi_pc); // and restore caller PC | |
392 __ jmp(rbx_method_fie); | |
393 | |
394 // If we get here, the Java runtime did not do its job of creating the exception. | |
395 // Do something that is at least causes a valid throw from the interpreter. | |
396 __ bind(no_method); | |
397 __ pop(rax_want); | |
398 if (TaggedStackInterpreter) __ pop(rcx_fail); | |
399 __ pop(rcx_fail); | |
400 __ push(rax_want); | |
401 __ push(rcx_fail); | |
370 __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); | 402 __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); |
371 } | 403 } |
372 break; | 404 break; |
373 | 405 |
374 case _invokestatic_mh: | 406 case _invokestatic_mh: |
440 // get receiver klass | 472 // get receiver klass |
441 Register rax_klass = rax_argslot; | 473 Register rax_klass = rax_argslot; |
442 __ load_klass(rax_klass, rcx_recv); | 474 __ load_klass(rax_klass, rcx_recv); |
443 __ verify_oop(rax_klass); | 475 __ verify_oop(rax_klass); |
444 | 476 |
445 Register rcx_temp = rcx_recv; | 477 Register rdi_temp = rdi; |
446 Register rbx_method = rbx_index; | 478 Register rbx_method = rbx_index; |
447 | 479 |
448 // get interface klass | 480 // get interface klass |
449 Label no_such_interface; | 481 Label no_such_interface; |
450 __ verify_oop(rdx_intf); | 482 __ verify_oop(rdx_intf); |
451 __ lookup_interface_method(rax_klass, rdx_intf, | 483 __ lookup_interface_method(rax_klass, rdx_intf, |
452 // note: next two args must be the same: | 484 // note: next two args must be the same: |
453 rbx_index, rbx_method, | 485 rbx_index, rbx_method, |
454 rcx_temp, | 486 rdi_temp, |
455 no_such_interface); | 487 no_such_interface); |
456 | 488 |
457 __ verify_oop(rbx_method); | 489 __ verify_oop(rbx_method); |
458 __ jmp(rbx_method_fie); | 490 __ jmp(rbx_method_fie); |
459 __ hlt(); | 491 __ hlt(); |
460 | 492 |
461 __ bind(no_such_interface); | 493 __ bind(no_such_interface); |
462 // Throw an exception. | 494 // Throw an exception. |
463 // For historical reasons, it will be IncompatibleClassChangeError. | 495 // For historical reasons, it will be IncompatibleClassChangeError. |
464 __ should_not_reach_here(); // %%% FIXME NYI | 496 __ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface |
497 __ push(rcx_recv); // bad receiver | |
498 __ push((int)Bytecodes::_invokeinterface); // who is complaining? | |
499 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | |
465 } | 500 } |
466 break; | 501 break; |
467 | 502 |
468 case _bound_ref_mh: | 503 case _bound_ref_mh: |
469 case _bound_int_mh: | 504 case _bound_int_mh: |
522 } | 557 } |
523 } | 558 } |
524 break; | 559 break; |
525 | 560 |
526 case _adapter_retype_only: | 561 case _adapter_retype_only: |
562 case _adapter_retype_raw: | |
527 // immediately jump to the next MH layer: | 563 // immediately jump to the next MH layer: |
528 __ movptr(rcx_recv, rcx_mh_vmtarget); | 564 __ movptr(rcx_recv, rcx_mh_vmtarget); |
529 __ verify_oop(rcx_recv); | 565 __ verify_oop(rcx_recv); |
530 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 566 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); |
531 // This is OK when all parameter types widen. | 567 // This is OK when all parameter types widen. |
543 | 579 |
544 // What class are we casting to? | 580 // What class are we casting to? |
545 __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object! | 581 __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object! |
546 __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); | 582 __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); |
547 | 583 |
548 // get the new MH: | |
549 __ movptr(rcx_recv, rcx_mh_vmtarget); | |
550 // (now we are done with the old MH) | |
551 | |
552 Label done; | 584 Label done; |
553 __ movptr(rdx_temp, vmarg); | 585 __ movptr(rdx_temp, vmarg); |
554 __ testl(rdx_temp, rdx_temp); | 586 __ testl(rdx_temp, rdx_temp); |
555 __ jcc(Assembler::zero, done); // no cast if null | 587 __ jcc(Assembler::zero, done); // no cast if null |
556 __ load_klass(rdx_temp, rdx_temp); | 588 __ load_klass(rdx_temp, rdx_temp); |
557 | 589 |
558 // live at this point: | 590 // live at this point: |
559 // - rbx_klass: klass required by the target method | 591 // - rbx_klass: klass required by the target method |
560 // - rdx_temp: argument klass to test | 592 // - rdx_temp: argument klass to test |
561 // - rcx_recv: method handle to invoke (after cast succeeds) | 593 // - rcx_recv: adapter method handle |
562 __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done); | 594 __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done); |
563 | 595 |
564 // If we get here, the type check failed! | 596 // If we get here, the type check failed! |
565 // Call the wrong_method_type stub, passing the failing argument type in rax. | 597 // Call the wrong_method_type stub, passing the failing argument type in rax. |
566 Register rax_mtype = rax_argslot; | 598 Register rax_mtype = rax_argslot; |
567 __ push(rbx_klass); // missed klass (required type) | 599 __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field |
568 __ push(rdx_temp); // bad actual type (1st stacked argument) | 600 __ movptr(rdx_temp, vmarg); |
569 __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); | 601 |
602 __ pushptr(rcx_amh_argument); // required class | |
603 __ push(rdx_temp); // bad object | |
604 __ push((int)Bytecodes::_checkcast); // who is complaining? | |
605 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | |
570 | 606 |
571 __ bind(done); | 607 __ bind(done); |
608 // get the new MH: | |
609 __ movptr(rcx_recv, rcx_mh_vmtarget); | |
572 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 610 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); |
573 } | 611 } |
574 break; | 612 break; |
575 | 613 |
576 case _adapter_prim_to_prim: | 614 case _adapter_prim_to_prim: |
1105 __ movptr(rcx_recv, rcx_mh_vmtarget); | 1143 __ movptr(rcx_recv, rcx_mh_vmtarget); |
1106 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 1144 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); |
1107 | 1145 |
1108 __ bind(bad_array_klass); | 1146 __ bind(bad_array_klass); |
1109 UNPUSH_RSI_RDI; | 1147 UNPUSH_RSI_RDI; |
1110 __ stop("bad array klass NYI"); | 1148 __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type |
1149 __ pushptr(vmarg); // bad array | |
1150 __ push((int)Bytecodes::_aaload); // who is complaining? | |
1151 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | |
1111 | 1152 |
1112 __ bind(bad_array_length); | 1153 __ bind(bad_array_length); |
1113 UNPUSH_RSI_RDI; | 1154 UNPUSH_RSI_RDI; |
1114 __ stop("bad array length NYI"); | 1155 __ push(rcx_recv); // AMH requiring a certain length |
1156 __ pushptr(vmarg); // bad array | |
1157 __ push((int)Bytecodes::_arraylength); // who is complaining? | |
1158 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | |
1115 | 1159 |
1116 #undef UNPUSH_RSI_RDI | 1160 #undef UNPUSH_RSI_RDI |
1117 } | 1161 } |
1118 break; | 1162 break; |
1119 | 1163 |