changeset 7869:840306ef66e4

8069412: Locks need better debug-printing support Summary: Added better debug-printing support and enhanced LogCompilation tool Reviewed-by: kvn, roland, dholmes
author drchase
date Tue, 17 Feb 2015 13:54:53 -0500
parents 16157f91ff41
children cf7251f51459
files src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java src/share/vm/oops/markOop.cpp src/share/vm/opto/callnode.cpp src/share/vm/opto/callnode.hpp src/share/vm/opto/escape.cpp src/share/vm/opto/graphKit.cpp src/share/vm/opto/macro.cpp src/share/vm/runtime/basicLock.cpp src/share/vm/runtime/vframe.cpp
diffstat 10 files changed, 258 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,12 +24,12 @@
 
 /**
  * A SAX based parser of LogCompilation output from HotSpot.  It takes a complete
- * @author never
  */
 
 package com.sun.hotspot.tools.compiler;
 
 import java.io.FileReader;
+import java.io.PrintStream;
 import java.io.Reader;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
@@ -134,6 +134,44 @@
         }
     };
 
+    class Jvms {
+        Jvms(Method method, int bci) {
+            this.method = method;
+            this.bci = bci;
+        }
+        final public Method method;
+        final public int bci;
+        final public String toString() {
+            return "@" + bci + " " + method;
+        }
+    }
+
+    class LockElimination extends BasicLogEvent {
+
+        ArrayList<Jvms> jvms = new ArrayList<Jvms>(1);
+        final String kind;
+        final String classId;
+        final String tagName;
+        LockElimination(String tagName, double start, String id, String kind, String classId) {
+            super(start, id);
+            this.kind = kind;
+            this.classId = classId;
+            this.tagName = tagName;
+        }
+
+        @Override
+        public void print(PrintStream stream) {
+            stream.printf("%s %s %s %s  %.3f ", getId(), tagName, kind, classId, getStart());
+            stream.print(jvms.toString());
+            stream.print("\n");
+        }
+
+        void addJVMS(Method method, int bci) {
+            jvms.add(new Jvms(method, bci));
+        }
+
+    }
+
     private ArrayList<LogEvent> events = new ArrayList<LogEvent>();
 
     private HashMap<String, String> types = new HashMap<String, String>();
@@ -147,6 +185,7 @@
     private CallSite site;
     private CallSite methodHandleSite;
     private Stack<Phase> phaseStack = new Stack<Phase>();
+    private LockElimination currentLockElimination;
     private UncommonTrapEvent currentTrap;
     private Stack<CallSite> lateInlineScope;
     private boolean lateInlining;
@@ -192,7 +231,12 @@
         }
 
         LogParser log = new LogParser();
-        p.parse(new InputSource(reader), log);
+        try {
+            p.parse(new InputSource(reader), log);
+        } catch (Throwable th) {
+            th.printStackTrace();
+            // Carry on with what we've got...
+        }
 
         // Associate compilations with their NMethods
         for (NMethod nm : log.nmethods.values()) {
@@ -418,8 +462,23 @@
                 // uncommon trap inserted during parsing.
                 // ignore for now
             }
