Fri, 25 Apr 2014 09:22:16 +0200
8041481: JVM crashes with collect_args_for_profiling
Summary: method handle call to c1 intrinsic tries to profile popped argument
Reviewed-by: kvn, twisti
1.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Mon May 05 15:10:43 2014 +0200 1.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Apr 25 09:22:16 2014 +0200 1.3 @@ -1697,6 +1697,15 @@ 1.4 return NULL; 1.5 } 1.6 1.7 +void GraphBuilder::check_args_for_profiling(Values* obj_args, int expected) { 1.8 +#ifdef ASSERT 1.9 + bool ignored_will_link; 1.10 + ciSignature* declared_signature = NULL; 1.11 + ciMethod* real_target = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); 1.12 + assert(expected == obj_args->length() || real_target->is_method_handle_intrinsic(), "missed on arg?"); 1.13 +#endif 1.14 +} 1.15 + 1.16 // Collect arguments that we want to profile in a list 1.17 Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) { 1.18 int start = 0; 1.19 @@ -1705,13 +1714,14 @@ 1.20 return NULL; 1.21 } 1.22 int s = obj_args->size(); 1.23 - for (int i = start, j = 0; j < s; i++) { 1.24 + // if called through method handle invoke, some arguments may have been popped 1.25 + for (int i = start, j = 0; j < s && i < args->length(); i++) { 1.26 if (args->at(i)->type()->is_object_kind()) { 1.27 obj_args->push(args->at(i)); 1.28 j++; 1.29 } 1.30 } 1.31 - assert(s == obj_args->length(), "missed on arg?"); 1.32 + check_args_for_profiling(obj_args, s); 1.33 return obj_args; 1.34 } 1.35 1.36 @@ -3843,14 +3853,7 @@ 1.37 j++; 1.38 } 1.39 } 1.40 -#ifdef ASSERT 1.41 - { 1.42 - bool ignored_will_link; 1.43 - ciSignature* declared_signature = NULL; 1.44 - ciMethod* real_target = method()->get_method_at_bci(bci(), ignored_will_link, &declared_signature); 1.45 - assert(s == obj_args->length() || real_target->is_method_handle_intrinsic(), "missed on arg?"); 1.46 - } 1.47 -#endif 1.48 + check_args_for_profiling(obj_args, s); 1.49 } 1.50 profile_call(callee, recv, holder_known ? callee->holder() : NULL, obj_args, true); 1.51 }
2.1 --- a/src/share/vm/c1/c1_GraphBuilder.hpp Mon May 05 15:10:43 2014 +0200 2.2 +++ b/src/share/vm/c1/c1_GraphBuilder.hpp Fri Apr 25 09:22:16 2014 +0200 2.3 @@ -392,6 +392,7 @@ 2.4 2.5 Values* args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver); 2.6 Values* collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver); 2.7 + void check_args_for_profiling(Values* obj_args, int expected); 2.8 2.9 public: 2.10 NOT_PRODUCT(void print_stats();)
3.1 --- a/src/share/vm/c1/c1_LIRGenerator.cpp Mon May 05 15:10:43 2014 +0200 3.2 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 25 09:22:16 2014 +0200 3.3 @@ -2634,8 +2634,10 @@ 3.4 // LIR_Assembler::emit_profile_type() from emitting useless code 3.5 profiled_k = ciTypeEntries::with_status(result, profiled_k); 3.6 } 3.7 - if (exact_signature_k != NULL && exact_klass != exact_signature_k) { 3.8 - assert(exact_klass == NULL, "obj and signature disagree?"); 3.9 + // exact_klass and exact_signature_k can be both non NULL but 3.10 + // different if exact_klass is loaded after the ciObject for 3.11 + // exact_signature_k is created. 3.12 + if (exact_klass == NULL && exact_signature_k != NULL && exact_klass != exact_signature_k) { 3.13 // sometimes the type of the signature is better than the best type 3.14 // the compiler has 3.15 exact_klass = exact_signature_k; 3.16 @@ -2646,8 +2648,7 @@ 3.17 if (improved_klass == NULL) { 3.18 improved_klass = comp->cha_exact_type(callee_signature_k); 3.19 } 3.20 - if (improved_klass != NULL && exact_klass != improved_klass) { 3.21 - assert(exact_klass == NULL, "obj and signature disagree?"); 3.22 + if (exact_klass == NULL && improved_klass != NULL && exact_klass != improved_klass) { 3.23 exact_klass = exact_signature_k; 3.24 } 3.25 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/compiler/profiling/TestMethodHandleInvokesIntrinsic.java Fri Apr 25 09:22:16 2014 +0200 4.3 @@ -0,0 +1,92 @@ 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 + * @test 4.29 + * @bug 8041458 4.30 + * @summary profiling of arguments in C1 at MethodHandle invoke of intrinsic tries to profile popped argument. 4.31 + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TieredStopAtLevel=3 TestMethodHandleInvokesIntrinsic 4.32 + * 4.33 + */ 4.34 + 4.35 +import java.lang.invoke.*; 4.36 + 4.37 +public class TestMethodHandleInvokesIntrinsic { 4.38 + 4.39 + static final MethodHandle mh_nanoTime; 4.40 + static final MethodHandle mh_getClass; 4.41 + static { 4.42 + MethodHandles.Lookup lookup = MethodHandles.lookup(); 4.43 + MethodType mt = MethodType.methodType(long.class); 4.44 + MethodHandle MH = null; 4.45 + try { 4.46 + MH = lookup.findStatic(System.class, "nanoTime", mt); 4.47 + } catch(NoSuchMethodException nsme) { 4.48 + nsme.printStackTrace(); 4.49 + throw new RuntimeException("TEST FAILED", nsme); 4.50 + } catch(IllegalAccessException iae) { 4.51 + iae.printStackTrace(); 4.52 + throw new RuntimeException("TEST FAILED", iae); 4.53 + } 4.54 + mh_nanoTime = MH; 4.55 + 4.56 + mt = MethodType.methodType(Class.class); 4.57 + MH = null; 4.58 + try { 4.59 + MH = lookup.findVirtual(Object.class, "getClass", mt); 4.60 + } catch(NoSuchMethodException nsme) { 4.61 + nsme.printStackTrace(); 4.62 + throw new RuntimeException("TEST FAILED", nsme); 4.63 + } catch(IllegalAccessException iae) { 4.64 + iae.printStackTrace(); 4.65 + throw new RuntimeException("TEST FAILED", iae); 4.66 + } 4.67 + mh_getClass = MH; 4.68 + } 4.69 + 4.70 + static long m1() throws Throwable { 4.71 + return (long)mh_nanoTime.invokeExact(); 4.72 + } 4.73 + 4.74 + static Class m2(Object o) throws Throwable { 4.75 + return (Class)mh_getClass.invokeExact(o); 4.76 + } 4.77 + 4.78 + static public void main(String[] args) { 4.79 + try { 4.80 + for (int i = 0; i < 20000; i++) { 4.81 + m1(); 4.82 + } 4.83 + TestMethodHandleInvokesIntrinsic o = new TestMethodHandleInvokesIntrinsic(); 4.84 + for (int i = 0; i < 20000; i++) { 4.85 + m2(o); 4.86 + } 4.87 + } catch(Throwable t) { 4.88 + System.out.println("Unexpected exception"); 4.89 + t.printStackTrace(); 4.90 + throw new RuntimeException("TEST FAILED", t); 4.91 + } 4.92 + 4.93 + System.out.println("TEST PASSED"); 4.94 + } 4.95 +}