comparison src/cpu/x86/vm/c1_Runtime1_x86.cpp @ 1429:abc670a709dc

* -XX:TraceC1X=0...5 controls the native c1x tracing * -Dc1x.debug=true turns on the logging proxies and lots of log output on the java side * provide more information about types to the compiler (type hierarchy, etc) * provide exception handler tables to the compiler * add exception handlers to the nmethod * correct implementation of ExceptionObject * exception handling/unwinding entry points * modified versions of handle/unwind exception stubs using standard calling conventions * exception throwing * implicit null pointer exception, implicit div by 0 exception * arraystore/classcast/arrayindex exceptions * checkcast implementation * newarray, anewarray, multinewarray implementation * correct new instance initialization * access to java class mirrors (for ldc) * unresolved methods * class resolving - class patching (asssembly prototype copying)
author Lukas Stadler <lukas.stadler@oracle.com>
date Tue, 31 Aug 2010 22:13:30 -0700
parents 760213a60e8b
children 72cfb36c6bb2
comparison
equal deleted inserted replaced
1428:695451afc619 1429:abc670a709dc
597 597
598 // target: the entry point of the method that creates and posts the exception oop 598 // target: the entry point of the method that creates and posts the exception oop
599 // has_argument: true if the exception needs an argument (passed on stack because registers must be preserved) 599 // has_argument: true if the exception needs an argument (passed on stack because registers must be preserved)
600 600
601 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { 601 OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) {
602 // preserve all registers 602 OopMapSet* oop_maps = new OopMapSet();
603 int num_rt_args = has_argument ? 2 : 1; 603 if (UseC1X) {
604 OopMap* oop_map = save_live_registers(sasm, num_rt_args); 604 // c1x passes the argument in r10
605 605 OopMap* oop_map = save_live_registers(sasm, 1);
606 // now all registers are saved and can be used freely 606
607 // verify that no old value is used accidentally 607 // now all registers are saved and can be used freely
608 __ invalidate_registers(true, true, true, true, true, true); 608 // verify that no old value is used accidentally
609 609 __ invalidate_registers(true, true, true, true, true, true);
610 // registers used by this stub 610
611 const Register temp_reg = rbx; 611 // registers used by this stub
612 612 const Register temp_reg = rbx;
613 // load argument for exception that is passed as an argument into the stub 613
614 if (has_argument) { 614 // load argument for exception that is passed as an argument into the stub
615 #ifdef _LP64 615 if (has_argument) {
616 __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord)); 616 __ movptr(c_rarg1, r10);
617 #else 617 }
618 __ movptr(temp_reg, Address(rbp, 2*BytesPerWord)); 618 int call_offset = __ call_RT(noreg, noreg, target, has_argument ? 1 : 0);
619 __ push(temp_reg); 619
620 #endif // _LP64 620 oop_maps->add_gc_map(call_offset, oop_map);
621 } else {
622 // preserve all registers
623 int num_rt_args = has_argument ? 2 : 1;
624 OopMap* oop_map = save_live_registers(sasm, num_rt_args);
625
626 // now all registers are saved and can be used freely
627 // verify that no old value is used accidentally
628 __ invalidate_registers(true, true, true, true, true, true);
629
630 // registers used by this stub
631 const Register temp_reg = rbx;
632
633 // load argument for exception that is passed as an argument into the stub
634 if (has_argument) {
635 #ifdef _LP64
636 __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord));
637 #else
638 __ movptr(temp_reg, Address(rbp, 2*BytesPerWord));
639 __ push(temp_reg);
640 #endif // _LP64
641 }
642 int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1);
643
644 oop_maps->add_gc_map(call_offset, oop_map);
621 } 645 }
622 int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1);
623
624 OopMapSet* oop_maps = new OopMapSet();
625 oop_maps->add_gc_map(call_offset, oop_map);
626 646
627 __ stop("should not reach here"); 647 __ stop("should not reach here");
628 648
629 return oop_maps; 649 return oop_maps;
630 } 650 }
713 733
714 // return to exception handler 734 // return to exception handler
715 __ leave(); 735 __ leave();
716 __ ret(0); 736 __ ret(0);
717 737
738 }
739
740 void Runtime1::c1x_generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map) {
741 NOT_LP64(fatal("64 bit only"));
742 // incoming parameters
743 const Register exception_oop = j_rarg0;
744 // other registers used in this stub
745 const Register exception_pc = j_rarg1;
746 const Register thread = r15_thread;
747
748 __ block_comment("c1x_generate_handle_exception");
749
750 // verify that rax, contains a valid exception
751 __ verify_not_null_oop(exception_oop);
752
753 #ifdef ASSERT
754 // check that fields in JavaThread for exception oop and issuing pc are
755 // empty before writing to them
756 Label oop_empty;
757 __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t) NULL_WORD);
758 __ jcc(Assembler::equal, oop_empty);
759 __ stop("exception oop already set");
760 __ bind(oop_empty);
761
762 Label pc_empty;
763 __ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0);
764 __ jcc(Assembler::equal, pc_empty);
765 __ stop("exception pc already set");
766 __ bind(pc_empty);
767 #endif
768
769 // save exception oop and issuing pc into JavaThread
770 // (exception handler will load it from here)
771 __ movptr(Address(thread, JavaThread::exception_oop_offset()), exception_oop);
772 __ movptr(exception_pc, Address(rbp, 1*BytesPerWord));
773 __ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc);
774
775 // compute the exception handler.
776 // the exception oop and the throwing pc are read from the fields in JavaThread
777 int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc));
778 oop_maps->add_gc_map(call_offset, oop_map);
779
780 // rax,: handler address
781 // will be the deopt blob if nmethod was deoptimized while we looked up
782 // handler regardless of whether handler existed in the nmethod.
783
784 // only rax, is valid at this time, all other registers have been destroyed by the runtime call
785 __ invalidate_registers(false, true, true, true, true, true);
786
787 #ifdef ASSERT
788 // Do we have an exception handler in the nmethod?
789 Label done;
790 __ testptr(rax, rax);
791 __ jcc(Assembler::notZero, done);
792 __ stop("no handler found");
793 __ bind(done);
794 #endif
795
796 // exception handler found
797 // patch the return address -> the stub will directly return to the exception handler
798 __ movptr(Address(rbp, 1*BytesPerWord), rax);
799
800 // restore registers
801 restore_live_registers(sasm, false);
802
803 // return to exception handler
804 __ leave();
805 __ ret(0);
718 } 806 }
719 807
720 808
721 void Runtime1::generate_unwind_exception(StubAssembler *sasm) { 809 void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
722 // incoming parameters 810 // incoming parameters
923 1011
924 return oop_maps; 1012 return oop_maps;
925 1013
926 } 1014 }
927 1015
1016 JRT_ENTRY(void, c1x_create_null_exception(JavaThread* thread))
1017 thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)());
1018 JRT_END
1019
1020
1021
928 1022
929 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { 1023 OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
930 1024
931 // for better readability 1025 // for better readability
932 const bool must_gc_arguments = true; 1026 const bool must_gc_arguments = true;
1305 generate_handle_exception(sasm, oop_maps, oop_map, save_fpu_registers); 1399 generate_handle_exception(sasm, oop_maps, oop_map, save_fpu_registers);
1306 } 1400 }
1307 break; 1401 break;
1308 1402
1309 case unwind_exception_id: 1403 case unwind_exception_id:
1310 { __ set_info("unwind_exception", dont_gc_arguments); 1404 {
1405 __ set_info("unwind_exception", dont_gc_arguments);
1311 // note: no stubframe since we are about to leave the current 1406 // note: no stubframe since we are about to leave the current
1312 // activation and we are calling a leaf VM function only. 1407 // activation and we are calling a leaf VM function only.
1313 generate_unwind_exception(sasm); 1408 generate_unwind_exception(sasm);
1314 } 1409 }
1315 break; 1410 break;
1733 1828
1734 } 1829 }
1735 break; 1830 break;
1736 #endif // !SERIALGC 1831 #endif // !SERIALGC
1737 1832
1833 case c1x_unwind_exception_call_id:
1834 {
1835 // remove the frame from the stack
1836 __ movptr(rsp, rbp);
1837 __ pop(rbp);
1838 // exception_oop is passed using ordinary java calling conventions
1839 __ movptr(rax, j_rarg0);
1840
1841 Label nonNullExceptionOop;
1842 __ testptr(rax, rax);
1843 __ jcc(Assembler::notZero, nonNullExceptionOop);
1844 {
1845 __ enter();
1846 oop_maps = new OopMapSet();
1847 OopMap* oop_map = save_live_registers(sasm, 0);
1848 int call_offset = __ call_RT(rax, noreg, (address)c1x_create_null_exception, 0);
1849 oop_maps->add_gc_map(call_offset, oop_map);
1850 __ leave();
1851 }
1852 __ bind(nonNullExceptionOop);
1853
1854 __ set_info("unwind_exception", dont_gc_arguments);
1855 // note: no stubframe since we are about to leave the current
1856 // activation and we are calling a leaf VM function only.
1857 generate_unwind_exception(sasm);
1858 __ should_not_reach_here();
1859 }
1860 break;
1861
1862 case c1x_handle_exception_id:
1863 { StubFrame f(sasm, "c1x_handle_exception", dont_gc_arguments);
1864 oop_maps = new OopMapSet();
1865 OopMap* oop_map = save_live_registers(sasm, 1, false);
1866 c1x_generate_handle_exception(sasm, oop_maps, oop_map);
1867 }
1868 break;
1869
1870 case c1x_global_implicit_null_id:
1871 {
1872 __ push(rax);
1873 __ push(rax);
1874 // move saved fp to make space for the inserted return address
1875 __ get_thread(rax);
1876 __ movptr(rax, Address(rax, JavaThread::saved_exception_pc_offset()));
1877 __ movptr(Address(rsp, HeapWordSize), rax);
1878 __ pop(rax);
1879
1880 { StubFrame f(sasm, "c1x_global_implicit_null_id", dont_gc_arguments);
1881 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false);
1882 }
1883 }
1884 break;
1885
1886 case c1x_throw_div0_exception_id:
1887 {
1888 __ push(rax);
1889 __ push(rax);
1890 // move saved fp to make space for the inserted return address
1891 __ get_thread(rax);
1892 __ movptr(rax, Address(rax, JavaThread::saved_exception_pc_offset()));
1893 __ movptr(Address(rsp, HeapWordSize), rax);
1894 __ pop(rax);
1895
1896 { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments);
1897 oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false);
1898 }
1899 }
1900 break;
1901
1902 case c1x_slow_subtype_check_id:
1903 {
1904 Label success;
1905 Label miss;
1906
1907 // TODO this should really be within the XirSnippets
1908 __ check_klass_subtype_fast_path(j_rarg0, j_rarg1, j_rarg2, &success, &miss, NULL);
1909 __ check_klass_subtype_slow_path(j_rarg0, j_rarg1, j_rarg2, j_rarg3, NULL, &miss);
1910
1911 // fallthrough on success:
1912 __ bind(success);
1913 __ movptr(rax, 1);
1914 __ ret(0);
1915
1916 __ bind(miss);
1917 __ movptr(rax, NULL_WORD);
1918 __ ret(0);
1919 }
1920 break;
1738 default: 1921 default:
1739 { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); 1922 { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments);
1740 __ movptr(rax, (int)id); 1923 __ movptr(rax, (int)id);
1741 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax); 1924 __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);
1742 __ should_not_reach_here(); 1925 __ should_not_reach_here();