< prev index next >
src/share/vm/opto/castnode.cpp
Print this page
*** 27,38 ****
--- 27,40 ----
#include "opto/callnode.hpp"
#include "opto/castnode.hpp"
#include "opto/connode.hpp"
#include "opto/matcher.hpp"
#include "opto/phaseX.hpp"
+ #include "opto/rootnode.hpp"
#include "opto/subnode.hpp"
#include "opto/type.hpp"
+ #include "opto/valuetypenode.hpp"
//=============================================================================
// If input is already higher or equal to cast type, then this is an identity.
Node* ConstraintCastNode::Identity(PhaseGVN* phase) {
Node* dom = dominating_cast(phase);
*** 278,287 ****
--- 280,309 ----
//=============================================================================
//------------------------------Identity---------------------------------------
// If input is already higher or equal to cast type, then this is an identity.
Node* CheckCastPPNode::Identity(PhaseGVN* phase) {
+ // This is a value type, its input is a phi. That phi is also a
+ // value type of that same type and its inputs are value types of
+ // the same type: push the cast through the phi.
+ if (phase->is_IterGVN() &&
+ in(0) == NULL &&
+ type()->isa_valuetypeptr() &&
+ in(1) != NULL &&
+ in(1)->is_Phi()) {
+ PhaseIterGVN* igvn = phase->is_IterGVN();
+ Node* phi = in(1);
+ const Type* vtptr = type();
+ for (uint i = 1; i < phi->req(); i++) {
+ if (phi->in(i) != NULL && !phase->type(phi->in(i))->higher_equal(vtptr)) {
+ Node* cast = phase->transform(new CheckCastPPNode(NULL, phi->in(i), vtptr));
+ igvn->replace_input_of(phi, i, cast);
+ }
+ }
+ return phi;
+ }
+
Node* dom = dominating_cast(phase);
if (dom != NULL) {
return dom;
}
if (_carry_dependency) {
*** 373,382 ****
--- 395,526 ----
// }
// // Not joining two pointers
// return join;
}
+ static void replace_in_uses(PhaseIterGVN *igvn, Node* n, Node* m, uint last) {
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ Node* u = n->fast_out(i);
+ if (u->_idx < last) {
+ assert(n != u && m != u, "cycle!");
+ igvn->rehash_node_delayed(u);
+ int nb = u->replace_edge(n, m);
+ --i, imax -= nb;
+ }
+ }
+ }
+
+ Node* CheckCastPPNode::Ideal(PhaseGVN *phase, bool can_reshape) {
+ // This is a value type. Its input is the return of a call: the call
+ // returns a value type and we now know its exact type: build a
+ // ValueTypePtrNode from the call.
+ if (can_reshape &&
+ in(0) == NULL &&
+ phase->C->can_add_value_type_ptr() &&
+ type()->isa_valuetypeptr() &&
+ in(1) != NULL && in(1)->is_Proj() &&
+ in(1)->in(0) != NULL && in(1)->in(0)->is_CallStaticJava() &&
+ in(1)->as_Proj()->_con == TypeFunc::Parms) {
+ ciValueKlass* vk = type()->is_valuetypeptr()->value_type()->value_klass();
+ assert(vk != phase->C->env()->___Value_klass(), "why cast to __Value?");
+ PhaseIterGVN *igvn = phase->is_IterGVN();
+
+ if (ValueTypeReturnedAsFields && vk->can_be_returned_as_fields()) {
+ CallNode* call = in(1)->in(0)->as_Call();
+ // We now know the return type of the call
+ const TypeTuple *range_sig = TypeTuple::make_range(vk, false);
+ const TypeTuple *range_cc = TypeTuple::make_range(vk, true);
+ assert(range_sig != call->_tf->range_sig() && range_cc != call->_tf->range_cc(), "type should change");
+ call->_tf = TypeFunc::make(call->_tf->domain_sig(), call->_tf->domain_cc(),
+ range_sig, range_cc);
+ phase->set_type(call, call->Value(phase));
+
+ CallProjections projs;
+ call->extract_projections(&projs, true, true);
+ Node* ctl = projs.fallthrough_catchproj;
+ Node* mem = projs.fallthrough_memproj;
+ Node* io = projs.fallthrough_ioproj;
+ Node* ex_ctl = projs.catchall_catchproj;
+ Node* ex_mem = projs.catchall_memproj;
+ Node* ex_io = projs.catchall_ioproj;
+
+ uint last = phase->C->unique();
+
+ Node* r = new RegionNode(3);
+ Node* mem_phi = new PhiNode(r, Type::MEMORY, TypePtr::BOTTOM);
+ Node* io_phi = new PhiNode(r, Type::ABIO);
+
+ r->init_req(2, ex_ctl);
+ mem_phi->init_req(2, ex_mem);
+ io_phi->init_req(2, ex_io);
+
+ // We need an oop pointer in case allocation elimination
+ // fails. Allocate a new instance here.
+ Node* javaoop = ValueTypeBaseNode::allocate(type(), ctl, mem, io,
+ call->in(TypeFunc::FramePtr),
+ ex_ctl, ex_mem, ex_io,
+ call->jvms(), igvn);
+
+
+
+ r->init_req(1, ex_ctl);
+ mem_phi->init_req(1, ex_mem);
+ io_phi->init_req(1, ex_io);
+
+ r = igvn->transform(r);
+ mem_phi = igvn->transform(mem_phi);
+ io_phi = igvn->transform(io_phi);
+
+ replace_in_uses(igvn, ex_ctl, r, last);
+ replace_in_uses(igvn, ex_mem, mem_phi, last);
+ replace_in_uses(igvn, ex_io, io_phi, last);
+
+ // Create the ValueTypePtrNode. This will add extra projections
+ // to the call.
+ ValueTypePtrNode* vtptr = ValueTypePtrNode::make(igvn, this);
+ igvn->set_delay_transform(true); // stores can be captured. If
+ // they are the whole subgraph
+ // shouldn't go away.
+
+ // Newly allocated value type must be initialized
+ vtptr->store(igvn, ctl, mem->as_MergeMem(), javaoop);
+ igvn->set_delay_transform(false);
+ vtptr->set_oop(javaoop);
+
+ mem = igvn->transform(mem);
+ replace_in_uses(igvn, projs.fallthrough_catchproj, ctl, last);
+ replace_in_uses(igvn, projs.fallthrough_memproj, mem, last);
+ replace_in_uses(igvn, projs.fallthrough_ioproj, io, last);
+
+ igvn->replace_node(in(1), igvn->transform(vtptr));
+
+ return this;
+ } else {
+ CallNode* call = in(1)->in(0)->as_Call();
+ // We now know the return type of the call
+ const TypeTuple *range = TypeTuple::make_range(vk, false);
+ if (range != call->_tf->range_sig()) {
+ // Build the ValueTypePtrNode by loading the fields. Use call
+ // return as oop edge in the ValueTypePtrNode.
+ call->_tf = TypeFunc::make(call->_tf->domain_sig(), call->_tf->domain_cc(),
+ range, range);
+ phase->set_type(call, call->Value(phase));
+ phase->set_type(in(1), in(1)->Value(phase));
+ uint last = phase->C->unique();
+ CallNode* call = in(1)->in(0)->as_Call();
+ CallProjections projs;
+ call->extract_projections(&projs, true, true);
+ Node* mem = projs.fallthrough_memproj;
+ Node* vtptr = ValueTypePtrNode::make(*phase, mem, in(1));
+
+ return vtptr;
+ }
+ }
+ }
+ return NULL;
+ }
+
//=============================================================================
//------------------------------Value------------------------------------------
const Type* CastX2PNode::Value(PhaseGVN* phase) const {
const Type* t = phase->type(in(1));
if (t == Type::TOP) return Type::TOP;
< prev index next >