mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 01:54:47 +02:00
8268347: C2: nested locks optimization may create unbalanced monitor enter/exit code
Reviewed-by: roland, vlivanov, dcubed
This commit is contained in:
parent
4a6da99f28
commit
4d8b5c70df
11 changed files with 369 additions and 39 deletions
|
@ -432,6 +432,7 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
|||
remove_useless_nodes(_skeleton_predicate_opaqs, useful);
|
||||
remove_useless_nodes(_expensive_nodes, useful); // remove useless expensive nodes
|
||||
remove_useless_nodes(_for_post_loop_igvn, useful); // remove useless node recorded for post loop opts IGVN pass
|
||||
remove_useless_coarsened_locks(useful); // remove useless coarsened locks nodes
|
||||
|
||||
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
|
||||
bs->eliminate_useless_gc_barriers(useful, this);
|
||||
|
@ -501,6 +502,12 @@ void Compile::print_compile_messages() {
|
|||
tty->print_cr("** Bailout: Recompile without boxing elimination **");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if ((_do_locks_coarsening != EliminateLocks) && PrintOpto) {
|
||||
// Recompiling without locks coarsening
|
||||
tty->print_cr("*********************************************************");
|
||||
tty->print_cr("** Bailout: Recompile without locks coarsening **");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if (env()->break_at_compile()) {
|
||||
// Open the debugger when compiling this method.
|
||||
tty->print("### Breaking when compiling: ");
|
||||
|
@ -528,13 +535,15 @@ debug_only( int Compile::_debug_idx = 100000; )
|
|||
|
||||
|
||||
Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
|
||||
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, bool install_code, DirectiveSet* directive)
|
||||
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing,
|
||||
bool do_locks_coarsening, bool install_code, DirectiveSet* directive)
|
||||
: Phase(Compiler),
|
||||
_compile_id(ci_env->compile_id()),
|
||||
_subsume_loads(subsume_loads),
|
||||
_do_escape_analysis(do_escape_analysis),
|
||||
_install_code(install_code),
|
||||
_eliminate_boxing(eliminate_boxing),
|
||||
_do_locks_coarsening(do_locks_coarsening),
|
||||
_method(target),
|
||||
_entry_bci(osr_bci),
|
||||
_stub_function(NULL),
|
||||
|
@ -566,6 +575,7 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
|
|||
_skeleton_predicate_opaqs (comp_arena(), 8, 0, NULL),
|
||||
_expensive_nodes (comp_arena(), 8, 0, NULL),
|
||||
_for_post_loop_igvn(comp_arena(), 8, 0, NULL),
|
||||
_coarsened_locks (comp_arena(), 8, 0, NULL),
|
||||
_congraph(NULL),
|
||||
NOT_PRODUCT(_printer(NULL) COMMA)
|
||||
_dead_node_list(comp_arena()),
|
||||
|
@ -832,6 +842,7 @@ Compile::Compile( ciEnv* ci_env,
|
|||
_do_escape_analysis(false),
|
||||
_install_code(true),
|
||||
_eliminate_boxing(false),
|
||||
_do_locks_coarsening(false),
|
||||
_method(NULL),
|
||||
_entry_bci(InvocationEntryBci),
|
||||
_stub_function(stub_function),
|
||||
|
@ -4447,6 +4458,101 @@ void Compile::add_expensive_node(Node * n) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Track coarsened Lock and Unlock nodes.
|
||||
*/
|
||||
|
||||
class Lock_List : public Node_List {
|
||||
uint _origin_cnt;
|
||||
public:
|
||||
Lock_List(Arena *a, uint cnt) : Node_List(a), _origin_cnt(cnt) {}
|
||||
uint origin_cnt() const { return _origin_cnt; }
|
||||
};
|
||||
|
||||
void Compile::add_coarsened_locks(GrowableArray<AbstractLockNode*>& locks) {
|
||||
int length = locks.length();
|
||||
if (length > 0) {
|
||||
// Have to keep this list until locks elimination during Macro nodes elimination.
|
||||
Lock_List* locks_list = new (comp_arena()) Lock_List(comp_arena(), length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
AbstractLockNode* lock = locks.at(i);
|
||||
assert(lock->is_coarsened(), "expecting only coarsened AbstractLock nodes, but got '%s'[%d] node", lock->Name(), lock->_idx);
|
||||
locks_list->push(lock);
|
||||
}
|
||||
_coarsened_locks.append(locks_list);
|
||||
}
|
||||
}
|
||||
|
||||
void Compile::remove_useless_coarsened_locks(Unique_Node_List& useful) {
|
||||
int count = coarsened_count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Node_List* locks_list = _coarsened_locks.at(i);
|
||||
for (uint j = 0; j < locks_list->size(); j++) {
|
||||
Node* lock = locks_list->at(j);
|
||||
assert(lock->is_AbstractLock(), "sanity");
|
||||
if (!useful.member(lock)) {
|
||||
locks_list->yank(lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compile::remove_coarsened_lock(Node* n) {
|
||||
if (n->is_AbstractLock()) {
|
||||
int count = coarsened_count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
Node_List* locks_list = _coarsened_locks.at(i);
|
||||
locks_list->yank(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Compile::coarsened_locks_consistent() {
|
||||
int count = coarsened_count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
bool unbalanced = false;
|
||||
bool modified = false; // track locks kind modifications
|
||||
Lock_List* locks_list = (Lock_List*)_coarsened_locks.at(i);
|
||||
uint size = locks_list->size();
|
||||
if (size != locks_list->origin_cnt()) {
|
||||
unbalanced = true; // Some locks were removed from list
|
||||
} else {
|
||||
for (uint j = 0; j < size; j++) {
|
||||
Node* lock = locks_list->at(j);
|
||||
// All nodes in group should have the same state (modified or not)
|
||||
if (!lock->as_AbstractLock()->is_coarsened()) {
|
||||
if (j == 0) {
|
||||
// first on list was modified, the rest should be too for consistency
|
||||
modified = true;
|
||||
} else if (!modified) {
|
||||
// this lock was modified but previous locks on the list were not
|
||||
unbalanced = true;
|
||||
break;
|
||||
}
|
||||
} else if (modified) {
|
||||
// previous locks on list were modified but not this lock
|
||||
unbalanced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unbalanced) {
|
||||
// unbalanced monitor enter/exit - only some [un]lock nodes were removed or modified
|
||||
#ifdef ASSERT
|
||||
if (PrintEliminateLocks) {
|
||||
tty->print_cr("=== unbalanced coarsened locks ===");
|
||||
for (uint l = 0; l < size; l++) {
|
||||
locks_list->at(l)->dump();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
record_failure(C2Compiler::retry_no_locks_coarsening());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the speculative part of types and clean up the graph
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue