提交 190dc7bf 编写于 作者: K kvn

6775880: EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")

Summary: Create new "eliminated" BoxLock node for monitor debug info when corresponding locks are eliminated.
Reviewed-by: never
上级 81cf138c
...@@ -395,7 +395,13 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) ...@@ -395,7 +395,13 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st)
OptoReg::regname(OptoReg::c_frame_pointer), OptoReg::regname(OptoReg::c_frame_pointer),
regalloc->reg2offset(box_reg)); regalloc->reg2offset(box_reg));
} }
format_helper( regalloc, st, obj, "MON-OBJ[", i, &scobjs ); const char* obj_msg = "MON-OBJ[";
if (EliminateLocks) {
while( !box->is_BoxLock() ) box = box->in(1);
if (box->as_BoxLock()->is_eliminated())
obj_msg = "MON-OBJ(LOCK ELIMINATED)[";
}
format_helper( regalloc, st, obj, obj_msg, i, &scobjs );
} }
for (i = 0; i < (uint)scobjs.length(); i++) { for (i = 0; i < (uint)scobjs.length(); i++) {
...@@ -908,8 +914,9 @@ void SafePointNode::push_monitor(const FastLockNode *lock) { ...@@ -908,8 +914,9 @@ void SafePointNode::push_monitor(const FastLockNode *lock) {
add_req(lock->box_node()); add_req(lock->box_node());
add_req(lock->obj_node()); add_req(lock->obj_node());
} else { } else {
add_req(NULL); Node* top = Compile::current()->top();
add_req(NULL); add_req(top);
add_req(top);
} }
jvms()->set_scloff(nextmon+MonitorEdges); jvms()->set_scloff(nextmon+MonitorEdges);
jvms()->set_endoff(req()); jvms()->set_endoff(req());
...@@ -1382,7 +1389,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1382,7 +1389,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// //
// If we are locking an unescaped object, the lock/unlock is unnecessary // If we are locking an unescaped object, the lock/unlock is unnecessary
// //
ConnectionGraph *cgr = Compile::current()->congraph(); ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape; PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL) if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase); es = cgr->escape_state(obj_node(), phase);
...@@ -1450,6 +1457,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1450,6 +1457,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Mark it eliminated to update any counters // Mark it eliminated to update any counters
lock->set_eliminated(); lock->set_eliminated();
lock->set_coarsened();
} }
} else if (result != NULL && ctrl->is_Region() && } else if (result != NULL && ctrl->is_Region() &&
iter->_worklist.member(ctrl)) { iter->_worklist.member(ctrl)) {
...@@ -1484,7 +1492,7 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -1484,7 +1492,7 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// //
// If we are unlocking an unescaped object, the lock/unlock is unnecessary. // If we are unlocking an unescaped object, the lock/unlock is unnecessary.
// //
ConnectionGraph *cgr = Compile::current()->congraph(); ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape; PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL) if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase); es = cgr->escape_state(obj_node(), phase);
......
...@@ -780,7 +780,8 @@ public: ...@@ -780,7 +780,8 @@ public:
//------------------------------AbstractLockNode----------------------------------- //------------------------------AbstractLockNode-----------------------------------
class AbstractLockNode: public CallNode { class AbstractLockNode: public CallNode {
private: private:
bool _eliminate; // indicates this lock can be safely eliminated bool _eliminate; // indicates this lock can be safely eliminated
bool _coarsened; // indicates this lock was coarsened
#ifndef PRODUCT #ifndef PRODUCT
NamedCounter* _counter; NamedCounter* _counter;
#endif #endif
...@@ -801,6 +802,7 @@ protected: ...@@ -801,6 +802,7 @@ protected:
public: public:
AbstractLockNode(const TypeFunc *tf) AbstractLockNode(const TypeFunc *tf)
: CallNode(tf, NULL, TypeRawPtr::BOTTOM), : CallNode(tf, NULL, TypeRawPtr::BOTTOM),
_coarsened(false),
_eliminate(false) _eliminate(false)
{ {
#ifndef PRODUCT #ifndef PRODUCT
...@@ -819,6 +821,9 @@ public: ...@@ -819,6 +821,9 @@ public:
// mark node as eliminated and update the counter if there is one // mark node as eliminated and update the counter if there is one
void set_eliminated(); void set_eliminated();
bool is_coarsened() { return _coarsened; }
void set_coarsened() { _coarsened = true; }
// locking does not modify its arguments // locking does not modify its arguments
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;} virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}
......
...@@ -1532,11 +1532,6 @@ void Compile::Optimize() { ...@@ -1532,11 +1532,6 @@ void Compile::Optimize() {
if (failing()) return; if (failing()) return;
// get rid of the connection graph since it's information is not
// updated by optimizations
_congraph = NULL;
// Loop transforms on the ideal graph. Range Check Elimination, // Loop transforms on the ideal graph. Range Check Elimination,
// peeling, unrolling, etc. // peeling, unrolling, etc.
......
...@@ -199,7 +199,8 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform ...@@ -199,7 +199,8 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform
es = ptnode_adr(idx)->escape_state(); es = ptnode_adr(idx)->escape_state();
// if we have already computed a value, return it // if we have already computed a value, return it
if (es != PointsToNode::UnknownEscape) if (es != PointsToNode::UnknownEscape &&
ptnode_adr(idx)->node_type() == PointsToNode::JavaObject)
return es; return es;
// PointsTo() calls n->uncast() which can return a new ideal node. // PointsTo() calls n->uncast() which can return a new ideal node.
......
...@@ -44,10 +44,15 @@ BoxLockNode::BoxLockNode( int slot ) : Node( Compile::current()->root() ), ...@@ -44,10 +44,15 @@ BoxLockNode::BoxLockNode( int slot ) : Node( Compile::current()->root() ),
_inmask.Insert(reg); _inmask.Insert(reg);
} }
//-----------------------------hash--------------------------------------------
uint BoxLockNode::hash() const {
return Node::hash() + _slot + (_is_eliminated ? Compile::current()->fixed_slots() : 0);
}
//------------------------------cmp-------------------------------------------- //------------------------------cmp--------------------------------------------
uint BoxLockNode::cmp( const Node &n ) const { uint BoxLockNode::cmp( const Node &n ) const {
const BoxLockNode &bn = (const BoxLockNode &)n; const BoxLockNode &bn = (const BoxLockNode &)n;
return bn._slot == _slot; return bn._slot == _slot && bn._is_eliminated == _is_eliminated;
} }
OptoReg::Name BoxLockNode::stack_slot(Node* box_node) { OptoReg::Name BoxLockNode::stack_slot(Node* box_node) {
......
...@@ -36,7 +36,7 @@ public: ...@@ -36,7 +36,7 @@ public:
virtual const RegMask &in_RegMask(uint) const; virtual const RegMask &in_RegMask(uint) const;
virtual const RegMask &out_RegMask() const; virtual const RegMask &out_RegMask() const;
virtual uint size_of() const; virtual uint size_of() const;
virtual uint hash() const { return Node::hash() + _slot; } virtual uint hash() const;
virtual uint cmp( const Node &n ) const; virtual uint cmp( const Node &n ) const;
virtual const class Type *bottom_type() const { return TypeRawPtr::BOTTOM; } virtual const class Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
virtual uint ideal_reg() const { return Op_RegP; } virtual uint ideal_reg() const { return Op_RegP; }
......
...@@ -59,7 +59,7 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal ...@@ -59,7 +59,7 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal
for (uint i = old_dbg_start; i < oldcall->req(); i++) { for (uint i = old_dbg_start; i < oldcall->req(); i++) {
Node* old_in = oldcall->in(i); Node* old_in = oldcall->in(i);
// Clone old SafePointScalarObjectNodes, adjusting their field contents. // Clone old SafePointScalarObjectNodes, adjusting their field contents.
if (old_in->is_SafePointScalarObject()) { if (old_in != NULL && old_in->is_SafePointScalarObject()) {
SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject(); SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
uint old_unique = C->unique(); uint old_unique = C->unique();
Node* new_in = old_sosn->clone(jvms_adj, sosn_map); Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
...@@ -1509,21 +1509,63 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { ...@@ -1509,21 +1509,63 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
if (!alock->is_eliminated()) { if (!alock->is_eliminated()) {
return false; return false;
} }
// Mark the box lock as eliminated if all correspondent locks are eliminated if (alock->is_Lock() && !alock->is_coarsened()) {
// to construct correct debug info. // Create new "eliminated" BoxLock node and use it
BoxLockNode* box = alock->box_node()->as_BoxLock(); // in monitor debug info for the same object.
if (!box->is_eliminated()) { BoxLockNode* oldbox = alock->box_node()->as_BoxLock();
bool eliminate = true; Node* obj = alock->obj_node();
for (DUIterator_Fast imax, i = box->fast_outs(imax); i < imax; i++) { if (!oldbox->is_eliminated()) {
Node *lck = box->fast_out(i); BoxLockNode* newbox = oldbox->clone()->as_BoxLock();
if (lck->is_Lock() && !lck->as_AbstractLock()->is_eliminated()) { newbox->set_eliminated();
eliminate = false; transform_later(newbox);
break; // Replace old box node with new box for all users
} // of the same object.
} for (uint i = 0; i < oldbox->outcnt();) {
if (eliminate)
box->set_eliminated(); bool next_edge = true;
} Node* u = oldbox->raw_out(i);
if (u == alock) {
i++;
continue; // It will be removed below
}
if (u->is_Lock() &&
u->as_Lock()->obj_node() == obj &&
// oldbox could be referenced in debug info also
u->as_Lock()->box_node() == oldbox) {
assert(u->as_Lock()->is_eliminated(), "sanity");
_igvn.hash_delete(u);
u->set_req(TypeFunc::Parms + 1, newbox);
next_edge = false;
#ifdef ASSERT
} else if (u->is_Unlock() && u->as_Unlock()->obj_node() == obj) {
assert(u->as_Unlock()->is_eliminated(), "sanity");
#endif
}
// Replace old box in monitor debug info.
if (u->is_SafePoint() && u->as_SafePoint()->jvms()) {
SafePointNode* sfn = u->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);
Node* box_node = sfn->monitor_box(jvms, idx);
if (box_node == oldbox && obj_node == obj) {
int j = jvms->monitor_box_offset(idx);
_igvn.hash_delete(u);
u->set_req(j, newbox);
next_edge = false;
}
} // for (int idx = 0;
} // for (int depth = 1;
} // if (u->is_SafePoint()
if (next_edge) i++;
} // for (uint i = 0; i < oldbox->outcnt();)
} // if (!oldbox->is_eliminated())
} // if (alock->is_Lock() && !lock->is_coarsened())
#ifndef PRODUCT #ifndef PRODUCT
if (PrintEliminateLocks) { if (PrintEliminateLocks) {
...@@ -1562,6 +1604,15 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { ...@@ -1562,6 +1604,15 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
_igvn.subsume_node(ctrlproj, fallthroughproj); _igvn.subsume_node(ctrlproj, fallthroughproj);
_igvn.hash_delete(memproj); _igvn.hash_delete(memproj);
_igvn.subsume_node(memproj, memproj_fallthrough); _igvn.subsume_node(memproj, memproj_fallthrough);
// Delete FastLock node also if this Lock node is unique user
// (a loop peeling may clone a Lock node).
Node* flock = alock->as_Lock()->fastlock_node();
if (flock->outcnt() == 1) {
assert(flock->unique_out() == alock, "sanity");
_igvn.hash_delete(flock);
_igvn.subsume_node(flock, top());
}
} }
// Seach for MemBarRelease node and delete it also. // Seach for MemBarRelease node and delete it also.
...@@ -1887,8 +1938,28 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { ...@@ -1887,8 +1938,28 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
bool PhaseMacroExpand::expand_macro_nodes() { bool PhaseMacroExpand::expand_macro_nodes() {
if (C->macro_count() == 0) if (C->macro_count() == 0)
return false; return false;
// attempt to eliminate allocations // First, attempt to eliminate locks
bool progress = true; bool progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
Node * n = C->macro_node(i-1);
bool success = false;
debug_only(int old_macro_count = C->macro_count(););
if (n->is_AbstractLock()) {
success = eliminate_locking_node(n->as_AbstractLock());
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
_igvn.add_users_to_worklist(n);
_igvn.hash_delete(n);
_igvn.subsume_node(n, n->in(1));
success = true;
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;
}
}
// Next, attempt to eliminate allocations
progress = true;
while (progress) { while (progress) {
progress = false; progress = false;
for (int i = C->macro_count(); i > 0; i--) { for (int i = C->macro_count(); i > 0; i--) {
...@@ -1902,17 +1973,10 @@ bool PhaseMacroExpand::expand_macro_nodes() { ...@@ -1902,17 +1973,10 @@ bool PhaseMacroExpand::expand_macro_nodes() {
break; break;
case Node::Class_Lock: case Node::Class_Lock:
case Node::Class_Unlock: case Node::Class_Unlock:
success = eliminate_locking_node(n->as_AbstractLock()); assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
break; break;
default: default:
if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { assert(false, "unknown node type in macro list");
_igvn.add_users_to_worklist(n);
_igvn.hash_delete(n);
_igvn.subsume_node(n, n->in(1));
success = true;
} else {
assert(false, "unknown node type in macro list");
}
} }
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success; progress = progress || success;
......
...@@ -849,10 +849,8 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { ...@@ -849,10 +849,8 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
// Loop over monitors and insert into array // Loop over monitors and insert into array
for(idx = 0; idx < num_mon; idx++) { for(idx = 0; idx < num_mon; idx++) {
// Grab the node that defines this monitor // Grab the node that defines this monitor
Node* box_node; Node* box_node = sfn->monitor_box(jvms, idx);
Node* obj_node; Node* obj_node = sfn->monitor_obj(jvms, idx);
box_node = sfn->monitor_box(jvms, idx);
obj_node = sfn->monitor_obj(jvms, idx);
// Create ScopeValue for object // Create ScopeValue for object
ScopeValue *scval = NULL; ScopeValue *scval = NULL;
...@@ -890,6 +888,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { ...@@ -890,6 +888,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node); OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
Location basic_lock = Location::new_stk_loc(Location::normal,_regalloc->reg2offset(box_reg)); Location basic_lock = Location::new_stk_loc(Location::normal,_regalloc->reg2offset(box_reg));
while( !box_node->is_BoxLock() ) box_node = box_node->in(1);
monarray->append(new MonitorValue(scval, basic_lock, box_node->as_BoxLock()->is_eliminated())); monarray->append(new MonitorValue(scval, basic_lock, box_node->as_BoxLock()->is_eliminated()));
} }
......
/*
* Copyright 2008 Sun Microsystems, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
/*
* @test
* @bug 6775880
* @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
* @compile -source 1.4 -target 1.4 Test.java
* @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test
*/
public class Test {
int cnt;
int b[];
String s;
String test() {
String res="";
for (int i=0; i < cnt; i++) {
if (i != 0) {
res = res +".";
}
res = res + b[i];
}
return res;
}
public static void main(String[] args) {
Test t = new Test();
t.cnt = 3;
t.b = new int[3];
t.b[0] = 0;
t.b[1] = 1;
t.b[2] = 2;
int j=0;
t.s = "";
for (int i=0; i<10001; i++) {
t.s = "c";
t.s = t.test();
}
System.out.println("After s=" + t.s);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册