+
+ return reinterpret_cast<jweak> (ref);
+}
+
+void JNICALL
+_Jv_JNI_DeleteWeakGlobalRef (JNIEnv *, jweak obj)
+{
+ // JDK compatibility.
+ if (obj == NULL)
+ return;
+
+ using namespace gnu::gcj::runtime;
+ JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
+ unmark_for_gc (ref, global_ref_table);
+ ref->clear ();
+}
+
+\f
+
+// Direct byte buffers.
+
+static jobject JNICALL
+_Jv_JNI_NewDirectByteBuffer (JNIEnv *, void *address, jlong length)
+{
+ using namespace gnu::gcj;
+ using namespace java::nio;
+ return new DirectByteBufferImpl$ReadWrite
+ (reinterpret_cast<RawData *> (address), length);
+}
+
+static void * JNICALL
+_Jv_JNI_GetDirectBufferAddress (JNIEnv *, jobject buffer)
+{
+ using namespace java::nio;
+ 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;
+ if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
+ return -1;
+ Buffer *tmp = static_cast<Buffer *> (buffer);
+ if (tmp->address == NULL)
+ return -1;
+ return tmp->capacity();
+}
+
+static jobjectRefType JNICALL
+_Jv_JNI_GetObjectRefType (JNIEnv *, MAYBE_UNUSED jobject object)
+{
+ JvFail("GetObjectRefType not implemented");
+ return JNIInvalidRefType;
+}
+
+\f
+
+struct NativeMethodCacheEntry : public JNINativeMethod
+{
+ char *className;
+};
+
+// Hash table of native methods.
+static NativeMethodCacheEntry *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 NativeMethodCacheEntry *method)
+{
+ char *ptr;
+ int hash = 0;
+
+ ptr = method->className;
+ while (*ptr)
+ hash = (31 * hash) + *ptr++;
+
+ 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 NativeMethodCacheEntry *
+nathash_find_slot (const NativeMethodCacheEntry *method)
+{
+ jint h = hash (method);
+ int step = (h ^ (h >> 16)) | 1;
+ int w = h & (nathash_size - 1);
+ int del = -1;
+
+ for (;;)
+ {
+ NativeMethodCacheEntry *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)
+ && ! strcmp (slotp->className, method->className))
+ 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 (NativeMethodCacheEntry *method)
+{
+ if (nathash == NULL)
+ return NULL;
+ NativeMethodCacheEntry *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 =
+ (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
+ * sizeof (NativeMethodCacheEntry));
+ }
+ else
+ {
+ int savesize = nathash_size;
+ NativeMethodCacheEntry *savehash = nathash;
+ nathash_size *= 2;
+ nathash =
+ (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
+ * sizeof (NativeMethodCacheEntry));
+
+ for (int i = 0; i < savesize; ++i)
+ {
+ if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
+ {
+ NativeMethodCacheEntry *slot = nathash_find_slot (&savehash[i]);
+ *slot = savehash[i];
+ }
+ }
+ }
+}
+
+static void
+nathash_add (const NativeMethodCacheEntry *method)
+{
+ if (3 * nathash_count >= 2 * nathash_size)
+ natrehash ();
+ NativeMethodCacheEntry *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: memory leak?
+ slot->name = strdup (method->name);
+ slot->className = strdup (method->className);
+ // This was already strduped in _Jv_JNI_RegisterNatives.
+ slot->signature = method->signature;
+ slot->fnPtr = method->fnPtr;
+}
+
+static jint JNICALL
+_Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
+ const JNINativeMethod *methods,
+ jint nMethods)
+{
+ // 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);
+
+ NativeMethodCacheEntry dottedMethod;