+        } else if (qname.startsWith("eliminate_lock")) {
+            String id = atts.getValue("compile_id");
+            if (id != null) {
+                id = makeId(atts);
+                String kind = atts.getValue("kind");
+                String classId = atts.getValue("class_id");
+                currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId);
+                events.add(currentLockElimination);
+            }
         } else if (qname.equals("late_inline")) {
-            long inlineId = Long.parseLong(search(atts, "inline_id"));
+            long inlineId = 0;
+            try {
+                Long.parseLong(search(atts, "inline_id"));
+            } catch (InternalError ex) {
+                // Log files from older hotspots may lack inline_id,
+                // and zero is an acceptable substitute that allows processing to continue.
+            }
             lateInlineScope = new Stack<CallSite>();
             site = new CallSite(-999, method(search(atts, "method")));
             site.setInlineId(inlineId);
@@ -428,13 +487,14 @@
             // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
             if (currentTrap != null) {
                 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
+            } else if (currentLockElimination != null) {
+                  currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci")));
             } else if (lateInlineScope != null) {
                 bci = Integer.parseInt(search(atts, "bci"));
                 site = new CallSite(bci, method(search(atts, "method")));
                 lateInlineScope.push(site);
             } else {
                 // Ignore <eliminate_allocation type='667'>,
-                //        <eliminate_lock lock='1'>,
                 //        <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
             }
         } else if (qname.equals("inline_id")) {
@@ -512,6 +572,8 @@
             }
         } else if (qname.equals("uncommon_trap")) {
             currentTrap = null;
+        } else if (qname.startsWith("eliminate_lock")) {
+            currentLockElimination = null;
         } else if (qname.equals("late_inline")) {
             // Populate late inlining info.
             if (scopes.size() != 0) {
@@ -522,8 +584,8 @@
             CallSite caller = lateInlineScope.pop();
             Method m = compile.getMethod();
             if (m != caller.getMethod()) {
-                System.out.println(m);
-                System.out.println(caller.getMethod() + " bci: " + bci);
+                System.err.println(m);
+                System.err.println(caller.getMethod() + " bci: " + bci);
                 throw new InternalError("call site and late_inline info don't match");
             }
 
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
     }
 
     public void print(PrintStream stream) {
-        stream.printf("%s uncommon trap %s %s\n", getId(), getReason(), getAction());
+        stream.printf("%s uncommon trap %.3f %s %s\n", getId(), getStart(), getReason(), getAction());
         stream.print(getJvms());
     }
 
--- a/src/share/vm/oops/markOop.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/oops/markOop.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,40 @@
 #include "precompiled.hpp"
 #include "oops/markOop.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/objectMonitor.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
 void markOopDesc::print_on(outputStream* st) const {
-  if (is_locked()) {
-    st->print("locked(" INTPTR_FORMAT ")->", value());
-    markOop(*(markOop*)value())->print_on(st);
+  if (is_marked()) {
+    st->print(" marked(" INTPTR_FORMAT ")", value());
+  } else if (is_locked()) {
+    st->print(" locked(" INTPTR_FORMAT ")->", value());
+    if (is_neutral()) {
+      st->print("is_neutral");
+      if (has_no_hash()) st->print(" no_hash");
+      else st->print(" hash=" INTPTR_FORMAT, hash());
+      st->print(" age=%d", age());
+    } else if (has_bias_pattern()) {
+      st->print("is_biased");
+      JavaThread* jt = biased_locker();
+      st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt));
+    } else if (has_monitor()) {
+      ObjectMonitor* mon = monitor();
+      if (mon == NULL)
+        st->print("monitor=NULL");
+      else {
+        BasicLock * bl = (BasicLock *) mon->owner();
+        st->print("monitor={count="INTPTR_FORMAT",waiters="INTPTR_FORMAT",recursions="INTPTR_FORMAT",owner="INTPTR_FORMAT"}",
+                mon->count(), mon->waiters(), mon->recursions(), p2i(bl));
+      }
+    } else {
+      st->print("??");
+    }
   } else {
     assert(is_unlocked() || has_bias_pattern(), "just checking");
     st->print("mark(");
-    if (has_bias_pattern())  st->print("biased,");
+    if (has_bias_pattern()) st->print("biased,");
     st->print("hash %#lx,", hash());
     st->print("age %d)", age());
   }
--- a/src/share/vm/opto/callnode.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/opto/callnode.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "compiler/compileLog.hpp"
 #include "ci/bcEscapeAnalyzer.hpp"
 #include "compiler/oopMap.hpp"
 #include "opto/callGenerator.hpp"
@@ -1673,6 +1674,9 @@
       // The lock could be marked eliminated by lock coarsening
       // code during first IGVN before EA. Replace coarsened flag
       // to eliminate all associated locks/unlocks.
+#ifdef ASSERT
+      this->log_lock_optimization(phase->C,"eliminate_lock_set_non_esc1");
+#endif
       this->set_non_esc_obj();
       return result;
     }
@@ -1734,6 +1738,9 @@
           AbstractLockNode* lock = lock_ops.at(i);
 
           // Mark it eliminated by coarsening and update any counters
