8286580: serviceability/jvmti/vthread/GetSetLocalTest failed with assert: Not supported for heap frames

Reviewed-by: lmesnik, rpressler, cjplummer
This commit is contained in:
Serguei Spitsyn 2022-06-23 16:21:32 +00:00
parent 3f5e48a44e
commit 4c9ea7e66a
4 changed files with 39 additions and 21 deletions

View File

@ -611,7 +611,7 @@ void VM_BaseGetOrSetLocal::doit() {
frame fr = _jvf->fr();
if (_set && _depth != 0 && Continuation::is_frame_in_continuation(_jvf->thread(), fr)) {
_result = JVMTI_ERROR_OPAQUE_FRAME; // deferred locals currently unsupported in continuations
_result = JVMTI_ERROR_OPAQUE_FRAME; // deferred locals are not fully supported in continuations
return;
}
@ -644,6 +644,17 @@ void VM_BaseGetOrSetLocal::doit() {
return;
}
if (_set) {
if (fr.is_heap_frame()) { // we want this check after the check for JVMTI_ERROR_INVALID_SLOT
assert(Continuation::is_frame_in_continuation(_jvf->thread(), fr), "sanity check");
// If the topmost frame is a heap frame, then it hasn't been thawed. This can happen
// if we are executing at a return barrier safepoint. The callee frame has been popped,
// but the caller frame has not been thawed. We can't support a JVMTI SetLocal in the callee
// frame at this point, because we aren't truly in the callee yet.
// fr.is_heap_frame() is impossible if a continuation is at a single step or breakpoint.
_result = JVMTI_ERROR_OPAQUE_FRAME; // deferred locals are not fully supported in continuations
return;
}
// Force deoptimization of frame if compiled because it's
// possible the compiler emitted some locals as constant values,
// meaning they are not mutable.

View File

@ -111,6 +111,7 @@ serviceability/sa/sadebugd/DebugdConnectTest.java 8239062,8270326 macosx-x64,mac
serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all
serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all
serviceability/jvmti/vthread/GetSetLocalTest/GetSetLocalTest.java 8286836 generic-all
serviceability/dcmd/gc/RunFinalizationTest.java 8227120 linux-all,windows-x64
serviceability/sa/ClhsdbCDSCore.java 8269982,8267433 macosx-aarch64,macosx-x64

View File

@ -35,8 +35,7 @@ import java.util.concurrent.*;
public class GetSetLocalTest {
private static final String agentLib = "GetSetLocalTest";
static final int MSG_COUNT = 600*1000;
static final SynchronousQueue<String> QUEUE = new SynchronousQueue<>();
static SynchronousQueue<String> QUEUE;
static native boolean completed();
static native void enableEvents(Thread thread);
static native void testSuspendedVirtualThreads(Thread thread);
@ -56,19 +55,17 @@ public class GetSetLocalTest {
static final Runnable PRODUCER = () -> {
try {
for (int i = 0; i < MSG_COUNT; i++) {
if (completed()) {
consumer.interrupt();
break;
}
while (!completed()) {
producer("msg: ");
}
} catch (InterruptedException e) { }
consumer.interrupt();
} catch (InterruptedException e) {
}
};
static final Runnable CONSUMER = () -> {
try {
for (int i = 0; i < MSG_COUNT; i++) {
while(true) {
String s = QUEUE.take();
}
} catch (InterruptedException e) {
@ -77,6 +74,7 @@ public class GetSetLocalTest {
};
public static void test1() throws Exception {
QUEUE = new SynchronousQueue<>();
producer = Thread.ofVirtual().name("VThread-Producer").start(PRODUCER);
consumer = Thread.ofVirtual().name("VThread-Consumer").start(CONSUMER);
@ -101,6 +99,10 @@ public class GetSetLocalTest {
}
GetSetLocalTest obj = new GetSetLocalTest();
obj.runTest();
for (int i = 0; i < 200; i++) {
obj.runTest();
}
}
}

View File

@ -232,7 +232,7 @@ test_GetLocal(jvmtiEnv *jvmti, JNIEnv *jni, jthread cthread, jthread vthread,
static bool
test_SetLocal(jvmtiEnv *jvmti, JNIEnv *jni, jthread cthread, jthread vthread,
int depth, int frame_count, Values *values) {
int depth, int frame_count, Values *values, bool at_event) {
jvmtiError err;
LOG("test_SetLocal: mounted: %d depth: %d fcount: %d\n", cthread != NULL, depth, frame_count);
@ -288,7 +288,7 @@ test_SetLocal(jvmtiEnv *jvmti, JNIEnv *jni, jthread cthread, jthread vthread,
fatal(jni, "JVMTI SetLocalObject for unmounted vthread pr depth > 0failed to return JVMTI_ERROR_OPAQUE_FRAME");
}
return false; // skip testing other types for unmounted vthread
} else if (err == JVMTI_ERROR_OPAQUE_FRAME) {
} else if (!at_event && err == JVMTI_ERROR_OPAQUE_FRAME) {
LOG("JVMTI SetLocalObject for mounted vthread at depth=0 returned JVMTI_ERROR_OPAQUE_FRAME: %d\n", err);
return false; // skip testing other types for compiled frame that can't be deoptimized
}
@ -309,7 +309,7 @@ test_SetLocal(jvmtiEnv *jvmti, JNIEnv *jni, jthread cthread, jthread vthread,
}
static void
test_GetSetLocal(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread, int depth, int frame_count) {
test_GetSetLocal(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread, int depth, int frame_count, bool at_event) {
Values values0 = { NULL, NULL, 1, 2L, (jfloat)3.2F, (jdouble)4.500000047683716 };
Values values1 = { NULL, NULL, 2, 3L, (jfloat)4.2F, (jdouble)5.500000047683716 };
jthread cthread = get_carrier_thread(jvmti, jni, vthread);
@ -319,8 +319,8 @@ test_GetSetLocal(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread, int depth, int f
LOG("test_GetSetLocal: test_GetLocal with values0\n");
test_GetLocal(jvmti, jni, cthread, vthread, depth, frame_count, &values0);
LOG("test_GetSetLocal: test_SetLocal with values1\n");
bool success = test_SetLocal(jvmti, jni, cthread, vthread, depth, frame_count, &values1);
LOG("test_GetSetLocal: test_SetLocal at_event: %d with values1\n", at_event);
bool success = test_SetLocal(jvmti, jni, cthread, vthread, depth, frame_count, &values1, at_event);
if (!success) {
goto End; // skip testing for compiled frame that can't be deoptimized
@ -334,8 +334,8 @@ test_GetSetLocal(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread, int depth, int f
} else {
LOG("test_GetSetLocal: test_GetLocal with values1\n");
test_GetLocal(jvmti, jni, cthread, vthread, depth, frame_count, &values1);
LOG("test_GetSetLocal: test_SetLocal with values0 to restore original local values\n");
test_SetLocal(jvmti, jni, cthread, vthread, depth, frame_count, &values0);
LOG("test_GetSetLocal: test_SetLocal at_event: %d with values0 to restore original local values\n", at_event);
test_SetLocal(jvmti, jni, cthread, vthread, depth, frame_count, &values0, at_event);
}
End:
LOG("test_GetSetLocal: finished\n\n");
@ -360,7 +360,7 @@ Breakpoint(jvmtiEnv *jvmti, JNIEnv* jni, jthread vthread,
{
int frame_count = get_frame_count(jvmti, jni, vthread);
test_GetSetLocal(jvmti, jni, vthread, depth, frame_count);
test_GetSetLocal(jvmti, jni, vthread, depth, frame_count, true /* at_event */);
}
deallocate(jvmti, jni, (void*)mname);
deallocate(jvmti, jni, (void*)tname);
@ -470,7 +470,7 @@ Java_GetSetLocalTest_testSuspendedVirtualThreads(JNIEnv *jni, jclass klass, jthr
#if 0
print_stack_trace(jvmti, jni, vthread);
#endif
test_GetSetLocal(jvmti, jni, vthread, depth, frame_count);
test_GetSetLocal(jvmti, jni, vthread, depth, frame_count, false /* !at_event */);
}
err = jvmti->ResumeThread(vthread);
@ -487,7 +487,11 @@ Java_GetSetLocalTest_testSuspendedVirtualThreads(JNIEnv *jni, jclass klass, jthr
JNIEXPORT jboolean JNICALL
Java_GetSetLocalTest_completed(JNIEnv *jni, jclass klass) {
return completed;
if (completed) {
completed = JNI_FALSE;
return JNI_TRUE;
}
return JNI_FALSE;
}
} // extern "C"