Skip to content

Commit 7d00d90

Browse files
authored
Merge branch 'eclipse-openj9:master' into Issue-21944
2 parents e585fb5 + 23a7108 commit 7d00d90

File tree

11 files changed

+87
-40
lines changed

11 files changed

+87
-40
lines changed

runtime/compiler/control/CompilationRuntime.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,9 @@ class CompilationInfo
10741074

10751075
void initCPUEntitlement();
10761076

1077+
bool isJVMStarved() const { return _jvmIsStarved; }
1078+
void setIsJVMStarved(bool val) { _jvmIsStarved = val; }
1079+
10771080
bool getLowCompDensityMode() const { return _lowCompDensityMode; }
10781081
void enterLowCompDensityMode() { _lowCompDensityMode = true; _hasEnteredLowCompDensityModeInThePast = true;}
10791082
void exitLowCompDensityMode() { _lowCompDensityMode = false; }
@@ -1367,6 +1370,7 @@ class CompilationInfo
13671370
bool _lowCompDensityMode; // set to true when compilations occur infrequently and are unlikely to contribute to JVM performance
13681371
bool _hasEnteredLowCompDensityModeInThePast; // set to true when _lowCompDensityMode is set to true at least once
13691372
bool _compileFromLPQRegardlessOfCPU;
1373+
bool _jvmIsStarved; // set to true if the JVM uses very little CPU because of external factors
13701374

13711375
#if defined(J9VM_OPT_JITSERVER)
13721376
ClientSessionHT *_clientSessionHT; // JITServer hashtable that holds session information about JITClients

runtime/compiler/control/HookedByTheJit.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6439,6 +6439,44 @@ static void suspendSamplerThreadForCheckpoint(J9VMThread *samplerThread, J9JITCo
64396439
}
64406440
#endif
64416441

