< 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 >