Mercurial > hg > graal-jvmci-8
comparison src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @ 2321:1b4e6a5d98e0
7012914: JSR 292 MethodHandlesTest C1: frame::verify_return_pc(return_address) failed: must be a return pc
Reviewed-by: never, bdelsart
author | twisti |
---|---|
date | Mon, 28 Feb 2011 06:07:12 -0800 |
parents | 635b068a7224 |
children | 3d42f82cd811 |
comparison
equal
deleted
inserted
replaced
2320:41d4973cf100 | 2321:1b4e6a5d98e0 |
---|---|
146 static int reg_save_size_in_words; | 146 static int reg_save_size_in_words; |
147 static int frame_size_in_bytes = -1; | 147 static int frame_size_in_bytes = -1; |
148 | 148 |
149 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { | 149 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { |
150 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), | 150 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), |
151 " mismatch in calculation"); | 151 "mismatch in calculation"); |
152 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); | 152 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); |
153 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); | 153 int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); |
154 OopMap* oop_map = new OopMap(frame_size_in_slots, 0); | 154 OopMap* oop_map = new OopMap(frame_size_in_slots, 0); |
155 | 155 |
156 int i; | 156 int i; |
174 return oop_map; | 174 return oop_map; |
175 } | 175 } |
176 | 176 |
177 static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) { | 177 static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) { |
178 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), | 178 assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), |
179 " mismatch in calculation"); | 179 "mismatch in calculation"); |
180 __ save_frame_c1(frame_size_in_bytes); | 180 __ save_frame_c1(frame_size_in_bytes); |
181 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); | |
182 | 181 |
183 // Record volatile registers as callee-save values in an OopMap so their save locations will be | 182 // Record volatile registers as callee-save values in an OopMap so their save locations will be |
184 // propagated to the caller frame's RegisterMap during StackFrameStream construction (needed for | 183 // propagated to the caller frame's RegisterMap during StackFrameStream construction (needed for |
185 // deoptimization; see compiledVFrame::create_stack_value). The caller's I, L and O registers | 184 // deoptimization; see compiledVFrame::create_stack_value). The caller's I, L and O registers |
186 // are saved in register windows - I's and L's in the caller's frame and O's in the stub frame | 185 // are saved in register windows - I's and L's in the caller's frame and O's in the stub frame |
365 | 364 |
366 // stub code & info for the different stubs | 365 // stub code & info for the different stubs |
367 switch (id) { | 366 switch (id) { |
368 case forward_exception_id: | 367 case forward_exception_id: |
369 { | 368 { |
370 // we're handling an exception in the context of a compiled | 369 oop_maps = generate_handle_exception(id, sasm); |
371 // frame. The registers have been saved in the standard | |
372 // places. Perform an exception lookup in the caller and | |
373 // dispatch to the handler if found. Otherwise unwind and | |
374 // dispatch to the callers exception handler. | |
375 | |
376 oop_maps = new OopMapSet(); | |
377 OopMap* oop_map = generate_oop_map(sasm, true); | |
378 | |
379 // transfer the pending exception to the exception_oop | |
380 __ ld_ptr(G2_thread, in_bytes(JavaThread::pending_exception_offset()), Oexception); | |
381 __ ld_ptr(Oexception, 0, G0); | |
382 __ st_ptr(G0, G2_thread, in_bytes(JavaThread::pending_exception_offset())); | |
383 __ add(I7, frame::pc_return_offset, Oissuing_pc); | |
384 | |
385 generate_handle_exception(sasm, oop_maps, oop_map); | |
386 __ should_not_reach_here(); | |
387 } | 370 } |
388 break; | 371 break; |
389 | 372 |
390 case new_instance_id: | 373 case new_instance_id: |
391 case fast_new_instance_id: | 374 case fast_new_instance_id: |
669 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); | 652 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); |
670 } | 653 } |
671 break; | 654 break; |
672 | 655 |
673 case handle_exception_id: | 656 case handle_exception_id: |
674 { | 657 { __ set_info("handle_exception", dont_gc_arguments); |
675 __ set_info("handle_exception", dont_gc_arguments); | 658 oop_maps = generate_handle_exception(id, sasm); |
676 // make a frame and preserve the caller's caller-save registers | 659 } |
677 | 660 break; |
678 oop_maps = new OopMapSet(); | 661 |
679 OopMap* oop_map = save_live_registers(sasm); | 662 case handle_exception_from_callee_id: |
680 __ mov(Oexception->after_save(), Oexception); | 663 { __ set_info("handle_exception_from_callee", dont_gc_arguments); |
681 __ mov(Oissuing_pc->after_save(), Oissuing_pc); | 664 oop_maps = generate_handle_exception(id, sasm); |
682 generate_handle_exception(sasm, oop_maps, oop_map); | |
683 } | 665 } |
684 break; | 666 break; |
685 | 667 |
686 case unwind_exception_id: | 668 case unwind_exception_id: |
687 { | 669 { |
694 | 676 |
695 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), | 677 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), |
696 G2_thread, Oissuing_pc->after_save()); | 678 G2_thread, Oissuing_pc->after_save()); |
697 __ verify_not_null_oop(Oexception->after_save()); | 679 __ verify_not_null_oop(Oexception->after_save()); |
698 | 680 |
699 // Restore SP from L7 if the exception PC is a MethodHandle call site. | 681 // Restore SP from L7 if the exception PC is a method handle call site. |
700 __ mov(O0, G5); // Save the target address. | 682 __ mov(O0, G5); // Save the target address. |
701 __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); | 683 __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); |
702 __ tst(L0); // Condition codes are preserved over the restore. | 684 __ tst(L0); // Condition codes are preserved over the restore. |
703 __ restore(); | 685 __ restore(); |
704 | 686 |
1004 } | 986 } |
1005 return oop_maps; | 987 return oop_maps; |
1006 } | 988 } |
1007 | 989 |
1008 | 990 |
1009 void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_maps, OopMap* oop_map, bool) { | 991 OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler* sasm) { |
1010 Label no_deopt; | 992 __ block_comment("generate_handle_exception"); |
993 | |
994 // Save registers, if required. | |
995 OopMapSet* oop_maps = new OopMapSet(); | |
996 OopMap* oop_map = NULL; | |
997 switch (id) { | |
998 case forward_exception_id: | |
999 // We're handling an exception in the context of a compiled frame. | |
1000 // The registers have been saved in the standard places. Perform | |
1001 // an exception lookup in the caller and dispatch to the handler | |
1002 // if found. Otherwise unwind and dispatch to the callers | |
1003 // exception handler. | |
1004 oop_map = generate_oop_map(sasm, true); | |
1005 | |
1006 // transfer the pending exception to the exception_oop | |
1007 __ ld_ptr(G2_thread, in_bytes(JavaThread::pending_exception_offset()), Oexception); | |
1008 __ ld_ptr(Oexception, 0, G0); | |
1009 __ st_ptr(G0, G2_thread, in_bytes(JavaThread::pending_exception_offset())); | |
1010 __ add(I7, frame::pc_return_offset, Oissuing_pc); | |
1011 break; | |
1012 case handle_exception_id: | |
1013 // At this point all registers MAY be live. | |
1014 oop_map = save_live_registers(sasm); | |
1015 __ mov(Oexception->after_save(), Oexception); | |
1016 __ mov(Oissuing_pc->after_save(), Oissuing_pc); | |
1017 break; | |
1018 case handle_exception_from_callee_id: | |
1019 // At this point all registers except exception oop (Oexception) | |
1020 // and exception pc (Oissuing_pc) are dead. | |
1021 oop_map = new OopMap(frame_size_in_bytes / sizeof(jint), 0); | |
1022 sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); | |
1023 __ save_frame_c1(frame_size_in_bytes); | |
1024 __ mov(Oexception->after_save(), Oexception); | |
1025 __ mov(Oissuing_pc->after_save(), Oissuing_pc); | |
1026 break; | |
1027 default: ShouldNotReachHere(); | |
1028 } | |
1011 | 1029 |
1012 __ verify_not_null_oop(Oexception); | 1030 __ verify_not_null_oop(Oexception); |
1013 | 1031 |
1014 // save the exception and issuing pc in the thread | 1032 // save the exception and issuing pc in the thread |
1015 __ st_ptr(Oexception, G2_thread, in_bytes(JavaThread::exception_oop_offset())); | 1033 __ st_ptr(Oexception, G2_thread, in_bytes(JavaThread::exception_oop_offset())); |
1016 __ st_ptr(Oissuing_pc, G2_thread, in_bytes(JavaThread::exception_pc_offset())); | 1034 __ st_ptr(Oissuing_pc, G2_thread, in_bytes(JavaThread::exception_pc_offset())); |
1017 | 1035 |
1018 // save the real return address and use the throwing pc as the return address to lookup (has bci & oop map) | 1036 // use the throwing pc as the return address to lookup (has bci & oop map) |
1019 __ mov(I7, L0); | |
1020 __ mov(Oissuing_pc, I7); | 1037 __ mov(Oissuing_pc, I7); |
1021 __ sub(I7, frame::pc_return_offset, I7); | 1038 __ sub(I7, frame::pc_return_offset, I7); |
1022 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); | 1039 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); |
1040 oop_maps->add_gc_map(call_offset, oop_map); | |
1023 | 1041 |
1024 // Note: if nmethod has been deoptimized then regardless of | 1042 // Note: if nmethod has been deoptimized then regardless of |
1025 // whether it had a handler or not we will deoptimize | 1043 // whether it had a handler or not we will deoptimize |
1026 // by entering the deopt blob with a pending exception. | 1044 // by entering the deopt blob with a pending exception. |
1027 | 1045 |
1028 #ifdef ASSERT | 1046 // Restore the registers that were saved at the beginning, remove |
1029 Label done; | 1047 // the frame and jump to the exception handler. |
1030 __ tst(O0); | 1048 switch (id) { |
1031 __ br(Assembler::notZero, false, Assembler::pn, done); | 1049 case forward_exception_id: |
1032 __ delayed()->nop(); | 1050 case handle_exception_id: |
1033 __ stop("should have found address"); | 1051 restore_live_registers(sasm); |
1034 __ bind(done); | 1052 __ jmp(O0, 0); |
1035 #endif | 1053 __ delayed()->restore(); |
1036 | 1054 break; |
1037 // restore the registers that were saved at the beginning and jump to the exception handler. | 1055 case handle_exception_from_callee_id: |
1038 restore_live_registers(sasm); | 1056 // Restore SP from L7 if the exception PC is a method handle call site. |
1039 | 1057 __ mov(O0, G5); // Save the target address. |
1040 __ jmp(O0, 0); | 1058 __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); |
1041 __ delayed()->restore(); | 1059 __ tst(L0); // Condition codes are preserved over the restore. |
1042 | 1060 __ restore(); |
1043 oop_maps->add_gc_map(call_offset, oop_map); | 1061 |
1062 __ jmp(G5, 0); // jump to the exception handler | |
1063 __ delayed()->movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP); // Restore SP if required. | |
1064 break; | |
1065 default: ShouldNotReachHere(); | |
1066 } | |
1067 | |
1068 return oop_maps; | |
1044 } | 1069 } |
1045 | 1070 |
1046 | 1071 |
1047 #undef __ | 1072 #undef __ |
1048 | |
1049 #define __ masm-> | |
1050 | 1073 |
1051 const char *Runtime1::pd_name_for_address(address entry) { | 1074 const char *Runtime1::pd_name_for_address(address entry) { |
1052 return "<unknown function>"; | 1075 return "<unknown function>"; |
1053 } | 1076 } |