hotspot/src/share/vm/opto/node.hpp
changeset 35539 9a687b686976
parent 35106 79f25c397652
child 35551 36ef3841fb34
--- a/hotspot/src/share/vm/opto/node.hpp	Fri Jan 08 11:39:47 2016 +0000
+++ b/hotspot/src/share/vm/opto/node.hpp	Fri Jan 08 11:41:04 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -423,6 +423,16 @@
   }
   // 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.
@@ -476,6 +486,19 @@
     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.
@@ -492,13 +515,23 @@
   // 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;