Fri, 20 Feb 2015 22:12:53 -0500
8069412: Locks need better debug-printing support
Summary: Added better debug-printing support and enhanced LogCompilation tool
Reviewed-by: kvn, roland, dholmes
1.1 --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Wed Feb 11 18:56:26 2015 -0800 1.2 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java Fri Feb 20 22:12:53 2015 -0500 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -24,12 +24,12 @@ 1.11 1.12 /** 1.13 * A SAX based parser of LogCompilation output from HotSpot. It takes a complete 1.14 - * @author never 1.15 */ 1.16 1.17 package com.sun.hotspot.tools.compiler; 1.18 1.19 import java.io.FileReader; 1.20 +import java.io.PrintStream; 1.21 import java.io.Reader; 1.22 import java.util.ArrayList; 1.23 import java.util.Collections; 1.24 @@ -133,6 +133,44 @@ 1.25 } 1.26 }; 1.27 1.28 + class Jvms { 1.29 + Jvms(Method method, int bci) { 1.30 + this.method = method; 1.31 + this.bci = bci; 1.32 + } 1.33 + final public Method method; 1.34 + final public int bci; 1.35 + final public String toString() { 1.36 + return "@" + bci + " " + method; 1.37 + } 1.38 + } 1.39 + 1.40 + class LockElimination extends BasicLogEvent { 1.41 + 1.42 + ArrayList<Jvms> jvms = new ArrayList<Jvms>(1); 1.43 + final String kind; 1.44 + final String classId; 1.45 + final String tagName; 1.46 + LockElimination(String tagName, double start, String id, String kind, String classId) { 1.47 + super(start, id); 1.48 + this.kind = kind; 1.49 + this.classId = classId; 1.50 + this.tagName = tagName; 1.51 + } 1.52 + 1.53 + @Override 1.54 + public void print(PrintStream stream) { 1.55 + stream.printf("%s %s %s %s %.3f ", getId(), tagName, kind, classId, getStart()); 1.56 + stream.print(jvms.toString()); 1.57 + stream.print("\n"); 1.58 + } 1.59 + 1.60 + void addJVMS(Method method, int bci) { 1.61 + jvms.add(new Jvms(method, bci)); 1.62 + } 1.63 + 1.64 + } 1.65 + 1.66 private ArrayList<LogEvent> events = new ArrayList<LogEvent>(); 1.67 1.68 private HashMap<String, String> types = new HashMap<String, String>(); 1.69 @@ -145,6 +183,7 @@ 1.70 private Compilation compile; 1.71 private CallSite site; 1.72 private Stack<Phase> phaseStack = new Stack<Phase>(); 1.73 + private LockElimination currentLockElimination; 1.74 private UncommonTrapEvent currentTrap; 1.75 private Stack<CallSite> late_inline_scope; 1.76 1.77 @@ -188,7 +227,12 @@ 1.78 } 1.79 1.80 LogParser log = new LogParser(); 1.81 - p.parse(new InputSource(reader), log); 1.82 + try { 1.83 + p.parse(new InputSource(reader), log); 1.84 + } catch (Throwable th) { 1.85 + th.printStackTrace(); 1.86 + // Carry on with what we've got... 1.87 + } 1.88 1.89 // Associate compilations with their NMethods 1.90 for (NMethod nm : log.nmethods.values()) { 1.91 @@ -370,6 +414,15 @@ 1.92 // uncommon trap inserted during parsing. 1.93 // ignore for now 1.94 } 1.95 + } else if (qname.startsWith("eliminate_lock")) { 1.96 + String id = atts.getValue("compile_id"); 1.97 + if (id != null) { 1.98 + id = makeId(atts); 1.99 + String kind = atts.getValue("kind"); 1.100 + String classId = atts.getValue("class_id"); 1.101 + currentLockElimination = new LockElimination(qname, Double.parseDouble(search(atts, "stamp")), id, kind, classId); 1.102 + events.add(currentLockElimination); 1.103 + } 1.104 } else if (qname.equals("late_inline")) { 1.105 late_inline_scope = new Stack<CallSite>(); 1.106 site = new CallSite(-999, method(search(atts, "method"))); 1.107 @@ -378,13 +431,14 @@ 1.108 // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/> 1.109 if (currentTrap != null) { 1.110 currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); 1.111 + } else if (currentLockElimination != null) { 1.112 + currentLockElimination.addJVMS(method(atts.getValue("method")), Integer.parseInt(atts.getValue("bci"))); 1.113 } else if (late_inline_scope != null) { 1.114 bci = Integer.parseInt(search(atts, "bci")); 1.115 site = new CallSite(bci, method(search(atts, "method"))); 1.116 late_inline_scope.push(site); 1.117 } else { 1.118 // Ignore <eliminate_allocation type='667'>, 1.119 - // <eliminate_lock lock='1'>, 1.120 // <replace_string_concat arguments='2' string_alloc='0' multiple='0'> 1.121 } 1.122 } else if (qname.equals("nmethod")) { 1.123 @@ -437,6 +491,8 @@ 1.124 scopes.pop(); 1.125 } else if (qname.equals("uncommon_trap")) { 1.126 currentTrap = null; 1.127 + } else if (qname.startsWith("eliminate_lock")) { 1.128 + currentLockElimination = null; 1.129 } else if (qname.equals("late_inline")) { 1.130 // Populate late inlining info. 1.131 1.132 @@ -445,8 +501,8 @@ 1.133 CallSite caller = late_inline_scope.pop(); 1.134 Method m = compile.getMethod(); 1.135 if (m != caller.getMethod()) { 1.136 - System.out.println(m); 1.137 - System.out.println(caller.getMethod() + " bci: " + bci); 1.138 + System.err.println(m); 1.139 + System.err.println(caller.getMethod() + " bci: " + bci); 1.140 throw new InternalError("call site and late_inline info don't match"); 1.141 } 1.142
2.1 --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Wed Feb 11 18:56:26 2015 -0800 2.2 +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java Fri Feb 20 22:12:53 2015 -0500 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 2.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.8 * 2.9 * This code is free software; you can redistribute it and/or modify it 2.10 @@ -50,7 +50,7 @@ 2.11 } 2.12 2.13 public void print(PrintStream stream) { 2.14 - stream.printf("%s uncommon trap %s %s\n", getId(), getReason(), getAction()); 2.15 + stream.printf("%s uncommon trap %.3f %s %s\n", getId(), getStart(), getReason(), getAction()); 2.16 stream.print(getJvms()); 2.17 } 2.18
3.1 --- a/src/share/vm/oops/markOop.cpp Wed Feb 11 18:56:26 2015 -0800 3.2 +++ b/src/share/vm/oops/markOop.cpp Fri Feb 20 22:12:53 2015 -0500 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.8 * 3.9 * This code is free software; you can redistribute it and/or modify it 3.10 @@ -25,17 +25,40 @@ 3.11 #include "precompiled.hpp" 3.12 #include "oops/markOop.hpp" 3.13 #include "runtime/thread.inline.hpp" 3.14 +#include "runtime/objectMonitor.inline.hpp" 3.15 3.16 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 3.17 3.18 void markOopDesc::print_on(outputStream* st) const { 3.19 - if (is_locked()) { 3.20 - st->print("locked(" INTPTR_FORMAT ")->", value()); 3.21 - markOop(*(markOop*)value())->print_on(st); 3.22 + if (is_marked()) { 3.23 + st->print(" marked(" INTPTR_FORMAT ")", value()); 3.24 + } else if (is_locked()) { 3.25 + st->print(" locked(" INTPTR_FORMAT ")->", value()); 3.26 + if (is_neutral()) { 3.27 + st->print("is_neutral"); 3.28 + if (has_no_hash()) st->print(" no_hash"); 3.29 + else st->print(" hash=" INTPTR_FORMAT, hash()); 3.30 + st->print(" age=%d", age()); 3.31 + } else if (has_bias_pattern()) { 3.32 + st->print("is_biased"); 3.33 + JavaThread* jt = biased_locker(); 3.34 + st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt)); 3.35 + } else if (has_monitor()) { 3.36 + ObjectMonitor* mon = monitor(); 3.37 + if (mon == NULL) 3.38 + st->print("monitor=NULL"); 3.39 + else { 3.40 + BasicLock * bl = (BasicLock *) mon->owner(); 3.41 + st->print("monitor={count="INTPTR_FORMAT",waiters="INTPTR_FORMAT",recursions="INTPTR_FORMAT",owner="INTPTR_FORMAT"}", 3.42 + mon->count(), mon->waiters(), mon->recursions(), p2i(bl)); 3.43 + } 3.44 + } else { 3.45 + st->print("??"); 3.46 + } 3.47 } else { 3.48 assert(is_unlocked() || has_bias_pattern(), "just checking"); 3.49 st->print("mark("); 3.50 - if (has_bias_pattern()) st->print("biased,"); 3.51 + if (has_bias_pattern()) st->print("biased,"); 3.52 st->print("hash %#lx,", hash()); 3.53 st->print("age %d)", age()); 3.54 }
4.1 --- a/src/share/vm/opto/callnode.cpp Wed Feb 11 18:56:26 2015 -0800 4.2 +++ b/src/share/vm/opto/callnode.cpp Fri Feb 20 22:12:53 2015 -0500 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -23,6 +23,7 @@ 4.11 */ 4.12 4.13 #include "precompiled.hpp" 4.14 +#include "compiler/compileLog.hpp" 4.15 #include "ci/bcEscapeAnalyzer.hpp" 4.16 #include "compiler/oopMap.hpp" 4.17 #include "opto/callGenerator.hpp" 4.18 @@ -1670,6 +1671,9 @@ 4.19 // The lock could be marked eliminated by lock coarsening 4.20 // code during first IGVN before EA. Replace coarsened flag 4.21 // to eliminate all associated locks/unlocks. 4.22 +#ifdef ASSERT 4.23 + this->log_lock_optimization(phase->C,"eliminate_lock_set_non_esc1"); 4.24 +#endif 4.25 this->set_non_esc_obj(); 4.26 return result; 4.27 } 4.28 @@ -1731,6 +1735,9 @@ 4.29 AbstractLockNode* lock = lock_ops.at(i); 4.30 4.31 // Mark it eliminated by coarsening and update any counters 4.32 +#ifdef ASSERT 4.33 + lock->log_lock_optimization(phase->C, "eliminate_lock_set_coarsened"); 4.34 +#endif 4.35 lock->set_coarsened(); 4.36 } 4.37 } else if (ctrl->is_Region() && 4.38 @@ -1749,16 +1756,33 @@ 4.39 4.40 //============================================================================= 4.41 bool LockNode::is_nested_lock_region() { 4.42 + return is_nested_lock_region(NULL); 4.43 +} 4.44 + 4.45 +// p is used for access to compilation log; no logging if NULL 4.46 +bool LockNode::is_nested_lock_region(Compile * c) { 4.47 BoxLockNode* box = box_node()->as_BoxLock(); 4.48 int stk_slot = box->stack_slot(); 4.49 - if (stk_slot <= 0) 4.50 + if (stk_slot <= 0) { 4.51 +#ifdef ASSERT 4.52 + this->log_lock_optimization(c, "eliminate_lock_INLR_1"); 4.53 +#endif 4.54 return false; // External lock or it is not Box (Phi node). 4.55 + } 4.56 4.57 // Ignore complex cases: merged locks or multiple locks. 4.58 Node* obj = obj_node(); 4.59 LockNode* unique_lock = NULL; 4.60 - if (!box->is_simple_lock_region(&unique_lock, obj) || 4.61 - (unique_lock != this)) { 4.62 + if (!box->is_simple_lock_region(&unique_lock, obj)) { 4.63 +#ifdef ASSERT 4.64 + this->log_lock_optimization(c, "eliminate_lock_INLR_2a"); 4.65 +#endif 4.66 + return false; 4.67 + } 4.68 + if (unique_lock != this) { 4.69 +#ifdef ASSERT 4.70 + this->log_lock_optimization(c, "eliminate_lock_INLR_2b"); 4.71 +#endif 4.72 return false; 4.73 } 4.74 4.75 @@ -1778,6 +1802,9 @@ 4.76 } 4.77 } 4.78 } 4.79 +#ifdef ASSERT 4.80 + this->log_lock_optimization(c, "eliminate_lock_INLR_3"); 4.81 +#endif 4.82 return false; 4.83 } 4.84 4.85 @@ -1809,8 +1836,40 @@ 4.86 // The lock could be marked eliminated by lock coarsening 4.87 // code during first IGVN before EA. Replace coarsened flag 4.88 // to eliminate all associated locks/unlocks. 4.89 +#ifdef ASSERT 4.90 + this->log_lock_optimization(phase->C, "eliminate_lock_set_non_esc2"); 4.91 +#endif 4.92 this->set_non_esc_obj(); 4.93 } 4.94 } 4.95 return result; 4.96 } 4.97 + 4.98 +const char * AbstractLockNode::kind_as_string() const { 4.99 + return is_coarsened() ? "coarsened" : 4.100 + is_nested() ? "nested" : 4.101 + is_non_esc_obj() ? "non_escaping" : 4.102 + "?"; 4.103 +} 4.104 + 4.105 +void AbstractLockNode::log_lock_optimization(Compile *C, const char * tag) const { 4.106 + if (C == NULL) { 4.107 + return; 4.108 + } 4.109 + CompileLog* log = C->log(); 4.110 + if (log != NULL) { 4.111 + log->begin_head("%s lock='%d' compile_id='%d' class_id='%s' kind='%s'", 4.112 + tag, is_Lock(), C->compile_id(), 4.113 + is_Unlock() ? "unlock" : is_Lock() ? "lock" : "?", 4.114 + kind_as_string()); 4.115 + log->stamp(); 4.116 + log->end_head(); 4.117 + JVMState* p = is_Unlock() ? (as_Unlock()->dbg_jvms()) : jvms(); 4.118 + while (p != NULL) { 4.119 + log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); 4.120 + p = p->caller(); 4.121 + } 4.122 + log->tail(tag); 4.123 + } 4.124 +} 4.125 +
5.1 --- a/src/share/vm/opto/callnode.hpp Wed Feb 11 18:56:26 2015 -0800 5.2 +++ b/src/share/vm/opto/callnode.hpp Fri Feb 20 22:12:53 2015 -0500 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -985,6 +985,9 @@ 5.11 bool is_coarsened() const { return (_kind == Coarsened); } 5.12 bool is_nested() const { return (_kind == Nested); } 5.13 5.14 + const char * kind_as_string() const; 5.15 + void log_lock_optimization(Compile* c, const char * tag) const; 5.16 + 5.17 void set_non_esc_obj() { _kind = NonEscObj; set_eliminated_lock_counter(); } 5.18 void set_coarsened() { _kind = Coarsened; set_eliminated_lock_counter(); } 5.19 void set_nested() { _kind = Nested; set_eliminated_lock_counter(); } 5.20 @@ -1045,15 +1048,24 @@ 5.21 } 5.22 5.23 bool is_nested_lock_region(); // Is this Lock nested? 5.24 + bool is_nested_lock_region(Compile * c); // Why isn't this Lock nested? 5.25 }; 5.26 5.27 //------------------------------Unlock--------------------------------------- 5.28 // High-level unlock operation 5.29 class UnlockNode : public AbstractLockNode { 5.30 +private: 5.31 +#ifdef ASSERT 5.32 + JVMState* const _dbg_jvms; // Pointer to list of JVM State objects 5.33 +#endif 5.34 public: 5.35 virtual int Opcode() const; 5.36 virtual uint size_of() const; // Size is bigger 5.37 - UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf ) { 5.38 + UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf ) 5.39 +#ifdef ASSERT 5.40 + , _dbg_jvms(NULL) 5.41 +#endif 5.42 + { 5.43 init_class_id(Class_Unlock); 5.44 init_flags(Flag_is_macro); 5.45 C->add_macro_node(this); 5.46 @@ -1061,6 +1073,14 @@ 5.47 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 5.48 // unlock is never a safepoint 5.49 virtual bool guaranteed_safepoint() { return false; } 5.50 +#ifdef ASSERT 5.51 + void set_dbg_jvms(JVMState* s) { 5.52 + *(JVMState**)&_dbg_jvms = s; // override const attribute in the accessor 5.53 + } 5.54 + JVMState* dbg_jvms() const { return _dbg_jvms; } 5.55 +#else 5.56 + JVMState* dbg_jvms() const { return NULL; } 5.57 +#endif 5.58 }; 5.59 5.60 #endif // SHARE_VM_OPTO_CALLNODE_HPP
6.1 --- a/src/share/vm/opto/escape.cpp Wed Feb 11 18:56:26 2015 -0800 6.2 +++ b/src/share/vm/opto/escape.cpp Fri Feb 20 22:12:53 2015 -0500 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -1794,6 +1794,9 @@ 6.11 // The lock could be marked eliminated by lock coarsening 6.12 // code during first IGVN before EA. Replace coarsened flag 6.13 // to eliminate all associated locks/unlocks. 6.14 +#ifdef ASSERT 6.15 + alock->log_lock_optimization(C, "eliminate_lock_set_non_esc3"); 6.16 +#endif 6.17 alock->set_non_esc_obj(); 6.18 } 6.19 }
7.1 --- a/src/share/vm/opto/graphKit.cpp Wed Feb 11 18:56:26 2015 -0800 7.2 +++ b/src/share/vm/opto/graphKit.cpp Fri Feb 20 22:12:53 2015 -0500 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. 7.6 + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -3211,6 +3211,9 @@ 7.11 7.12 const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type(); 7.13 UnlockNode *unlock = new (C) UnlockNode(C, tf); 7.14 +#ifdef ASSERT 7.15 + unlock->set_dbg_jvms(sync_jvms()); 7.16 +#endif 7.17 uint raw_idx = Compile::AliasIdxRaw; 7.18 unlock->init_req( TypeFunc::Control, control() ); 7.19 unlock->init_req( TypeFunc::Memory , memory(raw_idx) );
8.1 --- a/src/share/vm/opto/macro.cpp Wed Feb 11 18:56:26 2015 -0800 8.2 +++ b/src/share/vm/opto/macro.cpp Fri Feb 20 22:12:53 2015 -0500 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 8.6 + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -1890,7 +1890,7 @@ 8.11 // Box is used only in one lock region. Mark this box as eliminated. 8.12 _igvn.hash_delete(oldbox); 8.13 oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value 8.14 - _igvn.hash_insert(oldbox); 8.15 + _igvn.hash_insert(oldbox); 8.16 8.17 for (uint i = 0; i < oldbox->outcnt(); i++) { 8.18 Node* u = oldbox->raw_out(i); 8.19 @@ -1899,6 +1899,9 @@ 8.20 // Check lock's box since box could be referenced by Lock's debug info. 8.21 if (alock->box_node() == oldbox) { 8.22 // Mark eliminated all related locks and unlocks. 8.23 +#ifdef ASSERT 8.24 + alock->log_lock_optimization(C, "eliminate_lock_set_non_esc4"); 8.25 +#endif 8.26 alock->set_non_esc_obj(); 8.27 } 8.28 } 8.29 @@ -1925,6 +1928,9 @@ 8.30 AbstractLockNode* alock = u->as_AbstractLock(); 8.31 if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) { 8.32 // Replace Box and mark eliminated all related locks and unlocks. 8.33 +#ifdef ASSERT 8.34 + alock->log_lock_optimization(C, "eliminate_lock_set_non_esc5"); 8.35 +#endif 8.36 alock->set_non_esc_obj(); 8.37 _igvn.rehash_node_delayed(alock); 8.38 alock->set_box_node(newbox); 8.39 @@ -1971,26 +1977,38 @@ 8.40 return; 8.41 } else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened 8.42 // Only Lock node has JVMState needed here. 8.43 - if (alock->jvms() != NULL && alock->as_Lock()->is_nested_lock_region()) { 8.44 - // Mark eliminated related nested locks and unlocks. 8.45 - Node* obj = alock->obj_node(); 8.46 - BoxLockNode* box_node = alock->box_node()->as_BoxLock(); 8.47 - assert(!box_node->is_eliminated(), "should not be marked yet"); 8.48 - // Note: BoxLock node is marked eliminated only here 8.49 - // and it is used to indicate that all associated lock 8.50 - // and unlock nodes are marked for elimination. 8.51 - box_node->set_eliminated(); // Box's hash is always NO_HASH here 8.52 - for (uint i = 0; i < box_node->outcnt(); i++) { 8.53 - Node* u = box_node->raw_out(i); 8.54 - if (u->is_AbstractLock()) { 8.55 - alock = u->as_AbstractLock(); 8.56 - if (alock->box_node() == box_node) { 8.57 - // Verify that this Box is referenced only by related locks. 8.58 - assert(alock->obj_node()->eqv_uncast(obj), ""); 8.59 - // Mark all related locks and unlocks. 8.60 - alock->set_nested(); 8.61 + // Not that preceding claim is documented anywhere else. 8.62 + if (alock->jvms() != NULL) { 8.63 + if (alock->as_Lock()->is_nested_lock_region()) { 8.64 + // Mark eliminated related nested locks and unlocks. 8.65 + Node* obj = alock->obj_node(); 8.66 + BoxLockNode* box_node = alock->box_node()->as_BoxLock(); 8.67 + assert(!box_node->is_eliminated(), "should not be marked yet"); 8.68 + // Note: BoxLock node is marked eliminated only here 8.69 + // and it is used to indicate that all associated lock 8.70 + // and unlock nodes are marked for elimination. 8.71 + box_node->set_eliminated(); // Box's hash is always NO_HASH here 8.72 + for (uint i = 0; i < box_node->outcnt(); i++) { 8.73 + Node* u = box_node->raw_out(i); 8.74 + if (u->is_AbstractLock()) { 8.75 + alock = u->as_AbstractLock(); 8.76 + if (alock->box_node() == box_node) { 8.77 + // Verify that this Box is referenced only by related locks. 8.78 + assert(alock->obj_node()->eqv_uncast(obj), ""); 8.79 + // Mark all related locks and unlocks. 8.80 +#ifdef ASSERT 8.81 + alock->log_lock_optimization(C, "eliminate_lock_set_nested"); 8.82 +#endif 8.83 + alock->set_nested(); 8.84 + } 8.85 } 8.86 } 8.87 + } else { 8.88 +#ifdef ASSERT 8.89 + alock->log_lock_optimization(C, "eliminate_lock_NOT_nested_lock_region"); 8.90 + if (C->log() != NULL) 8.91 + alock->as_Lock()->is_nested_lock_region(C); // rerun for debugging output 8.92 +#endif 8.93 } 8.94 } 8.95 return; 8.96 @@ -2035,19 +2053,10 @@ 8.97 assert(oldbox->is_eliminated(), "should be done already"); 8.98 } 8.99 #endif 8.100 - CompileLog* log = C->log(); 8.101 - if (log != NULL) { 8.102 - log->head("eliminate_lock lock='%d'", 8.103 - alock->is_Lock()); 8.104 - JVMState* p = alock->jvms(); 8.105 - while (p != NULL) { 8.106 - log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); 8.107 - p = p->caller(); 8.108 - } 8.109 - log->tail("eliminate_lock"); 8.110 - } 8.111 8.112 - #ifndef PRODUCT 8.113 + alock->log_lock_optimization(C, "eliminate_lock"); 8.114 + 8.115 +#ifndef PRODUCT 8.116 if (PrintEliminateLocks) { 8.117 if (alock->is_Lock()) { 8.118 tty->print_cr("++++ Eliminated: %d Lock", alock->_idx); 8.119 @@ -2055,7 +2064,7 @@ 8.120 tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx); 8.121 } 8.122 } 8.123 - #endif 8.124 +#endif 8.125 8.126 Node* mem = alock->in(TypeFunc::Memory); 8.127 Node* ctrl = alock->in(TypeFunc::Control);
9.1 --- a/src/share/vm/runtime/basicLock.cpp Wed Feb 11 18:56:26 2015 -0800 9.2 +++ b/src/share/vm/runtime/basicLock.cpp Fri Feb 20 22:12:53 2015 -0500 9.3 @@ -1,5 +1,5 @@ 9.4 /* 9.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 9.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 9.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.8 * 9.9 * This code is free software; you can redistribute it and/or modify it 9.10 @@ -28,6 +28,9 @@ 9.11 9.12 void BasicLock::print_on(outputStream* st) const { 9.13 st->print("monitor"); 9.14 + markOop moop = displaced_header(); 9.15 + if (moop != NULL) 9.16 + moop->print_on(st); 9.17 } 9.18 9.19 void BasicLock::move_to(oop obj, BasicLock* dest) {
10.1 --- a/src/share/vm/runtime/vframe.cpp Wed Feb 11 18:56:26 2015 -0800 10.2 +++ b/src/share/vm/runtime/vframe.cpp Fri Feb 20 22:12:53 2015 -0500 10.3 @@ -1,5 +1,5 @@ 10.4 /* 10.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 10.6 + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 10.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.8 * 10.9 * This code is free software; you can redistribute it and/or modify it 10.10 @@ -189,6 +189,7 @@ 10.11 if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code 10.12 if (monitor->owner_is_scalar_replaced()) { 10.13 Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); 10.14 + // format below for lockbits matches this one. 10.15 st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name()); 10.16 } else { 10.17 oop obj = monitor->owner(); 10.18 @@ -206,9 +207,10 @@ 10.19 // see if we have completed the lock or we are blocked trying to 10.20 // acquire it - we can only be blocked if the monitor is inflated 10.21 10.22 + markOop mark = NULL; 10.23 const char *lock_state = "locked"; // assume we have the monitor locked 10.24 if (!found_first_monitor && frame_count == 0) { 10.25 - markOop mark = monitor->owner()->mark(); 10.26 + mark = monitor->owner()->mark(); 10.27 if (mark->has_monitor() && 10.28 ( // we have marked ourself as pending on this monitor 10.29 mark->monitor() == thread()->current_pending_monitor() || 10.30 @@ -216,11 +218,19 @@ 10.31 !mark->monitor()->is_entered(thread()) 10.32 )) { 10.33 lock_state = "waiting to lock"; 10.34 + } else { 10.35 + mark = NULL; // Disable printing below 10.36 } 10.37 } 10.38 + print_locked_object_class_name(st, monitor->owner(), lock_state); 10.39 + if (Verbose && mark != NULL) { 10.40 + // match with format above, replacing "-" with " ". 10.41 + st->print("\t lockbits="); 10.42 + mark->print_on(st); 10.43 + st->cr(); 10.44 + } 10.45 10.46 found_first_monitor = true; 10.47 - print_locked_object_class_name(st, monitor->owner(), lock_state); 10.48 } 10.49 } 10.50 } 10.51 @@ -578,10 +588,15 @@ 10.52 tty->print("( null )"); 10.53 } else { 10.54 monitor->owner()->print_value(); 10.55 - tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner()); 10.56 + tty->print("(owner=" INTPTR_FORMAT ")", (address)monitor->owner()); 10.57 } 10.58 - if (monitor->eliminated() && is_compiled_frame()) 10.59 - tty->print(" ( lock is eliminated )"); 10.60 + if (monitor->eliminated()) { 10.61 + if(is_compiled_frame()) { 10.62 + tty->print(" ( lock is eliminated in compiled frame )"); 10.63 + } else { 10.64 + tty->print(" ( lock is eliminated, frame not compiled )"); 10.65 + } 10.66 + } 10.67 tty->cr(); 10.68 tty->print("\t "); 10.69 monitor->lock()->print_on(tty);