#include <java/lang/Integer.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/Thread.h>
+#include <gnu/gcj/runtime/JNIWeakRef.h>
#include <gcj/method.h>
#include <gcj/field.h>
#include <java-interp.h>
#include <java-threads.h>
+using namespace gcj;
+
// This enum is used to select different template instantiations in
// the invocation code.
enum invocation_type
case JVMPI_EVENT_OBJECT_ALLOC:
_Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent;
break;
-
+
case JVMPI_EVENT_THREAD_START:
_Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent;
break;
-
+
case JVMPI_EVENT_THREAD_END:
_Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent;
break;
-
+
default:
return JVMPI_NOT_AVAILABLE;
}
-
+
return JVMPI_SUCCESS;
}
case JVMPI_EVENT_OBJECT_ALLOC:
_Jv_JVMPI_Notify_OBJECT_ALLOC = NULL;
break;
-
+
default:
return JVMPI_NOT_AVAILABLE;
}
-
+
return JVMPI_SUCCESS;
}
#endif
ref_table->put (obj, new Integer (val));
}
+// "Unwrap" some random non-reference type. This exists to simplify
+// other template functions.
+template<typename T>
+static T
+unwrap (T val)
+{
+ return val;
+}
+
+// Unwrap a weak reference, if required.
+template<typename T>
+static T *
+unwrap (T *obj)
+{
+ using namespace gnu::gcj::runtime;
+ // We can compare the class directly because JNIWeakRef is `final'.
+ // Doing it this way is much faster.
+ if (obj == NULL || obj->getClass () != &JNIWeakRef::class$)
+ return obj;
+ JNIWeakRef *wr = reinterpret_cast<JNIWeakRef *> (obj);
+ return reinterpret_cast<T *> (wr->get ());
+}
+
\f
static jobject
_Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
{
+ // This seems weird but I think it is correct.
+ obj = unwrap (obj);
mark_for_gc (obj, global_ref_table);
return obj;
}
static void
_Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
{
+ // This seems weird but I think it is correct.
+ obj = unwrap (obj);
unmark_for_gc (obj, global_ref_table);
}
{
_Jv_JNI_LocalFrame *frame;
+ // This seems weird but I think it is correct.
+ obj = unwrap (obj);
+
for (frame = env->locals; frame != NULL; frame = frame->next)
{
- for (int i = 0; i < FRAME_SIZE; ++i)
+ for (int i = 0; i < frame->size; ++i)
{
if (frame->vec[i] == obj)
{
static jobject
_Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
{
+ // This seems weird but I think it is correct.
+ obj = unwrap (obj);
+
// Try to find an open slot somewhere in the topmost frame.
_Jv_JNI_LocalFrame *frame = env->locals;
bool done = false, set = false;
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], local_ref_table);
}
static jclass
-_Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
+_Jv_JNI_DefineClass (JNIEnv *env, jobject loader,
const jbyte *buf, jsize bufLen)
{
try
{
+ loader = unwrap (loader);
+
jbyteArray bytes = JvNewByteArray (bufLen);
jbyte *elts = elements (bytes);
static jclass
_Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
{
- return (jclass) wrap_value (env, clazz->getSuperclass ());
+ return (jclass) wrap_value (env, unwrap (clazz)->getSuperclass ());
}
static jboolean
_Jv_JNI_IsAssignableFrom(JNIEnv *, jclass clazz1, jclass clazz2)
{
- return clazz1->isAssignableFrom (clazz2);
+ return unwrap (clazz1)->isAssignableFrom (unwrap (clazz2));
}
static jint
_Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
{
// We check in case the user did some funky cast.
+ obj = unwrap (obj);
JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
env->ex = obj;
return 0;
{
using namespace java::lang::reflect;
+ clazz = unwrap (clazz);
JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
int r = JNI_OK;
static jboolean
_Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
{
- return obj1 == obj2;
+ return unwrap (obj1) == unwrap (obj2);
}
static jobject
try
{
+ clazz = unwrap (clazz);
JvAssert (clazz && ! clazz->isArray ());
if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
env->ex = new java::lang::InstantiationException ();
static jclass
_Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
{
+ obj = unwrap (obj);
JvAssert (obj);
return (jclass) wrap_value (env, obj->getClass());
}
static jboolean
_Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
{
- return clazz->isInstance(obj);
+ return unwrap (clazz)->isInstance(unwrap (obj));
}
\f
{
try
{
+ clazz = unwrap (clazz);
_Jv_InitClass (clazz);
_Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
for (int i = 0; i < arg_types->length; ++i)
{
if (arg_elts[i] == JvPrimClass (byte))
- values[i].b = va_arg (vargs, jbyte);
+ values[i].b = (jbyte) va_arg (vargs, int);
else if (arg_elts[i] == JvPrimClass (short))
- values[i].s = va_arg (vargs, jshort);
+ values[i].s = (jshort) va_arg (vargs, int);
else if (arg_elts[i] == JvPrimClass (int))
values[i].i = va_arg (vargs, jint);
else if (arg_elts[i] == JvPrimClass (long))
else if (arg_elts[i] == JvPrimClass (double))
values[i].d = va_arg (vargs, jdouble);
else if (arg_elts[i] == JvPrimClass (boolean))
- values[i].z = va_arg (vargs, jboolean);
+ values[i].z = (jboolean) va_arg (vargs, int);
else if (arg_elts[i] == JvPrimClass (char))
- values[i].c = va_arg (vargs, jchar);
+ values[i].c = (jchar) va_arg (vargs, int);
else
{
// An object.
- values[i].l = va_arg (vargs, jobject);
+ values[i].l = unwrap (va_arg (vargs, jobject));
}
}
}
_Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
jmethodID id, va_list vargs)
{
+ obj = unwrap (obj);
+ klass = unwrap (klass);
+
if (style == normal)
id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
_Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
jmethodID id, jvalue *args)
{
+ obj = unwrap (obj);
+ klass = unwrap (klass);
+
if (style == normal)
id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
if (style == constructor)
return_type = klass;
+ // Unwrap arguments as required. Eww.
+ jclass *type_elts = elements (arg_types);
+ jvalue arg_copy[arg_types->length];
+ for (int i = 0; i < arg_types->length; ++i)
+ {
+ if (type_elts[i]->isPrimitive ())
+ arg_copy[i] = args[i];
+ else
+ arg_copy[i].l = unwrap (args[i].l);
+ }
+
jvalue result;
jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
style == constructor,
- arg_types, args, &result);
+ arg_types, arg_copy, &result);
if (ex != NULL)
env->ex = ex;
_Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
jmethodID id, va_list vargs)
{
+ obj = unwrap (obj);
+ klass = unwrap (klass);
+
if (style == normal)
id = _Jv_LookupDeclaredMethod (obj->getClass (), id->name, id->signature);
_Jv_GetTypesFromSignature (id, decl_class,
&arg_types, &return_type);
+ // Unwrap arguments as required. Eww.
+ jclass *type_elts = elements (arg_types);
+ jvalue arg_copy[arg_types->length];
+ for (int i = 0; i < arg_types->length; ++i)
+ {
+ if (type_elts[i]->isPrimitive ())
+ arg_copy[i] = args[i];
+ else
+ arg_copy[i].l = unwrap (args[i].l);
+ }
+
jthrowable ex = _Jv_CallAnyMethodA (obj, return_type, id,
style == constructor,
arg_types, args, NULL);
jmethodID id, va_list args)
{
JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
- JvAssert (java::lang::Class::class$.isInstance (klass));
+ JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
}
T result;
JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
- JvAssert (java::lang::Class::class$.isInstance (klass));
+ JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
va_start (args, id);
result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
jvalue *args)
{
JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
- JvAssert (java::lang::Class::class$.isInstance (klass));
+ JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
}
template<typename T>
static T
-_Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
+_Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
{
+ obj = unwrap (obj);
JvAssert (obj);
T *ptr = (T *) ((char *) obj + field->getOffset ());
return wrap_value (env, *ptr);
static void
_Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
{
+ obj = unwrap (obj);
+ value = unwrap (value);
+
JvAssert (obj);
T *ptr = (T *) ((char *) obj + field->getOffset ());
*ptr = value;
{
try
{
+ clazz = unwrap (clazz);
+
_Jv_InitClass (clazz);
_Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
static void
_Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
{
+ value = unwrap (value);
T *ptr = (T *) field->u.addr;
*ptr = value;
}
static jsize
_Jv_JNI_GetStringLength (JNIEnv *, jstring string)
{
- return string->length();
+ return unwrap (string)->length();
}
static const jchar *
_Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
{
+ string = unwrap (string);
jchar *result = _Jv_GetStringChars (string);
mark_for_gc (string, global_ref_table);
if (isCopy)
static void
_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
{
- unmark_for_gc (string, global_ref_table);
+ unmark_for_gc (unwrap (string), global_ref_table);
}
static jstring
static jsize
_Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
{
- return JvGetStringUTFLength (string);
+ return JvGetStringUTFLength (unwrap (string));
}
static const char *
_Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy)
{
+ string = unwrap (string);
jsize len = JvGetStringUTFLength (string);
try
{
_Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start, jsize len,
jchar *buf)
{
+ string = unwrap (string);
jchar *result = _Jv_GetStringChars (string);
if (start < 0 || start > string->length ()
|| len < 0 || start + len > string->length ())
_Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
jsize len, char *buf)
{
+ str = unwrap (str);
+
if (start < 0 || start > str->length ()
|| len < 0 || start + len > str->length ())
{
static const jchar *
_Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
{
- jchar *result = _Jv_GetStringChars (str);
+ jchar *result = _Jv_GetStringChars (unwrap (str));
if (isCopy)
*isCopy = false;
return result;
static jsize
_Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
{
- return array->length;
+ return unwrap (array)->length;
}
static jarray
{
try
{
+ elementClass = unwrap (elementClass);
+ init = unwrap (init);
+
jarray result = JvNewObjectArray (length, elementClass, init);
return (jarray) wrap_value (env, result);
}
static jobject
_Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index)
{
- jobject *elts = elements (array);
+ jobject *elts = elements (unwrap (array));
return wrap_value (env, elts[index]);
}
{
try
{
+ array = unwrap (array);
+ value = unwrap (value);
+
_Jv_CheckArrayStore (array, value);
jobject *elts = elements (array);
elts[index] = value;
_Jv_JNI_GetPrimitiveArrayElements (JNIEnv *, JArray<T> *array,
jboolean *isCopy)
{
+ array = unwrap (array);
T *elts = elements (array);
if (isCopy)
{
_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *, JArray<T> *array,
T *, jint /* mode */)
{
+ array = unwrap (array);
// 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.
jsize start, jsize len,
T *buf)
{
+ array = unwrap (array);
+
// The cast to unsigned lets us save a comparison.
if (start < 0 || len < 0
|| (unsigned long) (start + len) > (unsigned long) array->length)
template<typename T>
static void
-_Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
+_Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
jsize start, jsize len, T *buf)
{
+ array = unwrap (array);
+
// The cast to unsigned lets us save a comparison.
if (start < 0 || len < 0
|| (unsigned long) (start + len) > (unsigned long) array->length)
_Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
jboolean *isCopy)
{
+ array = unwrap (array);
// FIXME: does this work?
jclass klass = array->getClass()->getComponentType();
JvAssert (klass->isPrimitive ());
{
try
{
- _Jv_MonitorEnter (obj);
+ _Jv_MonitorEnter (unwrap (obj));
return 0;
}
catch (jthrowable t)
{
try
{
- _Jv_MonitorExit (obj);
+ _Jv_MonitorExit (unwrap (obj));
return 0;
}
catch (jthrowable t)
{
try
{
+ cls = unwrap (cls);
java::lang::reflect::Field *field = new java::lang::reflect::Field();
field->declaringClass = cls;
field->offset = (char*) fieldID - (char *) cls->fields;
{
using namespace java::lang::reflect;
+ f = unwrap (f);
Field *field = reinterpret_cast<Field *> (f);
return _Jv_FromReflectedField (field);
}
{
using namespace java::lang::reflect;
- // FIXME.
- static _Jv_Utf8Const *init_name = _Jv_makeUtf8Const ("<init>", 6);
-
jobject result = NULL;
+ klass = unwrap (klass);
try
{
_Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
{
using namespace java::lang::reflect;
+ method = unwrap (method);
if (Method::class$.isInstance (method))
return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
return
_Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
}
+// JDK 1.2.
+jweak
+_Jv_JNI_NewWeakGlobalRef (JNIEnv *env, jobject obj)
+{
+ using namespace gnu::gcj::runtime;
+ JNIWeakRef *ref = NULL;
+
+ try
+ {
+ // This seems weird but I think it is correct.
+ obj = unwrap (obj);
+ ref = new JNIWeakRef (obj);
+ mark_for_gc (ref, global_ref_table);
+ }
+ catch (jthrowable t)
+ {
+ env->ex = t;
+ }
+
+ return reinterpret_cast<jweak> (ref);
+}
+
+void
+_Jv_JNI_DeleteWeakGlobalRef (JNIEnv *, jweak obj)
+{
+ using namespace gnu::gcj::runtime;
+ JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
+ unmark_for_gc (ref, global_ref_table);
+ ref->clear ();
+}
+
\f
// Hash table of native methods.
JNI_CreateJavaVM (JavaVM **vm, void **penv, void *args)
{
JvAssert (! the_vm);
+
+ _Jv_CreateJavaVM (NULL);
+
// FIXME: synchronize
JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
if (nvm == NULL)
the_vm = nvm;
*vm = the_vm;
- _Jv_JNI_Init();
-
return 0;
}
\f
-#define NOT_IMPL NULL
#define RESERVED NULL
struct JNINativeInterface _Jv_JNIFunctions =
_Jv_JNI_GetStringCritical, // GetStringCritical
_Jv_JNI_ReleaseStringCritical, // ReleaseStringCritical
- NOT_IMPL /* newweakglobalref */,
- NOT_IMPL /* deleteweakglobalref */,
+ _Jv_JNI_NewWeakGlobalRef, // NewWeakGlobalRef
+ _Jv_JNI_DeleteWeakGlobalRef, // DeleteWeakGlobalRef
_Jv_JNI_ExceptionCheck
};