OSDN Git Service

* trans-intrinsic.c (gfc_conv_intrinsic_ishft): Fix signed /
[pf3gnuchains/gcc-fork.git] / libjava / jni.cc
index 6d8fd9d..6e0ab89 100644 (file)
@@ -41,7 +41,9 @@ details.  */
 #include <java/lang/ThreadGroup.h>
 #include <java/lang/Thread.h>
 #include <java/lang/IllegalAccessError.h>
+#include <java/nio/Buffer.h>
 #include <java/nio/DirectByteBufferImpl.h>
+#include <java/nio/DirectByteBufferImpl$ReadWrite.h>
 #include <java/util/IdentityHashMap.h>
 #include <gnu/gcj/RawData.h>
 
@@ -69,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
@@ -83,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;
@@ -287,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;
@@ -325,6 +331,7 @@ _Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
              set = true;
              done = true;
              frame->vec[i] = obj;
+             frame->allocated_p = 1;
              break;
            }
        }
@@ -342,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);
@@ -364,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;
        }
 
@@ -410,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;
@@ -562,11 +580,12 @@ _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
                                               NULL);
 
       jclass *elts = elements (argtypes);
-      elts[0] = &StringClass;
+      elts[0] = &java::lang::String::class$;
 
       Constructor *cons = clazz->getConstructor (argtypes);
 
-      jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
+      jobjectArray values = JvNewObjectArray (1, &java::lang::String::class$,
+                                             NULL);
       jobject *velts = elements (values);
       velts[0] = JvNewStringUTF (message);
 
@@ -1203,7 +1222,7 @@ _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
 
              // The field might be resolved or it might not be.  It
              // is much simpler to always resolve it.
-             _Jv_ResolveField (field, loader);
+             _Jv_Linker::resolve_field (field, loader);
              if (_Jv_equalUtf8Consts (f_name, a_name)
                  && field->getClass() == field_class)
                return field;
@@ -1723,24 +1742,30 @@ _Jv_JNI_NewDirectByteBuffer (JNIEnv *, void *address, jlong length)
 {
   using namespace gnu::gcj;
   using namespace java::nio;
-  return new DirectByteBufferImpl (reinterpret_cast<RawData *> (address),
-                                  length);
+  return new DirectByteBufferImpl$ReadWrite
+    (reinterpret_cast<RawData *> (address), length);
 }
 
 static void * JNICALL
 _Jv_JNI_GetDirectBufferAddress (JNIEnv *, jobject buffer)
 {
   using namespace java::nio;
-  DirectByteBufferImpl* bb = static_cast<DirectByteBufferImpl *> (buffer);
-  return reinterpret_cast<void *> (bb->address);
+  if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
+    return NULL;
+  Buffer *tmp = static_cast<Buffer *> (buffer);
+  return reinterpret_cast<void *> (tmp->address);
 }
 
 static jlong JNICALL
 _Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
 {
   using namespace java::nio;
-  DirectByteBufferImpl* bb = static_cast<DirectByteBufferImpl *> (buffer);
-  return bb->capacity();
+  if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
+    return -1;
+  Buffer *tmp = static_cast<Buffer *> (buffer);
+  if (tmp->address == NULL)
+    return -1;
+  return tmp->capacity();
 }
 
 \f
@@ -2021,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;
@@ -2029,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.
@@ -2265,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;