src/share/vm/opto/matcher.cpp

Print this page
rev 5728 : 8029015: PPC64 (part 216): opto: trap based null and range checks

@@ -2393,10 +2393,73 @@
     }
   }
   return false;
 }
 
+// Check whether node n is a branch to an uncommon trap that we could
+// optimize as test with very high branch costs in case of going to
+// the uncommon trap. The code must be able to be recompiled to use
+// a cheaper test.
+bool Matcher::branches_to_uncommon_trap(const Node *n) {
+  // Don't do it for natives, adapters, or runtime stubs
+  Compile *C = Compile::current();
+  if (!C->is_method_compilation()) return false;
+
+  assert(n->is_If(), "You should only call this on if nodes.");
+  IfNode *ifn = n->as_If();
+
+  Node *ifFalse = NULL;
+  for (DUIterator_Fast imax, i = ifn->fast_outs(imax); i < imax; i++) {
+    if (ifn->fast_out(i)->is_IfFalse()) {
+      ifFalse = ifn->fast_out(i);
+      break;
+    }
+  }
+  assert(ifFalse, "An If should have an ifFalse. Graph is broken.");
+
+  Node *reg = ifFalse;
+  int cnt = 4; // We must protect against cycles.  Limit to 4 iterations.
+               // Alternatively use visited set?  Seems too expensive.
+  while (reg != NULL && cnt > 0) {
+    CallNode *call = NULL;
+    RegionNode *nxt_reg = NULL;
+    for (DUIterator_Fast imax, i = reg->fast_outs(imax); i < imax; i++) {
+      Node *o = reg->fast_out(i);
+      if (o->is_Call()) {
+        call = o->as_Call();
+      }
+      if (o->is_Region()) {
+        nxt_reg = o->as_Region();
+      }
+    }
+
+    if (call &&
+        call->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point()) {
+      const Type* trtype = call->in(TypeFunc::Parms)->bottom_type();
+      if (trtype->isa_int() && trtype->is_int()->is_con()) {
+        jint tr_con = trtype->is_int()->get_con();
+        Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(tr_con);
+        Deoptimization::DeoptAction action = Deoptimization::trap_request_action(tr_con);
+        assert((int)reason < (int)BitsPerInt, "recode bit map");
+
+        if (is_set_nth_bit(C->allowed_deopt_reasons(), (int)reason)
+            && action != Deoptimization::Action_none) {
+          // This uncommon trap is sure to recompile, eventually.
+          // When that happens, C->too_many_traps will prevent
+          // this transformation from happening again.
+          return true;
+        }
+      }
+    }
+
+    reg = nxt_reg;
+    cnt--;
+  }
+
+  return false;
+}
+
 //=============================================================================
 //---------------------------State---------------------------------------------
 State::State(void) {
 #ifdef ASSERT
   _id = 0;