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;