diff --git a/vm/include/open/thread_helpers.h b/vm/include/open/thread_helpers.h index 5dfb134..3a9a169 100644 --- a/vm/include/open/thread_helpers.h +++ b/vm/include/open/thread_helpers.h @@ -44,6 +44,7 @@ char* gen_hythread_self_helper(char *ss) char* gen_monitorenter_fast_path_helper(char *ss, const R_Opnd & input_param1); char* gen_monitorenter_slow_path_helper(char *ss, const R_Opnd & input_param1); char* gen_monitor_exit_helper(char *ss, const R_Opnd & input_param1); +char* gen_monitorexit_slow_path_helper(char *ss, const R_Opnd & input_param1); #ifdef __cplusplus } diff --git a/vm/thread/src/thread_helpers.cpp b/vm/thread/src/thread_helpers.cpp index dcbe8dc..66f6154 100644 --- a/vm/thread/src/thread_helpers.cpp +++ b/vm/thread/src/thread_helpers.cpp @@ -225,6 +225,27 @@ #endif return ss; } +/** + * Generates slow path of monitor exit. + * This code could block on monitor and contains safepoint. + * The appropriate m2n frame should be generated and + * + * @param[in] ss buffer to put the assembly code to + * @param[in] input_param1 register should point to the jobject(handle) + * If input_param1 == eax it reduces one register mov. + * the code use and do not restore ecx, edx, eax registers + * @return 0 if success in eax register + */ +char* gen_monitorexit_slow_path_helper(char *ss, const R_Opnd & input_param1) { + if (&input_param1 != &eax_opnd) { + ss = mov(ss, eax_opnd, input_param1); + } + + ss = push(ss, eax_opnd); // push the address of the handle + ss = call(ss, (char *)jthread_monitor_exit); + ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(4)); // pop parameters + return ss; +} /** * Generates fast accessor to the TLS for the given key.
diff --git a/vm/thread/src/thread_java_monitors.c b/vm/thread/src/thread_java_monitors.c index 0433c04..9ad12cc 100644 --- a/vm/thread/src/thread_java_monitors.c +++ b/vm/thread/src/thread_java_monitors.c @@ -139,6 +139,7 @@ #endif //LOCK_RESERVATION contended_entered: if (ti_is_enabled()){ disable_count = reset_suspend_disable(); + set_contended_monitor(NULL); jvmti_send_contended_enter_or_entered_monitor_event(monitor, 0); set_suspend_disable(disable_count); // should be moved to event handler @@ -312,6 +313,7 @@ IDATA VMCALL jthread_monitor_timed_wait( if (ti_is_enabled()) { disable_count = reset_suspend_disable(); set_wait_monitor(monitor); + set_contended_monitor(monitor); jvmti_send_wait_monitor_event(monitor, (jlong)millis); set_suspend_disable(disable_count); @@ -346,6 +348,7 @@ IDATA VMCALL jthread_monitor_timed_wait( if (ti_is_enabled()){ add_owned_monitor(monitor); disable_count = reset_suspend_disable(); + set_contended_monitor(NULL); jvmti_send_waited_monitor_event(monitor, (status == APR_TIMEUP)?(jboolean)1:(jboolean)0); // should be moved to event handler set_suspend_disable(disable_count); @@ -422,6 +425,7 @@ void set_contended_monitor(jobject monit suspend_status = reset_suspend_disable(); tm_java_thread->contended_monitor = (*(tm_java_thread->jenv))->NewGlobalRef(tm_java_thread->jenv, monitor); + set_suspend_disable(suspend_status); } diff --git a/vm/thread/src/thread_native_thin_monitor.c b/vm/thread/src/thread_native_thin_monitor.c index 35ed1b3..45a6f44 100644 --- a/vm/thread/src/thread_native_thin_monitor.c +++ b/vm/thread/src/thread_native_thin_monitor.c @@ -723,9 +723,17 @@ IDATA VMCALL hythread_thin_monitor_get_r lockword = *lockword_ptr; if(IS_FAT_LOCK(lockword)) { fat_monitor = locktable_get_fat_monitor(FAT_LOCK_ID(lockword)); // find fat_monitor in lock table - return fat_monitor->recursion_count; + return fat_monitor->recursion_count+1; } - return RECURSION(lockword); + if(THREAD_ID(lockword) == 0) { + return 0; + } +#ifdef LOCK_RESERVATION + if (IS_RESERVED(lockword)) { + return RECURSION(lockword); + } +#endif + return RECURSION(lockword)+1; } //@} diff --git a/vm/thread/src/thread_ti_monitors.c b/vm/thread/src/thread_ti_monitors.c index ac3452f..4fb2fdb 100644 --- a/vm/thread/src/thread_ti_monitors.c +++ b/vm/thread/src/thread_ti_monitors.c @@ -114,11 +114,14 @@ IDATA VMCALL jthread_raw_monitor_destroy * @param[in] mon_ptr monitor */ IDATA VMCALL jthread_raw_monitor_enter(jrawMonitorID mon_ptr) { - hythread_monitor_t monitor; + hythread_monitor_t monitor; + IDATA stat; if (!(monitor = (hythread_monitor_t)array_get(jvmti_monitor_table, (UDATA)mon_ptr))) { return TM_ERROR_INVALID_MONITOR; } - return hythread_monitor_enter(monitor); + stat = hythread_monitor_enter(monitor); + hythread_safe_point(); + return stat; } /** @@ -142,10 +145,13 @@ IDATA VMCALL jthread_raw_monitor_try_ent */ IDATA VMCALL jthread_raw_monitor_exit(jrawMonitorID mon_ptr) { hythread_monitor_t monitor; + IDATA stat; if (!(monitor = (hythread_monitor_t)array_get(jvmti_monitor_table, (UDATA)mon_ptr))) { return TM_ERROR_INVALID_MONITOR; } - return hythread_monitor_exit(monitor); + stat = hythread_monitor_exit(monitor); + hythread_safe_point(); + return stat; } /** @@ -171,10 +177,13 @@ IDATA VMCALL jthread_raw_monitor_exit(jr */ IDATA VMCALL jthread_raw_monitor_wait(jrawMonitorID mon_ptr, I_64 millis) { hythread_monitor_t monitor; + IDATA stat; if (!(monitor = (hythread_monitor_t)array_get(jvmti_monitor_table, (UDATA)mon_ptr))) { return TM_ERROR_INVALID_MONITOR; } - return hythread_monitor_wait_interruptable(monitor, millis, 0); + stat = hythread_monitor_wait_interruptable(monitor, millis, 0); + hythread_safe_point(); + return stat; } /** diff --git a/vm/vmcore/src/jvmti/jvmti_object.cpp b/vm/vmcore/src/jvmti/jvmti_object.cpp index 74f50ba..2283e56 100644 --- a/vm/vmcore/src/jvmti/jvmti_object.cpp +++ b/vm/vmcore/src/jvmti/jvmti_object.cpp @@ -214,7 +214,7 @@ jvmtiGetObjectMonitorUsage(jvmtiEnv* env jthread_iterator_release(&iterator); jthread_get_lock_owner(object, &info_ptr->owner); - info_ptr->entry_count = jthread_get_lock_recursion(object, info_ptr->owner) + 1; + info_ptr->entry_count = jthread_get_lock_recursion(object, info_ptr->owner); info_ptr->waiter_count = enter_wait_count; info_ptr->waiters = enter_wait_array; info_ptr->notify_waiter_count = notify_wait_count; diff --git a/vm/vmcore/src/util/em64t/base/jit_lock_rt_support_em64t.cpp b/vm/vmcore/src/util/em64t/base/jit_lock_rt_support_em64t.cpp index 5050945..74ff48c 100644 --- a/vm/vmcore/src/util/em64t/base/jit_lock_rt_support_em64t.cpp +++ b/vm/vmcore/src/util/em64t/base/jit_lock_rt_support_em64t.cpp @@ -38,7 +38,7 @@ #include "vm_stats.h" #include "dump.h" static LilCodeStub * rth_get_lil_monitor_enter_generic(LilCodeStub * cs) { - +if(!VM_Global_State::loader_env->TI->isEnabled()) { return lil_parse_onto_end(cs, "out platform:ref:g4;" "o0 = l0;" @@ -55,6 +55,16 @@ static LilCodeStub * rth_get_lil_monitor vm_monitor_try_enter, TM_ERROR_NONE, vm_monitor_enter); +} else { + return lil_parse_onto_end(cs, + "push_m2n 0, 0;" + "out platform:ref:void;" + "o0 = l0;" + "call %0i;" + "pop_m2n;" + "ret;", + vm_monitor_enter); +} } NativeCodePtr rth_get_lil_monitor_enter_static() { @@ -172,6 +182,7 @@ #endif /* MONITOR EXIT RUNTIME SUPPORT */ static LilCodeStub * rth_get_lil_monitor_exit_generic(LilCodeStub * cs) { +if(!VM_Global_State::loader_env->TI->isEnabled()) { return lil_parse_onto_end(cs, "call %0i;" "jc r!=%1i, illegal_monitor;" @@ -182,6 +193,16 @@ static LilCodeStub * rth_get_lil_monitor vm_monitor_try_exit, TM_ERROR_NONE, lil_npc_to_fp(exn_get_rth_throw_illegal_monitor_state())); +}else{ + return lil_parse_onto_end(cs, + "push_m2n 0, 0;" + "out platform:ref:void;" + "o0 = l0;" + "call %0i;" + "pop_m2n;" + "ret;", + vm_monitor_exit); +} } NativeCodePtr rth_get_lil_monitor_exit_static() { diff --git a/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp b/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp index f146440..932f464 100644 --- a/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp +++ b/vm/vmcore/src/util/ia32/base/jit_lock_rt_support_ia32.cpp @@ -96,6 +96,9 @@ #endif ss = branch8(ss, Condition_Z, Imm_Opnd(size_8, 0)); char *backpatch_address__null_pointer = ((char *)ss) - 1; +// skip fast path if ti is enabled +// so all TI events will be generated +if(!VM_Global_State::loader_env->TI->isEnabled()) { ss = alu(ss, add_opc, ecx_opnd, Imm_Opnd(header_offset)); // pop parameters ss = gen_monitorenter_fast_path_helper(ss, ecx_opnd); ss = test(ss, eax_opnd, eax_opnd); @@ -106,7 +109,7 @@ #endif // Slow path: happens when the monitor is busy (contention case) offset = (signed)ss - (signed)backpatch_address__fast_monitor_failed - 1; *backpatch_address__fast_monitor_failed = (char)offset; - +} ss = gen_setup_j2n_frame(ss); ss = push(ss, M_Base_Opnd(esp_reg, m2n_sizeof_m2n_frame)); @@ -186,9 +189,20 @@ #endif ss = test(ss, ecx_opnd, ecx_opnd); ss = branch8(ss, Condition_Z, Imm_Opnd(size_8, 0)); char *backpatch_address__null_pointer = ((char *)ss) - 1; - +// skip fast path if ti is enabled +// so all TI events will be generated +if(!VM_Global_State::loader_env->TI->isEnabled()) { ss = alu(ss, add_opc, ecx_opnd, Imm_Opnd(header_offset)); ss = gen_monitor_exit_helper(ss, ecx_opnd); +} else { + ss = gen_setup_j2n_frame(ss); + ss = push(ss, M_Base_Opnd(esp_reg, m2n_sizeof_m2n_frame)); + + ss = call(ss, (char *)oh_convert_to_local_handle); + ss = alu(ss, add_opc, esp_opnd, Imm_Opnd(4)); // pop parameters + ss = gen_monitorexit_slow_path_helper(ss, eax_opnd); + ss = gen_pop_j2n_frame(ss); +} ss = test(ss, eax_opnd, eax_opnd); ss = branch8(ss, Condition_NZ, Imm_Opnd(size_8, 0)); char *backpatch_address__fast_monitor_failed = ((char *)ss) - 1;