8247743: Segmentation fault in debug builds due to stack overflow in find_recur with deep graphs
Replace the recursive algorithm of Node::find() by an iterative one to avoid a stack overflow crash with deep graphs. Reviewed-by: kvn, thartmann
This commit is contained in:
parent
4f99e1fb11
commit
18cf3d8080
@ -1554,78 +1554,95 @@ jfloat Node::getf() const {
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
//------------------------------find------------------------------------------
|
||||
// Find a neighbor of this Node with the given _idx
|
||||
// If idx is negative, find its absolute value, following both _in and _out.
|
||||
static void find_recur(Compile* C, Node* &result, Node *n, int idx, bool only_ctrl,
|
||||
VectorSet* old_space, VectorSet* new_space ) {
|
||||
int node_idx = (idx >= 0) ? idx : -idx;
|
||||
if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc.
|
||||
// Contained in new_space or old_space? Check old_arena first since it's mostly empty.
|
||||
VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
|
||||
if( v->test(n->_idx) ) return;
|
||||
if( (int)n->_idx == node_idx
|
||||
debug_only(|| n->debug_idx() == node_idx) ) {
|
||||
if (result != NULL)
|
||||
tty->print("find: " INTPTR_FORMAT " and " INTPTR_FORMAT " both have idx==%d\n",
|
||||
(uintptr_t)result, (uintptr_t)n, node_idx);
|
||||
result = n;
|
||||
}
|
||||
v->set(n->_idx);
|
||||
for( uint i=0; i<n->len(); i++ ) {
|
||||
if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;
|
||||
find_recur(C, result, n->in(i), idx, only_ctrl, old_space, new_space );
|
||||
}
|
||||
// Search along forward edges also:
|
||||
if (idx < 0 && !only_ctrl) {
|
||||
for( uint j=0; j<n->outcnt(); j++ ) {
|
||||
find_recur(C, result, n->raw_out(j), idx, only_ctrl, old_space, new_space );
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
// Search along debug_orig edges last, checking for cycles
|
||||
Node* orig = n->debug_orig();
|
||||
if (orig != NULL) {
|
||||
do {
|
||||
if (NotANode(orig)) break;
|
||||
find_recur(C, result, orig, idx, only_ctrl, old_space, new_space );
|
||||
orig = orig->debug_orig();
|
||||
} while (orig != NULL && orig != n->debug_orig());
|
||||
}
|
||||
#endif //ASSERT
|
||||
}
|
||||
|
||||
// call this from debugger:
|
||||
Node* find_node(Node* n, int idx) {
|
||||
// Call this from debugger:
|
||||
Node* find_node(Node* n, const int idx) {
|
||||
return n->find(idx);
|
||||
}
|
||||
|
||||
// call this from debugger with root node as default:
|
||||
Node* find_node(int idx) {
|
||||
// Call this from debugger with root node as default:
|
||||
Node* find_node(const int idx) {
|
||||
return Compile::current()->root()->find(idx);
|
||||
}
|
||||
|
||||
//------------------------------find-------------------------------------------
|
||||
Node* Node::find(int idx) const {
|
||||
VectorSet old_space, new_space;
|
||||
Node* result = NULL;
|
||||
find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space);
|
||||
return result;
|
||||
// Call this from debugger:
|
||||
Node* find_ctrl(Node* n, const int idx) {
|
||||
return n->find_ctrl(idx);
|
||||
}
|
||||
|
||||
// Call this from debugger with root node as default:
|
||||
Node* find_ctrl(const int idx) {
|
||||
return Compile::current()->root()->find_ctrl(idx);
|
||||
}
|
||||
|
||||
//------------------------------find_ctrl--------------------------------------
|
||||
// Find an ancestor to this node in the control history with given _idx
|
||||
Node* Node::find_ctrl(int idx) const {
|
||||
VectorSet old_space, new_space;
|
||||
Node* Node::find_ctrl(int idx) {
|
||||
return find(idx, true);
|
||||
}
|
||||
|
||||
//------------------------------find-------------------------------------------
|
||||
// Tries to find the node with the index |idx| starting from this node. If idx is negative,
|
||||
// the search also includes forward (out) edges. Returns NULL if not found.
|
||||
// If only_ctrl is set, the search will only be done on control nodes. Returns NULL if
|
||||
// not found or if the node to be found is not a control node (search will not find it).
|
||||
Node* Node::find(const int idx, bool only_ctrl) {
|
||||
ResourceMark rm;
|
||||
VectorSet old_space;
|
||||
VectorSet new_space;
|
||||
Node_List worklist;
|
||||
Arena* old_arena = Compile::current()->old_arena();
|
||||
add_to_worklist(this, &worklist, old_arena, &old_space, &new_space);
|
||||
Node* result = NULL;
|
||||
find_recur(Compile::current(), result, (Node*)this, idx, true, &old_space, &new_space);
|
||||
int node_idx = (idx >= 0) ? idx : -idx;
|
||||
|
||||
for (uint list_index = 0; list_index < worklist.size(); list_index++) {
|
||||
Node* n = worklist[list_index];
|
||||
|
||||
if ((int)n->_idx == node_idx debug_only(|| n->debug_idx() == node_idx)) {
|
||||
if (result != NULL) {
|
||||
tty->print("find: " INTPTR_FORMAT " and " INTPTR_FORMAT " both have idx==%d\n",
|
||||
(uintptr_t)result, (uintptr_t)n, node_idx);
|
||||
}
|
||||
result = n;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < n->len(); i++) {
|
||||
if (!only_ctrl || n->is_Region() || (n->Opcode() == Op_Root) || (i == TypeFunc::Control)) {
|
||||
// If only_ctrl is set: Add regions, the root node, or control inputs only
|
||||
add_to_worklist(n->in(i), &worklist, old_arena, &old_space, &new_space);
|
||||
}
|
||||
}
|
||||
|
||||
// Also search along forward edges if idx is negative and the search is not done on control nodes only
|
||||
if (idx < 0 && !only_ctrl) {
|
||||
for (uint i = 0; i < n->outcnt(); i++) {
|
||||
add_to_worklist(n->raw_out(i), &worklist, old_arena, &old_space, &new_space);
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
// Search along debug_orig edges last
|
||||
Node* orig = n->debug_orig();
|
||||
while (orig != NULL && add_to_worklist(orig, &worklist, old_arena, &old_space, &new_space)) {
|
||||
orig = orig->debug_orig();
|
||||
}
|
||||
#endif // ASSERT
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Node::add_to_worklist(Node* n, Node_List* worklist, Arena* old_arena, VectorSet* old_space, VectorSet* new_space) {
|
||||
if (NotANode(n)) {
|
||||
return false; // Gracefully handle NULL, -1, 0xabababab, etc.
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Contained in new_space or old_space? Check old_arena first since it's mostly empty.
|
||||
VectorSet* v = old_arena->contains(n) ? old_space : new_space;
|
||||
if (!v->test_set(n->_idx)) {
|
||||
worklist->push(n);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------Name-------------------------------------------
|
||||
extern const char *NodeClassNames[];
|
||||
@ -2227,7 +2244,7 @@ void Node::verify(Node* n, int verify_depth) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // not PRODUCT
|
||||
|
||||
//------------------------------walk-------------------------------------------
|
||||
// Graph walk, with both pre-order and post-order functions
|
||||
|
@ -1118,10 +1118,11 @@ private:
|
||||
void walk_(NFunc pre, NFunc post, void *env, VectorSet &visited);
|
||||
|
||||
//----------------- Printing, etc
|
||||
public:
|
||||
#ifndef PRODUCT
|
||||
Node* find(int idx) const; // Search the graph for the given idx.
|
||||
Node* find_ctrl(int idx) const; // Search control ancestors for the given idx.
|
||||
static bool add_to_worklist(Node* n, Node_List* worklist, Arena* old_arena, VectorSet* old_space, VectorSet* new_space);
|
||||
public:
|
||||
Node* find(int idx, bool only_ctrl = false); // Search the graph for the given idx.
|
||||
Node* find_ctrl(int idx); // Search control ancestors for the given idx.
|
||||
void dump() const { dump("\n"); } // Print this node.
|
||||
void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node.
|
||||
void dump(int depth) const; // Print this node, recursively to depth d
|
||||
|
90
test/hotspot/jtreg/compiler/c2/TestFindNode.java
Normal file
90
test/hotspot/jtreg/compiler/c2/TestFindNode.java
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8247743
|
||||
* @requires vm.debug == true & vm.flavor == "server"
|
||||
* @summary Test which uses some special flags in order to test Node::find() in debug builds which could result in an endless loop or a stack overflow crash.
|
||||
*
|
||||
* @run main/othervm -Xbatch -XX:CompileCommand=option,*::*,bool,Vectorize,true -XX:+PrintOpto -XX:+TraceLoopOpts compiler.c2.TestFindNode
|
||||
*/
|
||||
package compiler.c2;
|
||||
|
||||
public class TestFindNode {
|
||||
static volatile int[] iArr;
|
||||
static volatile int x;
|
||||
static int[] iArr2 = new int[100];
|
||||
static int[] iArr3 = new int[100];
|
||||
|
||||
public static void main(String[] arr) {
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
test();
|
||||
}
|
||||
}
|
||||
|
||||
public static void test() {
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 }; iArr = new int[] { x % 2 };
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
iArr2[i] = iArr3[i];
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user