8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943

Sat, 02 Aug 2014 07:06:08 +0200

author
roland
date
Sat, 02 Aug 2014 07:06:08 +0200
changeset 7166
f8afcfbdbf1c
parent 7164
fa6c442c59ee
child 7167
be56d800c946

8046698: assert(false) failed: only Initialize or AddP expected macro.cpp:943
Summary: PhiNode inserted between AllocateNode and Initialization node confuses allocation elimination
Reviewed-by: kvn

src/share/vm/opto/callnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/macro.cpp file | annotate | diff | comparison | revisions
test/compiler/macronodes/TestEliminateAllocationPhi.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/callnode.cpp	Wed Sep 10 16:06:53 2014 -0700
     1.2 +++ b/src/share/vm/opto/callnode.cpp	Sat Aug 02 07:06:08 2014 +0200
     1.3 @@ -777,7 +777,7 @@
     1.4  }
     1.5  
     1.6  // Returns the unique CheckCastPP of a call
     1.7 -// or 'this' if there are several CheckCastPP
     1.8 +// or 'this' if there are several CheckCastPP or unexpected uses
     1.9  // or returns NULL if there is no one.
    1.10  Node *CallNode::result_cast() {
    1.11    Node *cast = NULL;
    1.12 @@ -793,6 +793,13 @@
    1.13          return this;  // more than 1 CheckCastPP
    1.14        }
    1.15        cast = use;
    1.16 +    } else if (!use->is_Initialize() &&
    1.17 +               !use->is_AddP()) {
    1.18 +      // Expected uses are restricted to a CheckCastPP, an Initialize
    1.19 +      // node, and AddP nodes. If we encounter any other use (a Phi
    1.20 +      // node can be seen in rare cases) return this to prevent
    1.21 +      // incorrect optimizations.
    1.22 +      return this;
    1.23      }
    1.24    }
    1.25    return cast;
     2.1 --- a/src/share/vm/opto/macro.cpp	Wed Sep 10 16:06:53 2014 -0700
     2.2 +++ b/src/share/vm/opto/macro.cpp	Sat Aug 02 07:06:08 2014 +0200
     2.3 @@ -699,6 +699,7 @@
     2.4    ciType* elem_type;
     2.5  
     2.6    Node* res = alloc->result_cast();
     2.7 +  assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result");
     2.8    const TypeOopPtr* res_type = NULL;
     2.9    if (res != NULL) { // Could be NULL when there are no users
    2.10      res_type = _igvn.type(res)->isa_oopptr();
    2.11 @@ -1031,6 +1032,8 @@
    2.12      return false;
    2.13    }
    2.14  
    2.15 +  assert(boxing->result_cast() == NULL, "unexpected boxing node result");
    2.16 +
    2.17    extract_call_projections(boxing);
    2.18  
    2.19    const TypeTuple* r = boxing->tf()->range();
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/compiler/macronodes/TestEliminateAllocationPhi.java	Sat Aug 02 07:06:08 2014 +0200
     3.3 @@ -0,0 +1,94 @@
     3.4 +/*
     3.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + *
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + *
    3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.23 + * or visit www.oracle.com if you need additional information or have any
    3.24 + * questions.
    3.25 + */
    3.26 +
    3.27 +/*
    3.28 + * @test
    3.29 + * @bug 8046698
    3.30 + * @summary PhiNode inserted between AllocateNode and Initialization node confuses allocation elimination
    3.31 + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestEliminateAllocationPhi
    3.32 + *
    3.33 + */
    3.34 +
    3.35 +public class TestEliminateAllocationPhi {
    3.36 +
    3.37 +    // This will return I when called from m(0 and once optimized will
    3.38 +    // go away but this will confuse escape analysis in m(): it will
    3.39 +    // find I as non escaping but non scalar replaceable. In its own
    3.40 +    // method so that we can make the profile of the if() branch look
    3.41 +    // like it's taken sometimes.
    3.42 +    static Integer m2(Integer I, int i) {
    3.43 +        for (; i < 10; i=(i+2)*(i+2)) {
    3.44 +        }
    3.45 +        if (i == 121) {
    3.46 +            return II;
    3.47 +        }
    3.48 +        return I;
    3.49 +    }
    3.50 +
    3.51 +    static Integer II = new Integer(42);
    3.52 +
    3.53 +    static int m(int[] integers, boolean flag) {
    3.54 +        int j = 0;
    3.55 +        while(true) {
    3.56 +            try {
    3.57 +                int k = integers[j++];
    3.58 +                // A branch that will cause loop unswitching
    3.59 +                if (flag) {
    3.60 +                    k += 42;
    3.61 +                }
    3.62 +                if (k < 1000) {
    3.63 +                    throw new Exception();
    3.64 +                }
    3.65 +                // Because of the try/catch the Allocate node for this
    3.66 +                // new will be in the loop while the Initialization
    3.67 +                // node will be outside the loop. When loop
    3.68 +                // unswitching happens, the Allocate node will be
    3.69 +                // cloned and the results of both will be inputs to a
    3.70 +                // Phi that will be between the Allocate nodes and the
    3.71 +                // Initialization nodes.
    3.72 +                Integer I = new Integer(k);
    3.73 +
    3.74 +                I = m2(I, 0);
    3.75 +
    3.76 +                int i = I.intValue();
    3.77 +                return i;
    3.78 +            } catch(Exception e) {
    3.79 +            }
    3.80 +        }
    3.81 +    }
    3.82 +
    3.83 +    static public void main(String[] args) {
    3.84 +        for (int i = 0; i < 5000; i++) {
    3.85 +            m2(null, 1);
    3.86 +        }
    3.87 +
    3.88 +        int[] integers = { 2000 };
    3.89 +        for (int i = 0; i < 6000; i++) {
    3.90 +            m(integers, (i%2) == 0);
    3.91 +        }
    3.92 +        int[] integers2 = { 1, 2, 3, 4, 5, 2000 };
    3.93 +        for (int i = 0; i < 10000; i++) {
    3.94 +            m(integers2, (i%2) == 0);
    3.95 +        }
    3.96 +    }
    3.97 +}

mercurial