6442+
static void computeJVMStarvation(int32_t jvmCPUUtil, TR::CompilationInfo *compInfo)
6443+
{
6444+
if (compInfo->isJVMStarved())
6445+
{
6446+
if (jvmCPUUtil >= TR::Options::_jvmStarvationThreshold + 10)
6447+
{
6448+
compInfo->setIsJVMStarved(false);
6449+
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
6450+
{
6451+
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Exited JVM starvation mode. jvmCPUUtil=%d%%", (int)jvmCPUUtil);
6452+
}
6453+
}
6454+
}
6455+
else
6456+
{
6457+
if (jvmCPUUtil <= TR::Options::_jvmStarvationThreshold - 10)
6458+
{
6459+
compInfo->setIsJVMStarved(true);
6460+
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
6461+
{
6462+
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Entered JVM starvation mode. jvmCPUUtil=%d%%", (int)jvmCPUUtil);
6463+
}
6464+
}
6465+
}
6466+
}
6467+
6468+
static void clearJVMStarvation(int32_t cpuIdle, int32_t vmCpuUsage, TR::CompilationInfo *compInfo)
6469+
{
6470+
if (compInfo->isJVMStarved())
6471+
{
6472+
compInfo->setIsJVMStarved(false);
6473+
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
6474+
{
6475+
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Exited JVM starvation mode. cpuIdle=%d vmCpuUsage=%d", (int)cpuIdle, (int)vmCpuUsage);
6476+
}
6477+
}
6478+
}
6479+
64426480
/* Compute a "CpuLoadFactor" for this JVM and machine. The more utilized the machine is,
64436481
* the larger the CpuLoadFactor. This CpuLoadFactor is used to multiply the sleeping time of
64446482
* the sampling thread, so that we sample less often on very busy systems were the JVM
@@ -6477,16 +6515,22 @@ static uint32_t computeCpuLoadFactor(uint32_t numActiveThreads, TR::CompilationI
64776515
{
64786516
// Use the entitlement to adjust the loadFactor.
64796517
loadFactor = loadFactor * 100 / compInfo->getJvmCpuEntitlement();
6518+
6519+
clearJVMStarvation(cpuIdle, vmCpuUsage, compInfo);
64806520
}
64816521
else // Machine has very little idle CPU if any. It's likely this JVM cannot use its entitlement because of starvation.
64826522
{
64836523
// Use the effective CPU utilization of this JVM to compute the load factor.
64846524
loadFactor = loadFactor * 100 / (vmCpuUsage == 0 ? 1 : vmCpuUsage);
6525+
// Set the starvation flag if needed
6526+
computeJVMStarvation(vmCpuUsage, compInfo);
64856527
}
64866528
}
64876529
else // The JVM uses its entire entitlement.
64886530
{
64896531
loadFactor = loadFactor * 100 / compInfo->getJvmCpuEntitlement();
6532+
// Set the starvation flag if needed
6533+
computeJVMStarvation(vmCpuUsage, compInfo);
64906534
}
64916535
}
64926536
else

runtime/compiler/control/J9Options.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ bool J9::Options::_aggressiveLockReservation = false;
316316

317317
bool J9::Options::_xrsSync = false;
318318

319+
int32_t J9::Options::_jvmStarvationThreshold = 40; // 40% CPU utilization. Use 10 (or lower) to disable the feature
320+
319321
void
320322
J9::Options::findExternalOptions(J9JavaVM *vm, bool consume)
321323
{
@@ -1117,6 +1119,8 @@ TR::OptionTable OMR::Options::_feOptions[] = {
11171119
#endif /* defined(J9VM_OPT_JITSERVER) */
11181120
{"jProfilingEnablementSampleThreshold=", "M<nnn>\tNumber of global samples to allow generation of JProfiling bodies",
11191121
TR::Options::setStaticNumeric, (intptr_t)&TR::Options::_jProfilingEnablementSampleThreshold, 0, "F%d", NOT_IN_SUBSET },
1122+
{"jvmStarvationThreshold=", "M<nnn>\tCPU utilization of the JVM that determines whether the JVM is starved",
1123+
TR::Options::setStaticNumeric, (intptr_t)&TR::Options::_jvmStarvationThreshold , 0, "F%d", NOT_IN_SUBSET},
11201124
{"kcaoffsets", "I\tGenerate a header file with offset data for use with KCA", TR::Options::kcaOffsets, 0, 0, "F" },
11211125
{"largeTranslationTime=", "D<nnn>\tprint IL trees for methods that take more than this value (usec)"
11221126
"to compile. Need to have a log file defined on command line",

runtime/compiler/control/J9Options.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,8 @@ class OMR_EXTENSIBLE Options : public OMR::OptionsConnector
495495

496496
static bool _xrsSync;
497497

498+
static int32_t _jvmStarvationThreshold;
499+
498500
static ExternalOptionsMetadata _externalOptionsMetadata[ExternalOptions::TR_NumExternalOptions];
499501

500502
/**

runtime/compiler/env/J9KnownObjectTable.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,10 +534,8 @@ J9::KnownObjectTable::addStableArray(Index index, int32_t stableArrayRank)
534534
TR_OpaqueClassBlock *clazz =
535535
fej9->getObjectClassFromKnownObjectIndex(comp(), index);
536536

537-
// Null is only possible on failure to get VM access. Most of the time we
538-
// should find the class successfully anyway, so check only in that case.
539537
TR_ASSERT_FATAL(
540-
clazz == NULL || fej9->isClassArray(clazz),
538+
fej9->isClassArray(clazz),
541539
"addStableArray can only be called for arrays");
542540

543541
if (_stableArrayRanks[index] < stableArrayRank)

runtime/compiler/env/VMJ9.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,10 +1208,10 @@ TR_J9VMBase::getObjectClassAt(uintptr_t objectAddress)
12081208
TR_OpaqueClassBlock *
12091209
TR_J9VMBase::getObjectClassFromKnownObjectIndex(TR::Compilation *comp, TR::KnownObjectTable::Index idx)
12101210
{
1211-
TR::VMAccessCriticalSection getObjectClassFromKnownObjectIndex(comp, TR::VMAccessCriticalSection::tryToAcquireVMAccess);
1212-
TR_OpaqueClassBlock *clazz = NULL;
1213-
if (getObjectClassFromKnownObjectIndex.hasVMAccess())
1214-
clazz = getObjectClass(comp->getKnownObjectTable()->getPointer(idx));
1211+
TR::VMAccessCriticalSection getObjectClassFromKnownObjectIndex(comp);
1212+
TR_OpaqueClassBlock *clazz =
1213+
getObjectClass(comp->getKnownObjectTable()->getPointer(idx));
1214+
12151215
return clazz;
12161216
}
12171217

@@ -5157,14 +5157,7 @@ TR_J9VMBase::delegatingMethodHandleTarget(
51575157
TR_OpaqueClassBlock *dmhType =
51585158
getObjectClassFromKnownObjectIndex(comp, dmhIndex);
51595159

5160-
if (dmhType == NULL)
5161-
{
5162-
if (trace)
5163-
traceMsg(comp, "failed to determine concrete DelegatingMethodHandle type\n");
5164-
5165-
return TR::KnownObjectTable::UNKNOWN;
5166-
}
5167-
else if (isInstanceOf(dmhType, cwClass, true) != TR_yes)
5160+
if (isInstanceOf(dmhType, cwClass, true) != TR_yes)
51685161
{
51695162
if (trace)
51705163
traceMsg(comp, "object is not a CountingWrapper\n");
@@ -5238,7 +5231,6 @@ TR_J9VMBase::getLayoutVarHandle(TR::Compilation *comp, TR::KnownObjectTable::Ind
52385231
getObjectClassFromKnownObjectIndex(comp, layoutIndex);
52395232

52405233
if (layoutClass == NULL ||
5241-
layoutObjClass == NULL ||
52425234
isInstanceOf(layoutObjClass, layoutClass, true, true) != TR_yes)
52435235
{
52445236
if (comp->getOption(TR_TraceOptDetails))
@@ -5271,7 +5263,6 @@ TR_J9VMBase::getVarHandleAccessDescriptorMode(TR::Compilation *comp, TR::KnownOb
52715263
getObjectClassFromKnownObjectIndex(comp, adIndex);
52725264

52735265
if (adClass == NULL ||
5274-
adObjClass == NULL ||
52755266
isInstanceOf(adObjClass, adClass, true, true) != TR_yes)
52765267
{
52775268
if (comp->getOption(TR_TraceOptDetails))

runtime/compiler/optimizer/InterpreterEmulator.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,12 +1026,8 @@ InterpreterEmulator::getReturnValue(TR_ResolvedMethod *callee)
10261026
{
10271027
TR_OpaqueClassBlock *callSiteType =
10281028
fe()->getObjectClassFromKnownObjectIndex(comp(), callSiteIndex);
1029-
if (callSiteType == NULL)
1030-
{
1031-
debugTrace(tracer(), "failed to determine concrete CallSite type");
1032-
return NULL;
1033-
}
1034-
else if (fe()->isInstanceOf(callSiteType, mutableCallsiteClass, true) != TR_yes)
1029+
1030+
if (fe()->isInstanceOf(callSiteType, mutableCallsiteClass, true) != TR_yes)
10351031
{
10361032
debugTrace(tracer(), "not a MutableCallSite");
10371033
return NULL;

runtime/jvmti/jvmtiStackFrame.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,24 @@ jvmtiInternalGetStackTrace(
868868
}
869869
walkState.skipCount = framesWalked + start_depth;
870870
}
871+
871872
walkState.maxFrames = max_frame_count;
873+
874+
#if JAVA_SPEC_VERSION >= 20
875+
/* Adjusts the second‑pass stack walk limit (maxFrames) to include the
876+
* number of frames skipped in the first pass (userData1).
877+
*
878+
* When the first pass walks more frames than the original max_frame_count,
879+
* the skipped frame count is added to the limit so that, after skipping,
880+
* up to max_frame_count frames can still be returned to the caller.
881+
*/
882+
if (walkState.framesWalked > max_frame_count) {
883+
UDATA skippedFrames = (UDATA)walkState.userData1;
884+
Assert_JVMTI_true(skippedFrames <= (UDATA_MAX - max_frame_count));
885+
walkState.maxFrames += skippedFrames;
886+
}
887+
#endif /* JAVA_SPEC_VERSION >= 20 */
888+
872889
walkState.flags = J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_VISIBLE_ONLY
873890
| J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET | J9_STACKWALK_COUNT_SPECIFIED
874891
| J9_STACKWALK_ITERATE_FRAMES;

runtime/vm/BytecodeInterpreter.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3452,6 +3452,7 @@ class INTERPRETER_CLASS
34523452
UDATA continuationWalkRC = J9_STACKWALK_RC_NONE;
34533453
J9StackWalkState continuationWalkState= {0};
34543454
if (J9_ARE_ALL_BITS_SET(_vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_SHOW_CARRIER_FRAMES)
3455+
&& (NULL != _currentThread->threadObject)
34553456
&& IS_JAVA_LANG_VIRTUALTHREAD(_currentThread, _currentThread->threadObject)
34563457
) {
34573458
continuationWalkState.flags = walkFlags;

test/functional/DDR_Test/src/j9vm/test/ddrext/Constants.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,9 @@ public class Constants {
303303
public static final String J9STATICS_SUCCESS_KEY = "j9romstaticfieldshape," + J9CLASS_TEST_SUCCESS_KEY;
304304

305305
public static final String CL_FOR_NAME_CMD = "classforname";
306-
public static final String CL_FOR_NAME_CLASS = "java/lang/Object";
307-
public static final String CL_FOR_NAME_SUCCESS_KEY = "!j9class,Found 1 class\\(es\\) named java/lang/Object";
308-
public static final String CL_FOR_NAME_FAILURE_KEY = "Found 0 class(es) named java/lang/Object";
306+
public static final String CL_FOR_NAME_CLASS = "j9vm/test/corehelper/CoreGen";
307+
public static final String CL_FOR_NAME_SUCCESS_KEY = "!j9class,Found 1 class\\(es\\) named " + CL_FOR_NAME_CLASS;
308+
public static final String CL_FOR_NAME_FAILURE_KEY = "Found 0 class(es) named " + CL_FOR_NAME_CLASS;
309309
public static final String CL_FOR_NAME_CLASS_WC = "\\*Object\\*";
310310
public static final String CL_FOR_NAME_SUCCESS_KEY_WC = "!j9class,java/lang/reflect/AccessibleObject";
311311
public static final String CL_FOR_NAME_FAILURE_KEY_WC = "Found 0 class\\(es\\) named \\*Object\\*";
@@ -334,7 +334,7 @@ public class Constants {
334334
public static final String DUMP_ROM_CLASS_LINEAR_FAILURE_KEY = "";
335335

336336
public static final String DUMP_ROM_CLASS_CMD = "dumpromclass";
337-
public static final String DUMP_ROM_CLASS_SUCCESS_KEY = "ROM Size,Class Name: java/lang/Object,Superclass Name,Source File Name,Methods,Interfaces \\(0\\),Fields \\(0\\),CP Shape Description,Methods \\(14\\)";
337+
public static final String DUMP_ROM_CLASS_SUCCESS_KEY = "ROM Size,Class Name: " + CL_FOR_NAME_CLASS + ",Superclass Name,Source File Name,Methods,Interfaces \\(0\\),Fields \\(0\\),CP Shape Description,Methods \\(2\\)";
338338
public static final String DUMP_ROM_CLASS_FAILURE_KEY = "";
339339

340340
public static final String DUMP_ROM_CLASS_NAME_CMD = "name:";
@@ -347,7 +347,7 @@ public class Constants {
347347
public static final String DUMP_ROM_CLASS_NAME_WC_FAILURE_KEY = "Found 0 class\\(es\\) with name \\*Object\\*";
348348

349349
public static final String DUMP_ROM_CLASS_MAPS_CMD = "maps";
350-
public static final String DUMP_ROM_CLASS_MAPS_SUCCESS_KEY = "ROM Size,Class Name: java/lang/Object,Superclass Name,Source File Name: Object.java,Interfaces \\(0\\),Fields \\(0\\),CP Shape Description,Methods \\(14\\),lmap,dmap,smap";
350+
public static final String DUMP_ROM_CLASS_MAPS_SUCCESS_KEY = "ROM Size,Class Name: " + CL_FOR_NAME_CLASS + ",Superclass Name,Source File Name: CoreGen.java,Interfaces \\(0\\),Fields \\(0\\),CP Shape Description,Methods \\(2\\),lmap,dmap,smap";
351351
public static final String DUMP_ROM_CLASS_MAPS_FAILURE_KEY = "";
352352

353353
public static final String DUMP_ROM_CLASS_NAME_MAPS_SUCCESS_KEY = "ROM Size,Class Name: java/lang/Object,Superclass Name,Source File Name: Object.java,Interfaces \\(0\\),Fields \\(0\\),CP Shape Description,Methods \\(14\\),lmap,dmap,smap,Found 1 class\\(es\\) with name java/lang/Object";

0 commit comments

Comments
 (0)