< prev index next >

src/share/vm/opto/node.cpp

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

@@ -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.

@@ -795,11 +795,20 @@
           "remove node from hash table before modifying it");
   // First remove corresponding def-use edge
   Node *n = in(idx);
   if (n != NULL) n->del_out((Node *)this);
   _in[idx] = in(--_cnt);  // Compact the array
-  _in[_cnt] = NULL;       // NULL out emptied slot
+  // Avoid spec violation: Gap in prec edges.
+  uint i = _cnt;
+  Node *last = NULL;
+  for (; i < len()-1; ++i) {
+    Node *next = _in[i+1];
+    if (next == NULL) break;
+    last = next;
+  }
+  _in[_cnt] = last;      // Move last slot to empty one.
+  _in[i] = NULL;         // NULL out last slot.
   Compile::current()->record_modified_node(this);
 }
 
 //------------------------------del_req_ordered--------------------------------
 // Delete the required edge and compact the edge array with preserved order

@@ -808,14 +817,23 @@
   assert( !VerifyHashTableKeys || _hash_lock == 0,
           "remove node from hash table before modifying it");
   // First remove corresponding def-use edge
   Node *n = in(idx);
   if (n != NULL) n->del_out((Node *)this);
-  if (idx < _cnt - 1) { // Not last edge ?
-    Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*)));
+  if (idx < --_cnt) {    // Not last edge ?
+    Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx)*sizeof(Node*)));
+  }
+  // Avoid spec violation: Gap in prec edges.
+  uint i = _cnt;
+  Node *last = NULL;
+  for (; i < len()-1; ++i) {
+    Node *next = _in[i+1];
+    if (next == NULL) break;
+    last = next;
   }
-  _in[--_cnt] = NULL;   // NULL out emptied slot
+  _in[_cnt] = last;      // Move last slot to empty one.
+  _in[i] = NULL;         // NULL out last slot.
   Compile::current()->record_modified_node(this);
 }
 
 //------------------------------ins_req----------------------------------------
 // Insert a new required input at the end

@@ -843,14 +861,16 @@
 int Node::replace_edge(Node* old, Node* neww) {
   if (old == neww)  return 0;  // nothing to do
   uint nrep = 0;
   for (uint i = 0; i < len(); i++) {
     if (in(i) == old) {
-      if (i < req())
+      if (i < req()) {
         set_req(i, neww);
-      else
+      } else {
+        assert(find_prec_edge(neww) == -1, "spec violation: multiple prec edge (node %d -> %d)", _idx, neww->_idx);
         set_prec(i, neww);
+      }
       nrep++;
     }
   }
   return nrep;
 }

@@ -980,26 +1000,35 @@
   if( _cnt >= _max || in(_max-1) )
     grow( _max+1 );
 
   // Find a precedence edge to move
   uint i = _cnt;
-  while( in(i) != NULL ) i++;
+  while( in(i) != NULL ) {
+    if (in(i) == n) return; // Avoid spec violation: multiple prec edge.
+    i++;
+  }
   _in[i] = n;                                // Stuff prec edge over NULL
   if ( n != NULL) n->add_out((Node *)this);  // Add mirror edge
+
+#ifdef ASSERT
+  while ((++i)<_max) { assert(_in[i] == NULL, "spec violation: Gap in prec edges (node %d)", _idx); }
+#endif
 }
 
 //------------------------------rm_prec----------------------------------------
 // Remove a precedence input.  Precedence inputs are unordered, with
 // duplicates removed and NULLs packed down at the end.
 void Node::rm_prec( uint j ) {
+  if (_in[j] == NULL) return;   // Avoid spec violation: Gap in prec edges.
 
   // Find end of precedence list to pack NULLs
   uint i;
-  for( i=j; i<_max; i++ )
+  for( i=j+1; i<_max; i++ ) {
     if( !_in[i] )               // Find the NULL at end of prec edge list
       break;
-  if (_in[j] != NULL) _in[j]->del_out((Node *)this);
+  }
+  _in[j]->del_out((Node *)this);
   _in[j] = _in[--i];            // Move last element over removed guy
   _in[i] = NULL;                // NULL out last element
 }
 
 //------------------------------size_of----------------------------------------
< prev index next >