Skip to content

Commit 40fef23

Browse files
committed
8275908: Record null_check traps for calls and array_check traps in the interpreter
Reviewed-by: chagedorn, mdoerr
1 parent 3d810ad commit 40fef23

File tree

9 files changed

+636
-9
lines changed

9 files changed

+636
-9
lines changed

src/hotspot/share/interpreter/interpreterRuntime.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,11 @@ JRT_ENTRY(void, InterpreterRuntime::create_klass_exception(JavaThread* current,
407407
// lookup exception klass
408408
TempNewSymbol s = SymbolTable::new_symbol(name);
409409
if (ProfileTraps) {
410-
note_trap(current, Deoptimization::Reason_class_check);
410+
if (s == vmSymbols::java_lang_ArrayStoreException()) {
411+
note_trap(current, Deoptimization::Reason_array_check);
412+
} else {
413+
note_trap(current, Deoptimization::Reason_class_check);
414+
}
411415
}
412416
// create exception, with klass name as detail message
413417
Handle exception = Exceptions::new_exception(current, s, klass_name);
@@ -825,7 +829,18 @@ void InterpreterRuntime::resolve_invoke(JavaThread* current, Bytecodes::Code byt
825829
JavaThread* THREAD = current; // For exception macros.
826830
LinkResolver::resolve_invoke(info, receiver, pool,
827831
last_frame.get_index_u2_cpcache(bytecode), bytecode,
828-
CHECK);
832+
THREAD);
833+
834+
if (HAS_PENDING_EXCEPTION) {
835+
if (ProfileTraps && PENDING_EXCEPTION->klass()->name() == vmSymbols::java_lang_NullPointerException()) {
836+
// Preserve the original exception across the call to note_trap()
837+
PreserveExceptionMark pm(current);
838+
// Recording the trap will help the compiler to potentially recognize this exception as "hot"
839+
note_trap(current, Deoptimization::Reason_null_check);
840+
}
841+
return;
842+
}
843+
829844
if (JvmtiExport::can_hotswap_or_post_breakpoint() && info.resolved_method()->is_old()) {
830845
resolved_method = methodHandle(current, info.resolved_method()->get_new_method());
831846
} else {

src/hotspot/share/opto/graphKit.cpp

+12-7
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,10 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
580580
ex_obj = env()->ArrayIndexOutOfBoundsException_instance();
581581
break;
582582
case Deoptimization::Reason_class_check:
583-
if (java_bc() == Bytecodes::_aastore) {
584-
ex_obj = env()->ArrayStoreException_instance();
585-
} else {
586-
ex_obj = env()->ClassCastException_instance();
587-
}
583+
ex_obj = env()->ClassCastException_instance();
584+
break;
585+
case Deoptimization::Reason_array_check:
586+
ex_obj = env()->ArrayStoreException_instance();
588587
break;
589588
default:
590589
break;
@@ -3340,7 +3339,10 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
33403339
// It needs a null check because a null will *pass* the cast check.
33413340
// A non-null value will always produce an exception.
33423341
if (!objtp->maybe_null()) {
3343-
builtin_throw(Deoptimization::Reason_class_check, makecon(TypeKlassPtr::make(objtp->klass())));
3342+
bool is_aastore = (java_bc() == Bytecodes::_aastore);
3343+
Deoptimization::DeoptReason reason = is_aastore ?
3344+
Deoptimization::Reason_array_check : Deoptimization::Reason_class_check;
3345+
builtin_throw(reason, makecon(TypeKlassPtr::make(objtp->klass())));
33443346
return top();
33453347
} else if (!too_many_traps_or_recompiles(Deoptimization::Reason_null_assert)) {
33463348
return null_assert(obj);
@@ -3422,7 +3424,10 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
34223424
if (not_subtype_ctrl != top()) { // If failure is possible
34233425
PreserveJVMState pjvms(this);
34243426
set_control(not_subtype_ctrl);
3425-
builtin_throw(Deoptimization::Reason_class_check, load_object_klass(not_null_obj));
3427+
bool is_aastore = (java_bc() == Bytecodes::_aastore);
3428+
Deoptimization::DeoptReason reason = is_aastore ?
3429+
Deoptimization::Reason_array_check : Deoptimization::Reason_class_check;
3430+
builtin_throw(reason, load_object_klass(not_null_obj));
34263431
}
34273432
} else {
34283433
(*failure_control) = not_subtype_ctrl;

src/hotspot/share/prims/whitebox.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,72 @@ WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method
955955
}
956956
WB_END
957957

958+
WB_ENTRY(jint, WB_GetMethodDecompileCount(JNIEnv* env, jobject o, jobject method))
959+
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
960+
CHECK_JNI_EXCEPTION_(env, 0);
961+
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
962+
uint cnt = 0;
963+
MethodData* mdo = mh->method_data();
964+
if (mdo != NULL) {
965+
cnt = mdo->decompile_count();
966+
}
967+
return cnt;
968+
WB_END
969+
970+
// Get the trap count of a method for a specific reason. If the trap count for
971+
// that reason did overflow, this includes the overflow trap count of the method.
972+
// If 'reason' is NULL, the sum of the traps for all reasons will be returned.
973+
// This number includes the overflow trap count if the trap count for any reason
974+
// did overflow.
975+
WB_ENTRY(jint, WB_GetMethodTrapCount(JNIEnv* env, jobject o, jobject method, jstring reason_obj))
976+
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
977+
CHECK_JNI_EXCEPTION_(env, 0);
978+
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
979+
uint cnt = 0;
980+
MethodData* mdo = mh->method_data();
981+
if (mdo != NULL) {
982+
ResourceMark rm(THREAD);
983+
char* reason_str = (reason_obj == NULL) ?
984+
NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reason_obj));
985+
bool overflow = false;
986+
for (uint reason = 0; reason < mdo->trap_reason_limit(); reason++) {
987+
if (reason_str != NULL && !strcmp(reason_str, Deoptimization::trap_reason_name(reason))) {
988+
cnt = mdo->trap_count(reason);
989+
// Count in the overflow trap count on overflow
990+
if (cnt == (uint)-1) {
991+
cnt = mdo->trap_count_limit() + mdo->overflow_trap_count();
992+
}
993+
break;
994+
} else if (reason_str == NULL) {
995+
uint c = mdo->trap_count(reason);
996+
if (c == (uint)-1) {
997+
c = mdo->trap_count_limit();
998+
if (!overflow) {
999+
// Count overflow trap count just once
1000+
overflow = true;
1001+
c += mdo->overflow_trap_count();
1002+
}
1003+
}
1004+
cnt += c;
1005+
}
1006+
}
1007+
}
1008+
return cnt;
1009+
WB_END
1010+
1011+
WB_ENTRY(jint, WB_GetDeoptCount(JNIEnv* env, jobject o, jstring reason_obj, jstring action_obj))
1012+
if (reason_obj == NULL && action_obj == NULL) {
1013+
return Deoptimization::total_deoptimization_count();
1014+
}
1015+
ResourceMark rm(THREAD);
1016+
const char *reason_str = (reason_obj == NULL) ?
1017+
NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(reason_obj));
1018+
const char *action_str = (action_obj == NULL) ?
1019+
NULL : java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(action_obj));
1020+
1021+
return Deoptimization::deoptimization_count(reason_str, action_str);
1022+
WB_END
1023+
9581024
WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
9591025
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
9601026
CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
@@ -2527,6 +2593,13 @@ static JNINativeMethod methods[] = {
25272593
CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
25282594
{CC"getMethodCompilationLevel0",
25292595
CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel},
2596+
{CC"getMethodDecompileCount0",
2597+
CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodDecompileCount},
2598+
{CC"getMethodTrapCount0",
2599+
CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)I",
2600+
(void*)&WB_GetMethodTrapCount},
2601+
{CC"getDeoptCount0",
2602+
CC"(Ljava/lang/String;Ljava/lang/String;)I", (void*)&WB_GetDeoptCount},
25302603
{CC"getMethodEntryBci0",
25312604
CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci},
25322605
{CC"getCompileQueueSize",

src/hotspot/share/runtime/deoptimization.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -2608,6 +2608,30 @@ jint Deoptimization::total_deoptimization_count() {
26082608
return _deoptimization_hist[Reason_none][0][0];
26092609
}
26102610

2611+
// Get the deopt count for a specific reason and a specific action. If either
2612+
// one of 'reason' or 'action' is null, the method returns the sum of all
2613+
// deoptimizations with the specific 'action' or 'reason' respectively.
2614+
// If both arguments are null, the method returns the total deopt count.
2615+
jint Deoptimization::deoptimization_count(const char *reason_str, const char *action_str) {
2616+
if (reason_str == NULL && action_str == NULL) {
2617+
return total_deoptimization_count();
2618+
}
2619+
juint counter = 0;
2620+
for (int reason = 0; reason < Reason_LIMIT; reason++) {
2621+
if (reason_str == NULL || !strcmp(reason_str, trap_reason_name(reason))) {
2622+
for (int action = 0; action < Action_LIMIT; action++) {
2623+
if (action_str == NULL || !strcmp(action_str, trap_action_name(action))) {
2624+
juint* cases = _deoptimization_hist[reason][1+action];
2625+
for (int bc_case = 0; bc_case < BC_CASE_LIMIT; bc_case++) {
2626+
counter += cases[bc_case] >> LSB_BITS;
2627+
}
2628+
}
2629+
}
2630+
}
2631+
}
2632+
return counter;
2633+
}
2634+
26112635
void Deoptimization::print_statistics() {
26122636
juint total = total_deoptimization_count();
26132637
juint account = total;
@@ -2661,6 +2685,14 @@ const char* Deoptimization::trap_reason_name(int reason) {
26612685
return "unknown";
26622686
}
26632687

2688+
jint Deoptimization::total_deoptimization_count() {
2689+
return 0;
2690+
}
2691+
2692+
jint Deoptimization::deoptimization_count(const char *reason_str, const char *action_str) {
2693+
return 0;
2694+
}
2695+
26642696
void Deoptimization::print_statistics() {
26652697
// no output
26662698
}

src/hotspot/share/runtime/deoptimization.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ class Deoptimization : AllStatic {
433433
int trap_request);
434434

435435
static jint total_deoptimization_count();
436+
static jint deoptimization_count(const char* reason_str, const char* action_str);
436437

437438
// JVMTI PopFrame support
438439

0 commit comments

Comments
 (0)