changeset 1942:00bc9eaf0e24

Support for -XX:+UseFastLocking flag. Fixed monitor enter XIR template for correct debug info at the runtime call.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Wed, 29 Dec 2010 20:06:41 +0100
parents 79d04223b8a5
children 06f017f7daa7
files c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotVMConfig.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMExitsNative.java src/cpu/x86/vm/c1_Runtime1_x86.cpp src/os/linux/vm/os_linux.cpp src/os_cpu/linux_x86/vm/os_linux_x86.cpp src/share/vm/c1/c1_Runtime1.cpp src/share/vm/c1/c1_globals.hpp src/share/vm/c1x/c1x_CodeInstaller.cpp src/share/vm/c1x/c1x_Compiler.cpp src/share/vm/c1x/c1x_TargetMethod.hpp src/share/vm/c1x/c1x_VMEntries.cpp src/share/vm/oops/oop.inline.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/stackValue.cpp
diffstat 15 files changed, 81 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotVMConfig.java	Tue Dec 28 18:33:26 2010 +0100
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotVMConfig.java	Wed Dec 29 20:06:41 2010 +0100
@@ -33,6 +33,7 @@
     public boolean windowsOs;
     public int codeEntryAlignment;
     public boolean verifyPointers;
+    public boolean useFastLocking;
 
     // offsets, ...
     public int vmPageSize;
@@ -73,6 +74,8 @@
     public long throwArrayIndexException;
     public long monitorEnterStub;
     public long monitorExitStub;
+    public long fastMonitorEnterStub;
+    public long fastMonitorExitStub;
     public long verifyPointerStub;
 
     public void check() {
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java	Tue Dec 28 18:33:26 2010 +0100
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/HotSpotXirGenerator.java	Wed Dec 29 20:06:41 2010 +0100
@@ -314,9 +314,20 @@
                 asm.pload(CiKind.Word, asm.createTemp("temp", CiKind.Word), object, true);
             }
 
-            useRegisters(asm, AMD64.rbx, AMD64.rsi, AMD64.rdx);
-            useRegisters(asm, AMD64.rax);
-            asm.callRuntime(config.monitorEnterStub, null, object, lock);
+
+            // (tw) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object
+            // is not correctly garbage collected.
+            final boolean useInfoAfter = true;
+
+            if (config.useFastLocking) {
+                useRegisters(asm, AMD64.rbx, AMD64.rsi, AMD64.rdx, AMD64.rax);
+                asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock);
+            } else {
+                asm.reserveOutgoingStack(target.wordSize * 2);
+                asm.pstore(CiKind.Object, asm.createRegister("rsp", CiKind.Word, AMD64.RSP.asRegister()), asm.i(target.wordSize), object, false);
+                asm.pstore(CiKind.Word, asm.createRegister("rsp", CiKind.Word, AMD64.RSP.asRegister()), asm.i(0), lock, false);
+                asm.callRuntime(config.monitorEnterStub, null, useInfoAfter);
+            }
 
             return asm.finishTemplate("monitorEnter");
         }
@@ -330,9 +341,14 @@
             XirParameter object = asm.createInputParameter("object", CiKind.Object);
             XirParameter lock = asm.createInputParameter("lock", CiKind.Word);
 
-            useRegisters(asm, AMD64.rbx, AMD64.rsi, AMD64.rdx);
-            useRegisters(asm, AMD64.rax);
-            asm.callRuntime(config.monitorExitStub, null, object, lock);
+            if (config.useFastLocking) {
+                useRegisters(asm, AMD64.rbx, AMD64.rsi, AMD64.rdx, AMD64.rax);
+                asm.callRuntime(config.fastMonitorExitStub, null, object, lock);
+            } else {
+                asm.reserveOutgoingStack(target.wordSize);
+                asm.pstore(CiKind.Word, asm.createRegister("rsp", CiKind.Word, AMD64.RSP.asRegister()), asm.i(0), lock, false);
+                asm.callRuntime(config.monitorExitStub, null);
+            }
 
             return asm.finishTemplate("monitorExit");
         }
