< prev index next >

src/hotspot/share/opto/escape.cpp

Print this page

1489       assert((ptnode_adr(adr->_idx) == nullptr ||
1490               ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
1491     }
1492 #endif
1493     add_local_var_and_edge(n, PointsToNode::NoEscape,
1494                            adr, delayed_worklist);
1495   }
1496 }
1497 
1498 // Populate Connection Graph with PointsTo nodes and create simple
1499 // connection graph edges.
1500 void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
1501   assert(!_verify, "this method should not be called for verification");
1502   PhaseGVN* igvn = _igvn;
1503   uint n_idx = n->_idx;
1504   PointsToNode* n_ptn = ptnode_adr(n_idx);
1505   if (n_ptn != nullptr) {
1506     return; // No need to redefine PointsTo node during first iteration.
1507   }
1508   int opcode = n->Opcode();
1509   bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_to_con_graph(this, igvn, delayed_worklist, n, opcode);
1510   if (gc_handled) {
1511     return; // Ignore node if already handled by GC.
1512   }
1513 
1514   if (n->is_Call()) {
1515     // Arguments to allocation and locking don't escape.
1516     if (n->is_AbstractLock()) {
1517       // Put Lock and Unlock nodes on IGVN worklist to process them during
1518       // first IGVN optimization when escape information is still available.
1519       record_for_optimizer(n);
1520     } else if (n->is_Allocate()) {
1521       add_call_node(n->as_Call());
1522       record_for_optimizer(n);
1523     } else {
1524       if (n->is_CallStaticJava()) {
1525         const char* name = n->as_CallStaticJava()->_name;
1526         if (name != nullptr && strcmp(name, "uncommon_trap") == 0) {
1527           return; // Skip uncommon traps
1528         }
1529       }
1530       // Don't mark as processed since call's arguments have to be processed.
1531       delayed_worklist->push(n);
1532       // Check if a call returns an object.
1533       if ((n->as_Call()->returns_pointer() &&

1711   }
1712   return;
1713 }
1714 
1715 // Add final simple edges to graph.
1716 void ConnectionGraph::add_final_edges(Node *n) {
1717   PointsToNode* n_ptn = ptnode_adr(n->_idx);
1718 #ifdef ASSERT
1719   if (_verify && n_ptn->is_JavaObject())
1720     return; // This method does not change graph for JavaObject.
1721 #endif
1722 
1723   if (n->is_Call()) {
1724     process_call_arguments(n->as_Call());
1725     return;
1726   }
1727   assert(n->is_Store() || n->is_LoadStore() ||
1728          ((n_ptn != nullptr) && (n_ptn->ideal_node() != nullptr)),
1729          "node should be registered already");
1730   int opcode = n->Opcode();
1731   bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_final_edges(this, _igvn, n, opcode);
1732   if (gc_handled) {
1733     return; // Ignore node if already handled by GC.
1734   }
1735   switch (opcode) {
1736     case Op_AddP: {
1737       Node* base = get_addp_base(n);
1738       PointsToNode* ptn_base = ptnode_adr(base->_idx);
1739       assert(ptn_base != nullptr, "field's base should be registered");
1740       add_base(n_ptn->as_Field(), ptn_base);
1741       break;
1742     }
1743     case Op_CastPP:
1744     case Op_CheckCastPP:
1745     case Op_EncodeP:
1746     case Op_DecodeN:
1747     case Op_EncodePKlass:
1748     case Op_DecodeNKlass: {
1749       add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), nullptr);
1750       break;
1751     }
1752     case Op_CMoveP: {
1753       for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
1754         Node* in = n->in(i);

3439   BasicType bt = T_INT;
3440   if (offset == Type::OffsetBot) {
3441     // Check only oop fields.
3442     if (!adr_type->isa_aryptr() ||
3443         adr_type->isa_aryptr()->elem() == Type::BOTTOM ||
3444         adr_type->isa_aryptr()->elem()->make_oopptr() != nullptr) {
3445       // OffsetBot is used to reference array's element. Ignore first AddP.
3446       if (find_second_addp(n, n->in(AddPNode::Base)) == nullptr) {
3447         bt = T_OBJECT;
3448       }
3449     }
3450   } else if (offset != oopDesc::klass_offset_in_bytes()) {
3451     if (adr_type->isa_instptr()) {
3452       ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
3453       if (field != nullptr) {
3454         bt = field->layout_type();
3455       } else {
3456         // Check for unsafe oop field access
3457         if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3458             n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3459             n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN) ||
3460             BarrierSet::barrier_set()->barrier_set_c2()->escape_has_out_with_unsafe_object(n)) {
3461           bt = T_OBJECT;
3462           (*unsafe) = true;
3463         }
3464       }
3465     } else if (adr_type->isa_aryptr()) {
3466       if (offset == arrayOopDesc::length_offset_in_bytes()) {
3467         // Ignore array length load.
3468       } else if (find_second_addp(n, n->in(AddPNode::Base)) != nullptr) {
3469         // Ignore first AddP.
3470       } else {
3471         const Type* elemtype = adr_type->isa_aryptr()->elem();
3472         bt = elemtype->array_element_basic_type();
3473       }
3474     } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
3475       // Allocation initialization, ThreadLocal field access, unsafe access
3476       if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3477           n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3478           n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN) ||
3479           BarrierSet::barrier_set()->barrier_set_c2()->escape_has_out_with_unsafe_object(n)) {
3480         bt = T_OBJECT;
3481       }
3482     }
3483   }
3484   // Note: T_NARROWOOP is not classed as a real reference type
3485   return (is_reference_type(bt) || bt == T_NARROWOOP);
3486 }
3487 
3488 // Returns unique pointed java object or null.
3489 JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) const {
3490   // If the node was created after the escape computation we can't answer.
3491   uint idx = n->_idx;
3492   if (idx >= nodes_size()) {
3493     return nullptr;
3494   }
3495   PointsToNode* ptn = ptnode_adr(idx);
3496   if (ptn == nullptr) {
3497     return nullptr;
3498   }
3499   if (ptn->is_JavaObject()) {

4138     // skip over a call which does not affect this memory slice
4139     if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) {
4140       Node *proj_in = result->in(0);
4141       if (proj_in->is_Allocate() && proj_in->_idx == (uint)toop->instance_id()) {
4142         break;  // hit one of our sentinels
4143       } else if (proj_in->is_Call()) {
4144         // ArrayCopy node processed here as well
4145         CallNode *call = proj_in->as_Call();
4146         if (!call->may_modify(toop, igvn)) {
4147           result = call->in(TypeFunc::Memory);
4148         }
4149       } else if (proj_in->is_Initialize()) {
4150         AllocateNode* alloc = proj_in->as_Initialize()->allocation();
4151         // Stop if this is the initialization for the object instance which
4152         // which contains this memory slice, otherwise skip over it.
4153         if (alloc == nullptr || alloc->_idx != (uint)toop->instance_id()) {
4154           result = proj_in->in(TypeFunc::Memory);
4155         }
4156       } else if (proj_in->is_MemBar()) {
4157         // Check if there is an array copy for a clone
4158         // Step over GC barrier when ReduceInitialCardMarks is disabled
4159         BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
4160         Node* control_proj_ac = bs->step_over_gc_barrier(proj_in->in(0));
4161 
4162         if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) {
4163           // Stop if it is a clone
4164           ArrayCopyNode* ac = control_proj_ac->in(0)->as_ArrayCopy();
4165           if (ac->may_modify(toop, igvn)) {
4166             break;
4167           }
4168         }
4169         result = proj_in->in(TypeFunc::Memory);
4170       }
4171     } else if (result->is_MergeMem()) {
4172       MergeMemNode *mmem = result->as_MergeMem();
4173       result = step_through_mergemem(mmem, alias_idx, toop);
4174       if (result == mmem->base_memory()) {
4175         // Didn't find instance memory, search through general slice recursively.
4176         result = mmem->memory_at(C->get_general_index(alias_idx));
4177         result = find_inst_mem(result, alias_idx, orig_phis, rec_depth + 1);
4178         if (C->failing()) {
4179           return nullptr;
4180         }

1489       assert((ptnode_adr(adr->_idx) == nullptr ||
1490               ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
1491     }
1492 #endif
1493     add_local_var_and_edge(n, PointsToNode::NoEscape,
1494                            adr, delayed_worklist);
1495   }
1496 }
1497 
1498 // Populate Connection Graph with PointsTo nodes and create simple
1499 // connection graph edges.
1500 void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
1501   assert(!_verify, "this method should not be called for verification");
1502   PhaseGVN* igvn = _igvn;
1503   uint n_idx = n->_idx;
1504   PointsToNode* n_ptn = ptnode_adr(n_idx);
1505   if (n_ptn != nullptr) {
1506     return; // No need to redefine PointsTo node during first iteration.
1507   }
1508   int opcode = n->Opcode();





1509   if (n->is_Call()) {
1510     // Arguments to allocation and locking don't escape.
1511     if (n->is_AbstractLock()) {
1512       // Put Lock and Unlock nodes on IGVN worklist to process them during
1513       // first IGVN optimization when escape information is still available.
1514       record_for_optimizer(n);
1515     } else if (n->is_Allocate()) {
1516       add_call_node(n->as_Call());
1517       record_for_optimizer(n);
1518     } else {
1519       if (n->is_CallStaticJava()) {
1520         const char* name = n->as_CallStaticJava()->_name;
1521         if (name != nullptr && strcmp(name, "uncommon_trap") == 0) {
1522           return; // Skip uncommon traps
1523         }
1524       }
1525       // Don't mark as processed since call's arguments have to be processed.
1526       delayed_worklist->push(n);
1527       // Check if a call returns an object.
1528       if ((n->as_Call()->returns_pointer() &&

1706   }
1707   return;
1708 }
1709 
1710 // Add final simple edges to graph.
1711 void ConnectionGraph::add_final_edges(Node *n) {
1712   PointsToNode* n_ptn = ptnode_adr(n->_idx);
1713 #ifdef ASSERT
1714   if (_verify && n_ptn->is_JavaObject())
1715     return; // This method does not change graph for JavaObject.
1716 #endif
1717 
1718   if (n->is_Call()) {
1719     process_call_arguments(n->as_Call());
1720     return;
1721   }
1722   assert(n->is_Store() || n->is_LoadStore() ||
1723          ((n_ptn != nullptr) && (n_ptn->ideal_node() != nullptr)),
1724          "node should be registered already");
1725   int opcode = n->Opcode();




1726   switch (opcode) {
1727     case Op_AddP: {
1728       Node* base = get_addp_base(n);
1729       PointsToNode* ptn_base = ptnode_adr(base->_idx);
1730       assert(ptn_base != nullptr, "field's base should be registered");
1731       add_base(n_ptn->as_Field(), ptn_base);
1732       break;
1733     }
1734     case Op_CastPP:
1735     case Op_CheckCastPP:
1736     case Op_EncodeP:
1737     case Op_DecodeN:
1738     case Op_EncodePKlass:
1739     case Op_DecodeNKlass: {
1740       add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), nullptr);
1741       break;
1742     }
1743     case Op_CMoveP: {
1744       for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
1745         Node* in = n->in(i);

3430   BasicType bt = T_INT;
3431   if (offset == Type::OffsetBot) {
3432     // Check only oop fields.
3433     if (!adr_type->isa_aryptr() ||
3434         adr_type->isa_aryptr()->elem() == Type::BOTTOM ||
3435         adr_type->isa_aryptr()->elem()->make_oopptr() != nullptr) {
3436       // OffsetBot is used to reference array's element. Ignore first AddP.
3437       if (find_second_addp(n, n->in(AddPNode::Base)) == nullptr) {
3438         bt = T_OBJECT;
3439       }
3440     }
3441   } else if (offset != oopDesc::klass_offset_in_bytes()) {
3442     if (adr_type->isa_instptr()) {
3443       ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
3444       if (field != nullptr) {
3445         bt = field->layout_type();
3446       } else {
3447         // Check for unsafe oop field access
3448         if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3449             n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3450             n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) {

3451           bt = T_OBJECT;
3452           (*unsafe) = true;
3453         }
3454       }
3455     } else if (adr_type->isa_aryptr()) {
3456       if (offset == arrayOopDesc::length_offset_in_bytes()) {
3457         // Ignore array length load.
3458       } else if (find_second_addp(n, n->in(AddPNode::Base)) != nullptr) {
3459         // Ignore first AddP.
3460       } else {
3461         const Type* elemtype = adr_type->isa_aryptr()->elem();
3462         bt = elemtype->array_element_basic_type();
3463       }
3464     } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
3465       // Allocation initialization, ThreadLocal field access, unsafe access
3466       if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3467           n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3468           n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) {

3469         bt = T_OBJECT;
3470       }
3471     }
3472   }
3473   // Note: T_NARROWOOP is not classed as a real reference type
3474   return (is_reference_type(bt) || bt == T_NARROWOOP);
3475 }
3476 
3477 // Returns unique pointed java object or null.
3478 JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) const {
3479   // If the node was created after the escape computation we can't answer.
3480   uint idx = n->_idx;
3481   if (idx >= nodes_size()) {
3482     return nullptr;
3483   }
3484   PointsToNode* ptn = ptnode_adr(idx);
3485   if (ptn == nullptr) {
3486     return nullptr;
3487   }
3488   if (ptn->is_JavaObject()) {

4127     // skip over a call which does not affect this memory slice
4128     if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) {
4129       Node *proj_in = result->in(0);
4130       if (proj_in->is_Allocate() && proj_in->_idx == (uint)toop->instance_id()) {
4131         break;  // hit one of our sentinels
4132       } else if (proj_in->is_Call()) {
4133         // ArrayCopy node processed here as well
4134         CallNode *call = proj_in->as_Call();
4135         if (!call->may_modify(toop, igvn)) {
4136           result = call->in(TypeFunc::Memory);
4137         }
4138       } else if (proj_in->is_Initialize()) {
4139         AllocateNode* alloc = proj_in->as_Initialize()->allocation();
4140         // Stop if this is the initialization for the object instance which
4141         // which contains this memory slice, otherwise skip over it.
4142         if (alloc == nullptr || alloc->_idx != (uint)toop->instance_id()) {
4143           result = proj_in->in(TypeFunc::Memory);
4144         }
4145       } else if (proj_in->is_MemBar()) {
4146         // Check if there is an array copy for a clone
4147         Node* control_proj_ac = proj_in->in(0);


4148 
4149         if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) {
4150           // Stop if it is a clone
4151           ArrayCopyNode* ac = control_proj_ac->in(0)->as_ArrayCopy();
4152           if (ac->may_modify(toop, igvn)) {
4153             break;
4154           }
4155         }
4156         result = proj_in->in(TypeFunc::Memory);
4157       }
4158     } else if (result->is_MergeMem()) {
4159       MergeMemNode *mmem = result->as_MergeMem();
4160       result = step_through_mergemem(mmem, alias_idx, toop);
4161       if (result == mmem->base_memory()) {
4162         // Didn't find instance memory, search through general slice recursively.
4163         result = mmem->memory_at(C->get_general_index(alias_idx));
4164         result = find_inst_mem(result, alias_idx, orig_phis, rec_depth + 1);
4165         if (C->failing()) {
4166           return nullptr;
4167         }
< prev index next >