8214572: [Graal] nsk/jvmti/unit/ForceEarlyReturn/earlyretbase should not suspend the thread when the top frame executes JVMCI code

Reviewed-by: sspitsyn, dholmes, jcbeyler
This commit is contained in:
Daniil Titov 2018-12-04 21:13:45 -08:00
parent b93b62c2c9
commit cbaebf738e
4 changed files with 89 additions and 23 deletions
test/hotspot/jtreg/vmTestbase/nsk
jvmti/unit/ForceEarlyReturn
share/jvmti

@ -54,8 +54,7 @@ public class earlyretbase {
}
}
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 @@ public class earlyretbase {
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) {

@ -78,22 +78,29 @@ FramePop(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread,
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;
}
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;
}
printf("<<<<<<<< SuspendThread() is successfully done\n");
fflush(0);
return PASSED;
}
JNIEXPORT jint JNICALL
@ -119,7 +126,7 @@ Java_nsk_jvmti_unit_ForceEarlyReturn_earlyretbase_resThread(JNIEnv *env,
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 @@ Java_nsk_jvmti_unit_ForceEarlyReturn_earlyretbase_doForceEarlyReturn(JNIEnv *env
}
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()"

@ -633,6 +633,69 @@ int isThreadExpected(jvmtiEnv *jvmti, jthread thread) {
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)) {

@ -371,6 +371,12 @@ void nsk_jvmti_agentFailed();
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);