jni.cc (nathash, [...]): New globals.

* jni.cc (nathash, nathash_count, nathash_size): New globals.
	(DELETED_ENTRY): New define.
	(hash): New function.
	(nathash_find_slot): Likewise.
	(natrehash): Likewise.
	(nathash_add): Likewise.
	(_Jv_JNI_RegisterNatives): No longer interpreter-specific.  Use
	nathash_add.
	(nathash_find): New function.
	(_Jv_LookupJNIMethod): Use it.  Synchronize body.
	(call): Synchronize around assignment.

From-SVN: r45060
This commit is contained in:
Tom Tromey 2001-08-20 19:52:02 +00:00 committed by Tom Tromey
parent 010dc908b2
commit a4f291fc90
2 changed files with 166 additions and 21 deletions

View File

@ -1,3 +1,17 @@
2001-08-20 Tom Tromey <tromey@redhat.com>
* jni.cc (nathash, nathash_count, nathash_size): New globals.
(DELETED_ENTRY): New define.
(hash): New function.
(nathash_find_slot): Likewise.
(natrehash): Likewise.
(nathash_add): Likewise.
(_Jv_JNI_RegisterNatives): No longer interpreter-specific. Use
nathash_add.
(nathash_find): New function.
(_Jv_LookupJNIMethod): Use it. Synchronize body.
(call): Synchronize around assignment.
2001-08-17 Jeff Sturm <jsturm@one-point.com>
* gnu/gcj/convert/UnicodeToBytes.java (write): Write work buffer

View File

