Skip to content

Commit af4d560

Browse files
committed
8303951: Add asserts before record_method_not_compilable where possible
Reviewed-by: kvn, thartmann
1 parent c433862 commit af4d560

File tree

10 files changed

+58
-6
lines changed

10 files changed

+58
-6
lines changed

src/hotspot/share/compiler/compileBroker.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -2277,7 +2277,8 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
22772277
DirectivesStack::release(directive);
22782278

22792279
if (!ci_env.failing() && !task->is_success()) {
2280-
//assert(false, "compiler should always document failure");
2280+
assert(ci_env.failure_reason() != nullptr, "expect failure reason");
2281+
assert(false, "compiler should always document failure: %s", ci_env.failure_reason());
22812282
// The compiler elected, without comment, not to register a result.
22822283
// Do not attempt further compilations of this method.
22832284
ci_env.record_method_not_compilable("compile failed");

src/hotspot/share/opto/buildOopMap.cpp

+10-2
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,11 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i
251251

252252
// Check for a legal reg name in the oopMap and bailout if it is not.
253253
if (!omap->legal_vm_reg_name(r)) {
254-
regalloc->C->record_method_not_compilable("illegal oopMap register name");
254+
stringStream ss;
255+
ss.print("illegal oopMap register name: ");
256+
r->print_on(&ss);
257+
assert(false, "%s", ss.as_string());
258+
regalloc->C->record_method_not_compilable(ss.as_string());
255259
continue;
256260
}
257261
if( t->is_ptr()->_offset == 0 ) { // Not derived?
@@ -318,7 +322,11 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i
318322
assert( !OptoReg::is_valid(_callees[reg]), "oop can't be callee save" );
319323
// Check for a legal reg name in the oopMap and bailout if it is not.
320324
if (!omap->legal_vm_reg_name(r)) {
321-
regalloc->C->record_method_not_compilable("illegal oopMap register name");
325+
stringStream ss;
326+
ss.print("illegal oopMap register name: ");
327+
r->print_on(&ss);
328+
assert(false, "%s", ss.as_string());
329+
regalloc->C->record_method_not_compilable(ss.as_string());
322330
continue;
323331
}
324332
if( mcall ) {

src/hotspot/share/opto/compile.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,11 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
753753
}
754754
if (failing()) return;
755755
if (cg == nullptr) {
756-
record_method_not_compilable("cannot parse method");
756+
const char* reason = InlineTree::check_can_parse(method());
757+
assert(reason != nullptr, "expect reason for parse failure");
758+
stringStream ss;
759+
ss.print("cannot parse method: %s", reason);
760+
record_method_not_compilable(ss.as_string());
757761
return;
758762
}
759763

@@ -762,7 +766,10 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
762766
JVMState* jvms = build_start_state(start(), tf());
763767
if ((jvms = cg->generate(jvms)) == nullptr) {
764768
if (!failure_reason_is(C2Compiler::retry_class_loading_during_parsing())) {
765-
record_method_not_compilable("method parse failed");
769+
assert(failure_reason() != nullptr, "expect reason for parse failure");
770+
stringStream ss;
771+
ss.print("method parse failed: %s", failure_reason());
772+
record_method_not_compilable(ss.as_string());
766773
}
767774
return;
768775
}
@@ -3922,6 +3929,8 @@ bool Compile::final_graph_reshaping() {
39223929
// an infinite loop may have been eliminated by the optimizer,
39233930
// in which case the graph will be empty.
39243931
if (root()->req() == 1) {
3932+
// Do not compile method that is only a trivial infinite loop,
3933+
// since the content of the loop may have been eliminated.
39253934
record_method_not_compilable("trivial infinite loop");
39263935
return true;
39273936
}
@@ -3987,8 +3996,11 @@ bool Compile::final_graph_reshaping() {
39873996
}
39883997
}
39893998
}
3999+
39904000
// Recheck with a better notion of 'required_outcnt'
39914001
if (n->outcnt() != required_outcnt) {
4002+
DEBUG_ONLY( n->dump_bfs(1, 0, "-"); );
4003+
assert(false, "malformed control flow");
39924004
record_method_not_compilable("malformed control flow");
39934005
return true; // Not all targets reachable!
39944006
}
@@ -4007,6 +4019,9 @@ bool Compile::final_graph_reshaping() {
40074019
// must be infinite loops.
40084020
for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++)
40094021
if (!frc._visited.test(n->fast_out(j)->_idx)) {
4022+
DEBUG_ONLY( n->fast_out(j)->dump(); );
4023+
DEBUG_ONLY( n->dump_bfs(1, 0, "-"); );
4024+
assert(false, "infinite loop");
40104025
record_method_not_compilable("infinite loop");
40114026
return true; // Found unvisited kid; must be unreach
40124027
}

src/hotspot/share/opto/domgraph.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ void PhaseCFG::build_dominator_tree() {
8686
// such dead loops (as was done for the NTarjan code farther below).
8787
// Since this situation is so unlikely, instead I've decided to bail out.
8888
// CNC 7/24/2001
89+
assert(false, "unreachable loop");
8990
C->record_method_not_compilable("unreachable loop");
9091
return;
9192
}

src/hotspot/share/opto/gcm.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,7 @@ void PhaseCFG::global_code_motion() {
15001500
Node_Stack stack((C->live_nodes() >> 2) + 16); // pre-grow
15011501
if (!schedule_early(visited, stack)) {
15021502
// Bailout without retry
1503+
assert(false, "early schedule failed");
15031504
C->record_method_not_compilable("early schedule failed");
15041505
return;
15051506
}
@@ -1600,6 +1601,7 @@ void PhaseCFG::global_code_motion() {
16001601
Block* block = get_block(i);
16011602
if (!schedule_local(block, ready_cnt, visited, recalc_pressure_nodes)) {
16021603
if (!C->failure_reason_is(C2Compiler::retry_no_subsuming_loads())) {
1604+
assert(false, "local schedule failed");
16031605
C->record_method_not_compilable("local schedule failed");
16041606
}
16051607
_regalloc = nullptr;

src/hotspot/share/opto/loopnode.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -4310,6 +4310,7 @@ void PhaseIdealLoop::build_and_optimize() {
43104310
if (!has_node(C->root())) {
43114311
if (!_verify_only) {
43124312
C->clear_major_progress();
4313+
assert(false, "empty program detected during loop optimization");
43134314
C->record_method_not_compilable("empty program detected during loop optimization");
43144315
}
43154316
return;
@@ -5171,6 +5172,7 @@ int PhaseIdealLoop::build_loop_tree_impl( Node *n, int pre_order ) {
51715172
m->dump();
51725173
}
51735174
#endif
5175+
// This is a rare case that we do not want to handle in C2.
51745176
C->record_method_not_compilable("unhandled CFG detected during loop optimization");
51755177
return pre_order;
51765178
}

src/hotspot/share/opto/matcher.cpp

+15-1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ OptoReg::Name Matcher::warp_incoming_stk_arg( VMReg reg ) {
142142
_in_arg_limit = OptoReg::add(warped, 1); // Bump max stack slot seen
143143
if (!RegMask::can_represent_arg(warped)) {
144144
// the compiler cannot represent this method's calling sequence
145+
// Bailout. We do not have space to represent all arguments.
145146
C->record_method_not_compilable("unsupported incoming calling sequence");
146147
return OptoReg::Bad;
147148
}
@@ -311,6 +312,7 @@ void Matcher::match( ) {
311312

312313
if (!RegMask::can_represent_arg(OptoReg::add(_out_arg_limit,-1))) {
313314
// the compiler cannot represent this method's calling sequence
315+
// Bailout. We do not have space to represent all arguments.
314316
C->record_method_not_compilable("must be able to represent all call arguments in reg mask");
315317
}
316318

@@ -358,6 +360,7 @@ void Matcher::match( ) {
358360
Node* xroot = xform( C->root(), 1 );
359361
if (xroot == nullptr) {
360362
Matcher::soft_match_failure(); // recursive matching process failed
363+
assert(false, "instruction match failed");
361364
C->record_method_not_compilable("instruction match failed");
362365
} else {
363366
// During matching shared constants were attached to C->root()
@@ -389,7 +392,15 @@ void Matcher::match( ) {
389392
}
390393
}
391394
if (C->top() == nullptr || C->root() == nullptr) {
392-
C->record_method_not_compilable("graph lost"); // %%% cannot happen?
395+
// New graph lost. This is due to a compilation failure we encountered earlier.
396+
stringStream ss;
397+
if (C->failure_reason() != nullptr) {
398+
ss.print("graph lost: %s", C->failure_reason());
399+
} else {
400+
assert(C->failure_reason() != nullptr, "graph lost: reason unknown");
401+
ss.print("graph lost: reason unknown");
402+
}
403+
C->record_method_not_compilable(ss.as_string());
393404
}
394405
if (C->failing()) {
395406
// delete old;
@@ -1242,6 +1253,7 @@ OptoReg::Name Matcher::warp_outgoing_stk_arg( VMReg reg, OptoReg::Name begin_out
12421253
if( warped >= out_arg_limit_per_call )
12431254
out_arg_limit_per_call = OptoReg::add(warped,1);
12441255
if (!RegMask::can_represent_arg(warped)) {
1256+
// Bailout. For example not enough space on stack for all arguments. Happens for methods with too many arguments.
12451257
C->record_method_not_compilable("unsupported calling sequence");
12461258
return OptoReg::Bad;
12471259
}
@@ -1434,6 +1446,7 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) {
14341446
uint r_cnt = mcall->tf()->range()->cnt();
14351447
MachProjNode *proj = new MachProjNode( mcall, r_cnt+10000, RegMask::Empty, MachProjNode::fat_proj );
14361448
if (!RegMask::can_represent_arg(OptoReg::Name(out_arg_limit_per_call-1))) {
1449+
// Bailout. We do not have space to represent all arguments.
14371450
C->record_method_not_compilable("unsupported outgoing calling sequence");
14381451
} else {
14391452
for (int i = begin_out_arg_area; i < out_arg_limit_per_call; i++)
@@ -1621,6 +1634,7 @@ Node* Matcher::Label_Root(const Node* n, State* svec, Node* control, Node*& mem)
16211634
// out of stack space. See bugs 6272980 & 6227033 for more info.
16221635
LabelRootDepth++;
16231636
if (LabelRootDepth > MaxLabelRootDepth) {
1637+
// Bailout. Can for example be hit with a deep chain of operations.
16241638
C->record_method_not_compilable("Out of stack space, increase MaxLabelRootDepth");
16251639
return nullptr;
16261640
}

src/hotspot/share/opto/output.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2849,6 +2849,8 @@ void Scheduling::anti_do_def( Block *b, Node *def, OptoReg::Name def_reg, int is
28492849
pinch = new Node(1); // Pinch point to-be
28502850
}
28512851
if (pinch->_idx >= _regalloc->node_regs_max_index()) {
2852+
DEBUG_ONLY( pinch->dump(); );
2853+
assert(false, "too many D-U pinch points: %d >= %d", pinch->_idx, _regalloc->node_regs_max_index());
28522854
_cfg->C->record_method_not_compilable("too many D-U pinch points");
28532855
return;
28542856
}

src/hotspot/share/opto/parse1.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ void Parse::load_interpreter_state(Node* osr_buf) {
213213
}
214214
// Do not OSR inside finally clauses:
215215
if (osr_block->has_trap_at(osr_block->start())) {
216+
assert(false, "OSR starts with an immediate trap");
216217
C->record_method_not_compilable("OSR starts with an immediate trap");
217218
return;
218219
}
@@ -253,6 +254,7 @@ void Parse::load_interpreter_state(Node* osr_buf) {
253254
MethodLivenessResult live_locals = method()->liveness_at_bci(osr_bci());
254255
if (!live_locals.is_valid()) {
255256
// Degenerate or breakpointed method.
257+
assert(false, "OSR in empty or breakpointed method");
256258
C->record_method_not_compilable("OSR in empty or breakpointed method");
257259
return;
258260
}
@@ -429,6 +431,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
429431
_iter.reset_to_method(method());
430432
_flow = method()->get_flow_analysis();
431433
if (_flow->failing()) {
434+
assert(false, "type flow failed during parsing");
432435
C->record_method_not_compilable(_flow->failure_reason());
433436
}
434437

@@ -507,6 +510,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
507510
_entry_bci = C->entry_bci();
508511
_flow = method()->get_osr_flow_analysis(osr_bci());
509512
if (_flow->failing()) {
513+
assert(false, "type flow analysis failed for OSR compilation");
510514
C->record_method_not_compilable(_flow->failure_reason());
511515
#ifndef PRODUCT
512516
if (PrintOpto && (Verbose || WizardMode)) {
@@ -1044,6 +1048,7 @@ void Parse::do_exits() {
10441048
// loading. It could also be due to an error, so mark this method as not compilable because
10451049
// otherwise this could lead to an infinite compile loop.
10461050
// In any case, this code path is rarely (and never in my testing) reached.
1051+
assert(false, "Can't determine return type.");
10471052
C->record_method_not_compilable("Can't determine return type.");
10481053
return;
10491054
}
@@ -1119,6 +1124,7 @@ SafePointNode* Parse::create_entry_map() {
11191124
// Check for really stupid bail-out cases.
11201125
uint len = TypeFunc::Parms + method()->max_locals() + method()->max_stack();
11211126
if (len >= 32760) {
1127+
// Bailout expected, this is a very rare edge case.
11221128
C->record_method_not_compilable("too many local variables");
11231129
return nullptr;
11241130
}

src/hotspot/share/opto/reg_split.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ Node* clone_node(Node* def, Block *b, Compile* C) {
306306
C->record_failure(C2Compiler::retry_no_subsuming_loads());
307307
} else {
308308
// Bailout without retry
309+
assert(false, "RA Split failed: attempt to clone node with anti_dependence");
309310
C->record_method_not_compilable("RA Split failed: attempt to clone node with anti_dependence");
310311
}
311312
return 0;

0 commit comments

Comments
 (0)