# HG changeset patch # User vlivanov # Date 1426876894 25200 # Node ID a57955ac2bc1f7f053543d3a92b642670b4f6bf0 # Parent 0dce8215957a00047cbc2ede2311048d25fd18a0 8074548: Never-taken branches cause repeated deopts in MHs.GWT case Reviewed-by: jrose, kvn diff -r 0dce8215957a -r a57955ac2bc1 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Fri Mar 20 11:41:34 2015 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Mar 20 11:41:34 2015 -0700 @@ -5873,12 +5873,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 CmpINode(result, intcon(expected_val))); + Node* test = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); + + IfNode* check = create_and_map_if(control(), test, PROB_ALWAYS, COUNT_UNKNOWN); + Node* fast_path = _gvn.transform(new IfTrueNode(check)); + Node* slow_path = _gvn.transform(new 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 ProfileBooleanNode(argument(0), false_cnt, true_cnt)); + Node* profile = _gvn.transform(new ProfileBooleanNode(result, false_cnt, true_cnt)); C->record_for_igvn(profile); set_result(profile); return true;