# HG changeset patch # User vlivanov # Date 1426876894 25200 # Node ID d9593687713d8f296d6909dbb0ed69546b79e812 # Parent eb8b5cc64669d7b4ac7ccbabe23078438b5da2aa 8074548: Never-taken branches cause repeated deopts in MHs.GWT case Reviewed-by: jrose, kvn diff -r eb8b5cc64669 -r d9593687713d src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Thu Jan 29 10:25:59 2015 -0800 +++ b/src/share/vm/opto/library_call.cpp Fri Mar 20 11:41:34 2015 -0700 @@ -6576,12 +6576,46 @@ Deoptimization::Action_reinterpret); return true; } + + // result is a boolean (0 or 1) and its profile (false_cnt & true_cnt) + // is a number of each value occurrences. + Node* result = argument(0); + if (false_cnt == 0 || true_cnt == 0) { + // According to profile, one value has been never seen. + int expected_val = (false_cnt == 0) ? 1 : 0; + + Node* cmp = _gvn.transform(new (C) CmpINode(result, intcon(expected_val))); + Node* test = _gvn.transform(new (C) BoolNode(cmp, BoolTest::eq)); + + IfNode* check = create_and_map_if(control(), test, PROB_ALWAYS, COUNT_UNKNOWN); + Node* fast_path = _gvn.transform(new (C) IfTrueNode(check)); + Node* slow_path = _gvn.transform(new (C) IfFalseNode(check)); + + { // Slow path: uncommon trap for never seen value and then reexecute + // MethodHandleImpl::profileBoolean() to bump the count, so JIT knows + // the value has been seen at least once. + PreserveJVMState pjvms(this); + PreserveReexecuteState preexecs(this); + jvms()->set_should_reexecute(true); + + set_control(slow_path); + set_i_o(i_o()); + + uncommon_trap_exact(Deoptimization::Reason_intrinsic, + Deoptimization::Action_reinterpret); + } + // The guard for never seen value enables sharpening of the result and + // returning a constant. It allows to eliminate branches on the same value + // later on. + set_control(fast_path); + result = intcon(expected_val); + } // Stop profiling. - // MethodHandleImpl::profileBoolean() has profiling logic in it's bytecode. - // By replacing method's body with profile data (represented as ProfileBooleanNode + // MethodHandleImpl::profileBoolean() has profiling logic in its bytecode. + // By replacing method body with profile data (represented as ProfileBooleanNode // on IR level) we effectively disable profiling. // It enables full speed execution once optimized code is generated. - Node* profile = _gvn.transform(new (C) ProfileBooleanNode(argument(0), false_cnt, true_cnt)); + Node* profile = _gvn.transform(new (C) ProfileBooleanNode(result, false_cnt, true_cnt)); C->record_for_igvn(profile); set_result(profile); return true;