< prev index next >

src/hotspot/share/opto/escape.cpp

Print this page

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

1731   }
1732   return;
1733 }
1734 
1735 // Add final simple edges to graph.
1736 void ConnectionGraph::add_final_edges(Node *n) {
1737   PointsToNode* n_ptn = ptnode_adr(n->_idx);
1738 #ifdef ASSERT
1739   if (_verify && n_ptn->is_JavaObject())
1740     return; // This method does not change graph for JavaObject.
1741 #endif
1742 
1743   if (n->is_Call()) {
1744     process_call_arguments(n->as_Call());
1745     return;
1746   }
1747   assert(n->is_Store() || n->is_LoadStore() ||
1748          ((n_ptn != nullptr) && (n_ptn->ideal_node() != nullptr)),
1749          "node should be registered already");
1750   int opcode = n->Opcode();
1751   bool gc_handled = BarrierSet::barrier_set()->barrier_set_c2()->escape_add_final_edges(this, _igvn, n, opcode);
1752   if (gc_handled) {
1753     return; // Ignore node if already handled by GC.
1754   }
1755   switch (opcode) {
1756     case Op_AddP: {
1757       Node* base = get_addp_base(n);
1758       PointsToNode* ptn_base = ptnode_adr(base->_idx);
1759       assert(ptn_base != nullptr, "field's base should be registered");
1760       add_base(n_ptn->as_Field(), ptn_base);
1761       break;
1762     }
1763     case Op_CastPP:
1764     case Op_CheckCastPP:
1765     case Op_EncodeP:
1766     case Op_DecodeN:
1767     case Op_EncodePKlass:
1768     case Op_DecodeNKlass: {
1769       add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), nullptr);
1770       break;
1771     }
1772     case Op_CMoveP: {
1773       for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
1774         Node* in = n->in(i);

3465   BasicType bt = T_INT;
3466   if (offset == Type::OffsetBot) {
3467     // Check only oop fields.
3468     if (!adr_type->isa_aryptr() ||
3469         adr_type->isa_aryptr()->elem() == Type::BOTTOM ||
3470         adr_type->isa_aryptr()->elem()->make_oopptr() != nullptr) {
3471       // OffsetBot is used to reference array's element. Ignore first AddP.
3472       if (find_second_addp(n, n->in(AddPNode::Base)) == nullptr) {
3473         bt = T_OBJECT;
3474       }
3475     }
3476   } else if (offset != oopDesc::klass_offset_in_bytes()) {
3477     if (adr_type->isa_instptr()) {
3478       ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
3479       if (field != nullptr) {
3480         bt = field->layout_type();
3481       } else {
3482         // Check for unsafe oop field access
3483         if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3484             n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3485             n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN) ||
3486             BarrierSet::barrier_set()->barrier_set_c2()->escape_has_out_with_unsafe_object(n)) {
3487           bt = T_OBJECT;
3488           (*unsafe) = true;
3489         }
3490       }
3491     } else if (adr_type->isa_aryptr()) {
3492       if (offset == arrayOopDesc::length_offset_in_bytes()) {
3493         // Ignore array length load.
3494       } else if (find_second_addp(n, n->in(AddPNode::Base)) != nullptr) {
3495         // Ignore first AddP.
3496       } else {
3497         const Type* elemtype = adr_type->isa_aryptr()->elem();
3498         bt = elemtype->array_element_basic_type();
3499       }
3500     } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
3501       // Allocation initialization, ThreadLocal field access, unsafe access
3502       if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3503           n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3504           n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN) ||
3505           BarrierSet::barrier_set()->barrier_set_c2()->escape_has_out_with_unsafe_object(n)) {
3506         bt = T_OBJECT;
3507       }
3508     }
3509   }
3510   // Note: T_NARROWOOP is not classed as a real reference type
3511   return (is_reference_type(bt) || bt == T_NARROWOOP);
3512 }
3513 
3514 // Returns unique pointed java object or null.
3515 JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) const {
3516   // If the node was created after the escape computation we can't answer.
3517   uint idx = n->_idx;
3518   if (idx >= nodes_size()) {
3519     return nullptr;
3520   }
3521   PointsToNode* ptn = ptnode_adr(idx);
3522   if (ptn == nullptr) {
3523     return nullptr;
3524   }
3525   if (ptn->is_JavaObject()) {

4169       } else if (proj_in->is_Call()) {
4170         // ArrayCopy node processed here as well
4171         CallNode *call = proj_in->as_Call();
4172         if (!call->may_modify(toop, igvn)) {
4173           result = call->in(TypeFunc::Memory);
4174         }
4175       } else if (proj_in->is_Initialize()) {
4176         AllocateNode* alloc = proj_in->as_Initialize()->allocation();
4177         // Stop if this is the initialization for the object instance which
4178         // which contains this memory slice, otherwise skip over it.
4179         if (alloc == nullptr || alloc->_idx != (uint)toop->instance_id()) {
4180           result = proj_in->in(TypeFunc::Memory);
4181         } else if (C->get_alias_index(result->adr_type()) != alias_idx) {
4182           assert(C->get_general_index(alias_idx) == C->get_alias_index(result->adr_type()), "should be projection for the same field/array element");
4183           result = get_map(result->_idx);
4184           assert(result != nullptr, "new projection should have been allocated");
4185           break;
4186         }
4187       } else if (proj_in->is_MemBar()) {
4188         // Check if there is an array copy for a clone
4189         // Step over GC barrier when ReduceInitialCardMarks is disabled
4190         BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
4191         Node* control_proj_ac = bs->step_over_gc_barrier(proj_in->in(0));
4192 
4193         if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) {
4194           // Stop if it is a clone
4195           ArrayCopyNode* ac = control_proj_ac->in(0)->as_ArrayCopy();
4196           if (ac->may_modify(toop, igvn)) {
4197             break;
4198           }
4199         }
4200         result = proj_in->in(TypeFunc::Memory);
4201       }
4202     } else if (result->is_MergeMem()) {
4203       MergeMemNode *mmem = result->as_MergeMem();
4204       result = step_through_mergemem(mmem, alias_idx, toop);
4205       if (result == mmem->base_memory()) {
4206         // Didn't find instance memory, search through general slice recursively.
4207         result = mmem->memory_at(C->get_general_index(alias_idx));
4208         result = find_inst_mem(result, alias_idx, orig_phis, rec_depth + 1);
4209         if (C->failing()) {
4210           return nullptr;
4211         }

1509       assert((ptnode_adr(adr->_idx) == nullptr ||
1510               ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
1511     }
1512 #endif
1513     add_local_var_and_edge(n, PointsToNode::NoEscape,
1514                            adr, delayed_worklist);
1515   }
1516 }
1517 
1518 // Populate Connection Graph with PointsTo nodes and create simple
1519 // connection graph edges.
1520 void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
1521   assert(!_verify, "this method should not be called for verification");
1522   PhaseGVN* igvn = _igvn;
1523   uint n_idx = n->_idx;
1524   PointsToNode* n_ptn = ptnode_adr(n_idx);
1525   if (n_ptn != nullptr) {
1526     return; // No need to redefine PointsTo node during first iteration.
1527   }
1528   int opcode = n->Opcode();





1529   if (n->is_Call()) {
1530     // Arguments to allocation and locking don't escape.
1531     if (n->is_AbstractLock()) {
1532       // Put Lock and Unlock nodes on IGVN worklist to process them during
1533       // first IGVN optimization when escape information is still available.
1534       record_for_optimizer(n);
1535     } else if (n->is_Allocate()) {
1536       add_call_node(n->as_Call());
1537       record_for_optimizer(n);
1538     } else {
1539       if (n->is_CallStaticJava()) {
1540         const char* name = n->as_CallStaticJava()->_name;
1541         if (name != nullptr && strcmp(name, "uncommon_trap") == 0) {
1542           return; // Skip uncommon traps
1543         }
1544       }
1545       // Don't mark as processed since call's arguments have to be processed.
1546       delayed_worklist->push(n);
1547       // Check if a call returns an object.
1548       if ((n->as_Call()->returns_pointer() &&

1726   }
1727   return;
1728 }
1729 
1730 // Add final simple edges to graph.
1731 void ConnectionGraph::add_final_edges(Node *n) {
1732   PointsToNode* n_ptn = ptnode_adr(n->_idx);
1733 #ifdef ASSERT
1734   if (_verify && n_ptn->is_JavaObject())
1735     return; // This method does not change graph for JavaObject.
1736 #endif
1737 
1738   if (n->is_Call()) {
1739     process_call_arguments(n->as_Call());
1740     return;
1741   }
1742   assert(n->is_Store() || n->is_LoadStore() ||
1743          ((n_ptn != nullptr) && (n_ptn->ideal_node() != nullptr)),
1744          "node should be registered already");
1745   int opcode = n->Opcode();




1746   switch (opcode) {
1747     case Op_AddP: {
1748       Node* base = get_addp_base(n);
1749       PointsToNode* ptn_base = ptnode_adr(base->_idx);
1750       assert(ptn_base != nullptr, "field's base should be registered");
1751       add_base(n_ptn->as_Field(), ptn_base);
1752       break;
1753     }
1754     case Op_CastPP:
1755     case Op_CheckCastPP:
1756     case Op_EncodeP:
1757     case Op_DecodeN:
1758     case Op_EncodePKlass:
1759     case Op_DecodeNKlass: {
1760       add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), nullptr);
1761       break;
1762     }
1763     case Op_CMoveP: {
1764       for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
1765         Node* in = n->in(i);

3456   BasicType bt = T_INT;
3457   if (offset == Type::OffsetBot) {
3458     // Check only oop fields.
3459     if (!adr_type->isa_aryptr() ||
3460         adr_type->isa_aryptr()->elem() == Type::BOTTOM ||
3461         adr_type->isa_aryptr()->elem()->make_oopptr() != nullptr) {
3462       // OffsetBot is used to reference array's element. Ignore first AddP.
3463       if (find_second_addp(n, n->in(AddPNode::Base)) == nullptr) {
3464         bt = T_OBJECT;
3465       }
3466     }
3467   } else if (offset != oopDesc::klass_offset_in_bytes()) {
3468     if (adr_type->isa_instptr()) {
3469       ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
3470       if (field != nullptr) {
3471         bt = field->layout_type();
3472       } else {
3473         // Check for unsafe oop field access
3474         if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3475             n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3476             n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) {

3477           bt = T_OBJECT;
3478           (*unsafe) = true;
3479         }
3480       }
3481     } else if (adr_type->isa_aryptr()) {
3482       if (offset == arrayOopDesc::length_offset_in_bytes()) {
3483         // Ignore array length load.
3484       } else if (find_second_addp(n, n->in(AddPNode::Base)) != nullptr) {
3485         // Ignore first AddP.
3486       } else {
3487         const Type* elemtype = adr_type->isa_aryptr()->elem();
3488         bt = elemtype->array_element_basic_type();
3489       }
3490     } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
3491       // Allocation initialization, ThreadLocal field access, unsafe access
3492       if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
3493           n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
3494           n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) {

3495         bt = T_OBJECT;
3496       }
3497     }
3498   }
3499   // Note: T_NARROWOOP is not classed as a real reference type
3500   return (is_reference_type(bt) || bt == T_NARROWOOP);
3501 }
3502 
3503 // Returns unique pointed java object or null.
3504 JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) const {
3505   // If the node was created after the escape computation we can't answer.
3506   uint idx = n->_idx;
3507   if (idx >= nodes_size()) {
3508     return nullptr;
3509   }
3510   PointsToNode* ptn = ptnode_adr(idx);
3511   if (ptn == nullptr) {
3512     return nullptr;
3513   }
3514   if (ptn->is_JavaObject()) {

4158       } else if (proj_in->is_Call()) {
4159         // ArrayCopy node processed here as well
4160         CallNode *call = proj_in->as_Call();
4161         if (!call->may_modify(toop, igvn)) {
4162           result = call->in(TypeFunc::Memory);
4163         }
4164       } else if (proj_in->is_Initialize()) {
4165         AllocateNode* alloc = proj_in->as_Initialize()->allocation();
4166         // Stop if this is the initialization for the object instance which
4167         // which contains this memory slice, otherwise skip over it.
4168         if (alloc == nullptr || alloc->_idx != (uint)toop->instance_id()) {
4169           result = proj_in->in(TypeFunc::Memory);
4170         } else if (C->get_alias_index(result->adr_type()) != alias_idx) {
4171           assert(C->get_general_index(alias_idx) == C->get_alias_index(result->adr_type()), "should be projection for the same field/array element");
4172           result = get_map(result->_idx);
4173           assert(result != nullptr, "new projection should have been allocated");
4174           break;
4175         }
4176       } else if (proj_in->is_MemBar()) {
4177         // Check if there is an array copy for a clone
4178         Node* control_proj_ac = proj_in->in(0);


4179 
4180         if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) {
4181           // Stop if it is a clone
4182           ArrayCopyNode* ac = control_proj_ac->in(0)->as_ArrayCopy();
4183           if (ac->may_modify(toop, igvn)) {
4184             break;
4185           }
4186         }
4187         result = proj_in->in(TypeFunc::Memory);
4188       }
4189     } else if (result->is_MergeMem()) {
4190       MergeMemNode *mmem = result->as_MergeMem();
4191       result = step_through_mergemem(mmem, alias_idx, toop);
4192       if (result == mmem->base_memory()) {
4193         // Didn't find instance memory, search through general slice recursively.
4194         result = mmem->memory_at(C->get_general_index(alias_idx));
4195         result = find_inst_mem(result, alias_idx, orig_phis, rec_depth + 1);
4196         if (C->failing()) {
4197           return nullptr;
4198         }
< prev index next >