+#ifdef ASSERT
+          lock->log_lock_optimization(phase->C, "eliminate_lock_set_coarsened");
+#endif
           lock->set_coarsened();
         }
       } else if (ctrl->is_Region() &&
@@ -1752,16 +1759,33 @@
 
 //=============================================================================
 bool LockNode::is_nested_lock_region() {
+  return is_nested_lock_region(NULL);
+}
+
+// p is used for access to compilation log; no logging if NULL
+bool LockNode::is_nested_lock_region(Compile * c) {
   BoxLockNode* box = box_node()->as_BoxLock();
   int stk_slot = box->stack_slot();
-  if (stk_slot <= 0)
+  if (stk_slot <= 0) {
+#ifdef ASSERT
+    this->log_lock_optimization(c, "eliminate_lock_INLR_1");
+#endif
     return false; // External lock or it is not Box (Phi node).
+  }
 
   // Ignore complex cases: merged locks or multiple locks.
   Node* obj = obj_node();
   LockNode* unique_lock = NULL;
-  if (!box->is_simple_lock_region(&unique_lock, obj) ||
-      (unique_lock != this)) {
+  if (!box->is_simple_lock_region(&unique_lock, obj)) {
+#ifdef ASSERT
+    this->log_lock_optimization(c, "eliminate_lock_INLR_2a");
+#endif
+    return false;
+  }
+  if (unique_lock != this) {
+#ifdef ASSERT
+    this->log_lock_optimization(c, "eliminate_lock_INLR_2b");
+#endif
     return false;
   }
 
@@ -1781,6 +1805,9 @@
       }
     }
   }
+#ifdef ASSERT
+  this->log_lock_optimization(c, "eliminate_lock_INLR_3");
+#endif
   return false;
 }
 
@@ -1812,12 +1839,43 @@
       // The lock could be marked eliminated by lock coarsening
       // code during first IGVN before EA. Replace coarsened flag
       // to eliminate all associated locks/unlocks.
+#ifdef ASSERT
+      this->log_lock_optimization(phase->C, "eliminate_lock_set_non_esc2");
+#endif
       this->set_non_esc_obj();
     }
   }
   return result;
 }
 
+const char * AbstractLockNode::kind_as_string() const {
+  return is_coarsened()   ? "coarsened" :
+         is_nested()      ? "nested" :
+         is_non_esc_obj() ? "non_escaping" :
+         "?";
+}
+
+void AbstractLockNode::log_lock_optimization(Compile *C, const char * tag)  const {
+  if (C == NULL) {
+    return;
+  }
+  CompileLog* log = C->log();
+  if (log != NULL) {
+    log->begin_head("%s lock='%d' compile_id='%d' class_id='%s' kind='%s'",
+          tag, is_Lock(), C->compile_id(),
+          is_Unlock() ? "unlock" : is_Lock() ? "lock" : "?",
+          kind_as_string());
+    log->stamp();
+    log->end_head();
+    JVMState* p = is_Unlock() ? (as_Unlock()->dbg_jvms()) : jvms();
+    while (p != NULL) {
+      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
+      p = p->caller();
+    }
+    log->tail(tag);
+  }
+}
+
 ArrayCopyNode::ArrayCopyNode(Compile* C, bool alloc_tightly_coupled)
   : CallNode(arraycopy_type(), NULL, TypeRawPtr::BOTTOM),
     _alloc_tightly_coupled(alloc_tightly_coupled),
--- a/src/share/vm/opto/callnode.hpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/opto/callnode.hpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -985,6 +985,9 @@
   bool is_coarsened()   const { return (_kind == Coarsened); }
   bool is_nested()      const { return (_kind == Nested); }
 
+  const char * kind_as_string() const;
+  void log_lock_optimization(Compile* c, const char * tag) const;
+
   void set_non_esc_obj() { _kind = NonEscObj; set_eliminated_lock_counter(); }
   void set_coarsened()   { _kind = Coarsened; set_eliminated_lock_counter(); }
   void set_nested()      { _kind = Nested; set_eliminated_lock_counter(); }
@@ -1045,15 +1048,24 @@
   }
 
   bool is_nested_lock_region(); // Is this Lock nested?
+  bool is_nested_lock_region(Compile * c); // Why isn't this Lock nested?
 };
 
 //------------------------------Unlock---------------------------------------
 // High-level unlock operation
 class UnlockNode : public AbstractLockNode {
+private:
+#ifdef ASSERT
+  JVMState* const _dbg_jvms;      // Pointer to list of JVM State objects
+#endif
 public:
   virtual int Opcode() const;
   virtual uint size_of() const; // Size is bigger
-  UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf ) {
+  UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf )
+#ifdef ASSERT
+    , _dbg_jvms(NULL)
+#endif
+  {
     init_class_id(Class_Unlock);
     init_flags(Flag_is_macro);
     C->add_macro_node(this);
@@ -1061,6 +1073,14 @@
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
   // unlock is never a safepoint
   virtual bool        guaranteed_safepoint()  { return false; }
+#ifdef ASSERT
+  void set_dbg_jvms(JVMState* s) {
+    *(JVMState**)&_dbg_jvms = s;  // override const attribute in the accessor
+  }
+  JVMState* dbg_jvms() const { return _dbg_jvms; }
+#else
+  JVMState* dbg_jvms() const { return NULL; }
+#endif
 };
 
 class GraphKit;
