diff --git a/.hgtags b/.hgtags index 4737e76436d1a11888079795b8f94566160f9bfb..f48768375768ed9985d8a0cc395724619c9d376a 100644 --- a/.hgtags +++ b/.hgtags @@ -584,6 +584,10 @@ c3933f52eeb33f70ee562464edddfe9f01d944fd jdk8u40-b20 d2e9a6bec4f2eec8506eed16f7324992a85d8480 hs25.40-b24 25ec4a67433744bbe3406e5069e7fd1876ebbf2f jdk8u40-b21 0f0cb4eeab2d871274f4ffdcd6017d2fdfa89238 hs25.40-b25 +0ee548a1cda08c884eccd563e2d5fdb6ee769b5a jdk8u40-b22 +0e67683b700174eab71ea205d1cfa4f1cf4523ba jdk8u40-b23 +fa4e797f61e6dda1a60e06944018213bff2a1b76 jdk8u40-b24 +698dd28ecc785ffc43e3f12266b13e85382c26a8 jdk8u40-b25 d9349fa8822336e0244da0a8448f3e6b2d62741d jdk8u60-b00 d9349fa8822336e0244da0a8448f3e6b2d62741d hs25.60-b00 ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01 @@ -597,3 +601,5 @@ ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01 74931e85352be8556eaa511ca0dd7c38fe272ec3 hs25.60-b05 b13f1890afb8abc31ecb9c21fd2ba95aba3e33f8 jdk8u60-b05 b17a8a22a0344e3c93e2e4677de20d35f99cf4f5 hs25.60-b06 +7b70923c8e04920b60278f90ad23a63c773cee7b jdk8u60-b06 +d51ef6da82b486e7b2b3c08eef9ca0a186935ded hs25.60-b07 diff --git a/make/hotspot_version b/make/hotspot_version index 3cdc5902d21be4c6d88ade415ba6536140f6f926..e35d14d0bad73c6806458ff69810ceb0cf9379c8 100644 --- a/make/hotspot_version +++ b/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015 HS_MAJOR_VER=25 HS_MINOR_VER=60 -HS_BUILD_NUMBER=07 +HS_BUILD_NUMBER=08 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java index ecd17b309ec7553783bd57658b5c1923ba645efb..d2b6b55116e96c1006768df8307270010812885f 100644 --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java @@ -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.ArrayList; import java.util.Collections; @@ -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 = new ArrayList(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 events = new ArrayList(); private HashMap types = new HashMap(); @@ -145,6 +183,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants private Compilation compile; private CallSite site; private Stack phaseStack = new Stack(); + private LockElimination currentLockElimination; private UncommonTrapEvent currentTrap; private Stack late_inline_scope; @@ -188,7 +227,12 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants } 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()) { @@ -370,6 +414,15 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants // 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")) { late_inline_scope = new Stack(); site = new CallSite(-999, method(search(atts, "method"))); @@ -378,13 +431,14 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants // 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 (late_inline_scope != null) { bci = Integer.parseInt(search(atts, "bci")); site = new CallSite(bci, method(search(atts, "method"))); late_inline_scope.push(site); } else { // Ignore , - // , // } } else if (qname.equals("nmethod")) { @@ -437,6 +491,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants scopes.pop(); } 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. @@ -445,8 +501,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants CallSite caller = late_inline_scope.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"); } diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java index 9aa69c42562b57cdfe527a83f4f4aae5b868fc83..231e1e4ffaf4fd43361e85b34c83fae6cadbf448 100644 --- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java +++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrapEvent.java @@ -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 @@ class UncommonTrapEvent extends BasicLogEvent { } 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()); } diff --git a/src/share/vm/oops/markOop.cpp b/src/share/vm/oops/markOop.cpp index 85dd5a06a65000b74667b8ad0800e1bf1b67d801..1cc8a19f55fe798f782b031a3bef3e8246047c69 100644 --- a/src/share/vm/oops/markOop.cpp +++ b/src/share/vm/oops/markOop.cpp @@ -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()); } diff --git a/src/share/vm/opto/callnode.cpp b/src/share/vm/opto/callnode.cpp index 365b19d2aa3c73f5666e08b81aef5ff111176114..a99af8089ee3a1faa3dcb4572b6b7a9fa4597094 100644 --- a/src/share/vm/opto/callnode.cpp +++ b/src/share/vm/opto/callnode.cpp @@ -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" @@ -1670,6 +1671,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { // 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; } @@ -1731,6 +1735,9 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { 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() && @@ -1749,16 +1756,33 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { //============================================================================= 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; } @@ -1778,6 +1802,9 @@ bool LockNode::is_nested_lock_region() { } } } +#ifdef ASSERT + this->log_lock_optimization(c, "eliminate_lock_INLR_3"); +#endif return false; } @@ -1809,8 +1836,40 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { // 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); + } +} + diff --git a/src/share/vm/opto/callnode.hpp b/src/share/vm/opto/callnode.hpp index 6eb78b0cb7bde4f6a965ceb97400a0dcabdf62ce..26f5c6ba705f602b42b33a6b1be8a0d82de24bff 100644 --- a/src/share/vm/opto/callnode.hpp +++ b/src/share/vm/opto/callnode.hpp @@ -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 @@ public: 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 @@ public: } 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 @@ public: 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 }; #endif // SHARE_VM_OPTO_CALLNODE_HPP diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp index 86bc5b47d2fe811b929b8052a240b266b039de45..03a0e2d3ae5695fb2f86e9a768390035dd74a5f8 100644 --- a/src/share/vm/opto/escape.cpp +++ b/src/share/vm/opto/escape.cpp @@ -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 @@ -1794,6 +1794,9 @@ void ConnectionGraph::optimize_ideal_graph(GrowableArray& ptr_cmp_worklis // 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(); } } diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp index ca157ec91aa0679f8ebf4156f7aeab421b8e5f65..eb26fd0f93a2834bed07d933ebd719a418747d4a 100644 --- a/src/share/vm/opto/graphKit.cpp +++ b/src/share/vm/opto/graphKit.cpp @@ -1,5 +1,5 @@ /* - * 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. * * 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) { const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type(); UnlockNode *unlock = new (C) 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) ); diff --git a/src/share/vm/opto/macro.cpp b/src/share/vm/opto/macro.cpp index 94fdbf86aacc6e00cd6258388da311be64df2974..2d555c280b578ce80961b5c1073c48ecff175b16 100644 --- a/src/share/vm/opto/macro.cpp +++ b/src/share/vm/opto/macro.cpp @@ -1,5 +1,5 @@ /* - * 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. * * 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) { // 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 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { // 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 @@ void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { 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 @@ void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) { 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 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { 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 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { tty->print_cr("++++ Eliminated: %d Unlock", alock->_idx); } } - #endif +#endif Node* mem = alock->in(TypeFunc::Memory); Node* ctrl = alock->in(TypeFunc::Control); diff --git a/src/share/vm/runtime/basicLock.cpp b/src/share/vm/runtime/basicLock.cpp index 992f735509a283661a42e2e9bf982d61bba5758e..5d69b30ae1f69126d99ce4469b003ac7b2752cd2 100644 --- a/src/share/vm/runtime/basicLock.cpp +++ b/src/share/vm/runtime/basicLock.cpp @@ -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) { diff --git a/src/share/vm/runtime/vframe.cpp b/src/share/vm/runtime/vframe.cpp index a47f96c28122b2d88648f2be6be8b440c68c40c0..5a3951e7a292c4c80d023fccb7358c574f970871 100644 --- a/src/share/vm/runtime/vframe.cpp +++ b/src/share/vm/runtime/vframe.cpp @@ -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 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { 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 (a %s)", k->external_name()); } else { oop obj = monitor->owner(); @@ -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 // 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 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { !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); } } } @@ -578,10 +588,15 @@ void javaVFrame::print() { 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()) { + 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->print("\t "); monitor->lock()->print_on(tty);