< 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,580 ---- // } // // 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(); + + // We need an oop pointer in case allocation elimination + // fails. Allocate a new instance here. + MergeMemNode* all_mem = MergeMemNode::make(mem); + jint lhelper = vk->layout_helper(); + assert(lhelper != Klass::_lh_neutral_value, "unsupported"); + + AllocateNode* alloc = new AllocateNode(phase->C, + AllocateNode::alloc_type(Type::TOP), + ctl, + mem, + io, + phase->MakeConX(Klass::layout_helper_size_in_bytes(lhelper)), + phase->makecon(TypeKlassPtr::make(vk)), + phase->intcon(0), + NULL); + alloc->set_req(TypeFunc::FramePtr, call->in(TypeFunc::FramePtr)); + phase->C->add_safepoint_edges(alloc, call->jvms()); + Node* n = igvn->transform(alloc); + assert(n == alloc, "node shouldn't go away"); + + ctl = igvn->transform(new ProjNode(alloc, TypeFunc::Control)); + mem = igvn->transform(new ProjNode(alloc, TypeFunc::Memory, true)); + all_mem->set_memory_at(Compile::AliasIdxRaw, mem); + + io = igvn->transform(new ProjNode(alloc, TypeFunc::I_O, true)); + Node* catc = igvn->transform(new CatchNode(ctl, io, 2)); + Node* norm = igvn->transform(new CatchProjNode(catc, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci)); + Node* excp = igvn->transform(new CatchProjNode(catc, CatchProjNode::catch_all_index, CatchProjNode::no_handler_bci)); + + 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(1, excp); + mem_phi->init_req(1, igvn->transform(all_mem)); + io_phi->init_req(1, io); + r->init_req(2, ex_ctl); + mem_phi->init_req(2, ex_mem); + io_phi->init_req(2, 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); + + ctl = norm; + mem = igvn->transform(new ProjNode(alloc, TypeFunc::Memory)); + io = igvn->transform(new ProjNode(alloc, TypeFunc::I_O, false)); + Node* rawoop = igvn->transform(new ProjNode(alloc, TypeFunc::Parms)); + + MemBarNode* membar = MemBarNode::make(phase->C, Op_Initialize, Compile::AliasIdxRaw, rawoop); + membar->set_req(TypeFunc::Control, ctl); + + InitializeNode* init = membar->as_Initialize(); + + const TypeOopPtr* oop_type = type()->is_oopptr(); + MergeMemNode* minit_in = MergeMemNode::make(mem); + init->set_req(InitializeNode::Memory, minit_in); + n = igvn->transform(membar); + assert(n == membar, "node shouldn't go away"); + ctl = igvn->transform(new ProjNode(membar, TypeFunc::Control)); + mem = igvn->transform(new ProjNode(membar, TypeFunc::Memory)); + + Node* m = projs.fallthrough_memproj; + MergeMemNode* out_mem_merge = MergeMemNode::make(m); + for (int i = 0, len = vk->nof_nonstatic_fields(); i < len; i++) { + ciField* field = vk->nonstatic_field_at(i); + if (field->offset() >= TrackedInitializationLimit * HeapWordSize) + continue; + int fieldidx = phase->C->alias_type(field)->index(); + minit_in->set_memory_at(fieldidx, m); + out_mem_merge->set_memory_at(fieldidx, mem); + } + + n = igvn->transform(minit_in); + assert(n == minit_in, "node shouldn't go away"); + out_mem_merge->set_memory_at(Compile::AliasIdxRaw, mem); + + Node* javaoop = igvn->transform(new CheckCastPPNode(ctl, rawoop, oop_type)); + + // 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, out_mem_merge, javaoop); + igvn->set_delay_transform(false); + vtptr->set_oop(javaoop); + + mem = igvn->transform(out_mem_merge); + 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 >