8033626: assert(ex_map->jvms()->same_calls_as(_exceptions->jvms())) failed: all collected exceptions must come from the same place

Tue, 17 Jun 2014 09:02:30 +0000

author
vlivanov
date
Tue, 17 Jun 2014 09:02:30 +0000
changeset 6733
00c8a1255912
parent 6732
168c10900e79
child 6734
a07a3a29df67

8033626: assert(ex_map->jvms()->same_calls_as(_exceptions->jvms())) failed: all collected exceptions must come from the same place
Reviewed-by: kvn, roland

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
test/compiler/intrinsics/clone/TestObjectClone.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/graphKit.cpp	Fri Jun 13 15:04:38 2014 -0700
     1.2 +++ b/src/share/vm/opto/graphKit.cpp	Tue Jun 17 09:02:30 2014 +0000
     1.3 @@ -2458,7 +2458,7 @@
     1.4  
     1.5  //------------------------------make_slow_call_ex------------------------------
     1.6  // Make the exception handler hookups for the slow call
     1.7 -void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj) {
     1.8 +void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj, bool deoptimize) {
     1.9    if (stopped())  return;
    1.10  
    1.11    // Make a catch node with just two handlers:  fall-through and catch-all
    1.12 @@ -2472,11 +2472,17 @@
    1.13      set_i_o(i_o);
    1.14  
    1.15      if (excp != top()) {
    1.16 -      // Create an exception state also.
    1.17 -      // Use an exact type if the caller has specified a specific exception.
    1.18 -      const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull);
    1.19 -      Node*       ex_oop  = new (C) CreateExNode(ex_type, control(), i_o);
    1.20 -      add_exception_state(make_exception_state(_gvn.transform(ex_oop)));
    1.21 +      if (deoptimize) {
    1.22 +        // Deoptimize if an exception is caught. Don't construct exception state in this case.
    1.23 +        uncommon_trap(Deoptimization::Reason_unhandled,
    1.24 +                      Deoptimization::Action_none);
    1.25 +      } else {
    1.26 +        // Create an exception state also.
    1.27 +        // Use an exact type if the caller has specified a specific exception.
    1.28 +        const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull);
    1.29 +        Node*       ex_oop  = new (C) CreateExNode(ex_type, control(), i_o);
    1.30 +        add_exception_state(make_exception_state(_gvn.transform(ex_oop)));
    1.31 +      }
    1.32      }
    1.33    }
    1.34  
    1.35 @@ -3290,7 +3296,8 @@
    1.36  
    1.37  //---------------------------set_output_for_allocation-------------------------
    1.38  Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
    1.39 -                                          const TypeOopPtr* oop_type) {
    1.40 +                                          const TypeOopPtr* oop_type,
    1.41 +                                          bool deoptimize_on_exception) {
    1.42    int rawidx = Compile::AliasIdxRaw;
    1.43    alloc->set_req( TypeFunc::FramePtr, frameptr() );
    1.44    add_safepoint_edges(alloc);
    1.45 @@ -3298,7 +3305,7 @@
    1.46    set_control( _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Control) ) );
    1.47    // create memory projection for i_o
    1.48    set_memory ( _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Memory, true) ), rawidx );
    1.49 -  make_slow_call_ex(allocx, env()->Throwable_klass(), true);
    1.50 +  make_slow_call_ex(allocx, env()->Throwable_klass(), true, deoptimize_on_exception);
    1.51  
    1.52    // create a memory projection as for the normal control path
    1.53    Node* malloc = _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Memory));
    1.54 @@ -3376,9 +3383,11 @@
    1.55  // The optional arguments are for specialized use by intrinsics:
    1.56  //  - If 'extra_slow_test' if not null is an extra condition for the slow-path.
    1.57  //  - If 'return_size_val', report the the total object size to the caller.
    1.58 +//  - deoptimize_on_exception controls how Java exceptions are handled (rethrow vs deoptimize)
    1.59  Node* GraphKit::new_instance(Node* klass_node,
    1.60                               Node* extra_slow_test,
    1.61 -                             Node* *return_size_val) {
    1.62 +                             Node* *return_size_val,
    1.63 +                             bool deoptimize_on_exception) {
    1.64    // Compute size in doublewords
    1.65    // The size is always an integral number of doublewords, represented
    1.66    // as a positive bytewise size stored in the klass's layout_helper.
    1.67 @@ -3447,7 +3456,7 @@
    1.68                             size, klass_node,
    1.69                             initial_slow_test);
    1.70  
    1.71 -  return set_output_for_allocation(alloc, oop_type);
    1.72 +  return set_output_for_allocation(alloc, oop_type, deoptimize_on_exception);
    1.73  }
    1.74  
    1.75  //-------------------------------new_array-------------------------------------
    1.76 @@ -3457,7 +3466,8 @@
    1.77  Node* GraphKit::new_array(Node* klass_node,     // array klass (maybe variable)
    1.78                            Node* length,         // number of array elements
    1.79                            int   nargs,          // number of arguments to push back for uncommon trap
    1.80 -                          Node* *return_size_val) {
    1.81 +                          Node* *return_size_val,
    1.82 +                          bool deoptimize_on_exception) {
    1.83    jint  layout_con = Klass::_lh_neutral_value;
    1.84    Node* layout_val = get_layout_helper(klass_node, layout_con);
    1.85    int   layout_is_con = (layout_val == NULL);
    1.86 @@ -3600,7 +3610,7 @@
    1.87      ary_type = ary_type->is_aryptr()->cast_to_size(length_type);
    1.88    }
    1.89  
    1.90 -  Node* javaoop = set_output_for_allocation(alloc, ary_type);
    1.91 +  Node* javaoop = set_output_for_allocation(alloc, ary_type, deoptimize_on_exception);
    1.92  
    1.93    // Cast length on remaining path to be as narrow as possible
    1.94    if (map()->find_edge(length) >= 0) {
     2.1 --- a/src/share/vm/opto/graphKit.hpp	Fri Jun 13 15:04:38 2014 -0700
     2.2 +++ b/src/share/vm/opto/graphKit.hpp	Tue Jun 17 09:02:30 2014 +0000
     2.3 @@ -802,7 +802,7 @@
     2.4  
     2.5    // merge in all memory slices from new_mem, along the given path
     2.6    void merge_memory(Node* new_mem, Node* region, int new_path);
     2.7 -  void make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj);
     2.8 +  void make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj, bool deoptimize = false);
     2.9  
    2.10    // Helper functions to build synchronizations
    2.11    int next_monitor();
    2.12 @@ -844,13 +844,16 @@
    2.13  
    2.14    // implementation of object creation
    2.15    Node* set_output_for_allocation(AllocateNode* alloc,
    2.16 -                                  const TypeOopPtr* oop_type);
    2.17 +                                  const TypeOopPtr* oop_type,
    2.18 +                                  bool deoptimize_on_exception=false);
    2.19    Node* get_layout_helper(Node* klass_node, jint& constant_value);
    2.20    Node* new_instance(Node* klass_node,
    2.21                       Node* slow_test = NULL,
    2.22 -                     Node* *return_size_val = NULL);
    2.23 +                     Node* *return_size_val = NULL,
    2.24 +                     bool deoptimize_on_exception = false);
    2.25    Node* new_array(Node* klass_node, Node* count_val, int nargs,
    2.26 -                  Node* *return_size_val = NULL);
    2.27 +                  Node* *return_size_val = NULL,
    2.28 +                  bool deoptimize_on_exception = false);
    2.29  
    2.30    // java.lang.String helpers
    2.31    Node* load_String_offset(Node* ctrl, Node* str);
     3.1 --- a/src/share/vm/opto/library_call.cpp	Fri Jun 13 15:04:38 2014 -0700
     3.2 +++ b/src/share/vm/opto/library_call.cpp	Tue Jun 17 09:02:30 2014 +0000
     3.3 @@ -4576,7 +4576,10 @@
     3.4        // It's an instance, and it passed the slow-path tests.
     3.5        PreserveJVMState pjvms(this);
     3.6        Node* obj_size  = NULL;
     3.7 -      Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size);
     3.8 +      // Need to deoptimize on exception from allocation since Object.clone intrinsic
     3.9 +      // is reexecuted if deoptimization occurs and there could be problems when merging
    3.10 +      // exception state between multiple Object.clone versions (reexecute=true vs reexecute=false).
    3.11 +      Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size, /*deoptimize_on_exception=*/true);
    3.12  
    3.13        copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks());
    3.14  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/compiler/intrinsics/clone/TestObjectClone.java	Tue Jun 17 09:02:30 2014 +0000
     4.3 @@ -0,0 +1,80 @@
     4.4 +/*
     4.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.
    4.11 + *
    4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.15 + * version 2 for more details (a copy is included in the LICENSE file that
    4.16 + * accompanied this code).
    4.17 + *
    4.18 + * You should have received a copy of the GNU General Public License version
    4.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.21 + *
    4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.23 + * or visit www.oracle.com if you need additional information or have any
    4.24 + * questions.
    4.25 + *
    4.26 + */
    4.27 +
    4.28 +/*
    4.29 + * @test
    4.30 + * @bug 8033626
    4.31 + * @summary assert(ex_map->jvms()->same_calls_as(_exceptions->jvms())) failed: all collected exceptions must come from the same place
    4.32 + * @library /testlibrary
    4.33 + * @run main/othervm -XX:-TieredCompilation -Xbatch -XX:CompileOnly=TestObjectClone::f TestObjectClone
    4.34 + */
    4.35 +import com.oracle.java.testlibrary.Asserts;
    4.36 +
    4.37 +public class TestObjectClone implements Cloneable {
    4.38 +    static class A extends TestObjectClone {}
    4.39 +    static class B extends TestObjectClone {
    4.40 +        public B clone() {
    4.41 +            return (B)TestObjectClone.b;
    4.42 +        }
    4.43 +    }
    4.44 +    static class C extends TestObjectClone {
    4.45 +        public C clone() {
    4.46 +            return (C)TestObjectClone.c;
    4.47 +        }
    4.48 +    }
    4.49 +    static class D extends TestObjectClone {
    4.50 +        public D clone() {
    4.51 +            return (D)TestObjectClone.d;
    4.52 +        }
    4.53 +    }
    4.54 +    static TestObjectClone a = new A(), b = new B(), c = new C(), d = new D();
    4.55 +
    4.56 +    public static Object f(TestObjectClone o) throws CloneNotSupportedException {
    4.57 +        // Polymorphic call site: >90% Object::clone / <10% other methods
    4.58 +        return o.clone();
    4.59 +    }
    4.60 +
    4.61 +    public static void main(String[] args) throws Exception {
    4.62 +        TestObjectClone[] params1 = {a, a, a, a, a, a, a, a, a, a, a,
    4.63 +                          a, a, a, a, a, a, a, a, a, a, a,
    4.64 +                          a, a, a, a, a, a, a, a, a, a, a,
    4.65 +                          b, c, d};
    4.66 +
    4.67 +        for (int i = 0; i < 15000; i++) {
    4.68 +            f(params1[i % params1.length]);
    4.69 +        }
    4.70 +
    4.71 +        Asserts.assertTrue(f(a) != a);
    4.72 +        Asserts.assertTrue(f(b) == b);
    4.73 +        Asserts.assertTrue(f(c) == c);
    4.74 +        Asserts.assertTrue(f(d) == d);
    4.75 +
    4.76 +        try {
    4.77 +            f(null);
    4.78 +            throw new AssertionError("");
    4.79 +        } catch (NullPointerException e) { /* expected */ }
    4.80 +
    4.81 +        System.out.println("TEST PASSED");
    4.82 +    }
    4.83 +}

mercurial