--- old/src/share/vm/opto/callnode.cpp 2015-02-12 16:42:18.000000000 -0500 +++ new/src/share/vm/opto/callnode.cpp 2015-02-12 16:42:18.000000000 -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,"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, "eliminate_lock_set_coarsened"); +#endif lock->set_coarsened(); } } else if (ctrl->is_Region() && @@ -1784,6 +1791,48 @@ return false; } +#ifdef ASSERT +bool LockNode::is_nested_lock_region_debug(Phase * p) { + BoxLockNode* box = box_node()->as_BoxLock(); + int stk_slot = box->stack_slot(); + if (stk_slot <= 0) { + this->log_lock_optimization(p, "eliminate_lock_INLR_1"); + 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)) { + this->log_lock_optimization(p, "eliminate_lock_INLR_2a"); + return false; + } + if (unique_lock != this) { + this->log_lock_optimization(p, "eliminate_lock_INLR_2b"); + return false; + } + + // Look for external lock for the same object. + SafePointNode* sfn = this->as_SafePoint(); + JVMState* youngest_jvms = sfn->jvms(); + int max_depth = youngest_jvms->depth(); + for (int depth = 1; depth <= max_depth; depth++) { + JVMState* jvms = youngest_jvms->of_depth(depth); + int num_mon = jvms->nof_monitors(); + // Loop over monitors + for (int idx = 0; idx < num_mon; idx++) { + Node* obj_node = sfn->monitor_obj(jvms, idx); + BoxLockNode* box_node = sfn->monitor_box(jvms, idx)->as_BoxLock(); + if ((box_node->stack_slot() < stk_slot) && obj_node->eqv_uncast(obj)) { + return true; + } + } + } + this->log_lock_optimization(p, "eliminate_lock_INLR_3"); + return false; +} +#endif + //============================================================================= uint UnlockNode::size_of() const { return sizeof(*this); } @@ -1812,12 +1861,40 @@ // 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, "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(Phase *phase, const char * tag) const { + Compile * C = phase->C; + 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),