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);