8224162: assert(profile.count() == 0) failed: sanity in InlineTree::is_not_reached

Reviewed-by: vlivanov, kvn
This commit is contained in:
Jie Fu 2019-06-06 13:45:59 +03:00
parent 72daa46d46
commit d738e209f3
5 changed files with 116 additions and 8 deletions

View File

@ -461,6 +461,27 @@ const BitMap& ciMethod::bci_block_start() {
#endif // COMPILER1
// ------------------------------------------------------------------
// 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
//
@ -473,7 +494,7 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) {
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 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) {
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 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) {
// 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;

View File

@ -126,6 +126,9 @@ class ciMethod : public ciMetadata {
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"); }

View File

@ -558,8 +558,14 @@ public:
}
// 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 @@ public:
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;

View File

@ -1085,6 +1085,28 @@ JAVA_INTEGER_OP(*, java_multiply, jlong, julong)
#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

View File

@ -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");
}
}