提交 20bc114d 编写于 作者: D drchase

8069412: Locks need better debug-printing support

Summary: Added better debug-printing support and enhanced LogCompilation tool
Reviewed-by: kvn, roland, dholmes
上级 c777559f
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,12 +24,12 @@ ...@@ -24,12 +24,12 @@
/** /**
* A SAX based parser of LogCompilation output from HotSpot. It takes a complete * A SAX based parser of LogCompilation output from HotSpot. It takes a complete
* @author never
*/ */
package com.sun.hotspot.tools.compiler; package com.sun.hotspot.tools.compiler;
import java.io.FileReader; import java.io.FileReader;
import java.io.PrintStream;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
...@@ -133,6 +133,44 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -133,6 +133,44 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
} }
}; };
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 ArrayList<LogEvent> events = new ArrayList<LogEvent>();
private HashMap<String, String> types = new HashMap<String, String>(); private HashMap<String, String> types = new HashMap<String, String>();
...@@ -145,6 +183,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -145,6 +183,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
private Compilation compile; private Compilation compile;
private CallSite site; private CallSite site;
private Stack<Phase> phaseStack = new Stack<Phase>(); private Stack<Phase> phaseStack = new Stack<Phase>();
private LockElimination currentLockElimination;
private UncommonTrapEvent currentTrap; private UncommonTrapEvent currentTrap;
private Stack<CallSite> late_inline_scope; private Stack<CallSite> late_inline_scope;
...@@ -188,7 +227,12 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -188,7 +227,12 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
} }
LogParser log = new LogParser(); 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 // Associate compilations with their NMethods
for (NMethod nm : log.nmethods.values()) { for (NMethod nm : log.nmethods.values()) {
...@@ -370,6 +414,15 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -370,6 +414,15 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
// uncommon trap inserted during parsing. // uncommon trap inserted during parsing.
// ignore for now // 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")) { } else if (qname.equals("late_inline")) {
late_inline_scope = new Stack<CallSite>(); late_inline_scope = new Stack<CallSite>();
site = new CallSite(-999, method(search(atts, "method"))); site = new CallSite(-999, method(search(atts, "method")));
...@@ -378,13 +431,14 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -378,13 +431,14 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
// <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/> // <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
if (currentTrap != null) { if (currentTrap != null) {
currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci"))); 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 (late_inline_scope != null) { } else if (late_inline_scope != null) {
bci = Integer.parseInt(search(atts, "bci")); bci = Integer.parseInt(search(atts, "bci"));
site = new CallSite(bci, method(search(atts, "method"))); site = new CallSite(bci, method(search(atts, "method")));
late_inline_scope.push(site); late_inline_scope.push(site);
} else { } else {
// Ignore <eliminate_allocation type='667'>, // Ignore <eliminate_allocation type='667'>,
// <eliminate_lock lock='1'>,
// <replace_string_concat arguments='2' string_alloc='0' multiple='0'> // <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
} }
} else if (qname.equals("nmethod")) { } else if (qname.equals("nmethod")) {
...@@ -437,6 +491,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -437,6 +491,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
scopes.pop(); scopes.pop();
} else if (qname.equals("uncommon_trap")) { } else if (qname.equals("uncommon_trap")) {
currentTrap = null; currentTrap = null;
} else if (qname.startsWith("eliminate_lock")) {
currentLockElimination = null;
} else if (qname.equals("late_inline")) { } else if (qname.equals("late_inline")) {
// Populate late inlining info. // Populate late inlining info.
...@@ -445,8 +501,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -445,8 +501,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
CallSite caller = late_inline_scope.pop(); CallSite caller = late_inline_scope.pop();
Method m = compile.getMethod(); Method m = compile.getMethod();
if (m != caller.getMethod()) { if (m != caller.getMethod()) {
System.out.println(m); System.err.println(m);
System.out.println(caller.getMethod() + " bci: " + bci); System.err.println(caller.getMethod() + " bci: " + bci);
throw new InternalError("call site and late_inline info don't match"); throw new InternalError("call site and late_inline info don't match");
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -50,7 +50,7 @@ class UncommonTrapEvent extends BasicLogEvent { ...@@ -50,7 +50,7 @@ class UncommonTrapEvent extends BasicLogEvent {
} }
public void print(PrintStream stream) { 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()); stream.print(getJvms());
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,17 +25,40 @@ ...@@ -25,17 +25,40 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "oops/markOop.hpp" #include "oops/markOop.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/objectMonitor.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
void markOopDesc::print_on(outputStream* st) const { void markOopDesc::print_on(outputStream* st) const {
if (is_locked()) { if (is_marked()) {
st->print("locked(" INTPTR_FORMAT ")->", value()); st->print(" marked(" INTPTR_FORMAT ")", value());
markOop(*(markOop*)value())->print_on(st); } 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 { } else {
assert(is_unlocked() || has_bias_pattern(), "just checking"); assert(is_unlocked() || has_bias_pattern(), "just checking");
st->print("mark("); st->print("mark(");
if (has_bias_pattern()) st->print("biased,"); if (has_bias_pattern()) st->print("biased,");
st->print("hash %#lx,", hash()); st->print("hash %#lx,", hash());
st->print("age %d)", age()); st->print("age %d)", age());
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "compiler/compileLog.hpp"
#include "ci/bcEscapeAnalyzer.hpp" #include "ci/bcEscapeAnalyzer.hpp"
#include "compiler/oopMap.hpp" #include "compiler/oopMap.hpp"
#include "opto/callGenerator.hpp" #include "opto/callGenerator.hpp"
...@@ -1670,6 +1671,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1670,6 +1671,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// The lock could be marked eliminated by lock coarsening // The lock could be marked eliminated by lock coarsening
// code during first IGVN before EA. Replace coarsened flag // code during first IGVN before EA. Replace coarsened flag
// to eliminate all associated locks/unlocks. // 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(); this->set_non_esc_obj();
return result; return result;
} }
...@@ -1731,6 +1735,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1731,6 +1735,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
AbstractLockNode* lock = lock_ops.at(i); AbstractLockNode* lock = lock_ops.at(i);
// Mark it eliminated by coarsening and update any counters // 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(); lock->set_coarsened();
} }
} else if (ctrl->is_Region() && } else if (ctrl->is_Region() &&
...@@ -1749,16 +1756,33 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1749,16 +1756,33 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//============================================================================= //=============================================================================
bool LockNode::is_nested_lock_region() { 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(); BoxLockNode* box = box_node()->as_BoxLock();
int stk_slot = box->stack_slot(); 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). return false; // External lock or it is not Box (Phi node).
}
// Ignore complex cases: merged locks or multiple locks. // Ignore complex cases: merged locks or multiple locks.
Node* obj = obj_node(); Node* obj = obj_node();
LockNode* unique_lock = NULL; LockNode* unique_lock = NULL;
if (!box->is_simple_lock_region(&unique_lock, obj) || if (!box->is_simple_lock_region(&unique_lock, obj)) {
(unique_lock != this)) { #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; return false;
} }
...@@ -1778,6 +1802,9 @@ bool LockNode::is_nested_lock_region() { ...@@ -1778,6 +1802,9 @@ bool LockNode::is_nested_lock_region() {
} }
} }
} }
#ifdef ASSERT
this->log_lock_optimization(c, "eliminate_lock_INLR_3");
#endif
return false; return false;
} }
...@@ -1809,8 +1836,40 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1809,8 +1836,40 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// The lock could be marked eliminated by lock coarsening // The lock could be marked eliminated by lock coarsening
// code during first IGVN before EA. Replace coarsened flag // code during first IGVN before EA. Replace coarsened flag
// to eliminate all associated locks/unlocks. // 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(); this->set_non_esc_obj();
} }
} }
return result; 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);
}
}
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -985,6 +985,9 @@ public: ...@@ -985,6 +985,9 @@ public:
bool is_coarsened() const { return (_kind == Coarsened); } bool is_coarsened() const { return (_kind == Coarsened); }
bool is_nested() const { return (_kind == Nested); } 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_non_esc_obj() { _kind = NonEscObj; set_eliminated_lock_counter(); }
void set_coarsened() { _kind = Coarsened; set_eliminated_lock_counter(); } void set_coarsened() { _kind = Coarsened; set_eliminated_lock_counter(); }
void set_nested() { _kind = Nested; set_eliminated_lock_counter(); } void set_nested() { _kind = Nested; set_eliminated_lock_counter(); }
...@@ -1045,15 +1048,24 @@ public: ...@@ -1045,15 +1048,24 @@ public:
} }
bool is_nested_lock_region(); // Is this Lock nested? bool is_nested_lock_region(); // Is this Lock nested?
bool is_nested_lock_region(Compile * c); // Why isn't this Lock nested?
}; };
//------------------------------Unlock--------------------------------------- //------------------------------Unlock---------------------------------------
// High-level unlock operation // High-level unlock operation
class UnlockNode : public AbstractLockNode { class UnlockNode : public AbstractLockNode {
private:
#ifdef ASSERT
JVMState* const _dbg_jvms; // Pointer to list of JVM State objects
#endif
public: public:
virtual int Opcode() const; virtual int Opcode() const;
virtual uint size_of() const; // Size is bigger 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_class_id(Class_Unlock);
init_flags(Flag_is_macro); init_flags(Flag_is_macro);
C->add_macro_node(this); C->add_macro_node(this);
...@@ -1061,6 +1073,14 @@ public: ...@@ -1061,6 +1073,14 @@ public:
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
// unlock is never a safepoint // unlock is never a safepoint
virtual bool guaranteed_safepoint() { return false; } 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
}; };
#endif // SHARE_VM_OPTO_CALLNODE_HPP #endif // SHARE_VM_OPTO_CALLNODE_HPP
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1794,6 +1794,9 @@ void ConnectionGraph::optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklis ...@@ -1794,6 +1794,9 @@ void ConnectionGraph::optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklis
// The lock could be marked eliminated by lock coarsening // The lock could be marked eliminated by lock coarsening
// code during first IGVN before EA. Replace coarsened flag // code during first IGVN before EA. Replace coarsened flag
// to eliminate all associated locks/unlocks. // to eliminate all associated locks/unlocks.
#ifdef ASSERT
alock->log_lock_optimization(C, "eliminate_lock_set_non_esc3");
#endif
alock->set_non_esc_obj(); alock->set_non_esc_obj();
} }
} }
......
/* /*
* Copyright (c) 2001, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -3211,6 +3211,9 @@ void GraphKit::shared_unlock(Node* box, Node* obj) { ...@@ -3211,6 +3211,9 @@ void GraphKit::shared_unlock(Node* box, Node* obj) {
const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type(); const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type();
UnlockNode *unlock = new (C) UnlockNode(C, tf); UnlockNode *unlock = new (C) UnlockNode(C, tf);
#ifdef ASSERT
unlock->set_dbg_jvms(sync_jvms());
#endif
uint raw_idx = Compile::AliasIdxRaw; uint raw_idx = Compile::AliasIdxRaw;
unlock->init_req( TypeFunc::Control, control() ); unlock->init_req( TypeFunc::Control, control() );
unlock->init_req( TypeFunc::Memory , memory(raw_idx) ); unlock->init_req( TypeFunc::Memory , memory(raw_idx) );
......
/* /*
* Copyright (c) 2005, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1890,7 +1890,7 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { ...@@ -1890,7 +1890,7 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) {
// Box is used only in one lock region. Mark this box as eliminated. // Box is used only in one lock region. Mark this box as eliminated.
_igvn.hash_delete(oldbox); _igvn.hash_delete(oldbox);
oldbox->as_BoxLock()->set_eliminated(); // This changes box's hash value 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++) { for (uint i = 0; i < oldbox->outcnt(); i++) {
Node* u = oldbox->raw_out(i); Node* u = oldbox->raw_out(i);
...@@ -1899,6 +1899,9 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { ...@@ -1899,6 +1899,9 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) {
// Check lock's box since box could be referenced by Lock's debug info. // Check lock's box since box could be referenced by Lock's debug info.
if (alock->box_node() == oldbox) { if (alock->box_node() == oldbox) {
// Mark eliminated all related locks and unlocks. // 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(); alock->set_non_esc_obj();
} }
} }
...@@ -1925,6 +1928,9 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { ...@@ -1925,6 +1928,9 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) {
AbstractLockNode* alock = u->as_AbstractLock(); AbstractLockNode* alock = u->as_AbstractLock();
if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) { if (alock->box_node() == oldbox && alock->obj_node()->eqv_uncast(obj)) {
// Replace Box and mark eliminated all related locks and unlocks. // 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(); alock->set_non_esc_obj();
_igvn.rehash_node_delayed(alock); _igvn.rehash_node_delayed(alock);
alock->set_box_node(newbox); alock->set_box_node(newbox);
...@@ -1971,26 +1977,38 @@ void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) { ...@@ -1971,26 +1977,38 @@ void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) {
return; return;
} else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened } else if (!alock->is_non_esc_obj()) { // Not eliminated or coarsened
// Only Lock node has JVMState needed here. // Only Lock node has JVMState needed here.
if (alock->jvms() != NULL && alock->as_Lock()->is_nested_lock_region()) { // Not that preceding claim is documented anywhere else.
// Mark eliminated related nested locks and unlocks. if (alock->jvms() != NULL) {
Node* obj = alock->obj_node(); if (alock->as_Lock()->is_nested_lock_region()) {
BoxLockNode* box_node = alock->box_node()->as_BoxLock(); // Mark eliminated related nested locks and unlocks.
assert(!box_node->is_eliminated(), "should not be marked yet"); Node* obj = alock->obj_node();
// Note: BoxLock node is marked eliminated only here BoxLockNode* box_node = alock->box_node()->as_BoxLock();
// and it is used to indicate that all associated lock assert(!box_node->is_eliminated(), "should not be marked yet");
// and unlock nodes are marked for elimination. // Note: BoxLock node is marked eliminated only here
box_node->set_eliminated(); // Box's hash is always NO_HASH here // and it is used to indicate that all associated lock
for (uint i = 0; i < box_node->outcnt(); i++) { // and unlock nodes are marked for elimination.
Node* u = box_node->raw_out(i); box_node->set_eliminated(); // Box's hash is always NO_HASH here
if (u->is_AbstractLock()) { for (uint i = 0; i < box_node->outcnt(); i++) {
alock = u->as_AbstractLock(); Node* u = box_node->raw_out(i);
if (alock->box_node() == box_node) { if (u->is_AbstractLock()) {
// Verify that this Box is referenced only by related locks. alock = u->as_AbstractLock();
assert(alock->obj_node()->eqv_uncast(obj), ""); if (alock->box_node() == box_node) {
// Mark all related locks and unlocks. // Verify that this Box is referenced only by related locks.
alock->set_nested(); 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; return;
...@@ -2035,19 +2053,10 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { ...@@ -2035,19 +2053,10 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
assert(oldbox->is_eliminated(), "should be done already"); assert(oldbox->is_eliminated(), "should be done already");
} }
#endif #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 (PrintEliminateLocks) {
if (alock->is_Lock()) { if (alock->is_Lock()) {
tty->print_cr("++++ Eliminated: %d Lock", alock->_idx); tty->print_cr("++++ Eliminated: %d Lock", alock->_idx);
...@@ -2055,7 +2064,7 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { ...@@ -2055,7 +2064,7 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx); tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx);
} }
} }
#endif #endif
Node* mem = alock->in(TypeFunc::Memory); Node* mem = alock->in(TypeFunc::Memory);
Node* ctrl = alock->in(TypeFunc::Control); Node* ctrl = alock->in(TypeFunc::Control);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
void BasicLock::print_on(outputStream* st) const { void BasicLock::print_on(outputStream* st) const {
st->print("monitor"); st->print("monitor");
markOop moop = displaced_header();
if (moop != NULL)
moop->print_on(st);
} }
void BasicLock::move_to(oop obj, BasicLock* dest) { void BasicLock::move_to(oop obj, BasicLock* dest) {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -189,6 +189,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ...@@ -189,6 +189,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code
if (monitor->owner_is_scalar_replaced()) { if (monitor->owner_is_scalar_replaced()) {
Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); 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()); st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name());
} else { } else {
oop obj = monitor->owner(); oop obj = monitor->owner();
...@@ -206,9 +207,10 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ...@@ -206,9 +207,10 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
// see if we have completed the lock or we are blocked trying to // 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 // 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 const char *lock_state = "locked"; // assume we have the monitor locked
if (!found_first_monitor && frame_count == 0) { if (!found_first_monitor && frame_count == 0) {
markOop mark = monitor->owner()->mark(); mark = monitor->owner()->mark();
if (mark->has_monitor() && if (mark->has_monitor() &&
( // we have marked ourself as pending on this monitor ( // we have marked ourself as pending on this monitor
mark->monitor() == thread()->current_pending_monitor() || mark->monitor() == thread()->current_pending_monitor() ||
...@@ -216,11 +218,19 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ...@@ -216,11 +218,19 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
!mark->monitor()->is_entered(thread()) !mark->monitor()->is_entered(thread())
)) { )) {
lock_state = "waiting to lock"; 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; found_first_monitor = true;
print_locked_object_class_name(st, monitor->owner(), lock_state);
} }
} }
} }
...@@ -578,10 +588,15 @@ void javaVFrame::print() { ...@@ -578,10 +588,15 @@ void javaVFrame::print() {
tty->print("( null )"); tty->print("( null )");
} else { } else {
monitor->owner()->print_value(); monitor->owner()->print_value();
tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner()); tty->print("(owner=" INTPTR_FORMAT ")", (address)monitor->owner());
}
if (monitor->eliminated()) {
if(is_compiled_frame()) {
tty->print(" ( lock is eliminated in compiled frame )");
} else {
tty->print(" ( lock is eliminated, frame not compiled )");
}
} }
if (monitor->eliminated() && is_compiled_frame())
tty->print(" ( lock is eliminated )");
tty->cr(); tty->cr();
tty->print("\t "); tty->print("\t ");
monitor->lock()->print_on(tty); monitor->lock()->print_on(tty);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册