< prev index next >

src/hotspot/share/opto/escape.cpp

Print this page




2063   // Add edge from destination object to arraycopy node.
2064   (void)add_edge(dst, ptadr);
2065   dst->set_arraycopy_dst();
2066 }
2067 
2068 bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
2069   const Type* adr_type = n->as_AddP()->bottom_type();
2070   int field_offset = adr_type->isa_aryptr() ? adr_type->isa_aryptr()->field_offset().get() : Type::OffsetBot;
2071   BasicType bt = T_INT;
2072   if (offset == Type::OffsetBot && field_offset == Type::OffsetBot) {
2073     // Check only oop fields.
2074     if (!adr_type->isa_aryptr() ||
2075         (adr_type->isa_aryptr()->klass() == NULL) ||
2076          adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
2077       // OffsetBot is used to reference array's element. Ignore first AddP.
2078       if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
2079         bt = T_OBJECT;
2080       }
2081     }
2082   } else if (offset != oopDesc::klass_offset_in_bytes()) {
2083     if (adr_type->isa_instptr() || adr_type->isa_valuetypeptr()) {
2084       ciField* field = _compile->alias_type(adr_type->is_ptr())->field();
2085       if (field != NULL) {
2086         bt = field->layout_type();
2087       } else {
2088         // Check for unsafe oop field access
2089         if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
2090             n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
2091             n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) {
2092           bt = T_OBJECT;
2093           (*unsafe) = true;
2094         }
2095       }
2096     } else if (adr_type->isa_aryptr()) {
2097       if (offset == arrayOopDesc::length_offset_in_bytes()) {
2098         // Ignore array length load.
2099       } else if (find_second_addp(n, n->in(AddPNode::Base)) != NULL) {
2100         // Ignore first AddP.
2101       } else {
2102         const Type* elemtype = adr_type->isa_aryptr()->elem();
2103         if (elemtype->isa_valuetype() && field_offset != Type::OffsetBot) {


3024       }
3025       if (alloc->is_CallStaticJava()) {
3026         // Set the scalar_replaceable flag for boxing method
3027         // so it could be eliminated.
3028         alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
3029       }
3030       set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
3031       // in order for an object to be scalar-replaceable, it must be:
3032       //   - a direct allocation (not a call returning an object)
3033       //   - non-escaping
3034       //   - eligible to be a unique type
3035       //   - not determined to be ineligible by escape analysis
3036       set_map(alloc, n);
3037       set_map(n, alloc);
3038       const TypeOopPtr* tinst = t->cast_to_instance_id(ni);
3039       igvn->hash_delete(n);
3040       igvn->set_type(n,  tinst);
3041       n->raise_bottom_type(tinst);
3042       igvn->hash_insert(n);
3043       record_for_optimizer(n);
3044       if (alloc->is_Allocate() && (t->isa_instptr() || t->isa_aryptr() || t->isa_valuetypeptr())) {
3045 
3046         // First, put on the worklist all Field edges from Connection Graph
3047         // which is more accurate than putting immediate users from Ideal Graph.
3048         for (EdgeIterator e(ptn); e.has_next(); e.next()) {
3049           PointsToNode* tgt = e.get();
3050           if (tgt->is_Arraycopy()) {
3051             continue;
3052           }
3053           Node* use = tgt->ideal_node();
3054           assert(tgt->is_Field() && use->is_AddP(),
3055                  "only AddP nodes are Field edges in CG");
3056           if (use->outcnt() > 0) { // Don't process dead nodes
3057             Node* addp2 = find_second_addp(use, use->in(AddPNode::Base));
3058             if (addp2 != NULL) {
3059               assert(alloc->is_AllocateArray(),"array allocation was expected");
3060               alloc_worklist.append_if_missing(addp2);
3061             }
3062             alloc_worklist.append_if_missing(use);
3063           }
3064         }




2063   // Add edge from destination object to arraycopy node.
2064   (void)add_edge(dst, ptadr);
2065   dst->set_arraycopy_dst();
2066 }
2067 
2068 bool ConnectionGraph::is_oop_field(Node* n, int offset, bool* unsafe) {
2069   const Type* adr_type = n->as_AddP()->bottom_type();
2070   int field_offset = adr_type->isa_aryptr() ? adr_type->isa_aryptr()->field_offset().get() : Type::OffsetBot;
2071   BasicType bt = T_INT;
2072   if (offset == Type::OffsetBot && field_offset == Type::OffsetBot) {
2073     // Check only oop fields.
2074     if (!adr_type->isa_aryptr() ||
2075         (adr_type->isa_aryptr()->klass() == NULL) ||
2076          adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
2077       // OffsetBot is used to reference array's element. Ignore first AddP.
2078       if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
2079         bt = T_OBJECT;
2080       }
2081     }
2082   } else if (offset != oopDesc::klass_offset_in_bytes()) {
2083     if (adr_type->isa_instptr()) {
2084       ciField* field = _compile->alias_type(adr_type->is_ptr())->field();
2085       if (field != NULL) {
2086         bt = field->layout_type();
2087       } else {
2088         // Check for unsafe oop field access
2089         if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN) ||
2090             n->has_out_with(Op_GetAndSetP, Op_GetAndSetN, Op_CompareAndExchangeP, Op_CompareAndExchangeN) ||
2091             n->has_out_with(Op_CompareAndSwapP, Op_CompareAndSwapN, Op_WeakCompareAndSwapP, Op_WeakCompareAndSwapN)) {
2092           bt = T_OBJECT;
2093           (*unsafe) = true;
2094         }
2095       }
2096     } else if (adr_type->isa_aryptr()) {
2097       if (offset == arrayOopDesc::length_offset_in_bytes()) {
2098         // Ignore array length load.
2099       } else if (find_second_addp(n, n->in(AddPNode::Base)) != NULL) {
2100         // Ignore first AddP.
2101       } else {
2102         const Type* elemtype = adr_type->isa_aryptr()->elem();
2103         if (elemtype->isa_valuetype() && field_offset != Type::OffsetBot) {


3024       }
3025       if (alloc->is_CallStaticJava()) {
3026         // Set the scalar_replaceable flag for boxing method
3027         // so it could be eliminated.
3028         alloc->as_CallStaticJava()->_is_scalar_replaceable = true;
3029       }
3030       set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
3031       // in order for an object to be scalar-replaceable, it must be:
3032       //   - a direct allocation (not a call returning an object)
3033       //   - non-escaping
3034       //   - eligible to be a unique type
3035       //   - not determined to be ineligible by escape analysis
3036       set_map(alloc, n);
3037       set_map(n, alloc);
3038       const TypeOopPtr* tinst = t->cast_to_instance_id(ni);
3039       igvn->hash_delete(n);
3040       igvn->set_type(n,  tinst);
3041       n->raise_bottom_type(tinst);
3042       igvn->hash_insert(n);
3043       record_for_optimizer(n);
3044       if (alloc->is_Allocate() && (t->isa_instptr() || t->isa_aryptr())) {
3045 
3046         // First, put on the worklist all Field edges from Connection Graph
3047         // which is more accurate than putting immediate users from Ideal Graph.
3048         for (EdgeIterator e(ptn); e.has_next(); e.next()) {
3049           PointsToNode* tgt = e.get();
3050           if (tgt->is_Arraycopy()) {
3051             continue;
3052           }
3053           Node* use = tgt->ideal_node();
3054           assert(tgt->is_Field() && use->is_AddP(),
3055                  "only AddP nodes are Field edges in CG");
3056           if (use->outcnt() > 0) { // Don't process dead nodes
3057             Node* addp2 = find_second_addp(use, use->in(AddPNode::Base));
3058             if (addp2 != NULL) {
3059               assert(alloc->is_AllocateArray(),"array allocation was expected");
3060               alloc_worklist.append_if_missing(addp2);
3061             }
3062             alloc_worklist.append_if_missing(use);
3063           }
3064         }


< prev index next >