#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>
// 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
{
// 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;
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;
set = true;
done = true;
frame->vec[i] = obj;
+ frame->allocated_p = 1;
break;
}
}
_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);
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;
}
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;
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);
// 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;
{
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
_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;
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.
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;