Commit 84973b27 by Graydon Hoare Committed by Graydon Hoare

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
parent a0ee8b5f
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: ...@@ -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); ...@@ -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) ...@@ -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
......
...@@ -71,7 +71,7 @@ extern struct JNIInvokeInterface _Jv_JNI_InvokeFunctions; ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 * ...@@ -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) ...@@ -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, ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment