6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys

Wed, 09 Dec 2009 19:50:14 -0800

author
kvn
date
Wed, 09 Dec 2009 19:50:14 -0800
changeset 1536
7fee0a6cc6d4
parent 1535
f96a1a986f7b
child 1537
6dc5471e0f66

6896727: nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys
Summary: Move instance store's memory users to corresponding memory slices when updating its memory edge.
Reviewed-by: never

src/share/vm/opto/escape.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/escape.hpp file | annotate | diff | comparison | revisions
test/compiler/6896727/Test.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/escape.cpp	Wed Dec 09 16:40:45 2009 -0800
     1.2 +++ b/src/share/vm/opto/escape.cpp	Wed Dec 09 19:50:14 2009 -0800
     1.3 @@ -543,6 +543,7 @@
     1.4    int alias_idx = _compile->get_alias_index(tinst);
     1.5    igvn->set_type(addp, tinst);
     1.6    // record the allocation in the node map
     1.7 +  assert(ptnode_adr(addp->_idx)->_node != NULL, "should be registered");
     1.8    set_map(addp->_idx, get_map(base->_idx));
     1.9  
    1.10    // Set addp's Base and Address to 'base'.
    1.11 @@ -618,9 +619,14 @@
    1.12    const TypePtr *atype = C->get_adr_type(alias_idx);
    1.13    result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype);
    1.14    C->copy_node_notes_to(result, orig_phi);
    1.15 -  set_map_phi(orig_phi->_idx, result);
    1.16    igvn->set_type(result, result->bottom_type());
    1.17    record_for_optimizer(result);
    1.18 +
    1.19 +  debug_only(Node* pn = ptnode_adr(orig_phi->_idx)->_node;)
    1.20 +  assert(pn == NULL || pn == orig_phi, "wrong node");
    1.21 +  set_map(orig_phi->_idx, result);
    1.22 +  ptnode_adr(orig_phi->_idx)->_node = orig_phi;
    1.23 +
    1.24    new_created = true;
    1.25    return result;
    1.26  }
    1.27 @@ -711,6 +717,81 @@
    1.28  }
    1.29  
    1.30  //
    1.31 +// Move memory users to their memory slices.
    1.32 +//
    1.33 +void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn) {
    1.34 +  Compile* C = _compile;
    1.35 +
    1.36 +  const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr();
    1.37 +  assert(tp != NULL, "ptr type");
    1.38 +  int alias_idx = C->get_alias_index(tp);
    1.39 +  int general_idx = C->get_general_index(alias_idx);
    1.40 +
    1.41 +  // Move users first
    1.42 +  for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
    1.43 +    Node* use = n->fast_out(i);
    1.44 +    if (use->is_MergeMem()) {
    1.45 +      MergeMemNode* mmem = use->as_MergeMem();
    1.46 +      assert(n == mmem->memory_at(alias_idx), "should be on instance memory slice");
    1.47 +      if (n != mmem->memory_at(general_idx) || alias_idx == general_idx) {
    1.48 +        continue; // Nothing to do
    1.49 +      }
    1.50 +      // Replace previous general reference to mem node.
    1.51 +      uint orig_uniq = C->unique();
    1.52 +      Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
    1.53 +      assert(orig_uniq == C->unique(), "no new nodes");
    1.54 +      mmem->set_memory_at(general_idx, m);
    1.55 +      --imax;
    1.56 +      --i;
    1.57 +    } else if (use->is_MemBar()) {
    1.58 +      assert(!use->is_Initialize(), "initializing stores should not be moved");
    1.59 +      if (use->req() > MemBarNode::Precedent &&
    1.60 +          use->in(MemBarNode::Precedent) == n) {
    1.61 +        // Don't move related membars.
    1.62 +        record_for_optimizer(use);
    1.63 +        continue;
    1.64 +      }
    1.65 +      tp = use->as_MemBar()->adr_type()->isa_ptr();
    1.66 +      if (tp != NULL && C->get_alias_index(tp) == alias_idx ||
    1.67 +          alias_idx == general_idx) {
    1.68 +        continue; // Nothing to do
    1.69 +      }
    1.70 +      // Move to general memory slice.
    1.71 +      uint orig_uniq = C->unique();
    1.72 +      Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
    1.73 +      assert(orig_uniq == C->unique(), "no new nodes");
    1.74 +      igvn->hash_delete(use);
    1.75 +      imax -= use->replace_edge(n, m);
    1.76 +      igvn->hash_insert(use);
    1.77 +      record_for_optimizer(use);
    1.78 +      --i;
    1.79 +#ifdef ASSERT
    1.80 +    } else if (use->is_Mem()) {
    1.81 +      if (use->Opcode() == Op_StoreCM && use->in(MemNode::OopStore) == n) {
    1.82 +        // Don't move related cardmark.
    1.83 +        continue;
    1.84 +      }
    1.85 +      // Memory nodes should have new memory input.
    1.86 +      tp = igvn->type(use->in(MemNode::Address))->isa_ptr();
    1.87 +      assert(tp != NULL, "ptr type");
    1.88 +      int idx = C->get_alias_index(tp);
    1.89 +      assert(get_map(use->_idx) != NULL || idx == alias_idx,
    1.90 +             "Following memory nodes should have new memory input or be on the same memory slice");
    1.91 +    } else if (use->is_Phi()) {
    1.92 +      // Phi nodes should be split and moved already.
    1.93 +      tp = use->as_Phi()->adr_type()->isa_ptr();
    1.94 +      assert(tp != NULL, "ptr type");
    1.95 +      int idx = C->get_alias_index(tp);
    1.96 +      assert(idx == alias_idx, "Following Phi nodes should be on the same memory slice");
    1.97 +    } else {
    1.98 +      use->dump();
    1.99 +      assert(false, "should not be here");
   1.100 +#endif
   1.101 +    }
   1.102 +  }
   1.103 +}
   1.104 +
   1.105 +//
   1.106  // Search memory chain of "mem" to find a MemNode whose address
   1.107  // is the specified alias index.
   1.108  //
   1.109 @@ -775,6 +856,7 @@
   1.110                 C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) {
   1.111        Node *un = result->as_Phi()->unique_input(phase);
   1.112        if (un != NULL) {
   1.113 +        orig_phis.append_if_missing(result->as_Phi());
   1.114          result = un;
   1.115        } else {
   1.116          break;
   1.117 @@ -907,10 +989,12 @@
   1.118  void ConnectionGraph::split_unique_types(GrowableArray<Node *>  &alloc_worklist) {
   1.119    GrowableArray<Node *>  memnode_worklist;
   1.120    GrowableArray<PhiNode *>  orig_phis;
   1.121 +
   1.122    PhaseGVN  *igvn = _compile->initial_gvn();
   1.123    uint new_index_start = (uint) _compile->num_alias_types();
   1.124 -  VectorSet visited(Thread::current()->resource_area());
   1.125 -  VectorSet ptset(Thread::current()->resource_area());
   1.126 +  Arena* arena = Thread::current()->resource_area();
   1.127 +  VectorSet visited(arena);
   1.128 +  VectorSet ptset(arena);
   1.129  
   1.130  
   1.131    //  Phase 1:  Process possible allocations from alloc_worklist.
   1.132 @@ -986,6 +1070,8 @@
   1.133        //   - non-escaping
   1.134        //   - eligible to be a unique type
   1.135        //   - not determined to be ineligible by escape analysis
   1.136 +      assert(ptnode_adr(alloc->_idx)->_node != NULL &&
   1.137 +             ptnode_adr(n->_idx)->_node != NULL, "should be registered");
   1.138        set_map(alloc->_idx, n);
   1.139        set_map(n->_idx, alloc);
   1.140        const TypeOopPtr *t = igvn->type(n)->isa_oopptr();
   1.141 @@ -1182,6 +1268,10 @@
   1.142          return;
   1.143        }
   1.144        if (mem != n->in(MemNode::Memory)) {
   1.145 +        // We delay the memory edge update since we need old one in
   1.146 +        // MergeMem code below when instances memory slices are separated.
   1.147 +        debug_only(Node* pn = ptnode_adr(n->_idx)->_node;)
   1.148 +        assert(pn == NULL || pn == n, "wrong node");
   1.149          set_map(n->_idx, mem);
   1.150          ptnode_adr(n->_idx)->_node = n;
   1.151        }
   1.152 @@ -1249,6 +1339,8 @@
   1.153        Node* cur = NULL;
   1.154        if (mem == NULL || mem->is_top())
   1.155          continue;
   1.156 +      // First, update mergemem by moving memory nodes to corresponding slices
   1.157 +      // if their type became more precise since this mergemem was created.
   1.158        while (mem->is_Mem()) {
   1.159          const Type *at = igvn->type(mem->in(MemNode::Address));
   1.160          if (at != Type::TOP) {
   1.161 @@ -1267,7 +1359,7 @@
   1.162        }
   1.163        nmm->set_memory_at(i, (cur != NULL) ? cur : mem);
   1.164        // Find any instance of the current type if we haven't encountered
   1.165 -      // a value of the instance along the chain.
   1.166 +      // already a memory slice of the instance along the memory chain.
   1.167        for (uint ni = new_index_start; ni < new_index_end; ni++) {
   1.168          if((uint)_compile->get_general_index(ni) == i) {
   1.169            Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni);
   1.170 @@ -1283,11 +1375,11 @@
   1.171      }
   1.172      // Find the rest of instances values
   1.173      for (uint ni = new_index_start; ni < new_index_end; ni++) {
   1.174 -      const TypeOopPtr *tinst = igvn->C->get_adr_type(ni)->isa_oopptr();
   1.175 +      const TypeOopPtr *tinst = _compile->get_adr_type(ni)->isa_oopptr();
   1.176        Node* result = step_through_mergemem(nmm, ni, tinst);
   1.177        if (result == nmm->base_memory()) {
   1.178          // Didn't find instance memory, search through general slice recursively.
   1.179 -        result = nmm->memory_at(igvn->C->get_general_index(ni));
   1.180 +        result = nmm->memory_at(_compile->get_general_index(ni));
   1.181          result = find_inst_mem(result, ni, orig_phis, igvn);
   1.182          if (_compile->failing()) {
   1.183            return;
   1.184 @@ -1325,19 +1417,48 @@
   1.185    }
   1.186  
   1.187    // Update the memory inputs of MemNodes with the value we computed
   1.188 -  // in Phase 2.
   1.189 +  // in Phase 2 and move stores memory users to corresponding memory slices.
   1.190 +#ifdef ASSERT
   1.191 +  visited.Clear();
   1.192 +  Node_Stack old_mems(arena, _compile->unique() >> 2);
   1.193 +#endif
   1.194    for (uint i = 0; i < nodes_size(); i++) {
   1.195      Node *nmem = get_map(i);
   1.196      if (nmem != NULL) {
   1.197        Node *n = ptnode_adr(i)->_node;
   1.198 -      if (n != NULL && n->is_Mem()) {
   1.199 +      assert(n != NULL, "sanity");
   1.200 +      if (n->is_Mem()) {
   1.201 +#ifdef ASSERT
   1.202 +        Node* old_mem = n->in(MemNode::Memory);
   1.203 +        if (!visited.test_set(old_mem->_idx)) {
   1.204 +          old_mems.push(old_mem, old_mem->outcnt());
   1.205 +        }
   1.206 +#endif
   1.207 +        assert(n->in(MemNode::Memory) != nmem, "sanity");
   1.208 +        if (!n->is_Load()) {
   1.209 +          // Move memory users of a store first.
   1.210 +          move_inst_mem(n, orig_phis, igvn);
   1.211 +        }
   1.212 +        // Now update memory input
   1.213          igvn->hash_delete(n);
   1.214          n->set_req(MemNode::Memory, nmem);
   1.215          igvn->hash_insert(n);
   1.216          record_for_optimizer(n);
   1.217 +      } else {
   1.218 +        assert(n->is_Allocate() || n->is_CheckCastPP() ||
   1.219 +               n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
   1.220        }
   1.221      }
   1.222    }
   1.223 +#ifdef ASSERT
   1.224 +  // Verify that memory was split correctly
   1.225 +  while (old_mems.is_nonempty()) {
   1.226 +    Node* old_mem = old_mems.node();
   1.227 +    uint  old_cnt = old_mems.index();
   1.228 +    old_mems.pop();
   1.229 +    assert(old_cnt = old_mem->outcnt(), "old mem could be lost");
   1.230 +  }
   1.231 +#endif
   1.232  }
   1.233  
   1.234  bool ConnectionGraph::has_candidates(Compile *C) {
     2.1 --- a/src/share/vm/opto/escape.hpp	Wed Dec 09 16:40:45 2009 -0800
     2.2 +++ b/src/share/vm/opto/escape.hpp	Wed Dec 09 19:50:14 2009 -0800
     2.3 @@ -291,7 +291,7 @@
     2.4    bool split_AddP(Node *addp, Node *base,  PhaseGVN  *igvn);
     2.5    PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn, bool &new_created);
     2.6    PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn);
     2.7 -  Node *find_mem(Node *mem, int alias_idx, PhaseGVN  *igvn);
     2.8 +  void  move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn);
     2.9    Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *>  &orig_phi_worklist,  PhaseGVN  *igvn);
    2.10  
    2.11    // Propagate unique types created for unescaped allocated objects
    2.12 @@ -300,7 +300,6 @@
    2.13  
    2.14    // manage entries in _node_map
    2.15    void  set_map(int idx, Node *n)        { _node_map.map(idx, n); }
    2.16 -  void  set_map_phi(int idx, PhiNode *p) { _node_map.map(idx, (Node *) p); }
    2.17    Node *get_map(int idx)                 { return _node_map[idx]; }
    2.18    PhiNode *get_map_phi(int idx) {
    2.19      Node *phi = _node_map[idx];
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/compiler/6896727/Test.java	Wed Dec 09 19:50:14 2009 -0800
     3.3 @@ -0,0 +1,48 @@
     3.4 +/*
     3.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + *
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + *
    3.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    3.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    3.24 + * have any questions.
    3.25 + *
    3.26 + */
    3.27 +
    3.28 +/*
    3.29 + * @test
    3.30 + * @bug 6896727
    3.31 + * @summary nsk/logging/LoggingPermission/LoggingPermission/logperm002 fails with G1, EscapeAnalisys w/o COOPs
    3.32 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:+DoEscapeAnalysis -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC Test
    3.33 + */
    3.34 +
    3.35 +public class Test {
    3.36 +
    3.37 +    final static String testString = "abracadabra";
    3.38 +    public static void main(String args[]) {
    3.39 +        String params[][] = {
    3.40 +            {"control", testString}
    3.41 +        };
    3.42 +        for (int i=0; i<params.length; i++) {
    3.43 +            try {
    3.44 +                System.out.println("Params :" + testString + " and " + params[i][0] + ", " + params[i][1]);
    3.45 +                if (params[i][1] == null) {
    3.46 +                    System.exit(97);
    3.47 +                }
    3.48 +            } catch (Exception e) {}
    3.49 +        }
    3.50 +    }
    3.51 +}

mercurial