Skip to content

Commit f21e296

Browse files
authored
Merge pull request #16288 from gacholio/loop
Stack walk loop breaker for ASGCT
2 parents dc27a6c + c4b3775 commit f21e296

File tree

3 files changed

+64
-34
lines changed

3 files changed

+64
-34
lines changed

runtime/oti/j9consts.h

+6-8
Original file line numberDiff line numberDiff line change
@@ -375,16 +375,14 @@ extern "C" {
375375
#define J9_STARTPC_DLT_READY 0x8
376376
#define J9_STARTPC_STATUS 0xF
377377

378-
/* Frame iterator return values */
379-
#define J9_STACKWALK_STOP_ITERATING 0x0
380-
#define J9_STACKWALK_KEEP_ITERATING 0x1
381-
382378
/* Stackwalk return values */
383379
#define J9_STACKWALK_RC_NONE 0x0
384-
#define J9_STACKWALK_RC_NO_MEMORY 0x1
385-
#define J9_STACKWALK_RC_FRAME_NOT_FOUND 0x2
386-
#define J9_STACKWALK_RC_BAD_STATE_BUFFER 0x3
387-
#define J9_STACKWALK_RC_STACK_CORRUPT 0x4
380+
#define J9_STACKWALK_STOP_ITERATING 0x0 /* Must be the same as no error */
381+
#define J9_STACKWALK_KEEP_ITERATING 0x1
382+
#define J9_STACKWALK_RC_NO_MEMORY 0x2
383+
#define J9_STACKWALK_RC_FRAME_NOT_FOUND 0x3
384+
#define J9_STACKWALK_RC_BAD_STATE_BUFFER 0x4
385+
#define J9_STACKWALK_RC_STACK_CORRUPT 0x5
388386

389387
/* Tag for JIT artifact search cache */
390388
#define J9_STACKWALK_NO_JIT_CACHE 0x1

runtime/oti/j9nonbuilder.h

+1
Original file line numberDiff line numberDiff line change
@@ -2537,6 +2537,7 @@ typedef struct J9StackWalkState {
25372537
void* inlinedCallSite;
25382538
void* stackMap;
25392539
void* inlineMap;
2540+
UDATA loopBreaker;
25402541
/* The size of J9StackWalkState must be a multiple of 8 because it is inlined into
25412542
* J9VMThread where alignment assumotions are being made.
25422543
*/

runtime/vm/swalk.c

+57-26
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,40 @@ static void dropToCurrentFrame (J9StackWalkState * walkState);
9191
/* The minimum number of stack slots that a stack frame can occupy */
9292
#define J9_STACKWALK_MIN_FRAME_SLOTS (OMR_MIN(sizeof(J9JITFrame), sizeof(J9SFStackFrame)) / sizeof(UDATA))
9393

94+
static VMINLINE UDATA
95+
maxFramesOnStack(J9StackWalkState *walkState)
96+
{
97+
J9VMThread *walkThread = walkState->walkThread;
98+
J9JITConfig *jitConfig = walkThread->javaVM->jitConfig;
99+
UDATA * endOfStack = walkThread->stackObject->end;
100+
UDATA * sp = walkState->walkThread->sp;
101+
UDATA maxFrames = (endOfStack - sp) / J9_STACKWALK_MIN_FRAME_SLOTS;
102+
103+
if (NULL != jitConfig) {
104+
if (J9_ARE_NO_BITS_SET(walkState->flags, J9_STACKWALK_SKIP_INLINES)) {
105+
/* It's possible every frame on the stack is a fully inlined JIT frame */
106+
maxFrames *= (jitConfig->maxInlineDepth + 1);
107+
}
108+
}
109+
110+
if (J9_ARE_NO_BITS_SET(walkState->flags, J9_STACKWALK_NO_ERROR_REPORT)) {
111+
UDATA * stackStart = J9_LOWEST_STACK_SLOT(walkState->walkThread);
112+
#if defined(J9VM_INTERP_STACKWALK_TRACING)
113+
Assert_VRB_true(sp >= stackStart);
114+
Assert_VRB_true(sp <= endOfStack);
115+
#else /* J9VM_INTERP_STACKWALK_TRACING */
116+
Assert_VM_true(sp >= stackStart);
117+
Assert_VM_true(sp <= endOfStack);
118+
#endif /* J9VM_INTERP_STACKWALK_TRACING */
119+
}
120+
121+
return maxFrames;
122+
}
123+
94124
UDATA walkStackFrames(J9VMThread *currentThread, J9StackWalkState *walkState)
95125
{
96-
UDATA rc = (walkState->walkThread->privateFlags & J9_PRIVATE_FLAGS_STACK_CORRUPT) ? J9_STACKWALK_RC_STACK_CORRUPT : J9_STACKWALK_RC_NONE;
126+
UDATA rc = J9_STACKWALK_RC_NONE;
127+
UDATA walkRC = 0;
97128
J9Method * nextLiterals;
98129
UDATA * nextA0;
99130
UDATA savedFlags = walkState->flags;
@@ -120,9 +151,15 @@ UDATA walkStackFrames(J9VMThread *currentThread, J9StackWalkState *walkState)
120151
walkState->flags &= ~J9_STACKWALK_RESUME;
121152
goto resumeInterpreterWalk;
122153
}
123-
if (currentThread != NULL) {
154+
155+
walkState->loopBreaker = 0;
156+
if (NULL != currentThread) {
124157
oldState = currentThread->activeWalkState;
125158
currentThread->activeWalkState = walkState;
159+
if (J9_ARE_ANY_BITS_SET(currentThread->privateFlags2, J9_PRIVATE_FLAGS2_ASYNC_GET_CALL_TRACE)) {
160+
/* Add one because walkFrames decrements loopBreaker and bails when it reaches 0 */
161+
walkState->loopBreaker = maxFramesOnStack(walkState) + 1;
162+
}
126163
}
127164

128165
walkState->javaVM = walkState->walkThread->javaVM;
@@ -330,7 +367,9 @@ UDATA walkStackFrames(J9VMThread *currentThread, J9StackWalkState *walkState)
330367

331368
/* Walk the frame */
332369

333-
if (walkFrame(walkState) != J9_STACKWALK_KEEP_ITERATING) {
370+
walkRC = walkFrame(walkState);
371+
if (J9_STACKWALK_KEEP_ITERATING != walkRC) {
372+
rc = walkRC;
334373
goto terminationPoint;
335374
}
336375
resumeInterpreterWalk:
@@ -342,7 +381,9 @@ UDATA walkStackFrames(J9VMThread *currentThread, J9StackWalkState *walkState)
342381
#ifdef J9VM_INTERP_NATIVE_SUPPORT
343382
if (walkState->frameFlags & J9_STACK_FLAGS_JIT_TRANSITION_TO_INTERPRETER_MASK) {
344383
resumeJitWalk:
345-
if (jitWalkStackFrames(walkState) != J9_STACKWALK_KEEP_ITERATING) {
384+
walkRC = jitWalkStackFrames(walkState);
385+
if (J9_STACKWALK_KEEP_ITERATING != walkRC) {
386+
rc = walkRC;
346387
goto terminationPoint;
347388
}
348389
walkState->decompilationRecord = NULL;
@@ -400,12 +441,23 @@ UDATA walkStackFrames(J9VMThread *currentThread, J9StackWalkState *walkState)
400441
currentThread->activeWalkState = oldState;
401442
}
402443

444+
if (J9_ARE_ANY_BITS_SET(walkState->walkThread->privateFlags, J9_PRIVATE_FLAGS_STACK_CORRUPT)) {
445+
rc = J9_STACKWALK_RC_STACK_CORRUPT;
446+
}
447+
403448
return rc;
404449
}
405450

406451

407452
UDATA walkFrame(J9StackWalkState * walkState)
408453
{
454+
if (0 != walkState->loopBreaker) {
455+
walkState->loopBreaker -= 1;
456+
if (0 == walkState->loopBreaker) {
457+
return J9_STACKWALK_RC_STACK_CORRUPT;
458+
}
459+
}
460+
409461
if (walkState->flags & J9_STACKWALK_VISIBLE_ONLY) {
410462

411463
if ((((UDATA) walkState->pc == J9SF_FRAME_TYPE_NATIVE_METHOD) || ((UDATA) walkState->pc == J9SF_FRAME_TYPE_JNI_NATIVE_METHOD)) && !(walkState->flags & J9_STACKWALK_INCLUDE_NATIVES)) {
@@ -519,38 +571,17 @@ UDATA walkFrame(J9StackWalkState * walkState)
519571
static UDATA allocateCache(J9StackWalkState * walkState)
520572
{
521573
PORT_ACCESS_FROM_WALKSTATE(walkState);
522-
UDATA * endOfStack = walkState->walkThread->stackObject->end;
523-
UDATA framesPresent = 0;
574+
UDATA framesPresent = maxFramesOnStack(walkState);
524575
UDATA cacheElementSize = 0;
525576
UDATA cacheSize = 0;
526577
UDATA * stackStart = J9_LOWEST_STACK_SLOT(walkState->walkThread);
527578
UDATA * sp = walkState->walkThread->sp;
528579

529-
if (J9_ARE_NO_BITS_SET(walkState->flags, J9_STACKWALK_NO_ERROR_REPORT)) {
530-
#if defined(J9VM_INTERP_STACKWALK_TRACING)
531-
Assert_VRB_true(sp >= stackStart);
532-
Assert_VRB_true(sp <= endOfStack);
533-
#else /* J9VM_INTERP_STACKWALK_TRACING */
534-
Assert_VM_true(sp >= stackStart);
535-
Assert_VM_true(sp <= endOfStack);
536-
#endif /* J9VM_INTERP_STACKWALK_TRACING */
537-
}
538-
539-
framesPresent = (endOfStack - sp) / J9_STACKWALK_MIN_FRAME_SLOTS;
540-
541580
if (walkState->flags & J9_STACKWALK_CACHE_PCS) ++cacheElementSize;
542581
if (walkState->flags & J9_STACKWALK_CACHE_CPS) ++cacheElementSize;
543582
if (walkState->flags & J9_STACKWALK_CACHE_METHODS) ++cacheElementSize;
544583

545584
cacheSize = framesPresent * cacheElementSize;
546-
#ifdef J9VM_INTERP_NATIVE_SUPPORT
547-
if (walkState->walkThread->javaVM->jitConfig) {
548-
if (!(walkState->flags & J9_STACKWALK_SKIP_INLINES)) {
549-
/* computations above assume 1 cacheElement per frame, in reality there may be (maxInlinedMethods + 1) elements per frame */
550-
cacheSize *= (walkState->walkThread->javaVM->jitConfig->maxInlineDepth + 1);
551-
}
552-
}
553-
#endif
554585

555586
if ((walkState != walkState->walkThread->stackWalkState) || ((UDATA) (sp - stackStart) < cacheSize)
556587
#if defined (J9VM_INTERP_VERBOSE) || defined (J9VM_PROF_EVENT_REPORTING)

0 commit comments

Comments
 (0)