8262011: [JVMCI] allow printing to tty from unattached libgraal thread

Reviewed-by: kvn, never
This commit is contained in:
Doug Simon 2021-02-23 17:01:11 +00:00
parent 0257caad38
commit d2b9c227e5
8 changed files with 75 additions and 272 deletions

View file

@ -1575,91 +1575,22 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_
HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE);
C2V_END
// Creates a scope where the current thread is attached and detached
// from HotSpot if it wasn't already attached when entering the scope.
extern "C" int jio_printf(const char *fmt, ...);
class AttachDetach : public StackObj {
public:
bool _attached;
AttachDetach(JNIEnv* env, JavaThread* current_thread) {
if (current_thread == NULL) {
extern struct JavaVM_ main_vm;
JNIEnv* hotspotEnv;
jint res = main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL);
_attached = res == JNI_OK;
static volatile int report_attach_error = 0;
if (res != JNI_OK && report_attach_error == 0 && Atomic::cmpxchg(&report_attach_error, 0, 1) == 0) {
// Only report an attach error once
jio_printf("Warning: attaching current thread to VM failed with %d (future attach errors are suppressed)\n", res);
}
} else {
_attached = false;
}
}
~AttachDetach() {
if (_attached && get_current_thread() != NULL) {
extern struct JavaVM_ main_vm;
jint res = main_vm.DetachCurrentThread();
static volatile int report_detach_error = 0;
if (res != JNI_OK && report_detach_error == 0 && Atomic::cmpxchg(&report_detach_error, 0, 1) == 0) {
// Only report an attach error once
jio_printf("Warning: detaching current thread from VM failed with %d (future attach errors are suppressed)\n", res);
}
}
}
};
C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw))
AttachDetach ad(env, thread);
bool use_tty = true;
if (thread == NULL) {
if (!ad._attached) {
// Can only use tty if the current thread is attached
JVMCI_event_1("Cannot write to tty on unattached thread");
return 0;
}
thread = get_current_thread();
}
JVMCITraceMark jtm("writeDebugOutput");
C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length))
if (bytes == NULL) {
if (can_throw) {
JVMCI_THROW_0(NullPointerException);
}
return -1;
}
JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes);
// Check if offset and length are non negative.
if (offset < 0 || length < 0) {
if (can_throw) {
JVMCI_THROW_0(ArrayIndexOutOfBoundsException);
}
return -2;
}
// Check if the range is valid.
int array_length = JVMCIENV->get_length(array);
if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) {
if (can_throw) {
JVMCI_THROW_0(ArrayIndexOutOfBoundsException);
}
return -2;
}
jbyte buffer[O_BUFLEN];
while (length > 0) {
int copy_len = MIN2(length, (jint)O_BUFLEN);
JVMCIENV->copy_bytes_to(array, buffer, offset, copy_len);
tty->write((char*) buffer, copy_len);
length -= O_BUFLEN;
offset += O_BUFLEN;
// Use of tty does not require the current thread to be attached to the VM
// so no need for a full C2V_VMENTRY transition.
C2V_VMENTRY_PREFIX(void, writeDebugOutput, (JNIEnv* env, jobject, jlong buffer, jint length, bool flush))
if (length <= 8) {
tty->write((char*) &buffer, length);
} else {
tty->write((char*) buffer, length);
}
if (flush) {
tty->flush();
}
return 0;
C2V_END
C2V_VMENTRY(void, flushDebugOutput, (JNIEnv* env, jobject))
// Use of tty does not require the current thread to be attached to the VM
// so no need for a full C2V_VMENTRY transition.
C2V_VMENTRY_PREFIX(void, flushDebugOutput, (JNIEnv* env, jobject))
tty->flush();
C2V_END
@ -2793,7 +2724,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "iterateFrames", CC "([" RESOLVED_METHOD "[" RESOLVED_METHOD "I" INSPECTED_FRAME_VISITOR ")" OBJECT, FN_PTR(iterateFrames)},
{CC "materializeVirtualObjects", CC "(" HS_STACK_FRAME_REF "Z)V", FN_PTR(materializeVirtualObjects)},
{CC "shouldDebugNonSafepoints", CC "()Z", FN_PTR(shouldDebugNonSafepoints)},
{CC "writeDebugOutput", CC "([BIIZZ)I", FN_PTR(writeDebugOutput)},
{CC "writeDebugOutput", CC "(JIZ)V", FN_PTR(writeDebugOutput)},
{CC "flushDebugOutput", CC "()V", FN_PTR(flushDebugOutput)},
{CC "methodDataProfileDataSize", CC "(JI)I", FN_PTR(methodDataProfileDataSize)},
{CC "getFingerprint", CC "(J)J", FN_PTR(getFingerprint)},