< prev index next >

src/share/vm/opto/node.hpp

Print this page
rev 9822 : 8146612: C2: Precedence edges specification violated
Reviewed-by: kvn

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -421,10 +421,20 @@
     if (n != NULL)      n->add_out((Node *)this);
     Compile::current()->record_modified_node(this);
   }
   // Find first occurrence of n among my edges:
   int find_edge(Node* n);
+  int find_prec_edge(Node* n) {
+    for (uint i = req(); i < len(); i++) {
+      if (_in[i] == n) return i;
+      if (_in[i] == NULL) {
+        DEBUG_ONLY( while ((++i) < len()) assert(_in[i] == NULL, "Gap in prec edges!"); )
+        break;
+      }
+    }
+    return -1;
+  }
   int replace_edge(Node* old, Node* neww);
   int replace_edges_in_range(Node* old, Node* neww, int start, int end);
   // NULL out all inputs to eliminate incoming Def-Use edges.
   // Return the number of edges between 'n' and 'this'
   int  disconnect_inputs(Node *n, Compile *c);

@@ -474,10 +484,23 @@
     // Record that a change happened here.
     #if OPTO_DU_ITERATOR_ASSERT
     debug_only(_last_del = n; ++_del_tick);
     #endif
   }
+  // Close gap after removing edge.
+  void close_prec_gap_at(uint gap) {
+    assert(_cnt <= gap && gap < _max, "no valid prec edge");
+    uint i = gap;
+    Node *last = NULL;
+    for (; i < _max-1; ++i) {
+      Node *next = _in[i+1];
+      if (next == NULL) break;
+      last = next;
+    }
+    _in[gap] = last; // Move last slot to empty one.
+    _in[i] = NULL;   // NULL out last slot.
+  }
 
 public:
   // Globally replace this node by a given new node, updating all uses.
   void replace_by(Node* new_node);
   // Globally replace this node by a given new node, updating all uses

@@ -490,17 +513,27 @@
   // Find the one non-null required input.  RegionNode only
   Node *nonnull_req() const;
   // Add or remove precedence edges
   void add_prec( Node *n );
   void rm_prec( uint i );
+
+  // Note: prec(i) will not necessarily point to n if edge already exists.
   void set_prec( uint i, Node *n ) {
-    assert( is_not_dead(n), "can not use dead node");
-    assert( i >= _cnt, "not a precedence edge");
+    assert(i < _max, "oob: i=%d, _max=%d", i, _max);
+    assert(is_not_dead(n), "can not use dead node");
+    assert(i >= _cnt, "not a precedence edge");
+    // Avoid spec violation: duplicated prec edge.
+    if (_in[i] == n) return;
+    if (n == NULL || find_prec_edge(n) != -1) {
+      rm_prec(i);
+      return;
+    }
     if (_in[i] != NULL) _in[i]->del_out((Node *)this);
     _in[i] = n;
     if (n != NULL) n->add_out((Node *)this);
   }
+
   // Set this node's index, used by cisc_version to replace current node
   void set_idx(uint new_idx) {
     const node_idx_t* ref = &_idx;
     *(node_idx_t*)ref = new_idx;
   }
< prev index next >