8146612: C2: Precedence edges specification violated

Tue, 10 Mar 2020 10:46:35 +0100

author
mdoerr
date
Tue, 10 Mar 2020 10:46:35 +0100
changeset 9912
97d09139b360
parent 9911
6f33e450999c
child 9913
bd77de4e5e2b

8146612: C2: Precedence edges specification violated
Reviewed-by: kvn

src/share/vm/opto/lcm.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/node.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/node.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/lcm.cpp	Tue May 05 18:39:57 2020 +0100
     1.2 +++ b/src/share/vm/opto/lcm.cpp	Tue Mar 10 10:46:35 2020 +0100
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -815,6 +815,13 @@
    1.11          // and the edge will be lost. This is why this code should be
    1.12          // executed only when Precedent (== TypeFunc::Parms) edge is present.
    1.13          Node *x = n->in(TypeFunc::Parms);
    1.14 +        if (x != NULL && get_block_for_node(x) == block && n->find_prec_edge(x) != -1) {
    1.15 +          // Old edge to node within same block will get removed, but no precedence
    1.16 +          // edge will get added because it already exists. Update ready count.
    1.17 +          int cnt = ready_cnt.at(n->_idx);
    1.18 +          assert(cnt > 1, err_msg("MemBar node %d must not get ready here", n->_idx));
    1.19 +          ready_cnt.at_put(n->_idx, cnt-1);
    1.20 +        }
    1.21          n->del_req(TypeFunc::Parms);
    1.22          n->add_prec(x);
    1.23        }
     2.1 --- a/src/share/vm/opto/node.cpp	Tue May 05 18:39:57 2020 +0100
     2.2 +++ b/src/share/vm/opto/node.cpp	Tue Mar 10 10:46:35 2020 +0100
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -818,8 +818,9 @@
    2.11    // First remove corresponding def-use edge
    2.12    Node *n = in(idx);
    2.13    if (n != NULL) n->del_out((Node *)this);
    2.14 -  _in[idx] = in(--_cnt);  // Compact the array
    2.15 -  _in[_cnt] = NULL;       // NULL out emptied slot
    2.16 +  _in[idx] = in(--_cnt); // Compact the array
    2.17 +  // Avoid spec violation: Gap in prec edges.
    2.18 +  close_prec_gap_at(_cnt);
    2.19  }
    2.20  
    2.21  //------------------------------del_req_ordered--------------------------------
    2.22 @@ -831,10 +832,11 @@
    2.23    // First remove corresponding def-use edge
    2.24    Node *n = in(idx);
    2.25    if (n != NULL) n->del_out((Node *)this);
    2.26 -  if (idx < _cnt - 1) { // Not last edge ?
    2.27 -    Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*)));
    2.28 +  if (idx < --_cnt) {    // Not last edge ?
    2.29 +    Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx)*sizeof(Node*)));
    2.30    }
    2.31 -  _in[--_cnt] = NULL;   // NULL out emptied slot
    2.32 +  // Avoid spec violation: Gap in prec edges.
    2.33 +  close_prec_gap_at(_cnt);
    2.34  }
    2.35  
    2.36  //------------------------------ins_req----------------------------------------
    2.37 @@ -865,10 +867,12 @@
    2.38    uint nrep = 0;
    2.39    for (uint i = 0; i < len(); i++) {
    2.40      if (in(i) == old) {
    2.41 -      if (i < req())
    2.42 +      if (i < req()) {
    2.43          set_req(i, neww);
    2.44 -      else
    2.45 +      } else {
    2.46 +        assert(find_prec_edge(neww) == -1, err_msg("spec violation: duplicated prec edge (node %d -> %d)", _idx, neww->_idx));
    2.47          set_prec(i, neww);
    2.48 +      }
    2.49        nrep++;
    2.50      }
    2.51    }
    2.52 @@ -974,24 +978,27 @@
    2.53  
    2.54    // Find a precedence edge to move
    2.55    uint i = _cnt;
    2.56 -  while( in(i) != NULL ) i++;
    2.57 +  while( in(i) != NULL ) {
    2.58 +    if (in(i) == n) return; // Avoid spec violation: duplicated prec edge.
    2.59 +    i++;
    2.60 +  }
    2.61    _in[i] = n;                                // Stuff prec edge over NULL
    2.62    if ( n != NULL) n->add_out((Node *)this);  // Add mirror edge
    2.63 +
    2.64 +#ifdef ASSERT
    2.65 +  while ((++i)<_max) { assert(_in[i] == NULL, err_msg("spec violation: Gap in prec edges (node %d)", _idx)); }
    2.66 +#endif
    2.67  }
    2.68  
    2.69  //------------------------------rm_prec----------------------------------------
    2.70  // Remove a precedence input.  Precedence inputs are unordered, with
    2.71  // duplicates removed and NULLs packed down at the end.
    2.72  void Node::rm_prec( uint j ) {
    2.73 -
    2.74 -  // Find end of precedence list to pack NULLs
    2.75 -  uint i;
    2.76 -  for( i=j; i<_max; i++ )
    2.77 -    if( !_in[i] )               // Find the NULL at end of prec edge list
    2.78 -      break;
    2.79 -  if (_in[j] != NULL) _in[j]->del_out((Node *)this);
    2.80 -  _in[j] = _in[--i];            // Move last element over removed guy
    2.81 -  _in[i] = NULL;                // NULL out last element
    2.82 +  assert(j < _max, err_msg("oob: i=%d, _max=%d", j, _max));
    2.83 +  assert(j >= _cnt, "not a precedence edge");
    2.84 +  if (_in[j] == NULL) return;   // Avoid spec violation: Gap in prec edges.
    2.85 +  _in[j]->del_out((Node *)this);
    2.86 +  close_prec_gap_at(j);
    2.87  }
    2.88  
    2.89  //------------------------------size_of----------------------------------------
     3.1 --- a/src/share/vm/opto/node.hpp	Tue May 05 18:39:57 2020 +0100
     3.2 +++ b/src/share/vm/opto/node.hpp	Tue Mar 10 10:46:35 2020 +0100
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -423,6 +423,16 @@
    3.11    }
    3.12    // Find first occurrence of n among my edges:
    3.13    int find_edge(Node* n);
    3.14 +  int find_prec_edge(Node* n) {
    3.15 +    for (uint i = req(); i < len(); i++) {
    3.16 +      if (_in[i] == n) return i;
    3.17 +      if (_in[i] == NULL) {
    3.18 +        DEBUG_ONLY( while ((++i) < len()) assert(_in[i] == NULL, "Gap in prec edges!"); )
    3.19 +        break;
    3.20 +      }
    3.21 +    }
    3.22 +    return -1;
    3.23 +  }
    3.24    int replace_edge(Node* old, Node* neww);
    3.25    int replace_edges_in_range(Node* old, Node* neww, int start, int end);
    3.26    // NULL out all inputs to eliminate incoming Def-Use edges.
    3.27 @@ -469,6 +479,19 @@
    3.28      debug_only(_last_del = n; ++_del_tick);
    3.29      #endif
    3.30    }
    3.31 +  // Close gap after removing edge.
    3.32 +  void close_prec_gap_at(uint gap) {
    3.33 +    assert(_cnt <= gap && gap < _max, "no valid prec edge");
    3.34 +    uint i = gap;
    3.35 +    Node *last = NULL;
    3.36 +    for (; i < _max-1; ++i) {
    3.37 +      Node *next = _in[i+1];
    3.38 +      if (next == NULL) break;
    3.39 +      last = next;
    3.40 +    }
    3.41 +    _in[gap] = last; // Move last slot to empty one.
    3.42 +    _in[i] = NULL;   // NULL out last slot.
    3.43 +  }
    3.44  
    3.45  public:
    3.46    // Globally replace this node by a given new node, updating all uses.
    3.47 @@ -485,13 +508,23 @@
    3.48    // Add or remove precedence edges
    3.49    void add_prec( Node *n );
    3.50    void rm_prec( uint i );
    3.51 +
    3.52 +  // Note: prec(i) will not necessarily point to n if edge already exists.
    3.53    void set_prec( uint i, Node *n ) {
    3.54 -    assert( is_not_dead(n), "can not use dead node");
    3.55 -    assert( i >= _cnt, "not a precedence edge");
    3.56 +    assert(i < _max, err_msg("oob: i=%d, _max=%d", i, _max));
    3.57 +    assert(is_not_dead(n), "can not use dead node");
    3.58 +    assert(i >= _cnt, "not a precedence edge");
    3.59 +    // Avoid spec violation: duplicated prec edge.
    3.60 +    if (_in[i] == n) return;
    3.61 +    if (n == NULL || find_prec_edge(n) != -1) {
    3.62 +      rm_prec(i);
    3.63 +      return;
    3.64 +    }
    3.65      if (_in[i] != NULL) _in[i]->del_out((Node *)this);
    3.66      _in[i] = n;
    3.67      if (n != NULL) n->add_out((Node *)this);
    3.68    }
    3.69 +
    3.70    // Set this node's index, used by cisc_version to replace current node
    3.71    void set_idx(uint new_idx) {
    3.72      const node_idx_t* ref = &_idx;

mercurial