--- old/src/share/vm/opto/cfgnode.cpp 2017-07-25 14:58:28.887804919 +0200 +++ new/src/share/vm/opto/cfgnode.cpp 2017-07-25 14:58:23.942815232 +0200 @@ -1643,6 +1643,55 @@ } } + 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 @@ -2345,6 +2394,12 @@ // 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) )