aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@redhat.com>2005-01-14 07:36:27 +0000
committerGraydon Hoare <graydon@redhat.com>2005-01-14 07:36:27 +0000
commitb4d5fb79e370832a8202676c33b3f59b8b4ead1e (patch)
tree57a4dece632a26e9b5430fff053a24e1b01280d3 /libjava
parent0342724b2ba0d88dcf74f5d1b99f466a95d41669 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@93632 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r--libjava/ChangeLog8
-rw-r--r--libjava/include/jni.h4
-rw-r--r--libjava/include/jvm.h3
-rw-r--r--libjava/java/lang/natThread.cc1
-rw-r--r--libjava/jni.cc103
5 files changed, 98 insertions, 21 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 151ee652554..40b9998232e 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -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>
PR libgcj/17784
diff --git a/libjava/include/jni.h b/libjava/include/jni.h
index acffa97fd98..c1b6e20b5ab 100644
--- a/libjava/include/jni.h
+++ b/libjava/include/jni.h
@@ -693,6 +693,10 @@ private:
/* The chain of local frames. */
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:
jint GetVersion ()
{ return p->GetVersion (this); }
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index d45ef25b699..67a4b18176e 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -522,6 +522,9 @@ extern void _Jv_JNI_Init (void);
_Jv_JNIEnv *_Jv_GetCurrentJNIEnv ();
void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *);
+/* Free a JNIEnv. */
+void _Jv_FreeJNIEnv (_Jv_JNIEnv *);
+
struct _Jv_JavaVM;
_Jv_JavaVM *_Jv_GetJavaVM ();
diff --git a/libjava/java/lang/natThread.cc b/libjava/java/lang/natThread.cc
index af33b0db353..e79ab11b9c6 100644
--- a/libjava/java/lang/natThread.cc
+++ b/libjava/java/lang/natThread.cc
@@ -84,6 +84,7 @@ finalize_native (jobject ptr)
#ifdef _Jv_HaveMutexDestroy
_Jv_MutexDestroy (&nt->join_mutex);
#endif
+ _Jv_FreeJNIEnv(nt->jni_env);
}
jint
diff --git a/libjava/jni.cc b/libjava/jni.cc
index 2f4c3e4fc84..6e0ab899c3e 100644
--- a/libjava/jni.cc
+++ b/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
// 16.
-#define FRAME_SIZE 32
+#define FRAME_SIZE 16
// Mark value indicating this is an overflow frame.
#define MARK_NONE 0
@@ -85,10 +85,13 @@ struct _Jv_JNI_LocalFrame
{
// This is true if this frame object represents a pushed frame (eg
// from PushLocalFrame).
- int marker : 2;
+ int marker;
+
+ // Flag to indicate some locals were allocated.
+ int allocated_p;
// Number of elements in frame.
- int size : 30;
+ int size;
// Next frame in chain.
_Jv_JNI_LocalFrame *next;
@@ -289,6 +292,7 @@ _Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
frame->marker = MARK_NONE;
frame->size = size;
+ frame->allocated_p = 0;
memset (&frame->vec[0], 0, size * sizeof (jobject));
frame->next = env->locals;
env->locals = frame;
@@ -327,6 +331,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
set = true;
done = true;
frame->vec[i] = obj;
+ frame->allocated_p = 1;
break;
}
}
@@ -344,6 +349,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
_Jv_JNI_EnsureLocalCapacity (env, 16);
// We know the first element of the new frame will be ok.
env->locals->vec[0] = obj;
+ env->locals->allocated_p = 1;
}
mark_for_gc (obj, local_ref_table);
@@ -366,12 +372,14 @@ _Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
done = (rf->marker == stop);
_Jv_JNI_LocalFrame *n = rf->next;
- // When N==NULL, we've reached the stack-allocated frame, and we
- // must not free it. However, we must be sure to clear all its
- // elements, since we might conceivably reuse it.
+ // When N==NULL, we've reached the reusable bottom_locals, and we must
+ // not free it. However, we must be sure to clear all its elements.
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;
}
@@ -412,9 +420,17 @@ _Jv_JNI_check_types (JNIEnv *env, JArray<T> *array, jclass K)
extern "C" void
_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;
env->ex = NULL;
@@ -2030,7 +2046,7 @@ extern "C" JNIEnv *
_Jv_GetJNIEnvNewFrame (jclass klass)
{
JNIEnv *env = _Jv_GetCurrentJNIEnv ();
- if (env == NULL)
+ if (__builtin_expect (env == NULL, false))
{
env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
env->p = &_Jv_JNIFunctions;
@@ -2038,27 +2054,70 @@ _Jv_GetJNIEnvNewFrame (jclass klass)
env->locals = NULL;
// 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_JNI_LocalFrame *frame
- = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
- + (FRAME_SIZE
- * sizeof (jobject)));
+ // If we're in a simple JNI call (non-nested), we can just reuse the
+ // locals frame we allocated many calls ago, back when the env was first
+ // built, above.
- frame->marker = MARK_SYSTEM;
- frame->size = FRAME_SIZE;
- frame->next = env->locals;
+ if (__builtin_expect (env->locals == NULL, true))
+ env->locals = env->bottom_locals;
- for (int i = 0; i < frame->size; ++i)
- frame->vec[i] = NULL;
+ else
+ {
+ // 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;
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
// we can't find the function, we throw the appropriate exception.
// 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->ex = NULL;
env->klass = NULL;
- env->locals
+ env->bottom_locals
= (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
+ (FRAME_SIZE
* sizeof (jobject)));
+ env->locals = env->bottom_locals;
if (env->locals == NULL)
{
_Jv_Free (env);
return JNI_ERR;
}
+ env->locals->allocated_p = 0;
env->locals->marker = MARK_SYSTEM;
env->locals->size = FRAME_SIZE;
env->locals->next = NULL;