--- a/src/share/vm/opto/escape.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/opto/escape.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1802,6 +1802,9 @@
             // The lock could be marked eliminated by lock coarsening
             // code during first IGVN before EA. Replace coarsened flag
             // to eliminate all associated locks/unlocks.
+#ifdef ASSERT
+            alock->log_lock_optimization(C, "eliminate_lock_set_non_esc3");
+#endif
             alock->set_non_esc_obj();
           }
         }
--- a/src/share/vm/opto/graphKit.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/opto/graphKit.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -3244,6 +3244,9 @@
 
   const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type();
   UnlockNode *unlock = new UnlockNode(C, tf);
+#ifdef ASSERT
+  unlock->set_dbg_jvms(sync_jvms());
+#endif
   uint raw_idx = Compile::AliasIdxRaw;
   unlock->init_req( TypeFunc::Control, control() );
   unlock->init_req( TypeFunc::Memory , memory(raw_idx) );
--- a/src/share/vm/opto/macro.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/opto/macro.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1890,7 +1890,7 @@
     // Box is used only in one lock region. Mark this box as eliminated.
     _igvn.hash_delete(oldbox);
     oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value
-    _igvn.hash_insert(oldbox);
+     _igvn.hash_insert(oldbox);
 
     for (uint i = 0; i < oldbox->outcnt(); i++) {
       Node* u = oldbox->raw_out(i);
@@ -1899,6 +1899,9 @@
         // Check lock's box since box could be referenced by Lock's debug info.
         if (alock->box_node() == oldbox) {
           // Mark eliminated all related locks and unlocks.
+#ifdef ASSERT
+          alock->log_lock_optimization(C, "eliminate_lock_set_non_esc4");
+#endif
           alock->set_non_esc_obj();
         }
       }
@@ -1925,6 +1928,9 @@
       AbstractLockNode* alock = u->as_AbstractLock();
       if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) {
         // Replace Box and mark eliminated all related locks and unlocks.
+#ifdef ASSERT
+        alock->log_lock_optimization(C, "eliminate_lock_set_non_esc5");
+#endif
         alock->set_non_esc_obj();
         _igvn.rehash_node_delayed(alock);
         alock->set_box_node(newbox);
@@ -1971,26 +1977,38 @@
        return;
     } else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened
       // Only Lock node has JVMState needed here.
-      if (alock->jvms() != NULL && alock->as_Lock()->is_nested_lock_region()) {
-        // Mark eliminated related nested locks and unlocks.
-        Node* obj = alock->obj_node();
-        BoxLockNode* box_node = alock->box_node()->as_BoxLock();
-        assert(!box_node->is_eliminated(), "should not be marked yet");
-        // Note: BoxLock node is marked eliminated only here
-        // and it is used to indicate that all associated lock
-        // and unlock nodes are marked for elimination.
-        box_node->set_eliminated(); // Box's hash is always NO_HASH here
-        for (uint i = 0; i < box_node->outcnt(); i++) {
-          Node* u = box_node->raw_out(i);
-          if (u->is_AbstractLock()) {
-            alock = u->as_AbstractLock();
-            if (alock->box_node() == box_node) {
-              // Verify that this Box is referenced only by related locks.
-              assert(alock->obj_node()->eqv_uncast(obj), "");
-              // Mark all related locks and unlocks.
-              alock->set_nested();
+      // Not that preceding claim is documented anywhere else.
+      if (alock->jvms() != NULL) {
+        if (alock->as_Lock()->is_nested_lock_region()) {
+          // Mark eliminated related nested locks and unlocks.
+          Node* obj = alock->obj_node();
+          BoxLockNode* box_node = alock->box_node()->as_BoxLock();
+          assert(!box_node->is_eliminated(), "should not be marked yet");
+          // Note: BoxLock node is marked eliminated only here
+          // and it is used to indicate that all associated lock
+          // and unlock nodes are marked for elimination.
+          box_node->set_eliminated(); // Box's hash is always NO_HASH here
+          for (uint i = 0; i < box_node->outcnt(); i++) {
+            Node* u = box_node->raw_out(i);
+            if (u->is_AbstractLock()) {
+              alock = u->as_AbstractLock();
+              if (alock->box_node() == box_node) {
+                // Verify that this Box is referenced only by related locks.
+                assert(alock->obj_node()->eqv_uncast(obj), "");
+                // Mark all related locks and unlocks.
+#ifdef ASSERT
+                alock->log_lock_optimization(C, "eliminate_lock_set_nested");
+#endif
+                alock->set_nested();
+              }
             }
           }
+        } else {
+#ifdef ASSERT
+          alock->log_lock_optimization(C, "eliminate_lock_NOT_nested_lock_region");
+          if (C->log() != NULL)
+            alock->as_Lock()->is_nested_lock_region(C); // rerun for debugging output
+#endif
         }
       }
       return;
@@ -2035,19 +2053,10 @@
     assert(oldbox->is_eliminated(), "should be done already");
   }
 #endif
-  CompileLog* log = C->log();
-  if (log != NULL) {
-    log->head("eliminate_lock lock='%d'",
-              alock->is_Lock());
-    JVMState* p = alock->jvms();
-    while (p != NULL) {
-      log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method()));
-      p = p->caller();
-    }
-    log->tail("eliminate_lock");
-  }
 
-  #ifndef PRODUCT
+  alock->log_lock_optimization(C, "eliminate_lock");
+
+#ifndef PRODUCT
   if (PrintEliminateLocks) {
     if (alock->is_Lock()) {
       tty->print_cr("++++ Eliminated: %d Lock", alock->_idx);
@@ -2055,7 +2064,7 @@
       tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx);
     }
   }
