7024475: loop doesn't terminate when compiled

Sun, 27 Mar 2011 00:00:14 -0700

author
never
date
Sun, 27 Mar 2011 00:00:14 -0700
changeset 2685
1927db75dd85
parent 2684
244bf8afbbd3
child 2686
b40d4fa697bf

7024475: loop doesn't terminate when compiled
Reviewed-by: kvn

src/share/vm/compiler/compileBroker.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/idealGraphPrinter.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/idealGraphPrinter.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopTransform.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/node.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
test/compiler/7024475/Test7024475.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/compiler/compileBroker.cpp	Sat Mar 26 08:31:45 2011 -0700
     1.2 +++ b/src/share/vm/compiler/compileBroker.cpp	Sun Mar 27 00:00:14 2011 -0700
     1.3 @@ -874,6 +874,14 @@
     1.4      return;
     1.5    }
     1.6  
     1.7 +#ifndef PRODUCT
     1.8 +  if (osr_bci != -1 && !FLAG_IS_DEFAULT(OSROnlyBCI)) {
     1.9 +    if ((OSROnlyBCI > 0) ? (OSROnlyBCI != osr_bci) : (-OSROnlyBCI == osr_bci)) {
    1.10 +      // Positive OSROnlyBCI means only compile that bci.  Negative means don't compile that BCI.
    1.11 +      return;
    1.12 +    }
    1.13 +  }
    1.14 +#endif
    1.15  
    1.16    // If this method is already in the compile queue, then
    1.17    // we do not block the current thread.
     2.1 --- a/src/share/vm/opto/idealGraphPrinter.cpp	Sat Mar 26 08:31:45 2011 -0700
     2.2 +++ b/src/share/vm/opto/idealGraphPrinter.cpp	Sun Mar 27 00:00:14 2011 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 2007, 2011, 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 @@ -599,11 +599,35 @@
    2.11  
    2.12      if (caller != NULL) {
    2.13        stringStream bciStream;
    2.14 +      ciMethod* last = NULL;
    2.15 +      int last_bci;
    2.16        while(caller) {
    2.17 +        if (caller->has_method()) {
    2.18 +          last = caller->method();
    2.19 +          last_bci = caller->bci();
    2.20 +        }
    2.21          bciStream.print("%d ", caller->bci());
    2.22          caller = caller->caller();
    2.23        }
    2.24        print_prop("bci", bciStream.as_string());
    2.25 +      if (last != NULL && last->has_linenumber_table() && last_bci >= 0) {
    2.26 +        print_prop("line", last->line_number_from_bci(last_bci));
    2.27 +      }
    2.28 +    }
    2.29 +
    2.30 +    if (node->debug_orig() != NULL) {
    2.31 +      stringStream dorigStream;
    2.32 +      Node* dorig = node->debug_orig();
    2.33 +      if (dorig) {
    2.34 +        dorigStream.print("%d ", dorig->_idx);
    2.35 +        Node* first = dorig;
    2.36 +        dorig = first->debug_orig();
    2.37 +        while (dorig && dorig != first) {
    2.38 +          dorigStream.print("%d ", dorig->_idx);
    2.39 +          dorig = dorig->debug_orig();
    2.40 +        }
    2.41 +      }
    2.42 +      print_prop("debug_orig", dorigStream.as_string());
    2.43      }
    2.44  
    2.45      if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) {
    2.46 @@ -628,6 +652,17 @@
    2.47    GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL);
    2.48    nodeStack.push(start);
    2.49    visited.test_set(start->_idx);
    2.50 +  if (C->cfg() != NULL) {
    2.51 +    // once we have a CFG there are some nodes that aren't really
    2.52 +    // reachable but are in the CFG so add them here.
    2.53 +    for (uint i = 0; i < C->cfg()->_blocks.size(); i++) {
    2.54 +      Block *b = C->cfg()->_blocks[i];
    2.55 +      for (uint s = 0; s < b->_nodes.size(); s++) {
    2.56 +        nodeStack.push(b->_nodes[s]);
    2.57 +      }
    2.58 +    }
    2.59 +  }
    2.60 +
    2.61    while(nodeStack.length() > 0) {
    2.62  
    2.63      Node *n = nodeStack.pop();
    2.64 @@ -686,16 +721,23 @@
    2.65        end_head();
    2.66  
    2.67        head(SUCCESSORS_ELEMENT);
    2.68 -      for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) {
    2.69 +      for (uint s = 0; s < b->_num_succs; s++) {
    2.70          begin_elem(SUCCESSOR_ELEMENT);
    2.71          print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order);
    2.72          end_elem();
    2.73        }
    2.74        tail(SUCCESSORS_ELEMENT);
    2.75  
    2.76 +      head(NODES_ELEMENT);
    2.77 +      for (uint s = 0; s < b->_nodes.size(); s++) {
    2.78 +        begin_elem(NODE_ELEMENT);
    2.79 +        print_attr(NODE_ID_PROPERTY, get_node_id(b->_nodes[s]));
    2.80 +        end_elem();
    2.81 +      }
    2.82 +      tail(NODES_ELEMENT);
    2.83 +
    2.84        tail(BLOCK_ELEMENT);
    2.85      }
    2.86 -
    2.87      tail(CONTROL_FLOW_ELEMENT);
    2.88    }
    2.89    tail(GRAPH_ELEMENT);
     3.1 --- a/src/share/vm/opto/idealGraphPrinter.hpp	Sat Mar 26 08:31:45 2011 -0700
     3.2 +++ b/src/share/vm/opto/idealGraphPrinter.hpp	Sun Mar 27 00:00:14 2011 -0700
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2007, 2011, 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 @@ -45,15 +45,6 @@
    3.11  {
    3.12  private:
    3.13  
    3.14 -  enum State
    3.15 -  {
    3.16 -    Invalid,
    3.17 -    Valid,
    3.18 -    New
    3.19 -  };
    3.20 -
    3.21 -private:
    3.22 -
    3.23    static const char *INDENT;
    3.24    static const char *TOP_ELEMENT;
    3.25    static const char *GROUP_ELEMENT;
     4.1 --- a/src/share/vm/opto/loopTransform.cpp	Sat Mar 26 08:31:45 2011 -0700
     4.2 +++ b/src/share/vm/opto/loopTransform.cpp	Sun Mar 27 00:00:14 2011 -0700
     4.3 @@ -1608,15 +1608,7 @@
     4.4      return false; // Malformed loop
     4.5    if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue))))
     4.6      return false;             // Infinite loop
     4.7 -#ifndef PRODUCT
     4.8 -  if (PrintOpto) {
     4.9 -    tty->print("Removing empty loop");
    4.10 -    this->dump_head();
    4.11 -  } else if (TraceLoopOpts) {
    4.12 -    tty->print("Empty        ");
    4.13 -    this->dump_head();
    4.14 -  }
    4.15 -#endif
    4.16 +
    4.17  #ifdef ASSERT
    4.18    // Ensure only one phi which is the iv.
    4.19    Node* iv = NULL;
    4.20 @@ -1629,6 +1621,43 @@
    4.21    }
    4.22    assert(iv == cl->phi(), "Wrong phi" );
    4.23  #endif
    4.24 +
    4.25 +  // main and post loops have explicitly created zero trip guard
    4.26 +  bool needs_guard = !cl->is_main_loop() && !cl->is_post_loop();
    4.27 +  if (needs_guard) {
    4.28 +    // Check for an obvious zero trip guard.
    4.29 +    Node* inctrl = cl->in(LoopNode::EntryControl);
    4.30 +    if (inctrl->Opcode() == Op_IfTrue) {
    4.31 +      // The test should look like just the backedge of a CountedLoop
    4.32 +      Node* iff = inctrl->in(0);
    4.33 +      if (iff->is_If()) {
    4.34 +        Node* bol = iff->in(1);
    4.35 +        if (bol->is_Bool() && bol->as_Bool()->_test._test == cl->loopexit()->test_trip()) {
    4.36 +          Node* cmp = bol->in(1);
    4.37 +          if (cmp->is_Cmp() && cmp->in(1) == cl->init_trip() && cmp->in(2) == cl->limit()) {
    4.38 +            needs_guard = false;
    4.39 +          }
    4.40 +        }
    4.41 +      }
    4.42 +    }
    4.43 +  }
    4.44 +
    4.45 +#ifndef PRODUCT
    4.46 +  if (PrintOpto) {
    4.47 +    tty->print("Removing empty loop with%s zero trip guard", needs_guard ? "out" : "");
    4.48 +    this->dump_head();
    4.49 +  } else if (TraceLoopOpts) {
    4.50 +    tty->print("Empty with%s zero trip guard   ", needs_guard ? "out" : "");
    4.51 +    this->dump_head();
    4.52 +  }
    4.53 +#endif
    4.54 +
    4.55 +  if (needs_guard) {
    4.56 +    // Peel the loop to ensure there's a zero trip guard
    4.57 +    Node_List old_new;
    4.58 +    phase->do_peeling(this, old_new);
    4.59 +  }
    4.60 +
    4.61    // Replace the phi at loop head with the final value of the last
    4.62    // iteration.  Then the CountedLoopEnd will collapse (backedge never
    4.63    // taken) and all loop-invariant uses of the exit values will be correct.
     5.1 --- a/src/share/vm/opto/loopnode.cpp	Sat Mar 26 08:31:45 2011 -0700
     5.2 +++ b/src/share/vm/opto/loopnode.cpp	Sun Mar 27 00:00:14 2011 -0700
     5.3 @@ -1064,8 +1064,6 @@
     5.4    // Cache parts in locals for easy
     5.5    PhaseIterGVN &igvn = phase->_igvn;
     5.6  
     5.7 -  phase->C->print_method("Before beautify loops", 3);
     5.8 -
     5.9    igvn.hash_delete(_head);      // Yank from hash before hacking edges
    5.10  
    5.11    // Check for multiple fall-in paths.  Peel off a landing pad if need be.
    5.12 @@ -1547,6 +1545,7 @@
    5.13    ResourceMark rm;
    5.14  
    5.15    int old_progress = C->major_progress();
    5.16 +  uint orig_worklist_size = _igvn._worklist.size();
    5.17  
    5.18    // Reset major-progress flag for the driver's heuristics
    5.19    C->clear_major_progress();
    5.20 @@ -1610,6 +1609,7 @@
    5.21    // Split shared headers and insert loop landing pads.
    5.22    // Do not bother doing this on the Root loop of course.
    5.23    if( !_verify_me && !_verify_only && _ltree_root->_child ) {
    5.24 +    C->print_method("Before beautify loops", 3);
    5.25      if( _ltree_root->_child->beautify_loops( this ) ) {
    5.26        // Re-build loop tree!
    5.27        _ltree_root->_child = NULL;
    5.28 @@ -1694,7 +1694,7 @@
    5.29      for (int i = 0; i < old_progress; i++)
    5.30        C->set_major_progress();
    5.31      assert(C->unique() == unique, "verification mode made Nodes? ? ?");
    5.32 -    assert(_igvn._worklist.size() == 0, "shouldn't push anything");
    5.33 +    assert(_igvn._worklist.size() == orig_worklist_size, "shouldn't push anything");
    5.34      return;
    5.35    }
    5.36  
     6.1 --- a/src/share/vm/opto/node.cpp	Sat Mar 26 08:31:45 2011 -0700
     6.2 +++ b/src/share/vm/opto/node.cpp	Sun Mar 27 00:00:14 2011 -0700
     6.3 @@ -1373,12 +1373,12 @@
     6.4  //------------------------------find------------------------------------------
     6.5  // Find a neighbor of this Node with the given _idx
     6.6  // If idx is negative, find its absolute value, following both _in and _out.
     6.7 -static void find_recur( Node* &result, Node *n, int idx, bool only_ctrl,
     6.8 -                        VectorSet &old_space, VectorSet &new_space ) {
     6.9 +static void find_recur(Compile* C,  Node* &result, Node *n, int idx, bool only_ctrl,
    6.10 +                        VectorSet* old_space, VectorSet* new_space ) {
    6.11    int node_idx = (idx >= 0) ? idx : -idx;
    6.12    if (NotANode(n))  return;  // Gracefully handle NULL, -1, 0xabababab, etc.
    6.13 -  // Contained in new_space or old_space?
    6.14 -  VectorSet *v = Compile::current()->node_arena()->contains(n) ? &new_space : &old_space;
    6.15 +  // Contained in new_space or old_space?   Check old_arena first since it's mostly empty.
    6.16 +  VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
    6.17    if( v->test(n->_idx) ) return;
    6.18    if( (int)n->_idx == node_idx
    6.19        debug_only(|| n->debug_idx() == node_idx) ) {
    6.20 @@ -1390,19 +1390,23 @@
    6.21    v->set(n->_idx);
    6.22    for( uint i=0; i<n->len(); i++ ) {
    6.23      if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;
    6.24 -    find_recur( result, n->in(i), idx, only_ctrl, old_space, new_space );
    6.25 +    find_recur(C, result, n->in(i), idx, only_ctrl, old_space, new_space );
    6.26    }
    6.27    // Search along forward edges also:
    6.28    if (idx < 0 && !only_ctrl) {
    6.29      for( uint j=0; j<n->outcnt(); j++ ) {
    6.30 -      find_recur( result, n->raw_out(j), idx, only_ctrl, old_space, new_space );
    6.31 +      find_recur(C, result, n->raw_out(j), idx, only_ctrl, old_space, new_space );
    6.32      }
    6.33    }
    6.34  #ifdef ASSERT
    6.35 -  // Search along debug_orig edges last:
    6.36 -  for (Node* orig = n->debug_orig(); orig != NULL && n != orig; orig = orig->debug_orig()) {
    6.37 -    if (NotANode(orig))  break;
    6.38 -    find_recur( result, orig, idx, only_ctrl, old_space, new_space );
    6.39 +  // Search along debug_orig edges last, checking for cycles
    6.40 +  Node* orig = n->debug_orig();
    6.41 +  if (orig != NULL) {
    6.42 +    do {
    6.43 +      if (NotANode(orig))  break;
    6.44 +      find_recur(C, result, orig, idx, only_ctrl, old_space, new_space );
    6.45 +      orig = orig->debug_orig();
    6.46 +    } while (orig != NULL && orig != n->debug_orig());
    6.47    }
    6.48  #endif //ASSERT
    6.49  }
    6.50 @@ -1417,7 +1421,7 @@
    6.51    ResourceArea *area = Thread::current()->resource_area();
    6.52    VectorSet old_space(area), new_space(area);
    6.53    Node* result = NULL;
    6.54 -  find_recur( result, (Node*) this, idx, false, old_space, new_space );
    6.55 +  find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space );
    6.56    return result;
    6.57  }
    6.58  
    6.59 @@ -1427,7 +1431,7 @@
    6.60    ResourceArea *area = Thread::current()->resource_area();
    6.61    VectorSet old_space(area), new_space(area);
    6.62    Node* result = NULL;
    6.63 -  find_recur( result, (Node*) this, idx, true, old_space, new_space );
    6.64 +  find_recur(Compile::current(), result, (Node*) this, idx, true, &old_space, &new_space );
    6.65    return result;
    6.66  }
    6.67  #endif
     7.1 --- a/src/share/vm/runtime/globals.hpp	Sat Mar 26 08:31:45 2011 -0700
     7.2 +++ b/src/share/vm/runtime/globals.hpp	Sun Mar 27 00:00:14 2011 -0700
     7.3 @@ -2377,6 +2377,9 @@
     7.4    develop(intx, CICloneLoopTestLimit, 100,                                  \
     7.5            "size limit for blocks heuristically cloned in ciTypeFlow")       \
     7.6                                                                              \
     7.7 +  develop(intx, OSROnlyBCI, -1,                                             \
     7.8 +          "OSR only at this bci.  Negative values mean exclude that bci")   \
     7.9 +                                                                            \
    7.10    /* temp diagnostics */                                                    \
    7.11                                                                              \
    7.12    diagnostic(bool, TraceRedundantCompiles, false,                           \
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/compiler/7024475/Test7024475.java	Sun Mar 27 00:00:14 2011 -0700
     8.3 @@ -0,0 +1,71 @@
     8.4 +/*
     8.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.7 + *
     8.8 + * This code is free software; you can redistribute it and/or modify it
     8.9 + * under the terms of the GNU General Public License version 2 only, as
    8.10 + * published by the Free Software Foundation.
    8.11 + *
    8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    8.15 + * version 2 for more details (a copy is included in the LICENSE file that
    8.16 + * accompanied this code).
    8.17 + *
    8.18 + * You should have received a copy of the GNU General Public License version
    8.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    8.21 + *
    8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    8.23 + * or visit www.oracle.com if you need additional information or have any
    8.24 + * questions.
    8.25 + *
    8.26 + */
    8.27 +
    8.28 +/**
    8.29 + * @test
    8.30 + * @bug 7024475
    8.31 + * @summary loop doesn't terminate when compiled
    8.32 + *
    8.33 + * @run main Test7024475
    8.34 + */
    8.35 +
    8.36 +public class Test7024475 {
    8.37 +
    8.38 +    static int i;
    8.39 +    static int x1;
    8.40 +    static int[] bucket_B;
    8.41 +
    8.42 +    static void test(Test7024475 test, int i, int c0, int j, int c1) {
    8.43 +        for (;;) {
    8.44 +            if (c1 > c0) {
    8.45 +                if (c0 > 253) {
    8.46 +                    throw new InternalError("c0 = " + c0);
    8.47 +                }
    8.48 +                int index = c0 * 256 + c1;
    8.49 +                if (index == -1) return;
    8.50 +                i = bucket_B[index];
    8.51 +                if (1 < j - i && test != null)
    8.52 +                    x1 = 0;
    8.53 +                j = i;
    8.54 +                c1--;
    8.55 +            } else {
    8.56 +                c0--;
    8.57 +                if (j <= 0)
    8.58 +                    break;
    8.59 +                c1 = 255;
    8.60 +            }
    8.61 +        }
    8.62 +    }
    8.63 +
    8.64 +    public static void main(String args[]) {
    8.65 +        Test7024475 t = new Test7024475();
    8.66 +        bucket_B = new int[256*256];
    8.67 +        for (int i = 1; i < 256*256; i++) {
    8.68 +            bucket_B[i] = 1;
    8.69 +        }
    8.70 +        for (int n = 0; n < 100000; n++) {
    8.71 +            test(t, 2, 85, 1, 134);
    8.72 +        }
    8.73 +    }
    8.74 +}

mercurial