8214572: [Graal] nsk/jvmti/unit/ForceEarlyReturn/earlyretbase should not suspend the thread when the top frame executes JVMCI code
Reviewed-by: sspitsyn, dholmes, jcbeyler
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretbase.java Tue Dec 04 17:18:11 2018 -0800
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretbase.java Tue Dec 04 21:13:45 2018 -0800
@@ -54,8 +54,7 @@
}
}
- native static int doForceEarlyReturn(Class targCls,
- Thread earlyretThr, long valToRet);
+ native static int doForceEarlyReturn(Thread earlyretThr, long valToRet);
native static int suspThread(earlyretThread earlyretThr);
native static int resThread(earlyretThread earlyretThr);
native static int check();
@@ -96,8 +95,7 @@
out.println("Forcing early return...");
// force return from a top frame of the child thread
- retCode = doForceEarlyReturn(earlyretThread.class,
- earlyretThr, JAVA_BIRTH_YEAR);
+ retCode = doForceEarlyReturn(earlyretThr, JAVA_BIRTH_YEAR);
earlyretDone = true;
earlyretThr.letItGo();
if (retCode != Consts.TEST_PASSED) {
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretbase/earlyretbase.cpp Tue Dec 04 17:18:11 2018 -0800
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/ForceEarlyReturn/earlyretbase/earlyretbase.cpp Tue Dec 04 21:13:45 2018 -0800
@@ -78,22 +78,29 @@
JNIEXPORT jint JNICALL
Java_nsk_jvmti_unit_ForceEarlyReturn_earlyretbase_suspThread(JNIEnv *env,
jclass cls, jobject earlyretThr) {
- jvmtiError err;
if (!caps.can_force_early_return || !caps.can_suspend) {
return PASSED;
}
- printf(">>>>>>>> Invoke SuspendThread()\n");
- err = jvmti->SuspendThread(earlyretThr);
- if (err != JVMTI_ERROR_NONE) {
- printf("%s: Failed to call SuspendThread(): error=%d: %s\n",
- __FILE__, err, TranslateError(err));
- return JNI_ERR;
+ jclass clazz = env->GetObjectClass(earlyretThr);
+ if (clazz == NULL) {
+ printf("Cannot get class of thread object\n");
+ RETURN_FAILED;
}
- printf("<<<<<<<< SuspendThread() is successfully done\n");
- fflush(0);
- return PASSED;
+
+ midActiveMethod = env->GetMethodID(clazz, name_exp, sig_exp);
+ if (midActiveMethod == NULL) {
+ printf("Cannot find Method ID for method %s\n", name_exp);
+ RETURN_FAILED;
+ }
+
+ int result = suspendThreadAtMethod(jvmti, cls, earlyretThr, midActiveMethod);
+ if( result == NSK_TRUE) {
+ return PASSED;
+ } else {
+ RETURN_FAILED;
+ }
}
JNIEXPORT jint JNICALL
@@ -119,7 +126,7 @@
JNIEXPORT jint JNICALL
Java_nsk_jvmti_unit_ForceEarlyReturn_earlyretbase_doForceEarlyReturn(JNIEnv *env,
- jclass cls, jclass targCls, jthread earlyretThr, jlong valToRet) {
+ jclass cls, jthread earlyretThr, jlong valToRet) {
jvmtiError err;
if (!caps.can_force_early_return || !caps.can_suspend) {
@@ -160,14 +167,6 @@
}
printf(">>>>>>>> Invoke ForceEarlyReturn()\n");
- printf("Before call to GetMethodID(%s, %s)\n", name_exp, sig_exp);
- midActiveMethod = env->GetMethodID(targCls, name_exp, sig_exp);
- if (midActiveMethod == NULL) {
- printf("Cannot find Method ID for method %s\n", name_exp);
- RETURN_FAILED;
- }
- printf("After call to GetMethodID(%s, %s)\n", name_exp, sig_exp);
-
err = jvmti->ForceEarlyReturnLong(earlyretThr, valToRet);
if (err != JVMTI_ERROR_NONE) {
printf("TEST FAILED: the function ForceEarlyReturn()"
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp Tue Dec 04 17:18:11 2018 -0800
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp Tue Dec 04 21:13:45 2018 -0800
@@ -633,6 +633,69 @@
return 1;
}
+#define SLEEP_DELAY 10L
+
+int suspendThreadAtMethod(jvmtiEnv *jvmti, jclass cls, jobject thread, jmethodID testMethod) {
+ printf(">>>>>>>> Invoke SuspendThread()\n");
+
+ jvmtiError err = jvmti->SuspendThread(thread);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("%s: Failed to call SuspendThread(): error=%d: %s\n",
+ __FILE__, err, TranslateError(err));
+ return NSK_FALSE;
+ }
+
+ int result = NSK_TRUE;
+ jmethodID method = NULL;
+ jlocation loc;
+
+ // We need to ensure that the thread is suspended at the right place when the top
+ // frame belongs to the test rather than to incidental Java code (classloading,
+ // JVMCI, etc). Below we do resume/suspend in the loop until the target method
+ // is executed in the top frame or the loop counter exceeds the limit.
+ for (int i = 0; i < 10; i++) {
+ err = jvmti->GetFrameLocation(thread, 0, &method, &loc);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("(GetFrameLocation) unexpected error: %s (%d)\n",
+ TranslateError(err), err);
+ result = NSK_FALSE;
+ break;
+ }
+
+ char *name, *sig, *generic;
+ jvmti->GetMethodName(method, &name, &sig, &generic);
+ printf(">>> Attempt %d to suspend the thread. Top frame: \"%s%s\"\n",
+ i, name, sig);
+ if (method == testMethod) break;
+
+ err = jvmti->ResumeThread(thread);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("(ResumeThread) unexpected error: %s (%d)\n",
+ TranslateError(err), err);
+ result = NSK_FALSE;
+ }
+
+ mssleep(SLEEP_DELAY);
+
+ err = jvmti->SuspendThread(thread);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("(SuspendThread) unexpected error: %s (%d)\n",
+ TranslateError(err), err);
+ result = NSK_FALSE;
+ }
+ }
+ if(method == testMethod) {
+ printf("<<<<<<<< SuspendThread() is successfully done\n");
+ } else {
+ char *name, *sig, *generic;
+ jvmti->GetMethodName(testMethod, &name, &sig, &generic);
+ printf("Failed in the suspendThread: was not able to suspend thread "
+ "with required method \"%s%s\" on the top\n", name, sig);
+ result = NSK_FALSE;
+ }
+ return result;
+}
+
jint createRawMonitor(jvmtiEnv *env, const char *name, jrawMonitorID *monitor) {
jvmtiError error = env->CreateRawMonitor(name, monitor);
if (!NSK_JVMTI_VERIFY(error)) {
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.h Tue Dec 04 17:18:11 2018 -0800
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.h Tue Dec 04 21:13:45 2018 -0800
@@ -371,6 +371,12 @@
int isThreadExpected(jvmtiEnv *jvmti, jthread thread);
+/**
+* This method makes the thread to be suspended at the right place when the top frame
+* belongs to the test rather than to incidental Java code (classloading, JVMCI, etc).
+*/
+int suspendThreadAtMethod(jvmtiEnv *jvmti, jclass cls, jobject thread, jmethodID method);
+
jint createRawMonitor(jvmtiEnv *env, const char *name, jrawMonitorID *monitor);
void exitOnError(jvmtiError error);