From 8d00f6171a0825329c7a69f53ad744388ccb9022 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 7 Mar 2000 00:10:52 +0000 Subject: [PATCH] jni.cc (MARK_NONE): New define. * jni.cc (MARK_NONE): New define. (MARK_USER): Likewise. (MARK_SYSTEM): Likewise. (struct _Jv_JNI_LocalFrame): Made `marker' bigger and `size' smaller. (_Jv_JNI_DeleteLocalRef): Use MARK_NONE in assert. (_Jv_JNI_EnsureLocalCapacity): Use MARK_NONE. (_Jv_JNI_PushLocalFrame): Use MARK_USER. (_Jv_JNI_PopLocalFrame): New version with additional `stop' argument. (call): Use MARK_SYSTEM. (_Jv_GetJNIEnvNewFrame): New function. (_Jv_LookupJNIMethod): New function. (_Jv_JNI_PopSystemFrame): New function. (call): Use _Jv_JNI_PopSystemFrame and _Jv_LookupJNIMethod. From-SVN: r32373 --- libjava/ChangeLog | 18 ++++++ libjava/jni.cc | 149 ++++++++++++++++++++++++++++++---------------- 2 files changed, 117 insertions(+), 50 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 5dc588ce43dd..c33749c7a5a1 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,21 @@ +2000-03-06 Tom Tromey + + * jni.cc (MARK_NONE): New define. + (MARK_USER): Likewise. + (MARK_SYSTEM): Likewise. + (struct _Jv_JNI_LocalFrame): Made `marker' bigger and `size' + smaller. + (_Jv_JNI_DeleteLocalRef): Use MARK_NONE in assert. + (_Jv_JNI_EnsureLocalCapacity): Use MARK_NONE. + (_Jv_JNI_PushLocalFrame): Use MARK_USER. + (_Jv_JNI_PopLocalFrame): New version with additional `stop' + argument. + (call): Use MARK_SYSTEM. + (_Jv_GetJNIEnvNewFrame): New function. + (_Jv_LookupJNIMethod): New function. + (_Jv_JNI_PopSystemFrame): New function. + (call): Use _Jv_JNI_PopSystemFrame and _Jv_LookupJNIMethod. + 2000-03-05 Tom Tromey Fix for PR libgcj/43: diff --git a/libjava/jni.cc b/libjava/jni.cc index f06e5802026b..d25b03cc55e3 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -75,15 +75,22 @@ extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions; // 16. #define FRAME_SIZE 32 +// Mark value indicating this is an overflow frame. +#define MARK_NONE 0 +// Mark value indicating this is a user frame. +#define MARK_USER 1 +// Mark value indicating this is a system frame. +#define MARK_SYSTEM 2 + // This structure is used to keep track of local references. struct _Jv_JNI_LocalFrame { // This is true if this frame object represents a pushed frame (eg // from PushLocalFrame). - int marker : 1; + int marker : 2; // Number of elements in frame. - int size : 31; + int size : 30; // Next frame in chain. _Jv_JNI_LocalFrame *next; @@ -169,7 +176,7 @@ _Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj) } // Don't go past a marked frame. - JvAssert (! frame->marker); + JvAssert (frame->marker == MARK_NONE); } JvAssert (0); @@ -194,7 +201,7 @@ _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size) return JNI_ERR; } - frame->marker = true; + frame->marker = MARK_NONE; frame->size = size; memset (&frame->vec[0], 0, size * sizeof (jobject)); frame->next = env->locals; @@ -211,7 +218,7 @@ _Jv_JNI_PushLocalFrame (JNIEnv *env, jint size) return r; // The new frame is on top. - env->locals->marker = true; + env->locals->marker = MARK_USER; return 0; } @@ -248,7 +255,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj) } static jobject -_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) +_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop) { _Jv_JNI_LocalFrame *rf = env->locals; @@ -260,7 +267,7 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) unmark_for_gc (rf->vec[i]); // If the frame we just freed is the marker frame, we are done. - done = rf->marker; + done = (rf->marker == stop); _Jv_JNI_LocalFrame *n = rf->next; // When N==NULL, we've reached the stack-allocated frame, and we @@ -279,6 +286,20 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result); } +static jobject +_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result) +{ + return _Jv_JNI_PopLocalFrame (env, result, MARK_USER); +} + +// Pop a `system' frame from the stack. This is `extern "C"' as it is +// used by the compiler. +extern "C" void +_Jv_JNI_PopSystemFrame (JNIEnv *env) +{ + _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM); +} + // This function is used from other template functions. It wraps the // return value appropriately; we specialize it so that object returns // are turned into local references. @@ -1598,29 +1619,78 @@ mangled_name (jclass klass, _Jv_Utf8Const *func_name, buf[here] = '\0'; } -// This function is the stub which is used to turn an ordinary (CNI) -// method call into a JNI call. -void -_Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) +// Return the current thread's JNIEnv; if one does not exist, create +// it. Also create a new system frame for use. This is `extern "C"' +// because the compiler calls it. +extern "C" JNIEnv * +_Jv_GetJNIEnvNewFrame (jclass klass) { - _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this; + JNIEnv *env = _Jv_GetCurrentJNIEnv (); + if (env == NULL) + { + env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv)); + env->p = &_Jv_JNIFunctions; + env->ex = NULL; + env->klass = klass; + env->locals = NULL; - JNIEnv env; - _Jv_JNI_LocalFrame *frame - = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame) - + FRAME_SIZE * sizeof (jobject)); + _Jv_SetCurrentJNIEnv (env); + } - env.p = &_Jv_JNIFunctions; - env.ex = NULL; - env.klass = _this->defining_class; - env.locals = frame; + _Jv_JNI_LocalFrame *frame + = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame) + + (FRAME_SIZE + * sizeof (jobject))); - frame->marker = true; - frame->next = NULL; + frame->marker = MARK_SYSTEM; frame->size = FRAME_SIZE; + frame->next = env->locals; + env->locals = frame; + for (int i = 0; i < frame->size; ++i) frame->vec[i] = NULL; + return env; +} + +// Return the function which implements a particular JNI method. If +// we can't find the function, we throw the appropriate exception. +// This is `extern "C"' because the compiler uses it. +extern "C" void * +_Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name, + _Jv_Utf8Const *signature) +{ + char buf[10 + 6 * (name->length + signature->length)]; + int long_start; + void *function; + + mangled_name (klass, name, signature, buf, &long_start); + char c = buf[long_start]; + buf[long_start] = '\0'; + function = _Jv_FindSymbolInExecutable (buf); + if (function == NULL) + { + buf[long_start] = c; + function = _Jv_FindSymbolInExecutable (buf); + if (function == NULL) + { + jstring str = JvNewStringUTF (name->data); + JvThrow (new java::lang::AbstractMethodError (str)); + } + } + + return function; +} + +// This function is the stub which is used to turn an ordinary (CNI) +// method call into a JNI call. +void +_Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) +{ + _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this; + + JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class); + // FIXME: we should mark every reference parameter as a local. For // now we assume a conservative GC, and we assume that the // references are on the stack somewhere. @@ -1629,33 +1699,16 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) // a value we don't cache that fact -- we might subsequently load a // library which finds the function in question. if (_this->function == NULL) - { - char buf[10 + 6 * (_this->self->name->length - + _this->self->signature->length)]; - int long_start; - mangled_name (_this->defining_class, _this->self->name, - _this->self->signature, buf, &long_start); - char c = buf[long_start]; - buf[long_start] = '\0'; - _this->function = _Jv_FindSymbolInExecutable (buf); - if (_this->function == NULL) - { - buf[long_start] = c; - _this->function = _Jv_FindSymbolInExecutable (buf); - if (_this->function == NULL) - { - jstring str = JvNewStringUTF (_this->self->name->data); - JvThrow (new java::lang::AbstractMethodError (str)); - } - } - } + _this->function = _Jv_LookupJNIMethod (_this->defining_class, + _this->self->name, + _this->self->signature); JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0); ffi_raw real_args[2 + _this->args_raw_size / sizeof (ffi_raw)]; int offset = 0; // First argument is always the environment pointer. - real_args[offset++].ptr = &env; + real_args[offset++].ptr = env; // For a static method, we pass in the Class. For non-static // methods, the `this' argument is already handled. @@ -1669,14 +1722,10 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) ffi_raw_call (&_this->jni_cif, (void (*) (...)) _this->function, ret, real_args); - do - { - _Jv_JNI_PopLocalFrame (&env, NULL); - } - while (env.locals != frame); + _Jv_JNI_PopSystemFrame (env); - if (env.ex) - JvThrow (env.ex); + if (env->ex) + JvThrow (env->ex); } #endif /* INTERPRETER */ -- 2.43.5