src/share/vm/opto/memnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/opto

src/share/vm/opto/memnode.cpp

Print this page
rev 8052 : castpp gcm
rev 8568 : 8086046: escape analysis generates incorrect code as of B67
Summary: load bypasses arraycopy that sets the value after the ArrayCopyNode is expanded
Reviewed-by:


  91       st->print(", idx=Bot;");
  92     else if (atp->index() == Compile::AliasIdxTop)
  93       st->print(", idx=Top;");
  94     else if (atp->index() == Compile::AliasIdxRaw)
  95       st->print(", idx=Raw;");
  96     else {
  97       ciField* field = atp->field();
  98       if (field) {
  99         st->print(", name=");
 100         field->print_name_on(st);
 101       }
 102       st->print(", idx=%d;", atp->index());
 103     }
 104   }
 105 }
 106 
 107 extern void print_alias_types();
 108 
 109 #endif
 110 
 111 static bool membar_for_arraycopy_helper(const TypeOopPtr *t_oop, MergeMemNode* mm, PhaseTransform *phase) {
 112   if (mm->memory_at(Compile::AliasIdxRaw)->is_Proj()) {
 113     Node* n = mm->memory_at(Compile::AliasIdxRaw)->in(0);
 114     if ((n->is_ArrayCopy() && n->as_ArrayCopy()->may_modify(t_oop, phase)) ||
 115         (n->is_CallLeaf() && n->as_CallLeaf()->may_modify(t_oop, phase))) {
 116       return true;
 117     }
 118   }
 119   return false;
 120 }
 121 
 122 static bool membar_for_arraycopy(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTransform *phase) {
 123   Node* mem = mb->in(TypeFunc::Memory);

 124   if (mem->is_MergeMem()) {
 125     return membar_for_arraycopy_helper(t_oop, mem->as_MergeMem(), phase);
 126   } else if (mem->is_Phi()) {
 127     // after macro expansion of an ArrayCopyNode we may have a Phi
 128     for (uint i = 1; i < mem->req(); i++) {
 129       if (mem->in(i) != NULL && mem->in(i)->is_MergeMem() && membar_for_arraycopy_helper(t_oop, mem->in(i)->as_MergeMem(), phase)) {


 130         return true;
 131       }
 132     }
 133   }



 134   return false;
 135 }
 136 
 137 Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oop, Node *load, PhaseGVN *phase) {
 138   assert((t_oop != NULL), "sanity");
 139   bool is_instance = t_oop->is_known_instance_field();
 140   bool is_boxed_value_load = t_oop->is_ptr_to_boxed_value() &&
 141                              (load != NULL) && load->is_Load() &&
 142                              (phase->is_IterGVN() != NULL);
 143   if (!(is_instance || is_boxed_value_load))
 144     return mchain;  // don't try to optimize non-instance types
 145   uint instance_id = t_oop->instance_id();
 146   Node *start_mem = phase->C->start()->proj_out(TypeFunc::Memory);
 147   Node *prev = NULL;
 148   Node *result = mchain;
 149   while (prev != result) {
 150     prev = result;
 151     if (result == start_mem)
 152       break;  // hit one of our sentinels
 153     // skip over a call which does not affect this memory slice




  91       st->print(", idx=Bot;");
  92     else if (atp->index() == Compile::AliasIdxTop)
  93       st->print(", idx=Top;");
  94     else if (atp->index() == Compile::AliasIdxRaw)
  95       st->print(", idx=Raw;");
  96     else {
  97       ciField* field = atp->field();
  98       if (field) {
  99         st->print(", name=");
 100         field->print_name_on(st);
 101       }
 102       st->print(", idx=%d;", atp->index());
 103     }
 104   }
 105 }
 106 
 107 extern void print_alias_types();
 108 
 109 #endif
 110 
 111 static bool membar_for_arraycopy_helper(const TypeOopPtr *t_oop, Node* n, PhaseTransform *phase) {
 112   if (n->is_Proj()) {
 113     n = n->in(0);
 114     if (n->is_Call() && n->as_Call()->may_modify(t_oop, phase)) {

 115       return true;
 116     }
 117   }
 118   return false;
 119 }
 120 
 121 static bool membar_for_arraycopy(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTransform *phase) {
 122   Node* mem = mb->in(TypeFunc::Memory);
 123 
 124   if (mem->is_MergeMem()) {
 125     Node* n = mem->as_MergeMem()->memory_at(Compile::AliasIdxRaw);
 126     if (membar_for_arraycopy_helper(t_oop, n, phase)) {
 127       return true;
 128     } else if (n->is_Phi()) {
 129       for (uint i = 1; i < n->req(); i++) {
 130         if (n->in(i) != NULL) {
 131           if (membar_for_arraycopy_helper(t_oop, n->in(i), phase)) {
 132             return true;
 133           }
 134         }
 135       }
 136     }
 137   }
 138   
 139   return false;
 140 }
 141 
 142 Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypeOopPtr *t_oop, Node *load, PhaseGVN *phase) {
 143   assert((t_oop != NULL), "sanity");
 144   bool is_instance = t_oop->is_known_instance_field();
 145   bool is_boxed_value_load = t_oop->is_ptr_to_boxed_value() &&
 146                              (load != NULL) && load->is_Load() &&
 147                              (phase->is_IterGVN() != NULL);
 148   if (!(is_instance || is_boxed_value_load))
 149     return mchain;  // don't try to optimize non-instance types
 150   uint instance_id = t_oop->instance_id();
 151   Node *start_mem = phase->C->start()->proj_out(TypeFunc::Memory);
 152   Node *prev = NULL;
 153   Node *result = mchain;
 154   while (prev != result) {
 155     prev = result;
 156     if (result == start_mem)
 157       break;  // hit one of our sentinels
 158     // skip over a call which does not affect this memory slice


src/share/vm/opto/memnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File