diff --git a/runtime/codert_vm/jswalk.c b/runtime/codert_vm/jswalk.c index 18d59ff3610..d8c8a4f2d8a 100644 --- a/runtime/codert_vm/jswalk.c +++ b/runtime/codert_vm/jswalk.c @@ -1769,6 +1769,9 @@ walkLiveMonitorSlots(J9StackWalkState *walkState, J9JITStackAtlas *gcStackAtlas, j9object_t *objAddress; U_16 i; U_8 bit; + J9VMThread *currentThread = walkState->currentThread; + J9VMThread *targetThread = walkState->walkThread; + J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions; for (i = 0; i < numberOfMapBits; ++i) { bit = liveMonitorMap[i >> 3] & monitorMask[i >> 3] & (1 << (i & 7)); @@ -1786,7 +1789,7 @@ walkLiveMonitorSlots(J9StackWalkState *walkState, J9JITStackAtlas *gcStackAtlas, if (NULL != objAddress) { j9object_t obj = *objAddress; - if (NULL != obj) { + if ((NULL != obj) && !vmFuncs->objectIsBeingWaitedOn(currentThread, targetThread, obj)) { info->object = obj; info->count = 1; info->depth = (UDATA)walkState->userData4; @@ -1806,6 +1809,9 @@ countLiveMonitorSlots(J9StackWalkState *walkState, J9JITStackAtlas *gcStackAtlas IDATA monitorCount = (IDATA)walkState->userData2; U_16 i; U_8 bit; + J9VMThread *currentThread = walkState->currentThread; + J9VMThread *targetThread = walkState->walkThread; + J9InternalVMFunctions const * const vmFuncs = currentThread->javaVM->internalVMFunctions; for (i = 0; i < numberOfMapBits; ++i) { bit = liveMonitorMap[i >> 3] & monitorMask[i >> 3]; @@ -1816,8 +1822,12 @@ countLiveMonitorSlots(J9StackWalkState *walkState, J9JITStackAtlas *gcStackAtlas /* CMVC 188386 : if the object is stack allocates and the object is discontiguous on stack, * the jit stores a null in the slot. Skip this slot. */ - if ((NULL != objAddress) && (NULL != *objAddress)) { - monitorCount += 1; + if (NULL != objAddress) { + j9object_t obj = *objAddress; + + if ((NULL != obj) && !vmFuncs->objectIsBeingWaitedOn(currentThread, targetThread, obj)) { + monitorCount += 1; + } } } } diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 7f1c6a63208..b826493446a 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -4654,6 +4654,7 @@ typedef struct J9InternalVMFunctions { void ( *storeFlattenableArrayElement)(struct J9VMThread *currentThread, j9object_t receiverObject, U_32 index, j9object_t paramObject); j9object_t ( *loadFlattenableArrayElement)(struct J9VMThread *currentThread, j9object_t receiverObject, U_32 index, BOOLEAN fast); UDATA ( *jniIsInternalClassRef)(struct J9JavaVM *vm, jobject ref); + BOOLEAN (*objectIsBeingWaitedOn)(struct J9VMThread *currentThread, struct J9VMThread *targetThread, j9object_t obj); } J9InternalVMFunctions; /* Jazz 99339: define a new structure to replace JavaVM so as to pass J9NativeLibrary to JVMTIEnv */ diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index ff913ff2873..7a8df799f9b 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -4243,6 +4243,16 @@ typedef struct J9ObjectMonitorInfo { UDATA count; } J9ObjectMonitorInfo; +/** + * @brief See if an object is being waited on by targetThread + * @param currentThread + * @param targetThread + * @param obj + * @return BOOLEAN + */ +BOOLEAN +objectIsBeingWaitedOn(J9VMThread *currentThread, J9VMThread *targetThread, j9object_t obj); + /** * @brief Get the object monitors locked by a thread * @param currentThread diff --git a/runtime/vm/intfunc.c b/runtime/vm/intfunc.c index 39a643f112b..121fb90df34 100644 --- a/runtime/vm/intfunc.c +++ b/runtime/vm/intfunc.c @@ -392,5 +392,6 @@ J9InternalVMFunctions J9InternalFunctions = { #endif /* JAVA_SPEC_VERSION >= 15 */ storeFlattenableArrayElement, loadFlattenableArrayElement, - jniIsInternalClassRef + jniIsInternalClassRef, + objectIsBeingWaitedOn, }; diff --git a/runtime/vm/ownedmonitors.c b/runtime/vm/ownedmonitors.c index 13a7f233e45..25efdba1b75 100644 --- a/runtime/vm/ownedmonitors.c +++ b/runtime/vm/ownedmonitors.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2017 IBM Corp. and others + * Copyright (c) 2001, 2020 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -29,9 +29,19 @@ static UDATA getOwnedObjectMonitorsIterator(J9VMThread *currentThread, J9StackWalkState *walkState); static UDATA walkFrameMonitorEnterRecords(J9VMThread *currentThread, J9StackWalkState *walkState); static IDATA getJNIMonitors(J9VMThread *currentThread, J9VMThread *targetThread, J9ObjectMonitorInfo *minfoStart, J9ObjectMonitorInfo *minfoEnd); -static IDATA countMonitorEnterRecords(J9VMThread *targetThread); +static IDATA countMonitorEnterRecords(J9VMThread *currentThread, J9VMThread *targetThread); +BOOLEAN +objectIsBeingWaitedOn(J9VMThread *currentThread, J9VMThread *targetThread, j9object_t obj) +{ + BOOLEAN rc = FALSE; + if (J9_ARE_ANY_BITS_SET(targetThread->publicFlags, J9_PUBLIC_FLAGS_THREAD_WAITING)) { + rc = (obj == J9VMTHREAD_BLOCKINGENTEROBJECT(currentThread, targetThread)); + } + return rc; +} + /** * Get the object monitors owned by a thread * @param[in] currentThread @@ -89,7 +99,7 @@ getOwnedObjectMonitors(J9VMThread *currentThread, J9VMThread *targetThread, if (rc < 0) { return J9_GETOWNEDMONITORS_ERROR; } - rc += countMonitorEnterRecords(targetThread); + rc += countMonitorEnterRecords(currentThread, targetThread); } else { getJNIMonitors(currentThread, targetThread, walkState.userData1, walkState.userData2); rc = infoLen; @@ -136,8 +146,8 @@ walkFrameMonitorEnterRecords(J9VMThread *currentThread, J9StackWalkState *walkSt J9ObjectMonitorInfo *lastInfo = walkState->userData2; U_32 modifiers; UDATA *frameID; - IDATA monitorCount = (IDATA)walkState->userData2; + J9VMThread *targetThread = walkState->walkThread; /* * Walk the monitor enter records from this frame and @@ -154,8 +164,9 @@ walkFrameMonitorEnterRecords(J9VMThread *currentThread, J9StackWalkState *walkSt while (monitorEnterRecords && (frameID == CONVERT_FROM_RELATIVE_STACK_OFFSET(walkState->walkThread, monitorEnterRecords->arg0EA)) ) { + j9object_t obj = monitorEnterRecords->object; /* Do not report monitors for stack allocated objects */ - if (!isObjectStackAllocated(walkState->walkThread, monitorEnterRecords->object)) { + if (!(isObjectStackAllocated(targetThread, obj) || objectIsBeingWaitedOn(currentThread, targetThread, obj))) { if (NULL == info) { ++monitorCount; } else { @@ -163,7 +174,7 @@ walkFrameMonitorEnterRecords(J9VMThread *currentThread, J9StackWalkState *walkSt /* Don't overflow the MonitorInfo array */ return J9_STACKWALK_STOP_ITERATING; } - info->object = monitorEnterRecords->object; + info->object = obj; info->count = monitorEnterRecords->dropEnterCount; info->depth = (IDATA) walkState->userData4; info++; @@ -192,7 +203,7 @@ walkFrameMonitorEnterRecords(J9VMThread *currentThread, J9StackWalkState *walkSt } /* Do not report monitors for stack allocated objects */ - if ((!isObjectStackAllocated(walkState->walkThread, syncObject))) { + if (!(isObjectStackAllocated(targetThread, syncObject) || objectIsBeingWaitedOn(currentThread, targetThread, syncObject))) { if (NULL == info) { ++monitorCount; } else { @@ -227,12 +238,14 @@ getJNIMonitors(J9VMThread *currentThread, J9VMThread *targetThread, J9ObjectMoni enterRecord = targetThread->jniMonitorEnterRecords; while (enterRecord != NULL) { + j9object_t obj = enterRecord->object; + if (minfo > lastInfo) { /* Don't overflow the MonitorInfo array */ return count; } /* Do not report monitors for stack allocated objects */ - if (!isObjectStackAllocated(targetThread, enterRecord->object)) { + if (!(isObjectStackAllocated(targetThread, obj) || objectIsBeingWaitedOn(currentThread, targetThread, obj))) { minfo->object = enterRecord->object; minfo->count = enterRecord->dropEnterCount; minfo->depth = 0; @@ -250,13 +263,15 @@ getJNIMonitors(J9VMThread *currentThread, J9VMThread *targetThread, J9ObjectMoni * >=0 - number of records in list */ static IDATA -countMonitorEnterRecords(J9VMThread *targetThread) +countMonitorEnterRecords(J9VMThread *currentThread, J9VMThread *targetThread) { IDATA count = 0; J9MonitorEnterRecord *rec = targetThread->jniMonitorEnterRecords; while (rec != NULL) { - if (!isObjectStackAllocated(targetThread, rec->object)) { + j9object_t obj = rec->object; + + if (!(isObjectStackAllocated(targetThread, obj) || objectIsBeingWaitedOn(currentThread, targetThread, obj))) { ++count; } rec = rec->next;