mirror of git://gcc.gnu.org/git/gcc.git
jni.h (_Jv_JNIEnv::bottom_locals): New field.
2005-01-13 Graydon Hoare <graydon@redhat.com> * include/jni.h (_Jv_JNIEnv::bottom_locals): New field. * include/jvm.h (_Jv_FreeJNIEnv): Declare. * java/lang/natThread.cc (finalize_native): Call _Jv_FreeJNIEnv. * jni.cc: Reuse bottom frame between calls, avoid clearing frame when no local references are made. From-SVN: r93632
This commit is contained in:
parent
a0ee8b5f99
commit
84973b27e8
|
@ -1,3 +1,11 @@
|
||||||
|
2005-01-13 Graydon Hoare <graydon@redhat.com>
|
||||||
|
|
||||||
|
* include/jni.h (_Jv_JNIEnv::bottom_locals): New field.
|
||||||
|
* include/jvm.h (_Jv_FreeJNIEnv): Declare.
|
||||||
|
* java/lang/natThread.cc (finalize_native): Call _Jv_FreeJNIEnv.
|
||||||
|
* jni.cc: Reuse bottom frame between calls, avoid clearing
|
||||||
|
frame when no local references are made.
|
||||||
|
|
||||||
2005-01-13 Michael Koch <konqueror@gmx.de>
|
2005-01-13 Michael Koch <konqueror@gmx.de>
|
||||||
|
|
||||||
PR libgcj/17784
|
PR libgcj/17784
|
||||||
|
|
|
@ -693,6 +693,10 @@ private:
|
||||||
/* The chain of local frames. */
|
/* The chain of local frames. */
|
||||||
struct _Jv_JNI_LocalFrame *locals;
|
struct _Jv_JNI_LocalFrame *locals;
|
||||||
|
|
||||||
|
/* The bottom-most element of the chain, initialized with the env and
|
||||||
|
reused between non-nesting JNI calls. */
|
||||||
|
struct _Jv_JNI_LocalFrame *bottom_locals;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
jint GetVersion ()
|
jint GetVersion ()
|
||||||
{ return p->GetVersion (this); }
|
{ return p->GetVersion (this); }
|
||||||
|
|
|
@ -522,6 +522,9 @@ extern void _Jv_JNI_Init (void);
|
||||||
_Jv_JNIEnv *_Jv_GetCurrentJNIEnv ();
|
_Jv_JNIEnv *_Jv_GetCurrentJNIEnv ();
|
||||||
void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *);
|
void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *);
|
||||||
|
|
||||||
|
/* Free a JNIEnv. */
|
||||||
|
void _Jv_FreeJNIEnv (_Jv_JNIEnv *);
|
||||||
|
|
||||||
struct _Jv_JavaVM;
|
struct _Jv_JavaVM;
|
||||||
_Jv_JavaVM *_Jv_GetJavaVM ();
|
_Jv_JavaVM *_Jv_GetJavaVM ();
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ finalize_native (jobject ptr)
|
||||||
#ifdef _Jv_HaveMutexDestroy
|
#ifdef _Jv_HaveMutexDestroy
|
||||||
_Jv_MutexDestroy (&nt->join_mutex);
|
_Jv_MutexDestroy (&nt->join_mutex);
|
||||||
#endif
|
#endif
|
||||||
|
_Jv_FreeJNIEnv(nt->jni_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint
|
jint
|
||||||
|
|
103
libjava/jni.cc
103
libjava/jni.cc
|
@ -71,7 +71,7 @@ extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions;
|
||||||
|
|
||||||
// Number of slots in the default frame. The VM must allow at least
|
// Number of slots in the default frame. The VM must allow at least
|
||||||
// 16.
|
// 16.
|
||||||
#define FRAME_SIZE 32
|
#define FRAME_SIZE 16
|
||||||
|
|
||||||
// Mark value indicating this is an overflow frame.
|
// Mark value indicating this is an overflow frame.
|
||||||
#define MARK_NONE 0
|
#define MARK_NONE 0
|
||||||
|
@ -85,10 +85,13 @@ struct _Jv_JNI_LocalFrame
|
||||||
{
|
{
|
||||||
// This is true if this frame object represents a pushed frame (eg
|
// This is true if this frame object represents a pushed frame (eg
|
||||||
// from PushLocalFrame).
|
// from PushLocalFrame).
|
||||||
int marker : 2;
|
int marker;
|
||||||
|
|
||||||
|
// Flag to indicate some locals were allocated.
|
||||||
|
int allocated_p;
|
||||||
|
|
||||||
// Number of elements in frame.
|
// Number of elements in frame.
|
||||||
int size : 30;
|
int size;
|
||||||
|
|
||||||
// Next frame in chain.
|
// Next frame in chain.
|
||||||
_Jv_JNI_LocalFrame *next;
|
_Jv_JNI_LocalFrame *next;
|
||||||
|
@ -289,6 +292,7 @@ _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
|
||||||
|
|
||||||
frame->marker = MARK_NONE;
|
frame->marker = MARK_NONE;
|
||||||
frame->size = size;
|
frame->size = size;
|
||||||
|
frame->allocated_p = 0;
|
||||||
memset (&frame->vec[0], 0, size * sizeof (jobject));
|
memset (&frame->vec[0], 0, size * sizeof (jobject));
|
||||||
frame->next = env->locals;
|
frame->next = env->locals;
|
||||||
env->locals = frame;
|
env->locals = frame;
|
||||||
|
@ -327,6 +331,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
|
||||||
set = true;
|
set = true;
|
||||||
done = true;
|
done = true;
|
||||||
frame->vec[i] = obj;
|
frame->vec[i] = obj;
|
||||||
|
frame->allocated_p = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,6 +349,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
|
||||||
_Jv_JNI_EnsureLocalCapacity (env, 16);
|
_Jv_JNI_EnsureLocalCapacity (env, 16);
|
||||||
// We know the first element of the new frame will be ok.
|
// We know the first element of the new frame will be ok.
|
||||||
env->locals->vec[0] = obj;
|
env->locals->vec[0] = obj;
|
||||||
|
env->locals->allocated_p = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_for_gc (obj, local_ref_table);
|
mark_for_gc (obj, local_ref_table);
|
||||||
|
@ -366,12 +372,14 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
|
||||||
done = (rf->marker == stop);
|
done = (rf->marker == stop);
|
||||||
|
|
||||||
_Jv_JNI_LocalFrame *n = rf->next;
|
_Jv_JNI_LocalFrame *n = rf->next;
|
||||||
// When N==NULL, we've reached the stack-allocated frame, and we
|
// When N==NULL, we've reached the reusable bottom_locals, and we must
|
||||||
// must not free it. However, we must be sure to clear all its
|
// not free it. However, we must be sure to clear all its elements.
|
||||||
// elements, since we might conceivably reuse it.
|
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
{
|
{
|
||||||
memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
|
if (rf->allocated_p)
|
||||||
|
memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
|
||||||
|
rf->allocated_p = 0;
|
||||||
|
rf = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,9 +420,17 @@ _Jv_JNI_check_types (JNIEnv *env, JArray<T> *array, jclass K)
|
||||||
extern "C" void
|
extern "C" void
|
||||||
_Jv_JNI_PopSystemFrame (JNIEnv *env)
|
_Jv_JNI_PopSystemFrame (JNIEnv *env)
|
||||||
{
|
{
|
||||||
_Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
|
// Only enter slow path when we're not at the bottom, or there have been
|
||||||
|
// allocations. Usually this is false and we can just null out the locals
|
||||||
|
// field.
|
||||||
|
|
||||||
if (env->ex)
|
if (__builtin_expect ((env->locals->next
|
||||||
|
|| env->locals->allocated_p), false))
|
||||||
|
_Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
|
||||||
|
else
|
||||||
|
env->locals = NULL;
|
||||||
|
|
||||||
|
if (__builtin_expect (env->ex != NULL, false))
|
||||||
{
|
{
|
||||||
jthrowable t = env->ex;
|
jthrowable t = env->ex;
|
||||||
env->ex = NULL;
|
env->ex = NULL;
|
||||||
|
@ -2030,7 +2046,7 @@ extern "C" JNIEnv *
|
||||||
_Jv_GetJNIEnvNewFrame (jclass klass)
|
_Jv_GetJNIEnvNewFrame (jclass klass)
|
||||||
{
|
{
|
||||||
JNIEnv *env = _Jv_GetCurrentJNIEnv ();
|
JNIEnv *env = _Jv_GetCurrentJNIEnv ();
|
||||||
if (env == NULL)
|
if (__builtin_expect (env == NULL, false))
|
||||||
{
|
{
|
||||||
env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
|
env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
|
||||||
env->p = &_Jv_JNIFunctions;
|
env->p = &_Jv_JNIFunctions;
|
||||||
|
@ -2038,27 +2054,70 @@ _Jv_GetJNIEnvNewFrame (jclass klass)
|
||||||
env->locals = NULL;
|
env->locals = NULL;
|
||||||
// We set env->ex below.
|
// We set env->ex below.
|
||||||
|
|
||||||
|
// Set up the bottom, reusable frame.
|
||||||
|
env->bottom_locals = (_Jv_JNI_LocalFrame *)
|
||||||
|
_Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
|
||||||
|
+ (FRAME_SIZE
|
||||||
|
* sizeof (jobject)));
|
||||||
|
|
||||||
|
env->bottom_locals->marker = MARK_SYSTEM;
|
||||||
|
env->bottom_locals->size = FRAME_SIZE;
|
||||||
|
env->bottom_locals->next = NULL;
|
||||||
|
env->bottom_locals->allocated_p = 0;
|
||||||
|
memset (&env->bottom_locals->vec[0], 0,
|
||||||
|
env->bottom_locals->size * sizeof (jobject));
|
||||||
|
|
||||||
_Jv_SetCurrentJNIEnv (env);
|
_Jv_SetCurrentJNIEnv (env);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Jv_JNI_LocalFrame *frame
|
// If we're in a simple JNI call (non-nested), we can just reuse the
|
||||||
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
|
// locals frame we allocated many calls ago, back when the env was first
|
||||||
+ (FRAME_SIZE
|
// built, above.
|
||||||
* sizeof (jobject)));
|
|
||||||
|
|
||||||
frame->marker = MARK_SYSTEM;
|
if (__builtin_expect (env->locals == NULL, true))
|
||||||
frame->size = FRAME_SIZE;
|
env->locals = env->bottom_locals;
|
||||||
frame->next = env->locals;
|
|
||||||
|
|
||||||
for (int i = 0; i < frame->size; ++i)
|
else
|
||||||
frame->vec[i] = NULL;
|
{
|
||||||
|
// Alternatively, we might be re-entering JNI, in which case we can't
|
||||||
|
// reuse the bottom_locals frame, because it is already underneath
|
||||||
|
// us. So we need to make a new one.
|
||||||
|
|
||||||
|
_Jv_JNI_LocalFrame *frame
|
||||||
|
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
|
||||||
|
+ (FRAME_SIZE
|
||||||
|
* sizeof (jobject)));
|
||||||
|
|
||||||
|
frame->marker = MARK_SYSTEM;
|
||||||
|
frame->size = FRAME_SIZE;
|
||||||
|
frame->allocated_p = 0;
|
||||||
|
frame->next = env->locals;
|
||||||
|
|
||||||
|
memset (&frame->vec[0], 0,
|
||||||
|
frame->size * sizeof (jobject));
|
||||||
|
|
||||||
|
env->locals = frame;
|
||||||
|
}
|
||||||
|
|
||||||
env->locals = frame;
|
|
||||||
env->ex = NULL;
|
env->ex = NULL;
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy the env's reusable resources. This is called from the thread
|
||||||
|
// destructor "finalize_native" in natThread.cc
|
||||||
|
void
|
||||||
|
_Jv_FreeJNIEnv (_Jv_JNIEnv *env)
|
||||||
|
{
|
||||||
|
if (env == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (env->bottom_locals != NULL)
|
||||||
|
_Jv_Free (env->bottom_locals);
|
||||||
|
|
||||||
|
_Jv_Free (env);
|
||||||
|
}
|
||||||
|
|
||||||
// Return the function which implements a particular JNI method. If
|
// Return the function which implements a particular JNI method. If
|
||||||
// we can't find the function, we throw the appropriate exception.
|
// we can't find the function, we throw the appropriate exception.
|
||||||
// This is `extern "C"' because the compiler uses it.
|
// This is `extern "C"' because the compiler uses it.
|
||||||
|
@ -2274,16 +2333,18 @@ _Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
|
||||||
env->p = &_Jv_JNIFunctions;
|
env->p = &_Jv_JNIFunctions;
|
||||||
env->ex = NULL;
|
env->ex = NULL;
|
||||||
env->klass = NULL;
|
env->klass = NULL;
|
||||||
env->locals
|
env->bottom_locals
|
||||||
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
|
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
|
||||||
+ (FRAME_SIZE
|
+ (FRAME_SIZE
|
||||||
* sizeof (jobject)));
|
* sizeof (jobject)));
|
||||||
|
env->locals = env->bottom_locals;
|
||||||
if (env->locals == NULL)
|
if (env->locals == NULL)
|
||||||
{
|
{
|
||||||
_Jv_Free (env);
|
_Jv_Free (env);
|
||||||
return JNI_ERR;
|
return JNI_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env->locals->allocated_p = 0;
|
||||||
env->locals->marker = MARK_SYSTEM;
|
env->locals->marker = MARK_SYSTEM;
|
||||||
env->locals->size = FRAME_SIZE;
|
env->locals->size = FRAME_SIZE;
|
||||||
env->locals->next = NULL;
|
env->locals->next = NULL;
|
||||||
|
|
Loading…
Reference in New Issue