-  #endif
+#endif
 
   Node* mem  = alock->in(TypeFunc::Memory);
   Node* ctrl = alock->in(TypeFunc::Control);
--- a/src/share/vm/runtime/basicLock.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/runtime/basicLock.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,9 @@
 
 void BasicLock::print_on(outputStream* st) const {
   st->print("monitor");
+  markOop moop = displaced_header();
+  if (moop != NULL)
+    moop->print_on(st);
 }
 
 void BasicLock::move_to(oop obj, BasicLock* dest) {
--- a/src/share/vm/runtime/vframe.cpp	Mon Feb 16 08:47:39 2015 -0800
+++ b/src/share/vm/runtime/vframe.cpp	Tue Feb 17 13:54:53 2015 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -189,6 +189,7 @@
       if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code
         if (monitor->owner_is_scalar_replaced()) {
           Klass* k = java_lang_Class::as_Klass(monitor->owner_klass());
+          // format below for lockbits matches this one.
           st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name());
         } else {
           oop obj = monitor->owner();
@@ -206,9 +207,10 @@
         // see if we have completed the lock or we are blocked trying to
         // acquire it - we can only be blocked if the monitor is inflated
 
+        markOop mark = NULL;
         const char *lock_state = "locked"; // assume we have the monitor locked
         if (!found_first_monitor && frame_count == 0) {
-          markOop mark = monitor->owner()->mark();
+          mark = monitor->owner()->mark();
           if (mark->has_monitor() &&
               ( // we have marked ourself as pending on this monitor
                 mark->monitor() == thread()->current_pending_monitor() ||
@@ -216,11 +218,19 @@
                 !mark->monitor()->is_entered(thread())
               )) {
             lock_state = "waiting to lock";
+          } else {
+            mark = NULL; // Disable printing below
           }
         }
+        print_locked_object_class_name(st, monitor->owner(), lock_state);
+        if (Verbose && mark != NULL) {
+          // match with format above, replacing "-" with " ".
+          st->print("\t  lockbits=");
+          mark->print_on(st);
+          st->cr();
+        }
 
         found_first_monitor = true;
-        print_locked_object_class_name(st, monitor->owner(), lock_state);
       }
     }
   }
@@ -577,10 +587,15 @@
       tty->print("( null )");
     } else {
       monitor->owner()->print_value();
-      tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner());
+      tty->print("(owner=" INTPTR_FORMAT ")", (address)monitor->owner());
     }
-    if (monitor->eliminated() && is_compiled_frame())
-      tty->print(" ( lock is eliminated )");
+    if (monitor->eliminated()) {
+      if(is_compiled_frame()) {
+        tty->print(" ( lock is eliminated in compiled frame )");
+      } else {
+        tty->print(" ( lock is eliminated, frame not compiled )");
+      }
+    }
     tty->cr();
     tty->print("\t  ");
     monitor->lock()->print_on(tty);