src/share/vm/opto/memnode.cpp

changeset 4657
6931f425c517
parent 4479
b30b3c2a0cf2
child 4695
ff55877839bc
     1.1 --- a/src/share/vm/opto/memnode.cpp	Fri Feb 22 10:12:00 2013 -0800
     1.2 +++ b/src/share/vm/opto/memnode.cpp	Mon Feb 25 14:13:04 2013 +0100
     1.3 @@ -320,6 +320,9 @@
     1.4  
     1.5    if (mem != old_mem) {
     1.6      set_req(MemNode::Memory, mem);
     1.7 +    if (can_reshape && old_mem->outcnt() == 0) {
     1.8 +        igvn->_worklist.push(old_mem);
     1.9 +    }
    1.10      if (phase->type( mem ) == Type::TOP) return NodeSentinel;
    1.11      return this;
    1.12    }
    1.13 @@ -2319,9 +2322,9 @@
    1.14    if (ReduceFieldZeroing && /*can_reshape &&*/
    1.15        mem->is_Proj() && mem->in(0)->is_Initialize()) {
    1.16      InitializeNode* init = mem->in(0)->as_Initialize();
    1.17 -    intptr_t offset = init->can_capture_store(this, phase);
    1.18 +    intptr_t offset = init->can_capture_store(this, phase, can_reshape);
    1.19      if (offset > 0) {
    1.20 -      Node* moved = init->capture_store(this, offset, phase);
    1.21 +      Node* moved = init->capture_store(this, offset, phase, can_reshape);
    1.22        // If the InitializeNode captured me, it made a raw copy of me,
    1.23        // and I need to disappear.
    1.24        if (moved != NULL) {
    1.25 @@ -3134,7 +3137,7 @@
    1.26  // an initialization.  Returns zero if a check fails.
    1.27  // On success, returns the (constant) offset to which the store applies,
    1.28  // within the initialized memory.
    1.29 -intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase) {
    1.30 +intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) {
    1.31    const int FAIL = 0;
    1.32    if (st->req() != MemNode::ValueIn + 1)
    1.33      return FAIL;                // an inscrutable StoreNode (card mark?)
    1.34 @@ -3156,6 +3159,91 @@
    1.35    if (!detect_init_independence(val, true, complexity_count))
    1.36      return FAIL;                // stored value must be 'simple enough'
    1.37  
    1.38 +  // The Store can be captured only if nothing after the allocation
    1.39 +  // and before the Store is using the memory location that the store
    1.40 +  // overwrites.
    1.41 +  bool failed = false;
    1.42 +  // If is_complete_with_arraycopy() is true the shape of the graph is
    1.43 +  // well defined and is safe so no need for extra checks.
    1.44 +  if (!is_complete_with_arraycopy()) {
    1.45 +    // We are going to look at each use of the memory state following
    1.46 +    // the allocation to make sure nothing reads the memory that the
    1.47 +    // Store writes.
    1.48 +    const TypePtr* t_adr = phase->type(adr)->isa_ptr();
    1.49 +    int alias_idx = phase->C->get_alias_index(t_adr);
    1.50 +    ResourceMark rm;
    1.51 +    Unique_Node_List mems;
    1.52 +    mems.push(mem);
    1.53 +    Node* unique_merge = NULL;
    1.54 +    for (uint next = 0; next < mems.size(); ++next) {
    1.55 +      Node *m  = mems.at(next);
    1.56 +      for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
    1.57 +        Node *n = m->fast_out(j);
    1.58 +        if (n->outcnt() == 0) {
    1.59 +          continue;
    1.60 +        }
    1.61 +        if (n == st) {
    1.62 +          continue;
    1.63 +        } else if (n->in(0) != NULL && n->in(0) != ctl) {
    1.64 +          // If the control of this use is different from the control
    1.65 +          // of the Store which is right after the InitializeNode then
    1.66 +          // this node cannot be between the InitializeNode and the
    1.67 +          // Store.
    1.68 +          continue;
    1.69 +        } else if (n->is_MergeMem()) {
    1.70 +          if (n->as_MergeMem()->memory_at(alias_idx) == m) {
    1.71 +            // We can hit a MergeMemNode (that will likely go away
    1.72 +            // later) that is a direct use of the memory state
    1.73 +            // following the InitializeNode on the same slice as the
    1.74 +            // store node that we'd like to capture. We need to check
    1.75 +            // the uses of the MergeMemNode.
    1.76 +            mems.push(n);
    1.77 +          }
    1.78 +        } else if (n->is_Mem()) {
    1.79 +          Node* other_adr = n->in(MemNode::Address);
    1.80 +          if (other_adr == adr) {
    1.81 +            failed = true;
    1.82 +            break;
    1.83 +          } else {
    1.84 +            const TypePtr* other_t_adr = phase->type(other_adr)->isa_ptr();
    1.85 +            if (other_t_adr != NULL) {
    1.86 +              int other_alias_idx = phase->C->get_alias_index(other_t_adr);
    1.87 +              if (other_alias_idx == alias_idx) {
    1.88 +                // A load from the same memory slice as the store right
    1.89 +                // after the InitializeNode. We check the control of the
    1.90 +                // object/array that is loaded from. If it's the same as
    1.91 +                // the store control then we cannot capture the store.
    1.92 +                assert(!n->is_Store(), "2 stores to same slice on same control?");
    1.93 +                Node* base = other_adr;
    1.94 +                assert(base->is_AddP(), err_msg_res("should be addp but is %s", base->Name()));
    1.95 +                base = base->in(AddPNode::Base);
    1.96 +                if (base != NULL) {
    1.97 +                  base = base->uncast();
    1.98 +                  if (base->is_Proj() && base->in(0) == alloc) {
    1.99 +                    failed = true;
   1.100 +                    break;
   1.101 +                  }
   1.102 +                }
   1.103 +              }
   1.104 +            }
   1.105 +          }
   1.106 +        } else {
   1.107 +          failed = true;
   1.108 +          break;
   1.109 +        }
   1.110 +      }
   1.111 +    }
   1.112 +  }
   1.113 +  if (failed) {
   1.114 +    if (!can_reshape) {
   1.115 +      // We decided we couldn't capture the store during parsing. We
   1.116 +      // should try again during the next IGVN once the graph is
   1.117 +      // cleaner.
   1.118 +      phase->C->record_for_igvn(st);
   1.119 +    }
   1.120 +    return FAIL;
   1.121 +  }
   1.122 +
   1.123    return offset;                // success
   1.124  }
   1.125  
   1.126 @@ -3266,11 +3354,11 @@
   1.127  //                      rawstore1 rawstore2)
   1.128  //
   1.129  Node* InitializeNode::capture_store(StoreNode* st, intptr_t start,
   1.130 -                                    PhaseTransform* phase) {
   1.131 +                                    PhaseTransform* phase, bool can_reshape) {
   1.132    assert(stores_are_sane(phase), "");
   1.133  
   1.134    if (start < 0)  return NULL;
   1.135 -  assert(can_capture_store(st, phase) == start, "sanity");
   1.136 +  assert(can_capture_store(st, phase, can_reshape) == start, "sanity");
   1.137  
   1.138    Compile* C = phase->C;
   1.139    int size_in_bytes = st->memory_size();

mercurial