diff options
author | Tom Tromey <tromey@cygnus.com> | 2000-03-07 00:10:52 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2000-03-07 00:10:52 +0000 |
commit | 8d00f6171a0825329c7a69f53ad744388ccb9022 (patch) | |
tree | 4db67277e34fdff4998ca352076c9163233bd56c /libjava/jni.cc | |
parent | b1b41fe4acbba6e729d035d3d561e0f82ff5f06a (diff) | |
download | gcc-8d00f6171a0825329c7a69f53ad744388ccb9022.tar.gz |
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
Diffstat (limited to 'libjava/jni.cc')
-rw-r--r-- | libjava/jni.cc | 149 |
1 files changed, 99 insertions, 50 deletions
diff --git a/libjava/jni.cc b/libjava/jni.cc index f06e5802026..d25b03cc55e 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 */ |