8224162: assert(profile.count() == 0) failed: sanity in InlineTree::is_not_reached
Reviewed-by: vlivanov, kvn
--- a/src/hotspot/share/ci/ciMethod.cpp Tue Jun 04 17:56:16 2019 +0800
+++ b/src/hotspot/share/ci/ciMethod.cpp Thu Jun 06 13:45:59 2019 +0300
@@ -462,6 +462,27 @@
// ------------------------------------------------------------------
+// ciMethod::check_overflow
+//
+// Check whether the profile counter is overflowed and adjust if true.
+// For invoke* it will turn negative values into max_jint,
+// and for checkcast/aastore/instanceof turn positive values into min_jint.
+int ciMethod::check_overflow(int c, Bytecodes::Code code) {
+ switch (code) {
+ case Bytecodes::_aastore: // fall-through
+ case Bytecodes::_checkcast: // fall-through
+ case Bytecodes::_instanceof: {
+ return (c > 0 ? min_jint : c); // always non-positive
+ }
+ default: {
+ assert(Bytecodes::is_invoke(code), "%s", Bytecodes::name(code));
+ return (c < 0 ? max_jint : c); // always non-negative
+ }
+ }
+}
+
+
+// ------------------------------------------------------------------
// ciMethod::call_profile_at_bci
//
// Get the ciCallProfile for the invocation of this method.
@@ -473,7 +494,7 @@
ciProfileData* data = method_data()->bci_to_data(bci);
if (data != NULL && data->is_CounterData()) {
// Every profiled call site has a counter.
- int count = data->as_CounterData()->count();
+ int count = check_overflow(data->as_CounterData()->count(), java_code_at_bci(bci));
if (!data->is_ReceiverTypeData()) {
result._receiver_count[0] = 0; // that's a definite zero
@@ -502,9 +523,9 @@
for (uint i = 0; i < call->row_limit(); i++) {
ciKlass* receiver = call->receiver(i);
if (receiver == NULL) continue;
- int rcount = call->receiver_count(i) + epsilon;
+ int rcount = saturated_add(call->receiver_count(i), epsilon);
if (rcount == 0) rcount = 1; // Should be valid value
- receivers_count_total += rcount;
+ receivers_count_total = saturated_add(receivers_count_total, rcount);
// Add the receiver to result data.
result.add_receiver(receiver, rcount);
// If we extend profiling to record methods,
@@ -534,7 +555,7 @@
// do nothing. Otherwise, increase count to be the sum of all
// receiver's counts.
if (count >= 0) {
- count += receivers_count_total;
+ count = saturated_add(count, receivers_count_total);
}
}
result._count = count;
--- a/src/hotspot/share/ci/ciMethod.hpp Tue Jun 04 17:56:16 2019 +0800
+++ b/src/hotspot/share/ci/ciMethod.hpp Thu Jun 06 13:45:59 2019 +0300
@@ -126,6 +126,9 @@
void assert_virtual_call_type_ok(int bci);
void assert_call_type_ok(int bci);
+ // Check and update the profile counter in case of overflow
+ static int check_overflow(int c, Bytecodes::Code code);
+
public:
void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
--- a/src/hotspot/share/oops/methodData.hpp Tue Jun 04 17:56:16 2019 +0800
+++ b/src/hotspot/share/oops/methodData.hpp Thu Jun 06 13:45:59 2019 +0300
@@ -558,8 +558,14 @@
}
// Direct accessor
- uint count() const {
- return uint_at(count_off);
+ int count() const {
+ intptr_t raw_data = intptr_at(count_off);
+ if (raw_data > max_jint) {
+ raw_data = max_jint;
+ } else if (raw_data < min_jint) {
+ raw_data = min_jint;
+ }
+ return int(raw_data);
}
// Code generation support
@@ -570,8 +576,8 @@
return cell_offset(counter_cell_count);
}
- void set_count(uint count) {
- set_uint_at(count_off, count);
+ void set_count(int count) {
+ set_int_at(count_off, count);
}
void print_data_on(outputStream* st, const char* extra = NULL) const;
--- a/src/hotspot/share/utilities/globalDefinitions.hpp Tue Jun 04 17:56:16 2019 +0800
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp Thu Jun 06 13:45:59 2019 +0300
@@ -1085,6 +1085,28 @@
#undef JAVA_INTEGER_OP
+//----------------------------------------------------------------------------------------------------
+// The goal of this code is to provide saturating operations for int/uint.
+// Checks overflow conditions and saturates the result to min_jint/max_jint.
+#define SATURATED_INTEGER_OP(OP, NAME, TYPE1, TYPE2) \
+inline int NAME (TYPE1 in1, TYPE2 in2) { \
+ jlong res = static_cast<jlong>(in1); \
+ res OP ## = static_cast<jlong>(in2); \
+ if (res > max_jint) { \
+ res = max_jint; \
+ } else if (res < min_jint) { \
+ res = min_jint; \
+ } \
+ return static_cast<int>(res); \
+}
+
+SATURATED_INTEGER_OP(+, saturated_add, int, int)
+SATURATED_INTEGER_OP(+, saturated_add, int, uint)
+SATURATED_INTEGER_OP(+, saturated_add, uint, int)
+SATURATED_INTEGER_OP(+, saturated_add, uint, uint)
+
+#undef SATURATED_INTEGER_OP
+
// Dereference vptr
// All C++ compilers that we know of have the vtbl pointer in the first
// word. If there are exceptions, this function needs to be made compiler
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/profiling/TestProfileCounterOverflow.java Thu Jun 06 13:45:59 2019 +0300
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, Loongson Technology Co. Ltd. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8224162
+ * @summary Profile counter for a call site may overflow.
+ * @run main/othervm -Xbatch -XX:-UseOnStackReplacement -XX:MaxTrivialSize=0 compiler.profiling.TestProfileCounterOverflow
+ */
+
+package compiler.profiling;
+
+public class TestProfileCounterOverflow {
+ public static void test(long iterations) {
+ for (long j = 0; j < iterations; j++) {
+ call();
+ }
+ }
+
+ public static void call() {}
+
+ public static void main(String[] args) {
+ // trigger profiling on tier3
+ for (int i = 0; i < 500; i++) {
+ test(1);
+ }
+
+ test(Integer.MAX_VALUE + 10000L); // overflow call counter
+
+ // trigger c2 compilation
+ for (int i = 0; i < 10_000; i++) {
+ test(1);
+ }
+ System.out.println("TEST PASSED");
+ }
+}