@ -1543,19 +1543,131 @@ _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
_Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
}
// Hash table of native methods.
static JNINativeMethod *nathash;
// Number of slots used.
static int nathash_count = 0;
// Number of slots available. Must be power of 2.
static int nathash_size = 0;
#define DELETED_ENTRY ((char *) (~0))
// Compute a hash value for a native method descriptor.
static int
hash (const JNINativeMethod *method)
{
char *ptr;
int hash = 0;
ptr = method->name;
while (*ptr)
hash = (31 * hash) + *ptr++;
ptr = method->signature;
while (*ptr)
hash = (31 * hash) + *ptr++;
return hash;
}
// Find the slot where a native method goes.
static JNINativeMethod *
nathash_find_slot (const JNINativeMethod *method)
{
jint h = hash (method);
int step = (h ^ (h >> 16)) | 1;
int w = h & (nathash_size - 1);
int del = -1;
for (;;)
{
JNINativeMethod *slotp = &nathash[w];
if (slotp->name == NULL)
{
if (del >= 0)
return &nathash[del];
else
return slotp;
}
else if (slotp->name == DELETED_ENTRY)
del = w;
else if (! strcmp (slotp->name, method->name)
&& ! strcmp (slotp->signature, method->signature))
return slotp;
w = (w + step) & (nathash_size - 1);
}
}
// Find a method. Return NULL if it isn't in the hash table.
static void *
nathash_find (JNINativeMethod *method)
{
if (nathash == NULL)
return NULL;
JNINativeMethod *slot = nathash_find_slot (method);
if (slot->name == NULL || slot->name == DELETED_ENTRY)
return NULL;
return slot->fnPtr;
}
static void
natrehash ()
{
if (nathash == NULL)
{
nathash_size = 1024;
nathash =
(JNINativeMethod *) _Jv_AllocBytes (nathash_size
* sizeof (JNINativeMethod));
memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
}
else
{
int savesize = nathash_size;
JNINativeMethod *savehash = nathash;
nathash_size *= 2;
nathash =
(JNINativeMethod *) _Jv_AllocBytes (nathash_size
* sizeof (JNINativeMethod));
memset (nathash, 0, nathash_size * sizeof (JNINativeMethod));
for (int i = 0; i < savesize; ++i)
{
if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
{
JNINativeMethod *slot = nathash_find_slot (&savehash[i]);
*slot = savehash[i];
}
}
}
}
static void
nathash_add (const JNINativeMethod *method)
{
if (3 * nathash_count >= 2 * nathash_size)
natrehash ();
JNINativeMethod *slot = nathash_find_slot (method);
// If the slot has a real entry in it, then there is no work to do.
if (slot->name != NULL && slot->name != DELETED_ENTRY)
return;
// FIXME
slot->name = strdup (method->name);
slot->signature = strdup (method->signature);
slot->fnPtr = method->fnPtr;
}
static jint
_Jv_JNI_RegisterNatives (JNIEnv *env, jclass k,
_Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
const JNINativeMethod *methods,
jint nMethods)
{
#ifdef INTERPRETER
// For now, this only matters for interpreted methods. FIXME.
if (! _Jv_IsInterpretedClass (k))
{
// FIXME: throw exception.
return JNI_ERR;
}
_Jv_InterpClass *klass = reinterpret_cast<_Jv_InterpClass *> (k);
// Synchronize while we do the work. This must match
// synchronization in some other functions that manipulate or use
// the nathash table.
JvSynchronize sync (global_ref_table);
// Look at each descriptor given us, and find the corresponding
// method in the class.
@ -1563,11 +1675,10 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass k,
{
bool found = false;
_Jv_MethodBase **imeths = _Jv_GetFirstMethod (klass);
_Jv_Method *imeths = JvGetFirstMethod (klass);
for (int i = 0; i < JvNumMethods (klass); ++i)
{
_Jv_MethodBase *meth = imeths[i];
_Jv_Method *self = meth->get_method ();
_Jv_Method *self = &imeths[i];
if (! strcmp (self->name->data, methods[j].name)
&& ! strcmp (self->signature->data, methods[j].signature))
@ -1577,9 +1688,9 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass k,
break;
// Found a match that is native.
_Jv_JNIMethod *jmeth = reinterpret_cast<_Jv_JNIMethod *> (meth);
jmeth->set_function (methods[i].fnPtr);
found = true;
nathash_add (&methods[j]);
break;
}
}
@ -1600,14 +1711,12 @@ _Jv_JNI_RegisterNatives (JNIEnv *env, jclass k,
}
return JNI_OK;
#else /* INTERPRETER */
return JNI_ERR;
#endif /* INTERPRETER */
}
static jint
_Jv_JNI_UnregisterNatives (JNIEnv *, jclass)
{
// FIXME -- we could implement this.
return JNI_ERR;
}
@ -1751,6 +1860,22 @@ _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
int long_start;
void *function;
// Synchronize on something convenient. Right now we use the hash.
JvSynchronize sync (global_ref_table);
// First see if we have an override in the hash table.
strncpy (buf, name->data, name->length);
buf[name->length] = '\0';
strncpy (buf + name->length + 1, signature->data, signature->length);
buf[name->length + signature->length + 1] = '\0';
JNINativeMethod meth;
meth.name = buf;
meth.signature = buf + name->length + 1;
function = nathash_find (&meth);
if (function != NULL)
return function;
// If there was no override, then look in the symbol table.
mangled_name (klass, name, signature, buf, &long_start);
char c = buf[long_start];
buf[long_start] = '\0';
@ -1787,10 +1912,16 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this)
// We cache the value that we find, of course, but if we don't find
// a value we don't cache that fact -- we might subsequently load a
// library which finds the function in question.
if (_this->function == NULL)
_this->function = _Jv_LookupJNIMethod (_this->defining_class,
_this->self->name,
_this->self->signature);
{
// Synchronize on a convenient object to ensure sanity in case two
// threads reach this point for the same function at the same
// time.
JvSynchronize sync (global_ref_table);
if (_this->function == NULL)
_this->function = _Jv_LookupJNIMethod (_this->defining_class,
_this->self->name,
_this->self->signature);
}
JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0);
ffi_raw real_args[2 + _this->args_raw_size / sizeof (ffi_raw)];