6589834: deoptimization problem with -XX:+DeoptimizeALot

Thu, 23 Apr 2009 14:04:24 -0700

author
cfang
date
Thu, 23 Apr 2009 14:04:24 -0700
changeset 1165
9c6be3edf0dc
parent 1164
04fa5affa478
child 1166
aa92a90b1cc6

6589834: deoptimization problem with -XX:+DeoptimizeALot
Summary: Relocate the stack pointer adjustment to where uncommon_trap is actually inserted for new_array.
Reviewed-by: kvn, jrose

src/share/vm/opto/graphKit.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/graphKit.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/parse.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/parse3.cpp file | annotate | diff | comparison | revisions
test/compiler/6589834/Test_ia32.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/graphKit.cpp	Wed Apr 22 17:03:18 2009 -0700
     1.2 +++ b/src/share/vm/opto/graphKit.cpp	Thu Apr 23 14:04:24 2009 -0700
     1.3 @@ -2980,6 +2980,7 @@
     1.4  // See comments on new_instance for the meaning of the other arguments.
     1.5  Node* GraphKit::new_array(Node* klass_node,     // array klass (maybe variable)
     1.6                            Node* length,         // number of array elements
     1.7 +                          int   nargs,          // number of arguments to push back for uncommon trap
     1.8                            bool raw_mem_only,    // affect only raw memory
     1.9                            Node* *return_size_val) {
    1.10    jint  layout_con = Klass::_lh_neutral_value;
    1.11 @@ -2995,6 +2996,7 @@
    1.12      Node* cmp_lh = _gvn.transform( new(C, 3) CmpINode(layout_val, intcon(layout_con)) );
    1.13      Node* bol_lh = _gvn.transform( new(C, 2) BoolNode(cmp_lh, BoolTest::eq) );
    1.14      { BuildCutout unless(this, bol_lh, PROB_MAX);
    1.15 +      _sp += nargs;
    1.16        uncommon_trap(Deoptimization::Reason_class_check,
    1.17                      Deoptimization::Action_maybe_recompile);
    1.18      }
     2.1 --- a/src/share/vm/opto/graphKit.hpp	Wed Apr 22 17:03:18 2009 -0700
     2.2 +++ b/src/share/vm/opto/graphKit.hpp	Thu Apr 23 14:04:24 2009 -0700
     2.3 @@ -699,7 +699,7 @@
     2.4                       Node* slow_test = NULL,
     2.5                       bool raw_mem_only = false,
     2.6                       Node* *return_size_val = NULL);
     2.7 -  Node* new_array(Node* klass_node, Node* count_val,
     2.8 +  Node* new_array(Node* klass_node, Node* count_val, int nargs,
     2.9                    bool raw_mem_only = false, Node* *return_size_val = NULL);
    2.10  
    2.11    // Handy for making control flow
     3.1 --- a/src/share/vm/opto/library_call.cpp	Wed Apr 22 17:03:18 2009 -0700
     3.2 +++ b/src/share/vm/opto/library_call.cpp	Thu Apr 23 14:04:24 2009 -0700
     3.3 @@ -3055,9 +3055,7 @@
     3.4      // Normal case:  The array type has been cached in the java.lang.Class.
     3.5      // The following call works fine even if the array type is polymorphic.
     3.6      // It could be a dynamic mix of int[], boolean[], Object[], etc.
     3.7 -    _sp += nargs;  // set original stack for use by uncommon_trap
     3.8 -    Node* obj = new_array(klass_node, count_val);
     3.9 -    _sp -= nargs;
    3.10 +    Node* obj = new_array(klass_node, count_val, nargs);
    3.11      result_reg->init_req(_normal_path, control());
    3.12      result_val->init_req(_normal_path, obj);
    3.13      result_io ->init_req(_normal_path, i_o());
    3.14 @@ -3179,9 +3177,7 @@
    3.15      Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) );
    3.16      Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
    3.17  
    3.18 -    _sp += nargs;  // set original stack for use by uncommon_trap
    3.19 -    Node* newcopy = new_array(klass_node, length);
    3.20 -    _sp -= nargs;
    3.21 +    Node* newcopy = new_array(klass_node, length, nargs);
    3.22  
    3.23      // Generate a direct call to the right arraycopy function(s).
    3.24      // We know the copy is disjoint but we might not know if the
    3.25 @@ -3903,10 +3899,8 @@
    3.26      set_control(array_ctl);
    3.27      Node* obj_length = load_array_length(obj);
    3.28      Node* obj_size = NULL;
    3.29 -    _sp += nargs;  // set original stack for use by uncommon_trap
    3.30 -    Node* alloc_obj = new_array(obj_klass, obj_length,
    3.31 +    Node* alloc_obj = new_array(obj_klass, obj_length, nargs,
    3.32                                  raw_mem_only, &obj_size);
    3.33 -    _sp -= nargs;
    3.34      assert(obj_size != NULL, "");
    3.35      Node* raw_obj = alloc_obj->in(1);
    3.36      assert(raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), "");
     4.1 --- a/src/share/vm/opto/parse.hpp	Wed Apr 22 17:03:18 2009 -0700
     4.2 +++ b/src/share/vm/opto/parse.hpp	Thu Apr 23 14:04:24 2009 -0700
     4.3 @@ -476,7 +476,7 @@
     4.4    void do_newarray(BasicType elemtype);
     4.5    void do_anewarray();
     4.6    void do_multianewarray();
     4.7 -  Node* expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions);
     4.8 +  Node* expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions, int nargs);
     4.9  
    4.10    // implementation of jsr/ret
    4.11    void do_jsr();
     5.1 --- a/src/share/vm/opto/parse3.cpp	Wed Apr 22 17:03:18 2009 -0700
     5.2 +++ b/src/share/vm/opto/parse3.cpp	Thu Apr 23 14:04:24 2009 -0700
     5.3 @@ -335,7 +335,7 @@
     5.4  
     5.5    const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass);
     5.6    Node* count_val = pop();
     5.7 -  Node* obj = new_array(makecon(array_klass_type), count_val);
     5.8 +  Node* obj = new_array(makecon(array_klass_type), count_val, 1);
     5.9    push(obj);
    5.10  }
    5.11  
    5.12 @@ -345,17 +345,17 @@
    5.13  
    5.14    Node*   count_val = pop();
    5.15    const TypeKlassPtr* array_klass = TypeKlassPtr::make(ciTypeArrayKlass::make(elem_type));
    5.16 -  Node*   obj = new_array(makecon(array_klass), count_val);
    5.17 +  Node*   obj = new_array(makecon(array_klass), count_val, 1);
    5.18    // Push resultant oop onto stack
    5.19    push(obj);
    5.20  }
    5.21  
    5.22  // Expand simple expressions like new int[3][5] and new Object[2][nonConLen].
    5.23  // Also handle the degenerate 1-dimensional case of anewarray.
    5.24 -Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions) {
    5.25 +Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions, int nargs) {
    5.26    Node* length = lengths[0];
    5.27    assert(length != NULL, "");
    5.28 -  Node* array = new_array(makecon(TypeKlassPtr::make(array_klass)), length);
    5.29 +  Node* array = new_array(makecon(TypeKlassPtr::make(array_klass)), length, nargs);
    5.30    if (ndimensions > 1) {
    5.31      jint length_con = find_int_con(length, -1);
    5.32      guarantee(length_con >= 0, "non-constant multianewarray");
    5.33 @@ -364,7 +364,7 @@
    5.34      const Type*    elemtype = _gvn.type(array)->is_aryptr()->elem();
    5.35      const intptr_t header   = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
    5.36      for (jint i = 0; i < length_con; i++) {
    5.37 -      Node*    elem   = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1);
    5.38 +      Node*    elem   = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs);
    5.39        intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop);
    5.40        Node*    eaddr  = basic_plus_adr(array, offset);
    5.41        store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT);
    5.42 @@ -419,7 +419,7 @@
    5.43    // Can use multianewarray instead of [a]newarray if only one dimension,
    5.44    // or if all non-final dimensions are small constants.
    5.45    if (expand_count == 1 || (1 <= expand_count && expand_count <= expand_limit)) {
    5.46 -    Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions);
    5.47 +    Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions, ndimensions);
    5.48      push(obj);
    5.49      return;
    5.50    }
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/compiler/6589834/Test_ia32.java	Thu Apr 23 14:04:24 2009 -0700
     6.3 @@ -0,0 +1,126 @@
     6.4 +/*
     6.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.7 + *
     6.8 + * This code is free software; you can redistribute it and/or modify it
     6.9 + * under the terms of the GNU General Public License version 2 only, as
    6.10 + * published by the Free Software Foundation.
    6.11 + *
    6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    6.15 + * version 2 for more details (a copy is included in the LICENSE file that
    6.16 + * accompanied this code).
    6.17 + *
    6.18 + * You should have received a copy of the GNU General Public License version
    6.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    6.21 + *
    6.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    6.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    6.24 + * have any questions.
    6.25 + */
    6.26 +
    6.27 +/**
    6.28 + * @test
    6.29 + * @bug 6589834
    6.30 + * @summary: deoptimization problem with -XX:+DeoptimizeALot
    6.31 + *
    6.32 + * @run main/othervm -server Test_ia32
    6.33 + */
    6.34 +
    6.35 +/***************************************************************************************
    6.36 +NOTE: The bug shows up (with several "Bug!" message) even without the
    6.37 +      flag -XX:+DeoptimizeALot. In a debug build, you may want to try
    6.38 +      the flags -XX:+VerifyStack and -XX:+DeoptimizeALot to get more information.
    6.39 +****************************************************************************************/
    6.40 +import java.lang.reflect.Constructor;
    6.41 +
    6.42 +public class Test_ia32 {
    6.43 +
    6.44 +    public static int NUM_THREADS = 100;
    6.45 +
    6.46 +    public static int CLONE_LENGTH = 1000;
    6.47 +
    6.48 +    public static void main(String[] args) throws InterruptedException, ClassNotFoundException {
    6.49 +
    6.50 +        Reflector[] threads = new Reflector[NUM_THREADS];
    6.51 +        for (int i = 0; i < threads.length; i++) {
    6.52 +            threads[i] = new Reflector();
    6.53 +            threads[i].start();
    6.54 +        }
    6.55 +
    6.56 +        System.out.println("Give Reflector.run() some time to compile...");
    6.57 +        Thread.sleep(5000);
    6.58 +
    6.59 +        System.out.println("Load RMISecurityException causing run() deoptimization");
    6.60 +        ClassLoader.getSystemClassLoader().loadClass("java.rmi.RMISecurityException");
    6.61 +
    6.62 +        for (Reflector thread : threads)
    6.63 +            thread.requestStop();
    6.64 +
    6.65 +        for (Reflector thread : threads)
    6.66 +            try {
    6.67 +                thread.join();
    6.68 +            } catch (InterruptedException e) {
    6.69 +                System.out.println(e);
    6.70 +            }
    6.71 +
    6.72 +    }
    6.73 +
    6.74 +}
    6.75 +
    6.76 +class Reflector extends Thread {
    6.77 +
    6.78 +    volatile boolean _doSpin = true;
    6.79 +
    6.80 +    Test_ia32[] _tests;
    6.81 +
    6.82 +    Reflector() {
    6.83 +        _tests = new Test_ia32[Test_ia32.CLONE_LENGTH];
    6.84 +        for (int i = 0; i < _tests.length; i++) {
    6.85 +            _tests[i] = new Test_ia32();
    6.86 +        }
    6.87 +    }
    6.88 +
    6.89 +    static int g(int i1, int i2, Test_ia32[] arr, int i3, int i4) {
    6.90 +
    6.91 +        if (!(i1==1 && i2==2 && i3==3 && i4==4)) {
    6.92 +            System.out.println("Bug!");
    6.93 +        }
    6.94 +
    6.95 +        return arr.length;
    6.96 +    }
    6.97 +
    6.98 +    static int f(Test_ia32[] arr) {
    6.99 +        return g(1, 2, arr.clone(), 3, 4);
   6.100 +    }
   6.101 +
   6.102 +    @Override
   6.103 +    public void run() {
   6.104 +        Constructor[] ctrs = null;
   6.105 +        Class<Test_ia32> klass = Test_ia32.class;
   6.106 +        try {
   6.107 +            ctrs = klass.getConstructors();
   6.108 +        } catch (SecurityException e) {
   6.109 +            System.out.println(e);
   6.110 +        }
   6.111 +
   6.112 +        try {
   6.113 +            while (_doSpin) {
   6.114 +                if (f(_tests) < 0)
   6.115 +                    System.out.println("return value usage");
   6.116 +            }
   6.117 +        } catch (NullPointerException e) {
   6.118 +            e.printStackTrace();
   6.119 +        }
   6.120 +
   6.121 +        System.out.println(this + " - stopped.");
   6.122 +    }
   6.123 +
   6.124 +    public void requestStop() {
   6.125 +        System.out.println(this + " - stop requested.");
   6.126 +        _doSpin = false;
   6.127 +    }
   6.128 +
   6.129 +}

mercurial