< prev index next >
src/share/vm/opto/cfgnode.cpp
Print this page
@@ -1641,10 +1641,59 @@
}
return vt;
}
}
+ if (type()->isa_valuetypeptr() && can_reshape) {
+ // If the Phi merges the result from a mix of constant and non
+ // constant method handles, only some of its inputs are
+ // ValueTypePtr nodes and we can't push the ValueTypePtr node down
+ // to remove the need for allocations. This if fixed by transforming:
+ //
+ // (Phi ValueTypePtr#1 Node#2) to (Phi ValueTypePtr#1 CheckCastPP#2)
+ //
+ // Then pushing the CheckCastPP up through Phis until it reaches
+ // the non constant method handle call. The type of the return
+ // value is then known from the type of the CheckCastPP. A
+ // ValueTypePtr can be created by adding projections to the call
+ // for all values being returned. See
+ // CheckCastPPNode::Ideal(). That ValueTypePtr node can then be
+ // pushed down through Phis.
+ const TypeValueTypePtr* vtptr = NULL;
+ for (uint i = 1; i < req(); i++) {
+ if (in(i) != NULL && in(i)->is_ValueTypePtr()) {
+ const TypeValueTypePtr* t = phase->type(in(i))->is_valuetypeptr();
+ if (vtptr == NULL) {
+ vtptr = t;
+ } else {
+ assert(vtptr == t, "Phi should merge identical value types");
+ }
+ } else {
+ assert(in(i) == NULL || vtptr == NULL || phase->type(in(i))->higher_equal(vtptr) || phase->type(in(i)) == Type::TOP ||
+ phase->type(in(i))->is_valuetypeptr()->value_type()->value_klass() == phase->C->env()->___Value_klass(), "bad type");
+ }
+ }
+ if (vtptr != NULL) {
+ // One input is a value type. All inputs must have the same type.
+ bool progress = false;
+ PhaseIterGVN* igvn = phase->is_IterGVN();
+ for (uint i = 1; i < req(); i++) {
+ if (in(i) != NULL && !phase->type(in(i))->higher_equal(vtptr)) {
+ // Can't transform because CheckCastPPNode::Identity can
+ // push the cast up through another Phi and cause this same
+ // transformation to run again, indefinitely
+ Node* cast = igvn->register_new_node_with_optimizer(new CheckCastPPNode(NULL, in(i), vtptr));
+ set_req(i, cast);
+ progress = true;
+ }
+ }
+ if (progress) {
+ return this;
+ }
+ }
+ }
+
Node *top = phase->C->top();
bool new_phi = (outcnt() == 0); // transforming new Phi
// No change for igvn if new phi is not hooked
if (new_phi && can_reshape)
return NULL;
@@ -2343,10 +2392,16 @@
if( phase->type(in(1)) == Type::TOP ) return in(1);
if( phase->type(in(0)) == Type::TOP ) return in(0);
// We only come from CatchProj, unless the CatchProj goes away.
// If the CatchProj is optimized away, then we just carry the
// exception oop through.
+
+ // CheckCastPPNode::Ideal() for value types reuses the exception
+ // paths of a call to perform an allocation: we can see a Phi here.
+ if (in(1)->is_Phi()) {
+ return this;
+ }
CallNode *call = in(1)->in(0)->as_Call();
return ( in(0)->is_CatchProj() && in(0)->in(0)->in(1) == in(1) )
? this
: call->in(TypeFunc::Parms);
< prev index next >