Mercurial > hg > graal-compiler
diff 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 |
line wrap: on
line diff
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Thu Aug 19 14:34:52 2010 -0700 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Tue Aug 31 22:13:30 2010 -0700 @@ -599,30 +599,50 @@ // has_argument: true if the exception needs an argument (passed on stack because registers must be preserved) OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address target, bool has_argument) { - // preserve all registers - int num_rt_args = has_argument ? 2 : 1; - OopMap* oop_map = save_live_registers(sasm, num_rt_args); + OopMapSet* oop_maps = new OopMapSet(); + if (UseC1X) { + // c1x passes the argument in r10 + OopMap* oop_map = save_live_registers(sasm, 1); + + // now all registers are saved and can be used freely + // verify that no old value is used accidentally + __ invalidate_registers(true, true, true, true, true, true); - // now all registers are saved and can be used freely - // verify that no old value is used accidentally - __ invalidate_registers(true, true, true, true, true, true); + // registers used by this stub + const Register temp_reg = rbx; - // registers used by this stub - const Register temp_reg = rbx; + // load argument for exception that is passed as an argument into the stub + if (has_argument) { + __ movptr(c_rarg1, r10); + } + int call_offset = __ call_RT(noreg, noreg, target, has_argument ? 1 : 0); - // load argument for exception that is passed as an argument into the stub - if (has_argument) { -#ifdef _LP64 - __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord)); -#else - __ movptr(temp_reg, Address(rbp, 2*BytesPerWord)); - __ push(temp_reg); -#endif // _LP64 + oop_maps->add_gc_map(call_offset, oop_map); + } else { + // preserve all registers + int num_rt_args = has_argument ? 2 : 1; + OopMap* oop_map = save_live_registers(sasm, num_rt_args); + + // now all registers are saved and can be used freely + // verify that no old value is used accidentally + __ invalidate_registers(true, true, true, true, true, true); + + // registers used by this stub + const Register temp_reg = rbx; + + // load argument for exception that is passed as an argument into the stub + if (has_argument) { + #ifdef _LP64 + __ movptr(c_rarg1, Address(rbp, 2*BytesPerWord)); + #else + __ movptr(temp_reg, Address(rbp, 2*BytesPerWord)); + __ push(temp_reg); + #endif // _LP64 + } + int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1); + + oop_maps->add_gc_map(call_offset, oop_map); } - int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1); - - OopMapSet* oop_maps = new OopMapSet(); - oop_maps->add_gc_map(call_offset, oop_map); __ stop("should not reach here"); @@ -717,6 +737,74 @@ } +void Runtime1::c1x_generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map) { + NOT_LP64(fatal("64 bit only")); + // incoming parameters + const Register exception_oop = j_rarg0; + // other registers used in this stub + const Register exception_pc = j_rarg1; + const Register thread = r15_thread; + + __ block_comment("c1x_generate_handle_exception"); + + // verify that rax, contains a valid exception + __ verify_not_null_oop(exception_oop); + +#ifdef ASSERT + // check that fields in JavaThread for exception oop and issuing pc are + // empty before writing to them + Label oop_empty; + __ cmpptr(Address(thread, JavaThread::exception_oop_offset()), (int32_t) NULL_WORD); + __ jcc(Assembler::equal, oop_empty); + __ stop("exception oop already set"); + __ bind(oop_empty); + + Label pc_empty; + __ cmpptr(Address(thread, JavaThread::exception_pc_offset()), 0); + __ jcc(Assembler::equal, pc_empty); + __ stop("exception pc already set"); + __ bind(pc_empty); +#endif + + // save exception oop and issuing pc into JavaThread + // (exception handler will load it from here) + __ movptr(Address(thread, JavaThread::exception_oop_offset()), exception_oop); + __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); + __ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc); + + // compute the exception handler. + // the exception oop and the throwing pc are read from the fields in JavaThread + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); + oop_maps->add_gc_map(call_offset, oop_map); + + // rax,: handler address + // will be the deopt blob if nmethod was deoptimized while we looked up + // handler regardless of whether handler existed in the nmethod. + + // only rax, is valid at this time, all other registers have been destroyed by the runtime call + __ invalidate_registers(false, true, true, true, true, true); + +#ifdef ASSERT + // Do we have an exception handler in the nmethod? + Label done; + __ testptr(rax, rax); + __ jcc(Assembler::notZero, done); + __ stop("no handler found"); + __ bind(done); +#endif + + // exception handler found + // patch the return address -> the stub will directly return to the exception handler + __ movptr(Address(rbp, 1*BytesPerWord), rax); + + // restore registers + restore_live_registers(sasm, false); + + // return to exception handler + __ leave(); + __ ret(0); +} + void Runtime1::generate_unwind_exception(StubAssembler *sasm) { // incoming parameters @@ -925,6 +1013,12 @@ } +JRT_ENTRY(void, c1x_create_null_exception(JavaThread* thread)) + thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)()); +JRT_END + + + OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { @@ -1307,7 +1401,8 @@ break; case unwind_exception_id: - { __ set_info("unwind_exception", dont_gc_arguments); + { + __ set_info("unwind_exception", dont_gc_arguments); // note: no stubframe since we are about to leave the current // activation and we are calling a leaf VM function only. generate_unwind_exception(sasm); @@ -1735,6 +1830,94 @@ break; #endif // !SERIALGC + case c1x_unwind_exception_call_id: + { + // remove the frame from the stack + __ movptr(rsp, rbp); + __ pop(rbp); + // exception_oop is passed using ordinary java calling conventions + __ movptr(rax, j_rarg0); + + Label nonNullExceptionOop; + __ testptr(rax, rax); + __ jcc(Assembler::notZero, nonNullExceptionOop); + { + __ enter(); + oop_maps = new OopMapSet(); + OopMap* oop_map = save_live_registers(sasm, 0); + int call_offset = __ call_RT(rax, noreg, (address)c1x_create_null_exception, 0); + oop_maps->add_gc_map(call_offset, oop_map); + __ leave(); + } + __ bind(nonNullExceptionOop); + + __ set_info("unwind_exception", dont_gc_arguments); + // note: no stubframe since we are about to leave the current + // activation and we are calling a leaf VM function only. + generate_unwind_exception(sasm); + __ should_not_reach_here(); + } + break; + + case c1x_handle_exception_id: + { StubFrame f(sasm, "c1x_handle_exception", dont_gc_arguments); + oop_maps = new OopMapSet(); + OopMap* oop_map = save_live_registers(sasm, 1, false); + c1x_generate_handle_exception(sasm, oop_maps, oop_map); + } + break; + + case c1x_global_implicit_null_id: + { + __ push(rax); + __ push(rax); + // move saved fp to make space for the inserted return address + __ get_thread(rax); + __ movptr(rax, Address(rax, JavaThread::saved_exception_pc_offset())); + __ movptr(Address(rsp, HeapWordSize), rax); + __ pop(rax); + + { StubFrame f(sasm, "c1x_global_implicit_null_id", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); + } + } + break; + + case c1x_throw_div0_exception_id: + { + __ push(rax); + __ push(rax); + // move saved fp to make space for the inserted return address + __ get_thread(rax); + __ movptr(rax, Address(rax, JavaThread::saved_exception_pc_offset())); + __ movptr(Address(rsp, HeapWordSize), rax); + __ pop(rax); + + { StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); + } + } + break; + + case c1x_slow_subtype_check_id: + { + Label success; + Label miss; + + // TODO this should really be within the XirSnippets + __ check_klass_subtype_fast_path(j_rarg0, j_rarg1, j_rarg2, &success, &miss, NULL); + __ check_klass_subtype_slow_path(j_rarg0, j_rarg1, j_rarg2, j_rarg3, NULL, &miss); + + // fallthrough on success: + __ bind(success); + __ movptr(rax, 1); + __ ret(0); + + __ bind(miss); + __ movptr(rax, NULL_WORD); + __ ret(0); + } + break; default: { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); __ movptr(rax, (int)id);