< prev index next >

src/share/vm/opto/castnode.cpp

Print this page

        

*** 395,499 **** // } // // 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 --- 395,544 ---- // } // // Not joining two pointers // return join; } 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)->in(0)->as_CallStaticJava()->method() != NULL && 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()) { + igvn->set_delay_transform(true); CallNode* call = in(1)->in(0)->as_Call(); + phase->C->remove_macro_node(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)); + phase->set_type(in(1), in(1)->Value(phase)); CallProjections projs; call->extract_projections(&projs, true, true); ! Node* init_ctl = new Node(1); ! Node* init_mem = new Node(1); ! Node* init_io = new Node(1); ! Node* init_ex_ctl = new Node(1); ! Node* init_ex_mem = new Node(1); ! Node* init_ex_io = new Node(1); ! Node* res = new Node(1); ! ! Node* ctl = init_ctl; ! Node* mem = init_mem; ! Node* io = init_io; ! Node* ex_ctl = init_ex_ctl; ! Node* ex_mem = init_ex_mem; ! Node* ex_io = init_ex_io; ! ! Node* cast = phase->transform(new CastP2XNode(ctl, res)); ! Node* masked = phase->transform(new AndXNode(cast, phase->MakeConX(0x1))); ! Node* cmp = phase->transform(new CmpXNode(masked, phase->MakeConX(0x1))); ! Node* bol = phase->transform(new BoolNode(cmp, BoolTest::eq)); ! IfNode* iff = phase->transform(new IfNode(ctl, bol, PROB_MAX, COUNT_UNKNOWN))->as_If(); ! Node* iftrue = phase->transform(new IfTrueNode(iff)); ! Node* iffalse = phase->transform(new IfFalseNode(iff)); ! ! ctl = iftrue; ! ! Node* ex_r = new RegionNode(3); ! Node* ex_mem_phi = new PhiNode(ex_r, Type::MEMORY, TypePtr::BOTTOM); ! Node* ex_io_phi = new PhiNode(ex_r, Type::ABIO); ! ! ex_r->init_req(2, ex_ctl); ! ex_mem_phi->init_req(2, ex_mem); ! ex_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); ! ex_r->init_req(1, ex_ctl); ! ex_mem_phi->init_req(1, ex_mem); ! ex_io_phi->init_req(1, ex_io); ! ! ex_r = igvn->transform(ex_r); ! ex_mem_phi = igvn->transform(ex_mem_phi); ! ex_io_phi = igvn->transform(ex_io_phi); // Create the ValueTypePtrNode. This will add extra projections // to the call. ValueTypePtrNode* vtptr = ValueTypePtrNode::make(igvn, this); // Newly allocated value type must be initialized vtptr->store(igvn, ctl, mem->as_MergeMem(), javaoop); vtptr->set_oop(javaoop); ! Node* r = new RegionNode(3); ! Node* mem_phi = new PhiNode(r, Type::MEMORY, TypePtr::BOTTOM); ! Node* io_phi = new PhiNode(r, Type::ABIO); ! Node* res_phi = new PhiNode(r, type()); ! ! r->init_req(1, ctl); ! mem_phi->init_req(1, mem); ! io_phi->init_req(1, io); ! res_phi->init_req(1, igvn->transform(vtptr)); ! ! ctl = iffalse; ! mem = init_mem; ! io = init_io; ! ! Node* castnotnull = new CastPPNode(res, TypePtr::NOTNULL); ! castnotnull->set_req(0, ctl); ! castnotnull = phase->transform(castnotnull); ! Node* ccast = clone(); ! ccast->set_req(0, ctl); ! ccast->set_req(1, castnotnull); ! ccast = phase->transform(ccast); ! ! vtptr = ValueTypePtrNode::make(*phase, mem, ccast); ! ! r->init_req(2, ctl); ! mem_phi->init_req(2, mem); ! io_phi->init_req(2, io); ! res_phi->init_req(2, igvn->transform(vtptr)); ! ! r = igvn->transform(r); ! mem_phi = igvn->transform(mem_phi); ! io_phi = igvn->transform(io_phi); ! res_phi = igvn->transform(res_phi); ! ! igvn->replace_in_uses(projs.fallthrough_catchproj, r); ! igvn->replace_in_uses(projs.fallthrough_memproj, mem_phi); ! igvn->replace_in_uses(projs.fallthrough_ioproj, io_phi); ! igvn->replace_in_uses(projs.resproj, res_phi); ! igvn->replace_in_uses(projs.catchall_catchproj, ex_r); ! igvn->replace_in_uses(projs.catchall_memproj, ex_mem_phi); ! igvn->replace_in_uses(projs.catchall_ioproj, ex_io_phi); ! ! igvn->set_delay_transform(false); ! igvn->replace_node(init_ctl, projs.fallthrough_catchproj); ! igvn->replace_node(init_mem, projs.fallthrough_memproj); ! igvn->replace_node(init_io, projs.fallthrough_ioproj); ! igvn->replace_node(res, projs.resproj); ! igvn->replace_node(init_ex_ctl, projs.catchall_catchproj); ! igvn->replace_node(init_ex_mem, projs.catchall_memproj); ! igvn->replace_node(init_ex_io, projs.catchall_ioproj); return this; } else { CallNode* call = in(1)->in(0)->as_Call(); // We now know the return type of the call
< prev index next >