Christian Thalinger
Edwin Steiner
- $Id: jni.c 4573 2006-03-08 09:44:22Z twisti $
+ $Id: jni.c 4901 2006-05-11 12:18:55Z twisti $
*/
/* global reference table *****************************************************/
-static java_objectheader **global_ref_table;
+/* hashsize must be power of 2 */
-/* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/
-static classinfo *ihmclass = NULL;
-static methodinfo *putmid = NULL;
-static methodinfo *getmid = NULL;
-static methodinfo *removemid = NULL;
+#define HASHTABLE_GLOBAL_REF_SIZE 64 /* initial size of globalref-hash */
+
+static hashtable *hashtable_global_ref; /* hashtable for globalrefs */
/* direct buffer stuff ********************************************************/
bool jni_init(void)
{
- /* initalize global reference table */
-
- if (!(ihmclass =
- load_class_bootstrap(utf_new_char("java/util/IdentityHashMap"))))
- return false;
-
- global_ref_table = GCNEW(jobject);
+ /* create global ref hashtable */
- if (!(*global_ref_table = native_new_and_init(ihmclass)))
- return false;
+ hashtable_global_ref = NEW(hashtable);
- if (!(getmid = class_resolvemethod(ihmclass, utf_get,
- utf_java_lang_Object__java_lang_Object)))
- return false;
-
- if (!(putmid = class_resolvemethod(ihmclass, utf_put,
- utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"))))
- return false;
-
- if (!(removemid =
- class_resolvemethod(ihmclass, utf_remove,
- utf_java_lang_Object__java_lang_Object)))
- return false;
+ hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
/* direct buffer stuff */
classinfo *c;
s4 i;
s4 j;
+ s8 value;
paramcount = descr->paramcount;
paramtypes = descr->paramtypes;
if (o != NULL) {
/* this pointer */
- vmargs[0].type = TYPE_ADR;
- vmargs[0].data = (u8) (ptrint) o;
+ vmargs[0].type = TYPE_ADR;
+ vmargs[0].data.l = (u8) (ptrint) o;
paramtypes++;
paramcount--;
switch (paramtypes->decltype) {
case PRIMITIVETYPE_BOOLEAN:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Boolean *) param)->value;
+ value = (s8) ((java_lang_Boolean *) param)->value;
else
goto illegal_arg;
+
+ vmargs[i].data.l = value;
break;
case PRIMITIVETYPE_BYTE:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+ value = (s8) ((java_lang_Byte *) param)->value;
else
goto illegal_arg;
+
+ vmargs[i].data.l = value;
break;
case PRIMITIVETYPE_CHAR:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Character *) param)->value;
+ value = (s8) ((java_lang_Character *) param)->value;
else
goto illegal_arg;
+
+ vmargs[i].data.l = value;
break;
case PRIMITIVETYPE_SHORT:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Short *) param)->value;
+ value = (s8) ((java_lang_Short *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+ value = (s8) ((java_lang_Byte *) param)->value;
else
goto illegal_arg;
+
+ vmargs[i].data.l = value;
break;
case PRIMITIVETYPE_INT:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Integer *) param)->value;
+ value = (s8) ((java_lang_Integer *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Short *) param)->value;
+ value = (s8) ((java_lang_Short *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+ value = (s8) ((java_lang_Byte *) param)->value;
else
goto illegal_arg;
+
+ vmargs[i].data.l = value;
break;
case PRIMITIVETYPE_LONG:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Long *) param)->value;
+ value = (s8) ((java_lang_Long *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Integer *) param)->value;
+ value = (s8) ((java_lang_Integer *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Short *) param)->value;
+ value = (s8) ((java_lang_Short *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap)
- vmargs[i].data = (s8) ((java_lang_Byte *) param)->value;
+ value = (s8) ((java_lang_Byte *) param)->value;
else
goto illegal_arg;
+
+ vmargs[i].data.l = value;
break;
case PRIMITIVETYPE_FLOAT:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- *((jfloat *) (&vmargs[i].data)) = (jfloat) ((java_lang_Float *) param)->value;
+ vmargs[i].data.f = (jfloat) ((java_lang_Float *) param)->value;
else
goto illegal_arg;
break;
case PRIMITIVETYPE_DOUBLE:
if (c == primitivetype_table[paramtypes->decltype].class_wrap)
- *((jdouble *) (&vmargs[i].data)) = (jdouble) ((java_lang_Double *) param)->value;
+ vmargs[i].data.d = (jdouble) ((java_lang_Double *) param)->value;
else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap)
- *((jfloat *) (&vmargs[i].data)) = (jfloat) ((java_lang_Float *) param)->value;
+ vmargs[i].data.f = (jfloat) ((java_lang_Float *) param)->value;
else
goto illegal_arg;
break;
goto illegal_arg;
}
}
- vmargs[i].type = TYPE_ADR;
- vmargs[i].data = (u8) (ptrint) params->data[j];
+
+ vmargs[i].type = TYPE_ADR;
+ vmargs[i].data.l = (u8) (ptrint) params->data[j];
break;
default:
STATISTICS(jniinvokation());
cl = (java_lang_ClassLoader *) loader;
- s = javastring_new_char(name);
+ s = javastring_new_from_ascii(name);
ba = (java_bytearray *) buf;
c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba,
STATISTICS(jniinvokation());
- s = (java_lang_String *) javastring_new_char(msg);
+ s = (java_lang_String *) javastring_new_from_ascii(msg);
/* instantiate exception object */
*******************************************************************************/
-jobject NewGlobalRef(JNIEnv* env, jobject lobj)
+jobject NewGlobalRef(JNIEnv* env, jobject obj)
{
- java_objectheader *o;
- java_lang_Integer *refcount;
- java_objectheader *newval;
+ hashtable_global_ref_entry *gre;
+ u4 key; /* hashkey */
+ u4 slot; /* slot in hashtable */
STATISTICS(jniinvokation());
#if defined(USE_THREADS)
- builtin_monitorenter(*global_ref_table);
+ builtin_monitorenter(hashtable_global_ref->header);
#endif
+
+ /* normally addresses are aligned to 4, 8 or 16 bytes */
+
+ key = ((u4) (ptrint) obj) >> 4; /* align to 16-byte boundaries */
+ slot = key & (hashtable_global_ref->size - 1);
+ gre = hashtable_global_ref->ptr[slot];
- o = vm_call_method(getmid, *global_ref_table, lobj);
+ /* search external hash chain for the entry */
- refcount = (java_lang_Integer *) o;
+ while (gre) {
+ if (gre->o == obj) {
+ /* global object found, increment the reference */
- if (refcount == NULL) {
- newval = native_new_and_init_int(class_java_lang_Integer, 1);
+ gre->refs++;
- if (newval == NULL) {
#if defined(USE_THREADS)
- builtin_monitorexit(*global_ref_table);
+ builtin_monitorexit(hashtable_global_ref->header);
#endif
- return NULL;
+
+ return obj;
}
- (void) vm_call_method(putmid, *global_ref_table, lobj, newval);
+ gre = gre->hashlink; /* next element in external chain */
+ }
- } else {
- /* we can access the object itself, as we are in a
- synchronized section */
+ /* global ref not found, create a new one */
- refcount->value++;
- }
+ gre = NEW(hashtable_global_ref_entry);
+
+ gre->o = obj;
+ gre->refs = 1;
+
+ /* insert entry into hashtable */
+
+ gre->hashlink = hashtable_global_ref->ptr[slot];
+
+ hashtable_global_ref->ptr[slot] = gre;
+
+ /* update number of hashtable-entries */
+
+ hashtable_global_ref->entries++;
#if defined(USE_THREADS)
- builtin_monitorexit(*global_ref_table);
+ builtin_monitorexit(hashtable_global_ref->header);
#endif
- return lobj;
+ return obj;
}
void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
{
- java_objectheader *o;
- java_lang_Integer *refcount;
- s4 val;
+ hashtable_global_ref_entry *gre;
+ hashtable_global_ref_entry *prevgre;
+ u4 key; /* hashkey */
+ u4 slot; /* slot in hashtable */
STATISTICS(jniinvokation());
#if defined(USE_THREADS)
- builtin_monitorenter(*global_ref_table);
+ builtin_monitorenter(hashtable_global_ref->header);
#endif
- o = vm_call_method(getmid, *global_ref_table, globalRef);
+ /* normally addresses are aligned to 4, 8 or 16 bytes */
- refcount = (java_lang_Integer *) o;
+ key = ((u4) (ptrint) globalRef) >> 4; /* align to 16-byte boundaries */
+ slot = key & (hashtable_global_ref->size - 1);
+ gre = hashtable_global_ref->ptr[slot];
- if (refcount == NULL) {
- log_text("JNI-DeleteGlobalRef: unable to find global reference");
- return;
- }
+ /* initialize prevgre */
- /* we can access the object itself, as we are in a synchronized
- section */
+ prevgre = NULL;
- val = refcount->value - 1;
+ /* search external hash chain for the entry */
- if (val == 0) {
- (void) vm_call_method(removemid, *global_ref_table, refcount);
+ while (gre) {
+ if (gre->o == globalRef) {
+ /* global object found, decrement the reference count */
- } else {
- /* we do not create a new object, but set the new value into
- the old one */
+ gre->refs--;
+
+ /* if reference count is 0, remove the entry */
+
+ if (gre->refs == 0) {
+ /* special handling if it's the first in the chain */
+
+ if (prevgre == NULL)
+ hashtable_global_ref->ptr[slot] = gre->hashlink;
+ else
+ prevgre->hashlink = gre->hashlink;
+
+ FREE(gre, hashtable_global_ref_entry);
+ }
+
+#if defined(USE_THREADS)
+ builtin_monitorexit(hashtable_global_ref->header);
+#endif
- refcount->value = val;
+ return;
+ }
+
+ prevgre = gre; /* save current pointer for removal */
+ gre = gre->hashlink; /* next element in external chain */
}
+ log_println("JNI-DeleteGlobalRef: global reference not found");
+
#if defined(USE_THREADS)
- builtin_monitorexit(*global_ref_table);
+ builtin_monitorexit(hashtable_global_ref->header);
#endif
}
_Jv_env = env;
- /* actually create the JVM */
-
- if (!vm_create(_vm_args))
- return -1;
/* create and fill a JavaVM structure */
jvm->functions = &_Jv_JNIInvokeInterface;
/* XXX Set the global variable. Maybe we should do that differently. */
-
+ /* XXX JVMTI Agents needs a JavaVM */
_Jv_jvm = jvm;
+
+ /* actually create the JVM */
+
+ if (!vm_create(_vm_args))
+ return -1;
+
/* setup the local ref table (must be created after vm_create) */
lrt = GCNEW(localref_table);