--- a/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMExitsNative.java	Tue Dec 28 18:33:26 2010 +0100
+++ b/c1x4hotspotsrc/HotSpotVM/src/com/sun/hotspot/c1x/VMExitsNative.java	Wed Dec 29 20:06:41 2010 +0100
@@ -51,7 +51,7 @@
         C1XOptions.UseDeopt = false;
         C1XOptions.IRChecking = false;
         C1XOptions.DetailedAsserts = false;
-        C1XOptions.CommentedAssembly = true;
+        C1XOptions.CommentedAssembly = false;
         C1XOptions.MethodEndBreakpointGuards = 2;
     }
 
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -2010,6 +2010,7 @@
 
       Register scratch1 = rax;
       Register scratch2 = rbx;
+      assert_different_registers(obj, lock, scratch1, scratch2);
 
       // copied from LIR_Assembler::emit_lock
       if (UseFastLocking) {
@@ -2043,6 +2044,7 @@
       Register lock2 = rax;
       __ mov(lock2, lock);
       Register scratch1 = rbx;
+      assert_different_registers(obj, lock, scratch1, lock2);
 
       // copied from LIR_Assembler::emit_lock
       if (UseFastLocking) {
--- a/src/os/linux/vm/os_linux.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/os/linux/vm/os_linux.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -3408,6 +3408,7 @@
 
 void signalHandler(int sig, siginfo_t* info, void* uc) {
   assert(info != NULL && uc != NULL, "it must be old kernel");
+  ResourceMark rm;
   if (TraceSignals) {
     tty->print_cr(err_msg("signal received: code=%d errno=%d signo=%d thread=%s address=%x", info->si_code, info->si_errno, info->si_signo, Thread::current()->name(), info->si_addr));
   }
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -260,7 +260,7 @@
       if (cb != NULL && cb->is_nmethod()) {
         nmethod* nm = (nmethod*)cb;
         int rel = pc - nm->code_begin();
-        tty->print_cr("Implicit exception at %d of method %s", rel, nm->method()->name()->as_C_string());
+        tty->print_cr(err_msg("Implicit exception at %d of method %s", rel, nm->method()->name()->as_C_string()));
       } else {
         tty->print_cr("No code blob found for %x", pc);
       }
--- a/src/share/vm/c1/c1_Runtime1.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -596,12 +596,22 @@
 
 JRT_ENTRY_NO_ASYNC(void, Runtime1::monitorenter(JavaThread* thread, oopDesc* obj, BasicObjectLock* lock))
   NOT_PRODUCT(_monitorenter_slowcase_cnt++;)
+#ifdef ASSERT
+  if (TraceC1X >= 3) {
+    tty->print_cr("entered locking slow case with obj=" INTPTR_FORMAT " and lock= " INTPTR_FORMAT, obj, lock);
+  }
   if (PrintBiasedLockingStatistics) {
     Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
   }
+#endif
   Handle h_obj(thread, obj);
   assert(h_obj()->is_oop(), "must be NULL or an object");
   if (UseBiasedLocking) {
+    if (UseFastLocking) {
+      assert(obj == lock->obj(), "must match");
+    } else {
+      lock->set_obj(obj);
+    }
     // Retry fast entry if bias is revoked to avoid unnecessary inflation
     ObjectSynchronizer::fast_enter(h_obj, lock->lock(), true, CHECK);
   } else {
@@ -614,6 +624,14 @@
       ObjectSynchronizer::fast_enter(h_obj, lock->lock(), false, THREAD);
     }
   }
+#ifdef ASSERT
+  if (TraceC1X >= 3) {
+    tty->print_cr("exiting locking lock state: obj=" INTPTR_FORMAT, lock->obj());
+    lock->lock()->print_on(tty);
+    tty->print_cr("");
+    tty->print_cr("done");
+  }
+#endif
 JRT_END
 
 
@@ -631,7 +649,7 @@
     ResetNoHandleMark rhm;
     nmethod* method = thread->last_frame().cb()->as_nmethod_or_null();
     if (method != NULL) {
-      tty->print_cr("ERROR in monitorexit in method %s", method->name());
+      tty->print_cr("ERROR in monitorexit in method %s wrong obj " INTPTR_FORMAT, method->name(), obj);
     }
     thread->print_stack_on(tty);
     assert(false, "invalid lock object pointer dected");
--- a/src/share/vm/c1/c1_globals.hpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/c1/c1_globals.hpp	Wed Dec 29 20:06:41 2010 +0100
@@ -217,7 +217,7 @@
   develop(bool, UseFastNewObjectArray, true,                                \
           "Use fast inlined object array allocation")                       \
                                                                             \
-  develop(bool, UseFastLocking, true,                                       \
+  product(bool, UseFastLocking, true,                                       \
           "Use fast inlined locking code")                                  \
                                                                             \
   develop(bool, UseSlowPath, false,                                         \
--- a/src/share/vm/c1x/c1x_CodeInstaller.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/c1x/c1x_CodeInstaller.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -559,6 +559,7 @@
       Handle obj = CiConstant::object(constant);
 
       if (obj->is_a(HotSpotTypeResolved::klass())) {
+        assert(!obj.is_null(), "");
         *((jobject*) operand) = JNIHandles::make_local(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(obj)));
         _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
         TRACE_C1X_3("relocating (HotSpotType) at %016x/%016x", instruction, operand);
--- a/src/share/vm/c1x/c1x_Compiler.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/c1x/c1x_Compiler.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -139,6 +139,7 @@
 
   instanceKlass::cast(HotSpotTypeResolved::klass())->initialize(CHECK_NULL);
   oop obj = instanceKlass::cast(HotSpotTypeResolved::klass())->allocate_instance(CHECK_NULL);
+  assert(obj != NULL, "must succeed in allocating instance");
 
   HotSpotTypeResolved::set_javaMirror(obj, klass->java_mirror());
   HotSpotTypeResolved::set_name(obj, name());
--- a/src/share/vm/c1x/c1x_TargetMethod.hpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/c1x/c1x_TargetMethod.hpp	Wed Dec 29 20:06:41 2010 +0100
@@ -190,7 +190,7 @@
   class name : AllStatic {                      \
   private:                                      \
     friend class C1XCompiler;                   \
-    static void check(oop obj) { assert(obj != NULL, "NULL field access"); assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected"); } \
+    static void check(oop obj) { assert(obj != NULL, "NULL field access of class " #name); assert(obj->is_a(SystemDictionary::name##_klass()), "wrong class, " #name " expected"); } \
     static void compute_offsets();              \
   public:                                       \
     static klassOop klass() { return SystemDictionary::name##_klass(); }
--- a/src/share/vm/c1x/c1x_VMEntries.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/c1x/c1x_VMEntries.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -141,8 +141,12 @@
     klassOop resolved_type = NULL;
     // if the name isn't in the symbol table then the class isn't loaded anyway...
     if (nameSymbol != NULL) {
-      Handle classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader();
-      Handle protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain();
+      Handle classloader;
+      Handle protectionDomain;
+      if (JNIHandles::resolve(accessingClass) != NULL) {
+        classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader();
+        protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain();
+      }
       resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD);
       if (HAS_PENDING_EXCEPTION) {
         CLEAR_PENDING_EXCEPTION;
@@ -310,6 +314,7 @@
 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_1constantPool(JNIEnv *, jobject, jobject klass) {
   VM_ENTRY_MARK;
 
+  assert(JNIHandles::resolve(klass) != NULL, "");
   constantPoolOop constantPool = ((instanceKlass*)java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))->klass_part())->constants();
   return JNIHandles::make_local(VMExits::createRiConstantPool(VmIds::add<constantPoolOop>(constantPool), THREAD));
 }
@@ -318,6 +323,7 @@
 JNIEXPORT jobject JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) {
   VM_ENTRY_MARK;
 
+  assert(JNIHandles::resolve(resolved_type) != NULL, "");
   klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type));
   symbolOop name_symbol = VmIds::toSymbol(name);
   symbolOop signature_symbol = VmIds::toSymbol(signature);
@@ -336,6 +342,7 @@
 JNIEXPORT jboolean JNICALL Java_com_sun_hotspot_c1x_VMEntries_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) {
   oop other = JNIHandles::resolve(jother);
   assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected");
+  assert(JNIHandles::resolve(klass) != NULL, "");
   klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
   klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other));
   if (thisKlass->klass_part()->oop_is_instance_slow()) {
@@ -352,11 +359,13 @@
   ciArrayKlass* array_klass;
   {
     VM_ENTRY_MARK;
+    assert(JNIHandles::resolve(klass) != NULL, "");
     array_klass = (ciArrayKlass *) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
   }
   ciType* element_type = array_klass->element_type();
 
   VM_ENTRY_MARK;
+  assert(JNIHandles::resolve(klass) != NULL, "");
   return JNIHandles::make_local(C1XCompiler::get_RiType(element_type, java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)), THREAD));
 }
 
