* src/native/jni.c (PushLocalFrame): Implemented.
authortwisti <none@none>
Wed, 8 Mar 2006 09:44:22 +0000 (09:44 +0000)
committertwisti <none@none>
Wed, 8 Mar 2006 09:44:22 +0000 (09:44 +0000)
(PopLocalFrame): Likewise.
(DeleteLocalRef): Walk through all local frames.
(NewLocalRef): Allocate a new local frame if the current frame is out
of space.
(EnsureLocalCapacity): Implemented.
* src/vm/jit/codegen-common.c (codegen_finish_native_call): Release
all local reference frames.

src/native/jni.c
src/vm/jit/codegen-common.c

index cf499c7942831336a1181c8287fd484eb0ff2b8e..0d2371d9c9324a66fa13f88971bb4ad4bd2b6fd3 100644 (file)
@@ -32,7 +32,7 @@
             Christian Thalinger
                        Edwin Steiner
 
-   $Id: jni.c 4567 2006-03-07 10:48:24Z twisti $
+   $Id: jni.c 4573 2006-03-08 09:44:22Z twisti $
 
 */
 
@@ -151,6 +151,7 @@ localref_table *_no_threads_localref_table;
 /* some forward declarations **************************************************/
 
 jobject NewLocalRef(JNIEnv *env, jobject ref);
+jint EnsureLocalCapacity(JNIEnv* env, jint capacity);
 
 
 /* jni_init ********************************************************************
@@ -1321,15 +1322,48 @@ void FatalError(JNIEnv *env, const char *msg)
 
 jint PushLocalFrame(JNIEnv* env, jint capacity)
 {
+       s4              additionalrefs;
+       localref_table *lrt;
+       localref_table *nlrt;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!");
+       if (capacity <= 0)
+               return -1;
+
+       /* Allocate new local reference table on Java heap.  Calculate the
+          additional memory we have to allocate. */
 
-       assert(0);
+       if (capacity > LOCALREFTABLE_CAPACITY)
+               additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
+       else
+               additionalrefs = 0;
+
+       nlrt = GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+
+       if (nlrt == NULL)
+               return -1;
+
+       /* get current local reference table from thread */
+
+       lrt = LOCALREFTABLE;
+
+       /* Set up the new local reference table and add it to the local
+          frames chain. */
+
+       nlrt->capacity    = capacity;
+       nlrt->used        = 0;
+       nlrt->localframes = lrt->localframes + 1;
+       nlrt->prev        = lrt;
+
+       /* store new local reference table in thread */
+
+       LOCALREFTABLE = nlrt;
 
        return 0;
 }
 
+
 /* PopLocalFrame ***************************************************************
 
    Pops off the current local reference frame, frees all the local
@@ -1340,15 +1374,50 @@ jint PushLocalFrame(JNIEnv* env, jint capacity)
 
 jobject PopLocalFrame(JNIEnv* env, jobject result)
 {
+       localref_table *lrt;
+       localref_table *plrt;
+       s4              localframes;
+
        STATISTICS(jniinvokation());
 
-       log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!");
+       /* get current local reference table from thread */
 
-       assert(0);
+       lrt = LOCALREFTABLE;
+
+       localframes = lrt->localframes;
+
+       /* Don't delete the top local frame, as this one is allocated in
+          the native stub on the stack and is freed automagically on
+          return. */
+
+       if (localframes == 1)
+               return NewLocalRef(env, result);
+
+       /* release all current local frames */
+
+       for (; localframes >= 1; localframes--) {
+               /* get previous frame */
+
+               plrt = lrt->prev;
+
+               /* clear all reference entries */
+
+               MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+
+               lrt->prev = NULL;
+
+               /* set new local references table */
+
+               lrt = plrt;
+       }
+
+       /* store new local reference table in thread */
+
+       LOCALREFTABLE = lrt;
 
        /* add local reference and return the value */
 
-       return NewLocalRef(env, NULL);
+       return NewLocalRef(env, result);
 }
 
 
