changeset 22986:d9593687713d

8074548: Never-taken branches cause repeated deopts in MHs.GWT case Reviewed-by: jrose, kvn
author vlivanov
date Fri, 20 Mar 2015 11:41:34 -0700
parents eb8b5cc64669
children 4eeec0cdeb6a
files src/share/vm/opto/library_call.cpp
diffstat 1 files changed, 37 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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;