@@ -427,6 +436,7 @@
   set_boolean(env, config, "windowsOs", false);
 #endif
   set_boolean(env, config, "verifyPointers", VerifyOops);
+  set_boolean(env, config, "useFastLocking", UseFastLocking);
   set_int(env, config, "codeEntryAlignment", CodeEntryAlignment);
   set_int(env, config, "vmPageSize", os::vm_page_size());
   set_int(env, config, "stackShadowPages", StackShadowPages);
@@ -459,8 +469,10 @@
   set_long(env, config, "throwClassCastException", VmIds::addStub(Runtime1::entry_for(Runtime1::throw_class_cast_exception_id)));
   set_long(env, config, "throwArrayStoreException", VmIds::addStub(Runtime1::entry_for(Runtime1::throw_array_store_exception_id)));
   set_long(env, config, "throwArrayIndexException", VmIds::addStub(Runtime1::entry_for(Runtime1::throw_range_check_failed_id)));
-  set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorenter_id)));
-  set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorexit_id)));
+  set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id)));
+  set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id)));
+  set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorenter_id)));
+  set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::c1x_monitorexit_id)));
   set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size())));
 
   BarrierSet* bs = Universe::heap()->barrier_set();
--- a/src/share/vm/oops/oop.inline.hpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/oops/oop.inline.hpp	Wed Dec 29 20:06:41 2010 +0100
@@ -533,8 +533,8 @@
 // used only for asserts
 inline bool oopDesc::is_oop(bool ignore_mark_word) const {
   oop obj = (oop) this;
-  if (!check_obj_alignment(obj)) return false;
-  if (!Universe::heap()->is_in_reserved(obj)) return false;
+  if (!check_obj_alignment(obj)) { tty->print_cr("unaligned"); return false; }
+  if (!Universe::heap()->is_in_reserved(obj)) { tty->print_cr("not in reserved"); return false; }
   // obj is aligned and accessible in heap
   // try to find metaclass cycle safely without seg faulting on bad input
   // we should reach klassKlassObj by following klass link at most 3 times
--- a/src/share/vm/runtime/sharedRuntime.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -731,7 +731,7 @@
 #endif
           if (UseC1X) {
             if (TraceSignals) {
-              tty->print_cr("calling implicit call stub relative pc=%d method name = %s", pc - nm->entry_point(), nm->method()->name()->as_C_string());
+              tty->print_cr(err_msg("calling implicit call stub relative pc=%d method name = %s", pc - nm->entry_point(), nm->method()->name()->as_C_string()));
             }
             target_pc = Runtime1::entry_for(Runtime1::c1x_global_implicit_null_id);
           } else {
--- a/src/share/vm/runtime/stackValue.cpp	Tue Dec 28 18:33:26 2010 +0100
+++ b/src/share/vm/runtime/stackValue.cpp	Wed Dec 29 20:06:41 2010 +0100
@@ -116,7 +116,15 @@
 #endif
 #ifndef PRODUCT
       if (val != NULL && !val->is_oop()) {
-        tty->print_cr("found wrong oop " INTPTR_FORMAT " at location:", val);
+        ResourceMark rm;
+        tty->print_cr("found wrong oop " INTPTR_FORMAT " at location " INTPTR_FORMAT " (%d):", val, value_addr, val->is_oop());
+        if (fr->cb() != NULL) {
+          CodeBlob* cb = fr->cb();
+          if (cb->is_nmethod()) {
+            nmethod* nm = (nmethod*)cb;
+            tty->print_cr("method is %s", nm->method()->name()->as_C_string());
+          }
+        }
         sv->print();
         tty->print_cr("");
         tty->print_cr("one less %d; one more %d", (*(((oop *)value_addr) - 1))->is_oop(), (*(((oop *)value_addr) + 1))->is_oop());