@@ -1372,14 +1441,19 @@ void DeleteLocalRef(JNIEnv *env, jobject localRef)
 
        lrt = LOCALREFTABLE;
 
-       /* remove the reference */
+       /* go through all local frames */
 
-       for (i = 0; i < lrt->capacity; i++) {
-               if (lrt->refs[i] == o) {
-                       lrt->refs[i] = NULL;
-                       lrt->used--;
+       for (; lrt != NULL; lrt = lrt->prev) {
 
-                       return;
+               /* and try to remove the reference */
+
+               for (i = 0; i < lrt->capacity; i++) {
+                       if (lrt->refs[i] == o) {
+                               lrt->refs[i] = NULL;
+                               lrt->used--;
+
+                               return;
+                       }
                }
        }
 
@@ -1387,7 +1461,7 @@ void DeleteLocalRef(JNIEnv *env, jobject localRef)
 
 /*     if (opt_checkjni) */
 /*     FatalError(env, "Bad global or local ref passed to JNI"); */
-       log_text("JNI-DeleteLocalRef: Bad global or local ref passed to JNI");
+       log_text("JNI-DeleteLocalRef: Local ref passed to JNI not found");
 }
 
 
@@ -1428,13 +1502,17 @@ jobject NewLocalRef(JNIEnv *env, jobject ref)
 
        lrt = LOCALREFTABLE;
 
-       /* check if we have space for the requested reference */
+       /* Check if we have space for the requested reference?  No,
+          allocate a new frame.  This is actually not what the spec says,
+          but for compatibility reasons... */
 
        if (lrt->used == lrt->capacity) {
-/*             throw_cacao_exception_exit(string_java_lang_InternalError, */
-/*                                                                "Too many local references"); */
-               fprintf(stderr, "Too many local references");
-               assert(0);
+               if (EnsureLocalCapacity(env, 16) != 0)
+                       return NULL;
+
+               /* get the new local reference table */
+
+               lrt = LOCALREFTABLE;
        }
 
        /* insert the reference */
@@ -1469,6 +1547,8 @@ jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 {
        localref_table *lrt;
 
+       log_text("JNI-Call: EnsureLocalCapacity");
+
        STATISTICS(jniinvokation());
 
        /* get local reference table (thread specific) */
@@ -1477,10 +1557,8 @@ jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 
        /* check if capacity elements are available in the local references table */
 
-       if ((lrt->used + capacity) > lrt->capacity) {
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-               return -1;
-       }
+       if ((lrt->used + capacity) > lrt->capacity)
+               return PushLocalFrame(env, capacity);
 
        return 0;
 }
index 465c4392d863972ba117de57111683c8aad348a5..e6ce3b0b2187a57af91d5d5807051b90791a088f 100644 (file)
@@ -48,7 +48,7 @@
    memory. All functions writing values into the data area return the offset
    relative the begin of the code area (start of procedure).   
 
-   $Id: codegen-common.c 4560 2006-03-05 23:35:25Z twisti $
+   $Id: codegen-common.c 4573 2006-03-08 09:44:22Z twisti $
 
 */
 
@@ -950,6 +950,7 @@ void codegen_finish_native_call(u1 *datasp)
        stackframeinfo  *sfi;
        stackframeinfo **psfi;
        localref_table  *lrt;
+       localref_table  *plrt;
        s4               localframes;
 
        /* get data structures from stack */
@@ -968,10 +969,24 @@ void codegen_finish_native_call(u1 *datasp)
 
        lrt = LOCALREFTABLE;
 
-       /* got through all current local frames */
+       /* release all current local frames */
 
        for (localframes = lrt->localframes; localframes >= 1; localframes--) {
-               lrt = lrt->prev;
+               /* get previous frame */
+
+               plrt = lrt->prev;
+
+               /* Clear all reference entries (only for tables allocated on
+                  the Java heap). */
+
+               if (localframes > 1)
+                       MSET(&lrt->refs[0], 0, java_objectheader*, lrt->capacity);
+
+               lrt->prev = NULL;
+
+               /* set new local references table */
+
+               lrt = plrt;
        }
 
        /* now store the previous local frames in the thread structure */