< prev index next >
src/hotspot/share/ci/ciMethod.cpp
Print this page
*** 460,469 ****
--- 460,515 ----
}
#endif // COMPILER1
// ------------------------------------------------------------------
+ // ciMethod::saturated_add
+ //
+ // Update profile counters with saturating addition
+ // Wil check and handle the overflow condition
+ template <typename L, typename R>
+ int ciMethod::saturated_add(L a, R b) {
+ jlong src1 = a;
+ jlong src2 = b;
+ jlong sum = src1 + src2;
+ if (sum > max_jint) {
+ sum = max_jint;
+ } else if (sum < min_jint) {
+ sum = min_jint;
+ }
+
+ return (int)sum;
+ }
+
+
+ // ------------------------------------------------------------------
+ // ciMethod::check_overflow
+ //
+ // Check whether the profile counter is overflow and update it 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, int bci) {
+ check_is_loaded();
+ VM_ENTRY_MARK;
+
+ BytecodeStream bcs(methodHandle(THREAD, get_Method()), bci);
+ Bytecodes::Code code = bcs.next();
+
+ if (Bytecodes::is_invoke(code)) {
+ return c < 0 ? max_jint : c;
+ } else {
+ switch (code) {
+ case Bytecodes::_aastore: // fall-through
+ case Bytecodes::_checkcast: // fall-through
+ case Bytecodes::_instanceof: return c > 0 ? min_jint : c;
+ default: return c;
+ }
+ }
+ }
+
+
+ // ------------------------------------------------------------------
// ciMethod::call_profile_at_bci
//
// Get the ciCallProfile for the invocation of this method.
// Also reports receiver types for non-call type checks (if TypeProfileCasts).
ciCallProfile ciMethod::call_profile_at_bci(int bci) {
*** 471,481 ****
ciCallProfile result;
if (method_data() != NULL && method_data()->is_mature()) {
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();
if (!data->is_ReceiverTypeData()) {
result._receiver_count[0] = 0; // that's a definite zero
} else { // ReceiverTypeData is a subclass of CounterData
ciReceiverTypeData* call = (ciReceiverTypeData*)data->as_ReceiverTypeData();
--- 517,527 ----
ciCallProfile result;
if (method_data() != NULL && method_data()->is_mature()) {
ciProfileData* data = method_data()->bci_to_data(bci);
if (data != NULL && data->is_CounterData()) {
// Every profiled call site has a counter.
! int count = check_overflow(data->as_CounterData()->count(), bci);
if (!data->is_ReceiverTypeData()) {
result._receiver_count[0] = 0; // that's a definite zero
} else { // ReceiverTypeData is a subclass of CounterData
ciReceiverTypeData* call = (ciReceiverTypeData*)data->as_ReceiverTypeData();
*** 500,512 ****
}
}
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;
if (rcount == 0) rcount = 1; // Should be valid value
! receivers_count_total += rcount;
// Add the receiver to result data.
result.add_receiver(receiver, rcount);
// If we extend profiling to record methods,
// we will set result._method also.
}
--- 546,558 ----
}
}
for (uint i = 0; i < call->row_limit(); i++) {
ciKlass* receiver = call->receiver(i);
if (receiver == NULL) continue;
! int rcount = saturated_add(call->receiver_count(i), epsilon);
if (rcount == 0) rcount = 1; // Should be valid value
! 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,
// we will set result._method also.
}
*** 532,542 ****
// Make the count consistent if this is a call profile. If count is
// zero or less, presume that this is a typecheck profile and
// do nothing. Otherwise, increase count to be the sum of all
// receiver's counts.
if (count >= 0) {
! count += receivers_count_total;
}
}
result._count = count;
}
}
--- 578,588 ----
// Make the count consistent if this is a call profile. If count is
// zero or less, presume that this is a typecheck profile and
// do nothing. Otherwise, increase count to be the sum of all
// receiver's counts.
if (count >= 0) {
! count = saturated_add(count, receivers_count_total);
}
}
result._count = count;
}
}
< prev index next >