aboutsummaryrefslogtreecommitdiff
path: root/libjava/jni.cc
diff options
context:
space:
mode:
authorTom Tromey <tromey@cygnus.com>2000-02-01 06:14:26 +0000
committerTom Tromey <tromey@gcc.gnu.org>2000-02-01 06:14:26 +0000
commit7e648cf95405746284c49f1c5ba88ec8292c3875 (patch)
tree37bc5e7b05325b8b7a5590d5caf2fda61bb3f57d /libjava/jni.cc
parent07a3462a53b230baae7bb0438cf276de28d2aedf (diff)
downloadgcc-7e648cf95405746284c49f1c5ba88ec8292c3875.zip
gcc-7e648cf95405746284c49f1c5ba88ec8292c3875.tar.gz
gcc-7e648cf95405746284c49f1c5ba88ec8292c3875.tar.bz2
prims.cc (_Jv_MallocUnchecked): New function.
* prims.cc (_Jv_MallocUnchecked): New function. (main_init): Call _Jv_JNI_Init. * include/jvm.h (_Jv_MallocUnchecked): Declare. (_Jv_JNI_Init): Declare. * jni.cc: Include Hashtable.h, OutOfMemoryError.h, Integer.h, <string.h>. (_Jv_JNI_NewGlobalRef): New function. (_Jv_JNI_DeleteGlobalRef): New function. (_Jv_JNI_DeleteLocalRef): New function. (_Jv_JNI_conversion_call): Initialize and clear local reference frame. (_Jv_JNI_NewLocalRef): New function. (struct _Jv_JNI_LocalFrame): New structure. (_Jv_JNI_PushLocalFrame): New function. (_Jv_JNI_EnsureLocalCapacity): New function. (FRAME_SIZE): New define. (_Jv_JNI_GetStringChars): Mark string, not characters. (_Jv_JNI_ReleaseStringChars): Unmark string, not characters. (_Jv_JNI_GetPrimitiveArrayElements): Mark array, not elements. (_Jv_JNI_ReleasePrimitiveArrayElements): Unmark array, not elements. (_Jv_JNI_DefineClass): Make return value a local ref. (_Jv_JNI_FindClass): Likewise. (_Jv_JNI_GetSuperclass): Likewise. (_Jv_JNI_ExceptionOccurred): Likewise. (_Jv_JNI_AllocObject): Likewise. (_Jv_JNI_GetObjectClass): Likewise. (_Jv_JNI_CallAnyMethodV): Likewise. (_Jv_JNI_NewString): Likewise. (_Jv_JNI_NewStringUTF): Likewise. (_Jv_JNI_NewObjectArray): Likewise. (_Jv_JNI_GetObjectArrayElement): Likewise. (_Jv_JNI_ToReflectedField): Likewise. (_Jv_JNI_ToReflectedMethod): Likewise. (_Jv_JNIFunctions): Updated table for new functions. (_Jv_JNI_Init): New function. (mark_for_gc): Wrote. (unmark_for_gc): Wrote. * include/jni.h (struct JNINativeInterface): Removed name from PopLocalFrame parameter. (class _Jv_JNIEnv): Added `locals' field. From-SVN: r31730
Diffstat (limited to 'libjava/jni.cc')
-rw-r--r--libjava/jni.cc312
1 files changed, 267 insertions, 45 deletions
diff --git a/libjava/jni.cc b/libjava/jni.cc
index e67bd8c..0b51fce 100644
--- a/libjava/jni.cc
+++ b/libjava/jni.cc
@@ -17,6 +17,7 @@ details. */
#include <config.h>
#include <stddef.h>
+#include <string.h>
// Define this before including jni.h.
#define __GCJ_JNI_IMPL__
@@ -37,6 +38,9 @@ details. */
#include <java/lang/reflect/Constructor.h>
#include <java/lang/reflect/Method.h>
#include <java/lang/reflect/Modifier.h>
+#include <java/lang/OutOfMemoryError.h>
+#include <java/util/Hashtable.h>
+#include <java/lang/Integer.h>
#include <gcj/method.h>
#include <gcj/field.h>
@@ -62,20 +66,202 @@ enum invocation_type
// Forward declaration.
extern struct JNINativeInterface _Jv_JNIFunctions;
+// Number of slots in the default frame. The VM must allow at least
+// 16.
+#define FRAME_SIZE 32
+
+// 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;
+
+ // Number of elements in frame.
+ int size : 31;
+
+ // Next frame in chain.
+ _Jv_JNI_LocalFrame *next;
+
+ // The elements. These are allocated using the C "struct hack".
+ jobject vec[0];
+};
+
+// This holds a reference count for all local and global references.
+static java::util::Hashtable *ref_table;
+
+void
+_Jv_JNI_Init (void)
+{
+ ref_table = new java::util::Hashtable;
+}
+
// Tell the GC that a certain pointer is live.
static void
-mark_for_gc (void *)
+mark_for_gc (jobject obj)
{
- // FIXME.
+ JvSynchronize sync (ref_table);
+
+ using namespace java::lang;
+ Integer *refcount = (Integer *) ref_table->get (obj);
+ jint val = (refcount == NULL) ? 0 : refcount->intValue ();
+ ref_table->put (obj, new Integer (val + 1));
}
// Unmark a pointer.
static void
-unmark_for_gc (void *)
+unmark_for_gc (jobject obj)
{
- // FIXME.
+ JvSynchronize sync (ref_table);
+
+ using namespace java::lang;
+ Integer *refcount = (Integer *) ref_table->get (obj);
+ JvAssert (refcount);
+ jint val = refcount->intValue () - 1;
+ if (val == 0)
+ ref_table->remove (obj);
+ else
+ ref_table->put (obj, new Integer (val));
+}
+
+
+
+static jobject
+_Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
+{
+ mark_for_gc (obj);
+ return obj;
+}
+
+static void
+_Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
+{
+ unmark_for_gc (obj);
+}
+
+static void
+_Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
+{
+ _Jv_JNI_LocalFrame *frame;
+
+ for (frame = env->locals; frame != NULL; frame = frame->next)
+ {
+ for (int i = 0; i < FRAME_SIZE; ++i)
+ {
+ if (frame->vec[i] == obj)
+ {
+ frame->vec[i] = NULL;
+ unmark_for_gc (obj);
+ return;
+ }
+ }
+
+ // Don't go past a marked frame.
+ JvAssert (! frame->marker);
+ }
+
+ JvAssert (0);
+}
+
+static jint
+_Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
+{
+ // It is easier to just always allocate a new frame of the requested
+ // size. This isn't the most efficient thing, but for now we don't
+ // care. Note that _Jv_JNI_PushLocalFrame relies on this right now.
+
+ _Jv_JNI_LocalFrame *frame
+ = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
+ + size * sizeof (jobject));
+ if (frame == NULL)
+ {
+ // FIXME: exception processing.
+ env->ex = new java::lang::OutOfMemoryError;
+ return -1;
+ }
+
+ frame->marker = true;
+ frame->size = size;
+ memset (&frame->vec[0], 0, size * sizeof (jobject));
+ frame->next = env->locals;
+ env->locals = frame;
+
+ return 0;
+}
+
+static jint
+_Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
+{
+ jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
+ if (r < 0)
+ return r;
+
+ // The new frame is on top.
+ env->locals->marker = true;
+
+ return 0;
+}
+
+static jobject
+_Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
+{
+ // Try to find an open slot somewhere in the topmost frame.
+ _Jv_JNI_LocalFrame *frame = env->locals;
+ bool done = false, set = false;
+ while (frame != NULL && ! done)
+ {
+ for (int i = 0; i < frame->size; ++i)
+ if (frame->vec[i] == NULL)
+ {
+ set = true;
+ done = true;
+ frame->vec[i] = obj;
+ break;
+ }
+ }
+
+ if (! set)
+ {
+ // No slots, so we allocate a new frame. According to the spec
+ // we could just die here. FIXME: return value.
+ _Jv_JNI_EnsureLocalCapacity (env, 16);
+ // We know the first element of the new frame will be ok.
+ env->locals->vec[0] = obj;
+ }
+
+ mark_for_gc (obj);
+ return obj;
+}
+
+static jobject
+_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
+{
+ _Jv_JNI_LocalFrame *rf = env->locals;
+
+ bool done = false;
+ while (rf != NULL && ! done)
+ {
+ for (int i = 0; i < rf->size; ++i)
+ if (rf->vec[i] != NULL)
+ unmark_for_gc (rf->vec[i]);
+
+ // If the frame we just freed is the marker frame, we are done.
+ done = rf->marker;
+
+ _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.
+ if (n == NULL)
+ memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
+ else
+ _Jv_Free (rf);
+ rf = n;
+ }
+
+ return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
}
@@ -87,7 +273,7 @@ _Jv_JNI_GetVersion (JNIEnv *)
}
static jclass
-_Jv_JNI_DefineClass (JNIEnv *, jobject loader,
+_Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
const jbyte *buf, jsize bufLen)
{
jbyteArray bytes = JvNewByteArray (bufLen);
@@ -99,7 +285,7 @@ _Jv_JNI_DefineClass (JNIEnv *, jobject loader,
// FIXME: exception processing.
jclass result = l->defineClass (bytes, 0, bufLen);
- return result;
+ return (jclass) _Jv_JNI_NewLocalRef (env, result);
}
static jclass
@@ -125,13 +311,13 @@ _Jv_JNI_FindClass (JNIEnv *env, const char *name)
// FIXME: exception processing.
jclass r = loader->findClass (n);
- return r;
+ return (jclass) _Jv_JNI_NewLocalRef (env, r);
}
static jclass
-_Jv_JNI_GetSuperclass (JNIEnv *, jclass clazz)
+_Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
{
- return clazz->getSuperclass ();
+ return (jclass) _Jv_JNI_NewLocalRef (env, clazz->getSuperclass ());
}
static jboolean
@@ -175,8 +361,7 @@ _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
static jthrowable
_Jv_JNI_ExceptionOccurred (JNIEnv *env)
{
- // FIXME: create local reference.
- return env->ex;
+ return (jthrowable) _Jv_JNI_NewLocalRef (env, env->ex);
}
static void
@@ -204,6 +389,8 @@ _Jv_JNI_FatalError (JNIEnv *, const char *message)
JvFail (message);
}
+
+
static jboolean
_Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
{
@@ -224,13 +411,13 @@ _Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
obj = JvAllocObject (clazz);
}
- return obj;
+ return _Jv_JNI_NewLocalRef (env, obj);
}
static jclass
-_Jv_JNI_GetObjectClass (JNIEnv *, jobject obj)
+_Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
{
- return obj->getClass();
+ return (jclass) _Jv_JNI_NewLocalRef (env, obj->getClass());
}
static jboolean
@@ -346,6 +533,14 @@ _Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
if (ex != NULL)
env->ex = ex;
+ if (! return_type->isPrimitive ())
+ {
+ // Make sure we create a local reference. The cast hackery is
+ // to avoid problems for template instantations we know won't be
+ // used.
+ return (T) (long long) _Jv_JNI_NewLocalRef (env, result.l);
+ }
+
// We cheat a little here. FIXME.
return * (T *) &result;
}
@@ -390,6 +585,14 @@ _Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
if (ex != NULL)
env->ex = ex;
+ if (! return_type->isPrimitive ())
+ {
+ // Make sure we create a local reference. The cast hackery is
+ // to avoid problems for template instantations we know won't be
+ // used.
+ return (T) (long long) _Jv_JNI_NewLocalRef (env, result.l);
+ }
+
// We cheat a little here. FIXME.
return * (T *) &result;
}
@@ -608,6 +811,7 @@ _Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
+// FIXME: local reference
template<typename T>
static T
_Jv_JNI_GetField (JNIEnv *, jobject obj, jfieldID field)
@@ -675,6 +879,7 @@ _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
return NULL;
}
+// FIXME: local reference
template<typename T>
static T
_Jv_JNI_GetStaticField (JNIEnv *, jclass, jfieldID field)
@@ -692,11 +897,11 @@ _Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
}
static jstring
-_Jv_JNI_NewString (JNIEnv *, const jchar *unichars, jsize len)
+_Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
{
// FIXME: exception processing.
jstring r = _Jv_NewString (unichars, len);
- return r;
+ return (jstring) _Jv_JNI_NewLocalRef (env, r);
}
static jsize
@@ -709,24 +914,24 @@ static const jchar *
_Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
{
jchar *result = _Jv_GetStringChars (string);
- mark_for_gc (result);
+ mark_for_gc (string);
if (isCopy)
*isCopy = false;
return (const jchar *) result;
}
static void
-_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring, const jchar *chars)
+_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
{
- unmark_for_gc ((void *) chars);
+ unmark_for_gc (string);
}
static jstring
-_Jv_JNI_NewStringUTF (JNIEnv *, const char *bytes)
+_Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
{
// FIXME: exception processing.
- jstring r = JvNewStringUTF (bytes);
- return r;
+ jstring result = JvNewStringUTF (bytes);
+ return (jstring) _Jv_JNI_NewLocalRef (env, result);
}
static jsize
@@ -801,19 +1006,19 @@ _Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
}
static jarray
-_Jv_JNI_NewObjectArray (JNIEnv *, jsize length, jclass elementClass,
+_Jv_JNI_NewObjectArray (JNIEnv *env, jsize length, jclass elementClass,
jobject init)
{
// FIXME: exception processing.
jarray result = JvNewObjectArray (length, elementClass, init);
- return result;
+ return (jarray) _Jv_JNI_NewLocalRef (env, result);
}
static jobject
-_Jv_JNI_GetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index)
+_Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
{
jobject *elts = elements (array);
- return elts[index];
+ return _Jv_JNI_NewLocalRef (env, elts[index]);
}
static void
@@ -828,9 +1033,11 @@ _Jv_JNI_SetObjectArrayElement (JNIEnv *, jobjectArray array, jsize index,
template<typename T, jclass K>
static JArray<T> *
-_Jv_JNI_NewPrimitiveArray (JNIEnv *, jsize length)
+_Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
{
- return (JArray<T> *) _Jv_NewPrimArray (K, length);
+ // FIXME: exception processing.
+ return (JArray<T> *) _Jv_JNI_NewLocalRef (env,
+ _Jv_NewPrimArray (K, length));
}
template<typename T>
@@ -844,19 +1051,19 @@ _Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
// We elect never to copy.
*isCopy = false;
}
- mark_for_gc (elts);
+ mark_for_gc (array);
return elts;
}
template<typename T>
static void
-_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *,
- T *elems, jint /* mode */)
+_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
+ T *, jint /* mode */)
{
// Note that we ignore MODE. We can do this because we never copy
// the array elements. My reading of the JNI documentation is that
// this is an option for the implementor.
- unmark_for_gc (elems);
+ unmark_for_gc (array);
}
template<typename T>
@@ -931,7 +1138,7 @@ _Jv_JNI_MonitorExit (JNIEnv *, jobject obj)
// JDK 1.2
jobject
-_Jv_JNI_ToReflectedField (JNIEnv *, jclass cls, jfieldID fieldID,
+_Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
jboolean)
{
// FIXME: exception processing.
@@ -939,8 +1146,7 @@ _Jv_JNI_ToReflectedField (JNIEnv *, jclass cls, jfieldID fieldID,
field->declaringClass = cls;
field->offset = (char*) fieldID - (char *) cls->fields;
field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
- // FIXME: make a local reference.
- return field;
+ return _Jv_JNI_NewLocalRef (env, field);
}
// JDK 1.2
@@ -954,7 +1160,7 @@ _Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
}
jobject
-_Jv_JNI_ToReflectedMethod (JNIEnv *, jclass klass, jmethodID id,
+_Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
jboolean)
{
using namespace java::lang::reflect;
@@ -979,8 +1185,7 @@ _Jv_JNI_ToReflectedMethod (JNIEnv *, jclass klass, jmethodID id,
result = meth;
}
- // FIXME: make a local reference.
- return result;
+ return _Jv_JNI_NewLocalRef (env, result);
}
static jmethodID
@@ -1003,13 +1208,26 @@ static T
_Jv_JNI_conversion_call (fixme)
{
JNIEnv env;
+ _Jv_JNI_LocalFrame *frame
+ = (_Jv_JNI_LocalFrame *) alloca (sizeof (_Jv_JNI_LocalFrame)
+ + FRAME_SIZE * sizeof (jobject));
env.p = &_Jv_JNIFunctions;
env.ex = NULL;
env.klass = FIXME;
+ env.locals = frame;
+
+ frame->marker = true;
+ frame->next = NULL;
+ frame->size = FRAME_SIZE;
+ for (int i = 0; i < frame->size; ++i)
+ frame->vec[i] = NULL;
T result = FIXME_ffi_call (args);
+ while (env.locals != NULL)
+ _Jv_JNI_PopLocalFrame (&env, result);
+
if (env.ex)
JvThrow (env.ex);
@@ -1043,14 +1261,18 @@ struct JNINativeInterface _Jv_JNIFunctions =
_Jv_JNI_ExceptionDescribe,
_Jv_JNI_ExceptionClear,
_Jv_JNI_FatalError,
- NOT_IMPL,
- NOT_IMPL,
- NOT_IMPL /* NewGlobalRef */,
- NOT_IMPL /* DeleteGlobalRef */,
- NOT_IMPL /* DeleteLocalRef */,
+
+ _Jv_JNI_PushLocalFrame,
+ _Jv_JNI_PopLocalFrame,
+ _Jv_JNI_NewGlobalRef,
+ _Jv_JNI_DeleteGlobalRef,
+ _Jv_JNI_DeleteLocalRef,
+
_Jv_JNI_IsSameObject,
- NOT_IMPL,
- NOT_IMPL,
+
+ _Jv_JNI_NewLocalRef,
+ _Jv_JNI_EnsureLocalCapacity,
+
_Jv_JNI_AllocObject,
_Jv_JNI_NewObject,
_Jv_JNI_NewObjectV,