OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [libjava/] [jni.cc] - Diff between revs 753 and 783

Only display areas with differences | Details | Blame | View Log

Rev 753 Rev 783
// jni.cc - JNI implementation, including the jump table.
// jni.cc - JNI implementation, including the jump table.
 
 
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
   Free Software Foundation
   Free Software Foundation
 
 
   This file is part of libgcj.
   This file is part of libgcj.
 
 
This software is copyrighted work licensed under the terms of the
This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */
details.  */
 
 
#include <config.h>
#include <config.h>
 
 
#include <stdio.h>
#include <stdio.h>
#include <stddef.h>
#include <stddef.h>
#include <string.h>
#include <string.h>
 
 
#include <gcj/cni.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <jvm.h>
#include <java-assert.h>
#include <java-assert.h>
#include <jni.h>
#include <jni.h>
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
#include <jvmpi.h>
#include <jvmpi.h>
#endif
#endif
#ifdef INTERPRETER
#ifdef INTERPRETER
#include <jvmti.h>
#include <jvmti.h>
#include "jvmti-int.h"
#include "jvmti-int.h"
#endif
#endif
#include <java/lang/Class.h>
#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Throwable.h>
#include <java/lang/Throwable.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/StringIndexOutOfBoundsException.h>
#include <java/lang/StringIndexOutOfBoundsException.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/UnsatisfiedLinkError.h>
#include <java/lang/UnsatisfiedLinkError.h>
#include <java/lang/InstantiationException.h>
#include <java/lang/InstantiationException.h>
#include <java/lang/NoSuchFieldError.h>
#include <java/lang/NoSuchFieldError.h>
#include <java/lang/NoSuchMethodError.h>
#include <java/lang/NoSuchMethodError.h>
#include <java/lang/reflect/Constructor.h>
#include <java/lang/reflect/Constructor.h>
#include <java/lang/reflect/Method.h>
#include <java/lang/reflect/Method.h>
#include <java/lang/reflect/Modifier.h>
#include <java/lang/reflect/Modifier.h>
#include <java/lang/OutOfMemoryError.h>
#include <java/lang/OutOfMemoryError.h>
#include <java/lang/Integer.h>
#include <java/lang/Integer.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/Thread.h>
#include <java/lang/Thread.h>
#include <java/lang/IllegalAccessError.h>
#include <java/lang/IllegalAccessError.h>
#include <java/nio/Buffer.h>
#include <java/nio/Buffer.h>
#include <java/nio/DirectByteBufferImpl.h>
#include <java/nio/DirectByteBufferImpl.h>
#include <java/nio/DirectByteBufferImpl$ReadWrite.h>
#include <java/nio/DirectByteBufferImpl$ReadWrite.h>
#include <java/util/IdentityHashMap.h>
#include <java/util/IdentityHashMap.h>
#include <gnu/gcj/RawData.h>
#include <gnu/gcj/RawData.h>
#include <java/lang/ClassNotFoundException.h>
#include <java/lang/ClassNotFoundException.h>
 
 
#include <gcj/method.h>
#include <gcj/method.h>
#include <gcj/field.h>
#include <gcj/field.h>
 
 
#include <java-interp.h>
#include <java-interp.h>
#include <java-threads.h>
#include <java-threads.h>
 
 
using namespace gcj;
using namespace gcj;
 
 
// This enum is used to select different template instantiations in
// This enum is used to select different template instantiations in
// the invocation code.
// the invocation code.
enum invocation_type
enum invocation_type
{
{
  normal,
  normal,
  nonvirtual,
  nonvirtual,
  static_type,
  static_type,
  constructor
  constructor
};
};
 
 
// Forward declarations.
// Forward declarations.
extern struct JNINativeInterface_ _Jv_JNIFunctions;
extern struct JNINativeInterface_ _Jv_JNIFunctions;
extern struct JNIInvokeInterface_ _Jv_JNI_InvokeFunctions;
extern struct JNIInvokeInterface_ _Jv_JNI_InvokeFunctions;
 
 
// Number of slots in the default frame.  The VM must allow at least
// Number of slots in the default frame.  The VM must allow at least
// 16.
// 16.
#define FRAME_SIZE 16
#define FRAME_SIZE 16
 
 
// Mark value indicating this is an overflow frame.
// Mark value indicating this is an overflow frame.
#define MARK_NONE    0
#define MARK_NONE    0
// Mark value indicating this is a user frame.
// Mark value indicating this is a user frame.
#define MARK_USER    1
#define MARK_USER    1
// Mark value indicating this is a system frame.
// Mark value indicating this is a system frame.
#define MARK_SYSTEM  2
#define MARK_SYSTEM  2
 
 
// This structure is used to keep track of local references.
// This structure is used to keep track of local references.
struct _Jv_JNI_LocalFrame
struct _Jv_JNI_LocalFrame
{
{
  // This is one of the MARK_ constants.
  // This is one of the MARK_ constants.
  unsigned char marker;
  unsigned char marker;
 
 
  // Flag to indicate some locals were allocated.
  // Flag to indicate some locals were allocated.
  bool allocated_p;
  bool allocated_p;
 
 
  // Number of elements in frame.
  // Number of elements in frame.
  int size;
  int size;
 
 
  // The class loader of the JNI method that allocated this frame.
  // The class loader of the JNI method that allocated this frame.
  ::java::lang::ClassLoader *loader;
  ::java::lang::ClassLoader *loader;
 
 
  // Next frame in chain.
  // Next frame in chain.
  _Jv_JNI_LocalFrame *next;
  _Jv_JNI_LocalFrame *next;
 
 
  // The elements.  These are allocated using the C "struct hack".
  // The elements.  These are allocated using the C "struct hack".
  jobject vec[0];
  jobject vec[0];
};
};
 
 
// This holds a reference count for all local references.
// This holds a reference count for all local references.
static java::util::IdentityHashMap *local_ref_table;
static java::util::IdentityHashMap *local_ref_table;
// This holds a reference count for all global references.
// This holds a reference count for all global references.
static java::util::IdentityHashMap *global_ref_table;
static java::util::IdentityHashMap *global_ref_table;
 
 
// The only VM.
// The only VM.
JavaVM *_Jv_the_vm;
JavaVM *_Jv_the_vm;
 
 
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
// The only JVMPI interface description.
// The only JVMPI interface description.
static JVMPI_Interface _Jv_JVMPI_Interface;
static JVMPI_Interface _Jv_JVMPI_Interface;
 
 
static jint
static jint
jvmpiEnableEvent (jint event_type, void *)
jvmpiEnableEvent (jint event_type, void *)
{
{
  switch (event_type)
  switch (event_type)
    {
    {
    case JVMPI_EVENT_OBJECT_ALLOC:
    case JVMPI_EVENT_OBJECT_ALLOC:
      _Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent;
      _Jv_JVMPI_Notify_OBJECT_ALLOC = _Jv_JVMPI_Interface.NotifyEvent;
      break;
      break;
 
 
    case JVMPI_EVENT_THREAD_START:
    case JVMPI_EVENT_THREAD_START:
      _Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent;
      _Jv_JVMPI_Notify_THREAD_START = _Jv_JVMPI_Interface.NotifyEvent;
      break;
      break;
 
 
    case JVMPI_EVENT_THREAD_END:
    case JVMPI_EVENT_THREAD_END:
      _Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent;
      _Jv_JVMPI_Notify_THREAD_END = _Jv_JVMPI_Interface.NotifyEvent;
      break;
      break;
 
 
    default:
    default:
      return JVMPI_NOT_AVAILABLE;
      return JVMPI_NOT_AVAILABLE;
    }
    }
 
 
  return JVMPI_SUCCESS;
  return JVMPI_SUCCESS;
}
}
 
 
static jint
static jint
jvmpiDisableEvent (jint event_type, void *)
jvmpiDisableEvent (jint event_type, void *)
{
{
  switch (event_type)
  switch (event_type)
    {
    {
    case JVMPI_EVENT_OBJECT_ALLOC:
    case JVMPI_EVENT_OBJECT_ALLOC:
      _Jv_JVMPI_Notify_OBJECT_ALLOC = NULL;
      _Jv_JVMPI_Notify_OBJECT_ALLOC = NULL;
      break;
      break;
 
 
    default:
    default:
      return JVMPI_NOT_AVAILABLE;
      return JVMPI_NOT_AVAILABLE;
    }
    }
 
 
  return JVMPI_SUCCESS;
  return JVMPI_SUCCESS;
}
}
#endif
#endif
 
 


 
 
void
void
_Jv_JNI_Init (void)
_Jv_JNI_Init (void)
{
{
  local_ref_table = new java::util::IdentityHashMap;
  local_ref_table = new java::util::IdentityHashMap;
  global_ref_table = new java::util::IdentityHashMap;
  global_ref_table = new java::util::IdentityHashMap;
 
 
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
  _Jv_JVMPI_Interface.version = 1;
  _Jv_JVMPI_Interface.version = 1;
  _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent;
  _Jv_JVMPI_Interface.EnableEvent = &jvmpiEnableEvent;
  _Jv_JVMPI_Interface.DisableEvent = &jvmpiDisableEvent;
  _Jv_JVMPI_Interface.DisableEvent = &jvmpiDisableEvent;
  _Jv_JVMPI_Interface.EnableGC = &_Jv_EnableGC;
  _Jv_JVMPI_Interface.EnableGC = &_Jv_EnableGC;
  _Jv_JVMPI_Interface.DisableGC = &_Jv_DisableGC;
  _Jv_JVMPI_Interface.DisableGC = &_Jv_DisableGC;
  _Jv_JVMPI_Interface.RunGC = &_Jv_RunGC;
  _Jv_JVMPI_Interface.RunGC = &_Jv_RunGC;
#endif
#endif
}
}
 
 
// Tell the GC that a certain pointer is live.
// Tell the GC that a certain pointer is live.
static void
static void
mark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
mark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
{
{
  JvSynchronize sync (ref_table);
  JvSynchronize sync (ref_table);
 
 
  using namespace java::lang;
  using namespace java::lang;
  Integer *refcount = (Integer *) ref_table->get (obj);
  Integer *refcount = (Integer *) ref_table->get (obj);
  jint val = (refcount == NULL) ? 0 : refcount->intValue ();
  jint val = (refcount == NULL) ? 0 : refcount->intValue ();
  // FIXME: what about out of memory error?
  // FIXME: what about out of memory error?
  ref_table->put (obj, new Integer (val + 1));
  ref_table->put (obj, new Integer (val + 1));
}
}
 
 
// Unmark a pointer.
// Unmark a pointer.
static void
static void
unmark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
unmark_for_gc (jobject obj, java::util::IdentityHashMap *ref_table)
{
{
  JvSynchronize sync (ref_table);
  JvSynchronize sync (ref_table);
 
 
  using namespace java::lang;
  using namespace java::lang;
  Integer *refcount = (Integer *) ref_table->get (obj);
  Integer *refcount = (Integer *) ref_table->get (obj);
  JvAssert (refcount);
  JvAssert (refcount);
  jint val = refcount->intValue () - 1;
  jint val = refcount->intValue () - 1;
  JvAssert (val >= 0);
  JvAssert (val >= 0);
  if (val == 0)
  if (val == 0)
    ref_table->remove (obj);
    ref_table->remove (obj);
  else
  else
    // FIXME: what about out of memory error?
    // FIXME: what about out of memory error?
    ref_table->put (obj, new Integer (val));
    ref_table->put (obj, new Integer (val));
}
}
 
 
// "Unwrap" some random non-reference type.  This exists to simplify
// "Unwrap" some random non-reference type.  This exists to simplify
// other template functions.
// other template functions.
template<typename T>
template<typename T>
static T
static T
unwrap (T val)
unwrap (T val)
{
{
  return val;
  return val;
}
}
 
 
// Unwrap a weak reference, if required.
// Unwrap a weak reference, if required.
template<typename T>
template<typename T>
static T *
static T *
unwrap (T *obj)
unwrap (T *obj)
{
{
  using namespace gnu::gcj::runtime;
  using namespace gnu::gcj::runtime;
  // We can compare the class directly because JNIWeakRef is `final'.
  // We can compare the class directly because JNIWeakRef is `final'.
  // Doing it this way is much faster.
  // Doing it this way is much faster.
  if (obj == NULL || obj->getClass () != &JNIWeakRef::class$)
  if (obj == NULL || obj->getClass () != &JNIWeakRef::class$)
    return obj;
    return obj;
  JNIWeakRef *wr = reinterpret_cast<JNIWeakRef *> (obj);
  JNIWeakRef *wr = reinterpret_cast<JNIWeakRef *> (obj);
  return reinterpret_cast<T *> (wr->get ());
  return reinterpret_cast<T *> (wr->get ());
}
}
 
 
jobject
jobject
_Jv_UnwrapJNIweakReference (jobject obj)
_Jv_UnwrapJNIweakReference (jobject obj)
{
{
  return unwrap (obj);
  return unwrap (obj);
}
}
 
 


 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
_Jv_JNI_NewGlobalRef (JNIEnv *, jobject obj)
{
{
  // This seems weird but I think it is correct.
  // This seems weird but I think it is correct.
  obj = unwrap (obj);
  obj = unwrap (obj);
  mark_for_gc (obj, global_ref_table);
  mark_for_gc (obj, global_ref_table);
  return obj;
  return obj;
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
_Jv_JNI_DeleteGlobalRef (JNIEnv *, jobject obj)
{
{
  // This seems weird but I think it is correct.
  // This seems weird but I think it is correct.
  obj = unwrap (obj);
  obj = unwrap (obj);
 
 
  // NULL is ok here -- the JNI specification doesn't say so, but this
  // NULL is ok here -- the JNI specification doesn't say so, but this
  // is a no-op.
  // is a no-op.
  if (! obj)
  if (! obj)
    return;
    return;
 
 
  unmark_for_gc (obj, global_ref_table);
  unmark_for_gc (obj, global_ref_table);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
_Jv_JNI_DeleteLocalRef (JNIEnv *env, jobject obj)
{
{
  _Jv_JNI_LocalFrame *frame;
  _Jv_JNI_LocalFrame *frame;
 
 
  // This seems weird but I think it is correct.
  // This seems weird but I think it is correct.
  obj = unwrap (obj);
  obj = unwrap (obj);
 
 
  // NULL is ok here -- the JNI specification doesn't say so, but this
  // NULL is ok here -- the JNI specification doesn't say so, but this
  // is a no-op.
  // is a no-op.
  if (! obj)
  if (! obj)
    return;
    return;
 
 
  for (frame = env->locals; frame != NULL; frame = frame->next)
  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)
          if (frame->vec[i] == obj)
            {
            {
              frame->vec[i] = NULL;
              frame->vec[i] = NULL;
              unmark_for_gc (obj, local_ref_table);
              unmark_for_gc (obj, local_ref_table);
              return;
              return;
            }
            }
        }
        }
 
 
      // Don't go past a marked frame.
      // Don't go past a marked frame.
      JvAssert (frame->marker == MARK_NONE);
      JvAssert (frame->marker == MARK_NONE);
    }
    }
 
 
  JvAssert (0);
  JvAssert (0);
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
_Jv_JNI_EnsureLocalCapacity (JNIEnv *env, jint size)
{
{
  // It is easier to just always allocate a new frame of the requested
  // It is easier to just always allocate a new frame of the requested
  // size.  This isn't the most efficient thing, but for now we don't
  // size.  This isn't the most efficient thing, but for now we don't
  // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
  // care.  Note that _Jv_JNI_PushLocalFrame relies on this right now.
 
 
  _Jv_JNI_LocalFrame *frame;
  _Jv_JNI_LocalFrame *frame;
  try
  try
    {
    {
      frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame)
      frame = (_Jv_JNI_LocalFrame *) _Jv_Malloc (sizeof (_Jv_JNI_LocalFrame)
                                                 + size * sizeof (jobject));
                                                 + size * sizeof (jobject));
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return JNI_ERR;
      return JNI_ERR;
    }
    }
 
 
  frame->marker = MARK_NONE;
  frame->marker = MARK_NONE;
  frame->size = size;
  frame->size = size;
  frame->allocated_p = false;
  frame->allocated_p = false;
  memset (&frame->vec[0], 0, size * sizeof (jobject));
  memset (&frame->vec[0], 0, size * sizeof (jobject));
  frame->loader = env->locals->loader;
  frame->loader = env->locals->loader;
  frame->next = env->locals;
  frame->next = env->locals;
  env->locals = frame;
  env->locals = frame;
 
 
  return 0;
  return 0;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
_Jv_JNI_PushLocalFrame (JNIEnv *env, jint size)
{
{
  jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
  jint r = _Jv_JNI_EnsureLocalCapacity (env, size);
  if (r < 0)
  if (r < 0)
    return r;
    return r;
 
 
  // The new frame is on top.
  // The new frame is on top.
  env->locals->marker = MARK_USER;
  env->locals->marker = MARK_USER;
 
 
  return 0;
  return 0;
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
_Jv_JNI_NewLocalRef (JNIEnv *env, jobject obj)
{
{
  // This seems weird but I think it is correct.
  // This seems weird but I think it is correct.
  obj = unwrap (obj);
  obj = unwrap (obj);
 
 
  // Try to find an open slot somewhere in the topmost frame.
  // Try to find an open slot somewhere in the topmost frame.
  _Jv_JNI_LocalFrame *frame = env->locals;
  _Jv_JNI_LocalFrame *frame = env->locals;
  bool done = false, set = false;
  bool done = false, set = false;
  for (; frame != NULL && ! done; frame = frame->next)
  for (; frame != NULL && ! done; frame = frame->next)
    {
    {
      for (int i = 0; i < frame->size; ++i)
      for (int i = 0; i < frame->size; ++i)
        {
        {
          if (frame->vec[i] == NULL)
          if (frame->vec[i] == NULL)
            {
            {
              set = true;
              set = true;
              done = true;
              done = true;
              frame->vec[i] = obj;
              frame->vec[i] = obj;
              frame->allocated_p = true;
              frame->allocated_p = true;
              break;
              break;
            }
            }
        }
        }
 
 
      // If we found a slot, or if the frame we just searched is the
      // If we found a slot, or if the frame we just searched is the
      // mark frame, then we are done.
      // mark frame, then we are done.
      if (done || frame == NULL || frame->marker != MARK_NONE)
      if (done || frame == NULL || frame->marker != MARK_NONE)
        break;
        break;
    }
    }
 
 
  if (! set)
  if (! set)
    {
    {
      // No slots, so we allocate a new frame.  According to the spec
      // No slots, so we allocate a new frame.  According to the spec
      // we could just die here.  FIXME: return value.
      // we could just die here.  FIXME: return value.
      _Jv_JNI_EnsureLocalCapacity (env, 16);
      _Jv_JNI_EnsureLocalCapacity (env, 16);
      // We know the first element of the new frame will be ok.
      // We know the first element of the new frame will be ok.
      env->locals->vec[0] = obj;
      env->locals->vec[0] = obj;
      env->locals->allocated_p = true;
      env->locals->allocated_p = true;
    }
    }
 
 
  mark_for_gc (obj, local_ref_table);
  mark_for_gc (obj, local_ref_table);
  return obj;
  return obj;
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result, int stop)
{
{
  _Jv_JNI_LocalFrame *rf = env->locals;
  _Jv_JNI_LocalFrame *rf = env->locals;
 
 
  bool done = false;
  bool done = false;
  while (rf != NULL && ! done)
  while (rf != NULL && ! done)
    {
    {
      for (int i = 0; i < rf->size; ++i)
      for (int i = 0; i < rf->size; ++i)
        if (rf->vec[i] != NULL)
        if (rf->vec[i] != NULL)
          unmark_for_gc (rf->vec[i], local_ref_table);
          unmark_for_gc (rf->vec[i], local_ref_table);
 
 
      // If the frame we just freed is the marker frame, we are done.
      // If the frame we just freed is the marker frame, we are done.
      done = (rf->marker == stop);
      done = (rf->marker == stop);
 
 
      _Jv_JNI_LocalFrame *n = rf->next;
      _Jv_JNI_LocalFrame *n = rf->next;
      // When N==NULL, we've reached the reusable bottom_locals, and we must
      // 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.
      // not free it.  However, we must be sure to clear all its elements.
      if (n == NULL)
      if (n == NULL)
        {
        {
          if (rf->allocated_p)
          if (rf->allocated_p)
            memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
            memset (&rf->vec[0], 0, rf->size * sizeof (jobject));
          rf->allocated_p = false;
          rf->allocated_p = false;
          rf = NULL;
          rf = NULL;
          break;
          break;
        }
        }
 
 
      _Jv_Free (rf);
      _Jv_Free (rf);
      rf = n;
      rf = n;
    }
    }
 
 
  // Update the local frame information.
  // Update the local frame information.
  env->locals = rf;
  env->locals = rf;
 
 
  return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
  return result == NULL ? NULL : _Jv_JNI_NewLocalRef (env, result);
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
_Jv_JNI_PopLocalFrame (JNIEnv *env, jobject result)
{
{
  return _Jv_JNI_PopLocalFrame (env, result, MARK_USER);
  return _Jv_JNI_PopLocalFrame (env, result, MARK_USER);
}
}
 
 
// Make sure an array's type is compatible with the type of the
// Make sure an array's type is compatible with the type of the
// destination.
// destination.
template<typename T>
template<typename T>
static bool
static bool
_Jv_JNI_check_types (JNIEnv *env, JArray<T> *array, jclass K)
_Jv_JNI_check_types (JNIEnv *env, JArray<T> *array, jclass K)
{
{
  jclass klass = array->getClass()->getComponentType();
  jclass klass = array->getClass()->getComponentType();
  if (__builtin_expect (klass != K, false))
  if (__builtin_expect (klass != K, false))
    {
    {
      env->ex = new java::lang::IllegalAccessError ();
      env->ex = new java::lang::IllegalAccessError ();
      return false;
      return false;
    }
    }
  else
  else
    return true;
    return true;
}
}
 
 
// Pop a `system' frame from the stack.  This is `extern "C"' as it is
// Pop a `system' frame from the stack.  This is `extern "C"' as it is
// used by the compiler.
// used by the compiler.
extern "C" void
extern "C" void
_Jv_JNI_PopSystemFrame (JNIEnv *env)
_Jv_JNI_PopSystemFrame (JNIEnv *env)
{
{
  // Only enter slow path when we're not at the bottom, or there have been
  // 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
  // allocations. Usually this is false and we can just null out the locals
  // field.
  // field.
 
 
  if (__builtin_expect ((env->locals->next
  if (__builtin_expect ((env->locals->next
                         || env->locals->allocated_p), false))
                         || env->locals->allocated_p), false))
    _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
    _Jv_JNI_PopLocalFrame (env, NULL, MARK_SYSTEM);
  else
  else
    env->locals = NULL;
    env->locals = NULL;
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
  if (__builtin_expect (env->ex != NULL, false))
  if (__builtin_expect (env->ex != NULL, false))
    {
    {
      jthrowable t = env->ex;
      jthrowable t = env->ex;
      env->ex = NULL;
      env->ex = NULL;
      if (JVMTI_REQUESTED_EVENT (Exception))
      if (JVMTI_REQUESTED_EVENT (Exception))
        _Jv_ReportJVMTIExceptionThrow (t);
        _Jv_ReportJVMTIExceptionThrow (t);
      throw t;
      throw t;
    }
    }
#endif
#endif
}
}
 
 
template<typename T> T extract_from_jvalue(jvalue const & t);
template<typename T> T extract_from_jvalue(jvalue const & t);
template<> jboolean extract_from_jvalue(jvalue const & jv) { return jv.z; }
template<> jboolean extract_from_jvalue(jvalue const & jv) { return jv.z; }
template<> jbyte    extract_from_jvalue(jvalue const & jv) { return jv.b; }
template<> jbyte    extract_from_jvalue(jvalue const & jv) { return jv.b; }
template<> jchar    extract_from_jvalue(jvalue const & jv) { return jv.c; }
template<> jchar    extract_from_jvalue(jvalue const & jv) { return jv.c; }
template<> jshort   extract_from_jvalue(jvalue const & jv) { return jv.s; }
template<> jshort   extract_from_jvalue(jvalue const & jv) { return jv.s; }
template<> jint     extract_from_jvalue(jvalue const & jv) { return jv.i; }
template<> jint     extract_from_jvalue(jvalue const & jv) { return jv.i; }
template<> jlong    extract_from_jvalue(jvalue const & jv) { return jv.j; }
template<> jlong    extract_from_jvalue(jvalue const & jv) { return jv.j; }
template<> jfloat   extract_from_jvalue(jvalue const & jv) { return jv.f; }
template<> jfloat   extract_from_jvalue(jvalue const & jv) { return jv.f; }
template<> jdouble  extract_from_jvalue(jvalue const & jv) { return jv.d; }
template<> jdouble  extract_from_jvalue(jvalue const & jv) { return jv.d; }
template<> jobject  extract_from_jvalue(jvalue const & jv) { return jv.l; }
template<> jobject  extract_from_jvalue(jvalue const & jv) { return jv.l; }
 
 
 
 
// This function is used from other template functions.  It wraps the
// This function is used from other template functions.  It wraps the
// return value appropriately; we specialize it so that object returns
// return value appropriately; we specialize it so that object returns
// are turned into local references.
// are turned into local references.
template<typename T>
template<typename T>
static T
static T
wrap_value (JNIEnv *, T value)
wrap_value (JNIEnv *, T value)
{
{
  return value;
  return value;
}
}
 
 
// This specialization is used for jobject, jclass, jstring, jarray,
// This specialization is used for jobject, jclass, jstring, jarray,
// etc.
// etc.
template<typename R, typename T>
template<typename R, typename T>
static T *
static T *
wrap_value (JNIEnv *env, T *value)
wrap_value (JNIEnv *env, T *value)
{
{
  return (value == NULL
  return (value == NULL
          ? value
          ? value
          : (T *) _Jv_JNI_NewLocalRef (env, (jobject) value));
          : (T *) _Jv_JNI_NewLocalRef (env, (jobject) value));
}
}
 
 


 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_GetVersion (JNIEnv *)
_Jv_JNI_GetVersion (JNIEnv *)
{
{
  return JNI_VERSION_1_4;
  return JNI_VERSION_1_4;
}
}
 
 
static jclass JNICALL
static jclass JNICALL
_Jv_JNI_DefineClass (JNIEnv *env, const char *name, jobject loader,
_Jv_JNI_DefineClass (JNIEnv *env, const char *name, jobject loader,
                     const jbyte *buf, jsize bufLen)
                     const jbyte *buf, jsize bufLen)
{
{
  try
  try
    {
    {
      loader = unwrap (loader);
      loader = unwrap (loader);
 
 
      jstring sname = JvNewStringUTF (name);
      jstring sname = JvNewStringUTF (name);
      jbyteArray bytes = JvNewByteArray (bufLen);
      jbyteArray bytes = JvNewByteArray (bufLen);
 
 
      jbyte *elts = elements (bytes);
      jbyte *elts = elements (bytes);
      memcpy (elts, buf, bufLen * sizeof (jbyte));
      memcpy (elts, buf, bufLen * sizeof (jbyte));
 
 
      java::lang::ClassLoader *l
      java::lang::ClassLoader *l
        = reinterpret_cast<java::lang::ClassLoader *> (loader);
        = reinterpret_cast<java::lang::ClassLoader *> (loader);
 
 
      jclass result = l->defineClass (sname, bytes, 0, bufLen);
      jclass result = l->defineClass (sname, bytes, 0, bufLen);
      return (jclass) wrap_value (env, result);
      return (jclass) wrap_value (env, result);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return NULL;
      return NULL;
    }
    }
}
}
 
 
static jclass JNICALL
static jclass JNICALL
_Jv_JNI_FindClass (JNIEnv *env, const char *name)
_Jv_JNI_FindClass (JNIEnv *env, const char *name)
{
{
  // FIXME: assume that NAME isn't too long.
  // FIXME: assume that NAME isn't too long.
  int len = strlen (name);
  int len = strlen (name);
  char s[len + 1];
  char s[len + 1];
  for (int i = 0; i <= len; ++i)
  for (int i = 0; i <= len; ++i)
    s[i] = (name[i] == '/') ? '.' : name[i];
    s[i] = (name[i] == '/') ? '.' : name[i];
 
 
  jclass r = NULL;
  jclass r = NULL;
  try
  try
    {
    {
      // This might throw an out of memory exception.
      // This might throw an out of memory exception.
      jstring n = JvNewStringUTF (s);
      jstring n = JvNewStringUTF (s);
 
 
      java::lang::ClassLoader *loader = NULL;
      java::lang::ClassLoader *loader = NULL;
      if (env->locals->loader != NULL)
      if (env->locals->loader != NULL)
        loader = env->locals->loader;
        loader = env->locals->loader;
 
 
      if (loader == NULL)
      if (loader == NULL)
        {
        {
          // FIXME: should use getBaseClassLoader, but we don't have that
          // FIXME: should use getBaseClassLoader, but we don't have that
          // yet.
          // yet.
          loader = java::lang::ClassLoader::getSystemClassLoader ();
          loader = java::lang::ClassLoader::getSystemClassLoader ();
        }
        }
 
 
      r = loader->loadClass (n);
      r = loader->loadClass (n);
      _Jv_InitClass (r);
      _Jv_InitClass (r);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return (jclass) wrap_value (env, r);
  return (jclass) wrap_value (env, r);
}
}
 
 
static jclass JNICALL
static jclass JNICALL
_Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
_Jv_JNI_GetSuperclass (JNIEnv *env, jclass clazz)
{
{
  return (jclass) wrap_value (env, unwrap (clazz)->getSuperclass ());
  return (jclass) wrap_value (env, unwrap (clazz)->getSuperclass ());
}
}
 
 
static jboolean JNICALL
static jboolean JNICALL
_Jv_JNI_IsAssignableFrom (JNIEnv *, jclass clazz1, jclass clazz2)
_Jv_JNI_IsAssignableFrom (JNIEnv *, jclass clazz1, jclass clazz2)
{
{
  return unwrap (clazz2)->isAssignableFrom (unwrap (clazz1));
  return unwrap (clazz2)->isAssignableFrom (unwrap (clazz1));
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
_Jv_JNI_Throw (JNIEnv *env, jthrowable obj)
{
{
  // We check in case the user did some funky cast.
  // We check in case the user did some funky cast.
  obj = unwrap (obj);
  obj = unwrap (obj);
  JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
  JvAssert (obj != NULL && java::lang::Throwable::class$.isInstance (obj));
  env->ex = obj;
  env->ex = obj;
  return 0;
  return 0;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
_Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
{
{
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
 
 
  clazz = unwrap (clazz);
  clazz = unwrap (clazz);
  JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
  JvAssert (java::lang::Throwable::class$.isAssignableFrom (clazz));
 
 
  int r = JNI_OK;
  int r = JNI_OK;
  try
  try
    {
    {
      JArray<jclass> *argtypes
      JArray<jclass> *argtypes
        = (JArray<jclass> *) JvNewObjectArray (1, &java::lang::Class::class$,
        = (JArray<jclass> *) JvNewObjectArray (1, &java::lang::Class::class$,
                                               NULL);
                                               NULL);
 
 
      jclass *elts = elements (argtypes);
      jclass *elts = elements (argtypes);
      elts[0] = &java::lang::String::class$;
      elts[0] = &java::lang::String::class$;
 
 
      Constructor *cons = clazz->getConstructor (argtypes);
      Constructor *cons = clazz->getConstructor (argtypes);
 
 
      jobjectArray values = JvNewObjectArray (1, &java::lang::String::class$,
      jobjectArray values = JvNewObjectArray (1, &java::lang::String::class$,
                                              NULL);
                                              NULL);
      jobject *velts = elements (values);
      jobject *velts = elements (values);
      velts[0] = JvNewStringUTF (message);
      velts[0] = JvNewStringUTF (message);
 
 
      jobject obj = cons->newInstance (values);
      jobject obj = cons->newInstance (values);
 
 
      env->ex = reinterpret_cast<jthrowable> (obj);
      env->ex = reinterpret_cast<jthrowable> (obj);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      r = JNI_ERR;
      r = JNI_ERR;
    }
    }
 
 
  return r;
  return r;
}
}
 
 
static jthrowable JNICALL
static jthrowable JNICALL
_Jv_JNI_ExceptionOccurred (JNIEnv *env)
_Jv_JNI_ExceptionOccurred (JNIEnv *env)
{
{
  return (jthrowable) wrap_value (env, env->ex);
  return (jthrowable) wrap_value (env, env->ex);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_ExceptionDescribe (JNIEnv *env)
_Jv_JNI_ExceptionDescribe (JNIEnv *env)
{
{
  if (env->ex != NULL)
  if (env->ex != NULL)
    env->ex->printStackTrace();
    env->ex->printStackTrace();
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_ExceptionClear (JNIEnv *env)
_Jv_JNI_ExceptionClear (JNIEnv *env)
{
{
  env->ex = NULL;
  env->ex = NULL;
}
}
 
 
static jboolean JNICALL
static jboolean JNICALL
_Jv_JNI_ExceptionCheck (JNIEnv *env)
_Jv_JNI_ExceptionCheck (JNIEnv *env)
{
{
  return env->ex != NULL;
  return env->ex != NULL;
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_FatalError (JNIEnv *, const char *message)
_Jv_JNI_FatalError (JNIEnv *, const char *message)
{
{
  JvFail (message);
  JvFail (message);
}
}
 
 


 
 
static jboolean JNICALL
static jboolean JNICALL
_Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
_Jv_JNI_IsSameObject (JNIEnv *, jobject obj1, jobject obj2)
{
{
  return unwrap (obj1) == unwrap (obj2);
  return unwrap (obj1) == unwrap (obj2);
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
_Jv_JNI_AllocObject (JNIEnv *env, jclass clazz)
{
{
  jobject obj = NULL;
  jobject obj = NULL;
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
 
 
  try
  try
    {
    {
      clazz = unwrap (clazz);
      clazz = unwrap (clazz);
      JvAssert (clazz && ! clazz->isArray ());
      JvAssert (clazz && ! clazz->isArray ());
      if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
      if (clazz->isInterface() || Modifier::isAbstract(clazz->getModifiers()))
        env->ex = new java::lang::InstantiationException ();
        env->ex = new java::lang::InstantiationException ();
      else
      else
        obj = _Jv_AllocObject (clazz);
        obj = _Jv_AllocObject (clazz);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return wrap_value (env, obj);
  return wrap_value (env, obj);
}
}
 
 
static jclass JNICALL
static jclass JNICALL
_Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
_Jv_JNI_GetObjectClass (JNIEnv *env, jobject obj)
{
{
  obj = unwrap (obj);
  obj = unwrap (obj);
  JvAssert (obj);
  JvAssert (obj);
  return (jclass) wrap_value (env, obj->getClass());
  return (jclass) wrap_value (env, obj->getClass());
}
}
 
 
static jboolean JNICALL
static jboolean JNICALL
_Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
_Jv_JNI_IsInstanceOf (JNIEnv *, jobject obj, jclass clazz)
{
{
  return unwrap (clazz)->isInstance(unwrap (obj));
  return unwrap (clazz)->isInstance(unwrap (obj));
}
}
 
 


 
 
//
//
// This section concerns method invocation.
// This section concerns method invocation.
//
//
 
 
template<jboolean is_static>
template<jboolean is_static>
static jmethodID JNICALL
static jmethodID JNICALL
_Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
_Jv_JNI_GetAnyMethodID (JNIEnv *env, jclass clazz,
                        const char *name, const char *sig)
                        const char *name, const char *sig)
{
{
  try
  try
    {
    {
      clazz = unwrap (clazz);
      clazz = unwrap (clazz);
      _Jv_InitClass (clazz);
      _Jv_InitClass (clazz);
 
 
      _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
      _Jv_Utf8Const *name_u = _Jv_makeUtf8Const ((char *) name, -1);
 
 
      // FIXME: assume that SIG isn't too long.
      // FIXME: assume that SIG isn't too long.
      int len = strlen (sig);
      int len = strlen (sig);
      char s[len + 1];
      char s[len + 1];
      for (int i = 0; i <= len; ++i)
      for (int i = 0; i <= len; ++i)
        s[i] = (sig[i] == '/') ? '.' : sig[i];
        s[i] = (sig[i] == '/') ? '.' : sig[i];
      _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) s, -1);
      _Jv_Utf8Const *sig_u = _Jv_makeUtf8Const ((char *) s, -1);
 
 
      JvAssert (! clazz->isPrimitive());
      JvAssert (! clazz->isPrimitive());
 
 
      using namespace java::lang::reflect;
      using namespace java::lang::reflect;
 
 
      while (clazz != NULL)
      while (clazz != NULL)
        {
        {
          jint count = JvNumMethods (clazz);
          jint count = JvNumMethods (clazz);
          jmethodID meth = JvGetFirstMethod (clazz);
          jmethodID meth = JvGetFirstMethod (clazz);
 
 
          for (jint i = 0; i < count; ++i)
          for (jint i = 0; i < count; ++i)
            {
            {
              if (((is_static && Modifier::isStatic (meth->accflags))
              if (((is_static && Modifier::isStatic (meth->accflags))
                   || (! is_static && ! Modifier::isStatic (meth->accflags)))
                   || (! is_static && ! Modifier::isStatic (meth->accflags)))
                  && _Jv_equalUtf8Consts (meth->name, name_u)
                  && _Jv_equalUtf8Consts (meth->name, name_u)
                  && _Jv_equalUtf8Consts (meth->signature, sig_u))
                  && _Jv_equalUtf8Consts (meth->signature, sig_u))
                return meth;
                return meth;
 
 
              meth = meth->getNextMethod();
              meth = meth->getNextMethod();
            }
            }
 
 
          clazz = clazz->getSuperclass ();
          clazz = clazz->getSuperclass ();
        }
        }
 
 
      java::lang::StringBuffer *name_sig =
      java::lang::StringBuffer *name_sig =
        new java::lang::StringBuffer (JvNewStringUTF (name));
        new java::lang::StringBuffer (JvNewStringUTF (name));
      name_sig->append ((jchar) ' ');
      name_sig->append ((jchar) ' ');
      name_sig->append (JvNewStringUTF (s));
      name_sig->append (JvNewStringUTF (s));
      env->ex = new java::lang::NoSuchMethodError (name_sig->toString ());
      env->ex = new java::lang::NoSuchMethodError (name_sig->toString ());
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return NULL;
  return NULL;
}
}
 
 
// This is a helper function which turns a va_list into an array of
// This is a helper function which turns a va_list into an array of
// `jvalue's.  It needs signature information in order to do its work.
// `jvalue's.  It needs signature information in order to do its work.
// The array of values must already be allocated.
// The array of values must already be allocated.
static void
static void
array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
array_from_valist (jvalue *values, JArray<jclass> *arg_types, va_list vargs)
{
{
  jclass *arg_elts = elements (arg_types);
  jclass *arg_elts = elements (arg_types);
  for (int i = 0; i < arg_types->length; ++i)
  for (int i = 0; i < arg_types->length; ++i)
    {
    {
      // Here we assume that sizeof(int) >= sizeof(jint), because we
      // Here we assume that sizeof(int) >= sizeof(jint), because we
      // use `int' when decoding the varargs.  Likewise for
      // use `int' when decoding the varargs.  Likewise for
      // float, and double.  Also we assume that sizeof(jlong) >=
      // float, and double.  Also we assume that sizeof(jlong) >=
      // sizeof(int), i.e. that jlong values are not further
      // sizeof(int), i.e. that jlong values are not further
      // promoted.
      // promoted.
      JvAssert (sizeof (int) >= sizeof (jint));
      JvAssert (sizeof (int) >= sizeof (jint));
      JvAssert (sizeof (jlong) >= sizeof (int));
      JvAssert (sizeof (jlong) >= sizeof (int));
      JvAssert (sizeof (double) >= sizeof (jfloat));
      JvAssert (sizeof (double) >= sizeof (jfloat));
      JvAssert (sizeof (double) >= sizeof (jdouble));
      JvAssert (sizeof (double) >= sizeof (jdouble));
      if (arg_elts[i] == JvPrimClass (byte))
      if (arg_elts[i] == JvPrimClass (byte))
        values[i].b = (jbyte) va_arg (vargs, int);
        values[i].b = (jbyte) va_arg (vargs, int);
      else if (arg_elts[i] == JvPrimClass (short))
      else if (arg_elts[i] == JvPrimClass (short))
        values[i].s = (jshort) va_arg (vargs, int);
        values[i].s = (jshort) va_arg (vargs, int);
      else if (arg_elts[i] == JvPrimClass (int))
      else if (arg_elts[i] == JvPrimClass (int))
        values[i].i = (jint) va_arg (vargs, int);
        values[i].i = (jint) va_arg (vargs, int);
      else if (arg_elts[i] == JvPrimClass (long))
      else if (arg_elts[i] == JvPrimClass (long))
        values[i].j = (jlong) va_arg (vargs, jlong);
        values[i].j = (jlong) va_arg (vargs, jlong);
      else if (arg_elts[i] == JvPrimClass (float))
      else if (arg_elts[i] == JvPrimClass (float))
        values[i].f = (jfloat) va_arg (vargs, double);
        values[i].f = (jfloat) va_arg (vargs, double);
      else if (arg_elts[i] == JvPrimClass (double))
      else if (arg_elts[i] == JvPrimClass (double))
        values[i].d = (jdouble) va_arg (vargs, double);
        values[i].d = (jdouble) va_arg (vargs, double);
      else if (arg_elts[i] == JvPrimClass (boolean))
      else if (arg_elts[i] == JvPrimClass (boolean))
        values[i].z = (jboolean) va_arg (vargs, int);
        values[i].z = (jboolean) va_arg (vargs, int);
      else if (arg_elts[i] == JvPrimClass (char))
      else if (arg_elts[i] == JvPrimClass (char))
        values[i].c = (jchar) va_arg (vargs, int);
        values[i].c = (jchar) va_arg (vargs, int);
      else
      else
        {
        {
          // An object.
          // An object.
          values[i].l = unwrap (va_arg (vargs, jobject));
          values[i].l = unwrap (va_arg (vargs, jobject));
        }
        }
    }
    }
}
}
 
 
// This can call any sort of method: virtual, "nonvirtual", static, or
// This can call any sort of method: virtual, "nonvirtual", static, or
// constructor.
// constructor.
template<typename T, invocation_type style>
template<typename T, invocation_type style>
static T JNICALL
static T JNICALL
_Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
_Jv_JNI_CallAnyMethodV (JNIEnv *env, jobject obj, jclass klass,
                        jmethodID id, va_list vargs)
                        jmethodID id, va_list vargs)
{
{
  obj = unwrap (obj);
  obj = unwrap (obj);
  klass = unwrap (klass);
  klass = unwrap (klass);
 
 
  jclass decl_class = klass ? klass : obj->getClass ();
  jclass decl_class = klass ? klass : obj->getClass ();
  JvAssert (decl_class != NULL);
  JvAssert (decl_class != NULL);
 
 
  jclass return_type;
  jclass return_type;
  JArray<jclass> *arg_types;
  JArray<jclass> *arg_types;
 
 
  try
  try
    {
    {
      _Jv_GetTypesFromSignature (id, decl_class,
      _Jv_GetTypesFromSignature (id, decl_class,
                                 &arg_types, &return_type);
                                 &arg_types, &return_type);
 
 
      jvalue args[arg_types->length];
      jvalue args[arg_types->length];
      array_from_valist (args, arg_types, vargs);
      array_from_valist (args, arg_types, vargs);
 
 
      // For constructors we need to pass the Class we are instantiating.
      // For constructors we need to pass the Class we are instantiating.
      if (style == constructor)
      if (style == constructor)
        return_type = klass;
        return_type = klass;
 
 
      jvalue result;
      jvalue result;
      _Jv_CallAnyMethodA (obj, return_type, id,
      _Jv_CallAnyMethodA (obj, return_type, id,
                          style == constructor,
                          style == constructor,
                          style == normal,
                          style == normal,
                          arg_types, args, &result);
                          arg_types, args, &result);
 
 
      return wrap_value (env, extract_from_jvalue<T>(result));
      return wrap_value (env, extract_from_jvalue<T>(result));
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return wrap_value (env, (T) 0);
  return wrap_value (env, (T) 0);
}
}
 
 
template<typename T, invocation_type style>
template<typename T, invocation_type style>
static T JNICALL
static T JNICALL
_Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
_Jv_JNI_CallAnyMethod (JNIEnv *env, jobject obj, jclass klass,
                       jmethodID method, ...)
                       jmethodID method, ...)
{
{
  va_list args;
  va_list args;
  T result;
  T result;
 
 
  va_start (args, method);
  va_start (args, method);
  result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
  result = _Jv_JNI_CallAnyMethodV<T, style> (env, obj, klass, method, args);
  va_end (args);
  va_end (args);
 
 
  return result;
  return result;
}
}
 
 
template<typename T, invocation_type style>
template<typename T, invocation_type style>
static T JNICALL
static T JNICALL
_Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
_Jv_JNI_CallAnyMethodA (JNIEnv *env, jobject obj, jclass klass,
                        jmethodID id, const jvalue *args)
                        jmethodID id, const jvalue *args)
{
{
  obj = unwrap (obj);
  obj = unwrap (obj);
  klass = unwrap (klass);
  klass = unwrap (klass);
 
 
  jclass decl_class = klass ? klass : obj->getClass ();
  jclass decl_class = klass ? klass : obj->getClass ();
  JvAssert (decl_class != NULL);
  JvAssert (decl_class != NULL);
 
 
  jclass return_type;
  jclass return_type;
  JArray<jclass> *arg_types;
  JArray<jclass> *arg_types;
  try
  try
    {
    {
      _Jv_GetTypesFromSignature (id, decl_class,
      _Jv_GetTypesFromSignature (id, decl_class,
                                 &arg_types, &return_type);
                                 &arg_types, &return_type);
 
 
      // For constructors we need to pass the Class we are instantiating.
      // For constructors we need to pass the Class we are instantiating.
      if (style == constructor)
      if (style == constructor)
        return_type = klass;
        return_type = klass;
 
 
      // Unwrap arguments as required.  Eww.
      // Unwrap arguments as required.  Eww.
      jclass *type_elts = elements (arg_types);
      jclass *type_elts = elements (arg_types);
      jvalue arg_copy[arg_types->length];
      jvalue arg_copy[arg_types->length];
      for (int i = 0; i < arg_types->length; ++i)
      for (int i = 0; i < arg_types->length; ++i)
        {
        {
          if (type_elts[i]->isPrimitive ())
          if (type_elts[i]->isPrimitive ())
            arg_copy[i] = args[i];
            arg_copy[i] = args[i];
          else
          else
            arg_copy[i].l = unwrap (args[i].l);
            arg_copy[i].l = unwrap (args[i].l);
        }
        }
 
 
      jvalue result;
      jvalue result;
      _Jv_CallAnyMethodA (obj, return_type, id,
      _Jv_CallAnyMethodA (obj, return_type, id,
                          style == constructor,
                          style == constructor,
                          style == normal,
                          style == normal,
                          arg_types, arg_copy, &result);
                          arg_types, arg_copy, &result);
 
 
      return wrap_value (env, extract_from_jvalue<T>(result));
      return wrap_value (env, extract_from_jvalue<T>(result));
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return wrap_value (env, (T) 0);
  return wrap_value (env, (T) 0);
}
}
 
 
template<invocation_type style>
template<invocation_type style>
static void JNICALL
static void JNICALL
_Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
_Jv_JNI_CallAnyVoidMethodV (JNIEnv *env, jobject obj, jclass klass,
                            jmethodID id, va_list vargs)
                            jmethodID id, va_list vargs)
{
{
  obj = unwrap (obj);
  obj = unwrap (obj);
  klass = unwrap (klass);
  klass = unwrap (klass);
 
 
  jclass decl_class = klass ? klass : obj->getClass ();
  jclass decl_class = klass ? klass : obj->getClass ();
  JvAssert (decl_class != NULL);
  JvAssert (decl_class != NULL);
 
 
  jclass return_type;
  jclass return_type;
  JArray<jclass> *arg_types;
  JArray<jclass> *arg_types;
  try
  try
    {
    {
      _Jv_GetTypesFromSignature (id, decl_class,
      _Jv_GetTypesFromSignature (id, decl_class,
                                 &arg_types, &return_type);
                                 &arg_types, &return_type);
 
 
      jvalue args[arg_types->length];
      jvalue args[arg_types->length];
      array_from_valist (args, arg_types, vargs);
      array_from_valist (args, arg_types, vargs);
 
 
      // For constructors we need to pass the Class we are instantiating.
      // For constructors we need to pass the Class we are instantiating.
      if (style == constructor)
      if (style == constructor)
        return_type = klass;
        return_type = klass;
 
 
      _Jv_CallAnyMethodA (obj, return_type, id,
      _Jv_CallAnyMethodA (obj, return_type, id,
                          style == constructor,
                          style == constructor,
                          style == normal,
                          style == normal,
                          arg_types, args, NULL);
                          arg_types, args, NULL);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
}
}
 
 
template<invocation_type style>
template<invocation_type style>
static void JNICALL
static void JNICALL
_Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
_Jv_JNI_CallAnyVoidMethod (JNIEnv *env, jobject obj, jclass klass,
                           jmethodID method, ...)
                           jmethodID method, ...)
{
{
  va_list args;
  va_list args;
 
 
  va_start (args, method);
  va_start (args, method);
  _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
  _Jv_JNI_CallAnyVoidMethodV<style> (env, obj, klass, method, args);
  va_end (args);
  va_end (args);
}
}
 
 
template<invocation_type style>
template<invocation_type style>
static void JNICALL
static void JNICALL
_Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
_Jv_JNI_CallAnyVoidMethodA (JNIEnv *env, jobject obj, jclass klass,
                            jmethodID id, const jvalue *args)
                            jmethodID id, const jvalue *args)
{
{
  jclass decl_class = klass ? klass : obj->getClass ();
  jclass decl_class = klass ? klass : obj->getClass ();
  JvAssert (decl_class != NULL);
  JvAssert (decl_class != NULL);
 
 
  jclass return_type;
  jclass return_type;
  JArray<jclass> *arg_types;
  JArray<jclass> *arg_types;
  try
  try
    {
    {
      _Jv_GetTypesFromSignature (id, decl_class,
      _Jv_GetTypesFromSignature (id, decl_class,
                                 &arg_types, &return_type);
                                 &arg_types, &return_type);
 
 
      // Unwrap arguments as required.  Eww.
      // Unwrap arguments as required.  Eww.
      jclass *type_elts = elements (arg_types);
      jclass *type_elts = elements (arg_types);
      jvalue arg_copy[arg_types->length];
      jvalue arg_copy[arg_types->length];
      for (int i = 0; i < arg_types->length; ++i)
      for (int i = 0; i < arg_types->length; ++i)
        {
        {
          if (type_elts[i]->isPrimitive ())
          if (type_elts[i]->isPrimitive ())
            arg_copy[i] = args[i];
            arg_copy[i] = args[i];
          else
          else
            arg_copy[i].l = unwrap (args[i].l);
            arg_copy[i].l = unwrap (args[i].l);
        }
        }
 
 
      _Jv_CallAnyMethodA (obj, return_type, id,
      _Jv_CallAnyMethodA (obj, return_type, id,
                          style == constructor,
                          style == constructor,
                          style == normal,
                          style == normal,
                          arg_types, args, NULL);
                          arg_types, args, NULL);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
}
}
 
 
// Functions with this signature are used to implement functions in
// Functions with this signature are used to implement functions in
// the CallMethod family.
// the CallMethod family.
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_CallMethodV (JNIEnv *env, jobject obj,
_Jv_JNI_CallMethodV (JNIEnv *env, jobject obj,
                     jmethodID id, va_list args)
                     jmethodID id, va_list args)
{
{
  return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
  return _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
}
}
 
 
// Functions with this signature are used to implement functions in
// Functions with this signature are used to implement functions in
// the CallMethod family.
// the CallMethod family.
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
_Jv_JNI_CallMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
{
{
  va_list args;
  va_list args;
  T result;
  T result;
 
 
  va_start (args, id);
  va_start (args, id);
  result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
  result = _Jv_JNI_CallAnyMethodV<T, normal> (env, obj, NULL, id, args);
  va_end (args);
  va_end (args);
 
 
  return result;
  return result;
}
}
 
 
// Functions with this signature are used to implement functions in
// Functions with this signature are used to implement functions in
// the CallMethod family.
// the CallMethod family.
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_CallMethodA (JNIEnv *env, jobject obj,
_Jv_JNI_CallMethodA (JNIEnv *env, jobject obj,
                     jmethodID id, const jvalue *args)
                     jmethodID id, const jvalue *args)
{
{
  return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
  return _Jv_JNI_CallAnyMethodA<T, normal> (env, obj, NULL, id, args);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj,
_Jv_JNI_CallVoidMethodV (JNIEnv *env, jobject obj,
                         jmethodID id, va_list args)
                         jmethodID id, va_list args)
{
{
  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
_Jv_JNI_CallVoidMethod (JNIEnv *env, jobject obj, jmethodID id, ...)
{
{
  va_list args;
  va_list args;
 
 
  va_start (args, id);
  va_start (args, id);
  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
  _Jv_JNI_CallAnyVoidMethodV<normal> (env, obj, NULL, id, args);
  va_end (args);
  va_end (args);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj,
_Jv_JNI_CallVoidMethodA (JNIEnv *env, jobject obj,
                         jmethodID id, const jvalue *args)
                         jmethodID id, const jvalue *args)
{
{
  _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
  _Jv_JNI_CallAnyVoidMethodA<normal> (env, obj, NULL, id, args);
}
}
 
 
// Functions with this signature are used to implement functions in
// Functions with this signature are used to implement functions in
// the CallStaticMethod family.
// the CallStaticMethod family.
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
_Jv_JNI_CallStaticMethodV (JNIEnv *env, jclass klass,
                           jmethodID id, va_list args)
                           jmethodID id, va_list args)
{
{
  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
 
 
  return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
  return _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass, id, args);
}
}
 
 
// Functions with this signature are used to implement functions in
// Functions with this signature are used to implement functions in
// the CallStaticMethod family.
// the CallStaticMethod family.
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass,
_Jv_JNI_CallStaticMethod (JNIEnv *env, jclass klass,
                          jmethodID id, ...)
                          jmethodID id, ...)
{
{
  va_list args;
  va_list args;
  T result;
  T result;
 
 
  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
 
 
  va_start (args, id);
  va_start (args, id);
  result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
  result = _Jv_JNI_CallAnyMethodV<T, static_type> (env, NULL, klass,
                                                   id, args);
                                                   id, args);
  va_end (args);
  va_end (args);
 
 
  return result;
  return result;
}
}
 
 
// Functions with this signature are used to implement functions in
// Functions with this signature are used to implement functions in
// the CallStaticMethod family.
// the CallStaticMethod family.
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
_Jv_JNI_CallStaticMethodA (JNIEnv *env, jclass klass, jmethodID id,
                           const jvalue *args)
                           const jvalue *args)
{
{
  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
  JvAssert (((id->accflags) & java::lang::reflect::Modifier::STATIC));
  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
  JvAssert (java::lang::Class::class$.isInstance (unwrap (klass)));
 
 
  return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
  return _Jv_JNI_CallAnyMethodA<T, static_type> (env, NULL, klass, id, args);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass,
_Jv_JNI_CallStaticVoidMethodV (JNIEnv *env, jclass klass,
                               jmethodID id, va_list args)
                               jmethodID id, va_list args)
{
{
  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass,
_Jv_JNI_CallStaticVoidMethod (JNIEnv *env, jclass klass,
                              jmethodID id, ...)
                              jmethodID id, ...)
{
{
  va_list args;
  va_list args;
 
 
  va_start (args, id);
  va_start (args, id);
  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
  _Jv_JNI_CallAnyVoidMethodV<static_type> (env, NULL, klass, id, args);
  va_end (args);
  va_end (args);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass,
_Jv_JNI_CallStaticVoidMethodA (JNIEnv *env, jclass klass,
                               jmethodID id, const jvalue *args)
                               jmethodID id, const jvalue *args)
{
{
  _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
  _Jv_JNI_CallAnyVoidMethodA<static_type> (env, NULL, klass, id, args);
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
_Jv_JNI_NewObjectV (JNIEnv *env, jclass klass,
                    jmethodID id, va_list args)
                    jmethodID id, va_list args)
{
{
  JvAssert (klass && ! klass->isArray ());
  JvAssert (klass && ! klass->isArray ());
  JvAssert (! strcmp (id->name->chars(), "<init>")
  JvAssert (! strcmp (id->name->chars(), "<init>")
            && id->signature->len() > 2
            && id->signature->len() > 2
            && id->signature->chars()[0] == '('
            && id->signature->chars()[0] == '('
            && ! strcmp (&id->signature->chars()[id->signature->len() - 2],
            && ! strcmp (&id->signature->chars()[id->signature->len() - 2],
                         ")V"));
                         ")V"));
 
 
  return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
  return _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
                                                       id, args);
                                                       id, args);
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
_Jv_JNI_NewObject (JNIEnv *env, jclass klass, jmethodID id, ...)
{
{
  JvAssert (klass && ! klass->isArray ());
  JvAssert (klass && ! klass->isArray ());
  JvAssert (! strcmp (id->name->chars(), "<init>")
  JvAssert (! strcmp (id->name->chars(), "<init>")
            && id->signature->len() > 2
            && id->signature->len() > 2
            && id->signature->chars()[0] == '('
            && id->signature->chars()[0] == '('
            && ! strcmp (&id->signature->chars()[id->signature->len() - 2],
            && ! strcmp (&id->signature->chars()[id->signature->len() - 2],
                         ")V"));
                         ")V"));
 
 
  va_list args;
  va_list args;
  jobject result;
  jobject result;
 
 
  va_start (args, id);
  va_start (args, id);
  result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
  result = _Jv_JNI_CallAnyMethodV<jobject, constructor> (env, NULL, klass,
                                                         id, args);
                                                         id, args);
  va_end (args);
  va_end (args);
 
 
  return result;
  return result;
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
_Jv_JNI_NewObjectA (JNIEnv *env, jclass klass, jmethodID id,
                    const jvalue *args)
                    const jvalue *args)
{
{
  JvAssert (klass && ! klass->isArray ());
  JvAssert (klass && ! klass->isArray ());
  JvAssert (! strcmp (id->name->chars(), "<init>")
  JvAssert (! strcmp (id->name->chars(), "<init>")
            && id->signature->len() > 2
            && id->signature->len() > 2
            && id->signature->chars()[0] == '('
            && id->signature->chars()[0] == '('
            && ! strcmp (&id->signature->chars()[id->signature->len() - 2],
            && ! strcmp (&id->signature->chars()[id->signature->len() - 2],
                         ")V"));
                         ")V"));
 
 
  return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
  return _Jv_JNI_CallAnyMethodA<jobject, constructor> (env, NULL, klass,
                                                       id, args);
                                                       id, args);
}
}
 
 


 
 
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
_Jv_JNI_GetField (JNIEnv *env, jobject obj, jfieldID field)
{
{
  obj = unwrap (obj);
  obj = unwrap (obj);
  JvAssert (obj);
  JvAssert (obj);
  T *ptr = (T *) ((char *) obj + field->getOffset ());
  T *ptr = (T *) ((char *) obj + field->getOffset ());
  return wrap_value (env, *ptr);
  return wrap_value (env, *ptr);
}
}
 
 
template<typename T>
template<typename T>
static void JNICALL
static void JNICALL
_Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
_Jv_JNI_SetField (JNIEnv *, jobject obj, jfieldID field, T value)
{
{
  obj = unwrap (obj);
  obj = unwrap (obj);
  value = unwrap (value);
  value = unwrap (value);
 
 
  JvAssert (obj);
  JvAssert (obj);
  T *ptr = (T *) ((char *) obj + field->getOffset ());
  T *ptr = (T *) ((char *) obj + field->getOffset ());
  *ptr = value;
  *ptr = value;
}
}
 
 
template<jboolean is_static>
template<jboolean is_static>
static jfieldID JNICALL
static jfieldID JNICALL
_Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
_Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
                       const char *name, const char *sig)
                       const char *name, const char *sig)
{
{
  try
  try
    {
    {
      clazz = unwrap (clazz);
      clazz = unwrap (clazz);
 
 
      _Jv_InitClass (clazz);
      _Jv_InitClass (clazz);
 
 
      _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
      _Jv_Utf8Const *a_name = _Jv_makeUtf8Const ((char *) name, -1);
 
 
      // FIXME: assume that SIG isn't too long.
      // FIXME: assume that SIG isn't too long.
      int len = strlen (sig);
      int len = strlen (sig);
      char s[len + 1];
      char s[len + 1];
      for (int i = 0; i <= len; ++i)
      for (int i = 0; i <= len; ++i)
        s[i] = (sig[i] == '/') ? '.' : sig[i];
        s[i] = (sig[i] == '/') ? '.' : sig[i];
      java::lang::ClassLoader *loader = clazz->getClassLoaderInternal ();
      java::lang::ClassLoader *loader = clazz->getClassLoaderInternal ();
      jclass field_class = _Jv_FindClassFromSignature ((char *) s, loader);
      jclass field_class = _Jv_FindClassFromSignature ((char *) s, loader);
      if (! field_class)
      if (! field_class)
        throw new java::lang::ClassNotFoundException(JvNewStringUTF(s));
        throw new java::lang::ClassNotFoundException(JvNewStringUTF(s));
 
 
      while (clazz != NULL)
      while (clazz != NULL)
        {
        {
          // We acquire the class lock so that fields aren't resolved
          // We acquire the class lock so that fields aren't resolved
          // while we are running.
          // while we are running.
          JvSynchronize sync (clazz);
          JvSynchronize sync (clazz);
 
 
          jint count = (is_static
          jint count = (is_static
                        ? JvNumStaticFields (clazz)
                        ? JvNumStaticFields (clazz)
                        : JvNumInstanceFields (clazz));
                        : JvNumInstanceFields (clazz));
          jfieldID field = (is_static
          jfieldID field = (is_static
                            ? JvGetFirstStaticField (clazz)
                            ? JvGetFirstStaticField (clazz)
                            : JvGetFirstInstanceField (clazz));
                            : JvGetFirstInstanceField (clazz));
          for (jint i = 0; i < count; ++i)
          for (jint i = 0; i < count; ++i)
            {
            {
              _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
              _Jv_Utf8Const *f_name = field->getNameUtf8Const(clazz);
 
 
              // The field might be resolved or it might not be.  It
              // The field might be resolved or it might not be.  It
              // is much simpler to always resolve it.
              // is much simpler to always resolve it.
              _Jv_Linker::resolve_field (field, loader);
              _Jv_Linker::resolve_field (field, loader);
              if (_Jv_equalUtf8Consts (f_name, a_name)
              if (_Jv_equalUtf8Consts (f_name, a_name)
                  && field->getClass() == field_class)
                  && field->getClass() == field_class)
                return field;
                return field;
 
 
              field = field->getNextField ();
              field = field->getNextField ();
            }
            }
 
 
          clazz = clazz->getSuperclass ();
          clazz = clazz->getSuperclass ();
        }
        }
 
 
      env->ex = new java::lang::NoSuchFieldError ();
      env->ex = new java::lang::NoSuchFieldError ();
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
  return NULL;
  return NULL;
}
}
 
 
template<typename T>
template<typename T>
static T JNICALL
static T JNICALL
_Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
_Jv_JNI_GetStaticField (JNIEnv *env, jclass, jfieldID field)
{
{
  T *ptr = (T *) field->u.addr;
  T *ptr = (T *) field->u.addr;
  return wrap_value (env, *ptr);
  return wrap_value (env, *ptr);
}
}
 
 
template<typename T>
template<typename T>
static void JNICALL
static void JNICALL
_Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
_Jv_JNI_SetStaticField (JNIEnv *, jclass, jfieldID field, T value)
{
{
  value = unwrap (value);
  value = unwrap (value);
  T *ptr = (T *) field->u.addr;
  T *ptr = (T *) field->u.addr;
  *ptr = value;
  *ptr = value;
}
}
 
 
static jstring JNICALL
static jstring JNICALL
_Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
_Jv_JNI_NewString (JNIEnv *env, const jchar *unichars, jsize len)
{
{
  try
  try
    {
    {
      jstring r = _Jv_NewString (unichars, len);
      jstring r = _Jv_NewString (unichars, len);
      return (jstring) wrap_value (env, r);
      return (jstring) wrap_value (env, r);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return NULL;
      return NULL;
    }
    }
}
}
 
 
static jsize JNICALL
static jsize JNICALL
_Jv_JNI_GetStringLength (JNIEnv *, jstring string)
_Jv_JNI_GetStringLength (JNIEnv *, jstring string)
{
{
  return unwrap (string)->length();
  return unwrap (string)->length();
}
}
 
 
static const jchar * JNICALL
static const jchar * JNICALL
_Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
_Jv_JNI_GetStringChars (JNIEnv *, jstring string, jboolean *isCopy)
{
{
  string = unwrap (string);
  string = unwrap (string);
  jchar *result = _Jv_GetStringChars (string);
  jchar *result = _Jv_GetStringChars (string);
  mark_for_gc (string, global_ref_table);
  mark_for_gc (string, global_ref_table);
  if (isCopy)
  if (isCopy)
    *isCopy = false;
    *isCopy = false;
  return (const jchar *) result;
  return (const jchar *) result;
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
_Jv_JNI_ReleaseStringChars (JNIEnv *, jstring string, const jchar *)
{
{
  unmark_for_gc (unwrap (string), global_ref_table);
  unmark_for_gc (unwrap (string), global_ref_table);
}
}
 
 
static jstring JNICALL
static jstring JNICALL
_Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
_Jv_JNI_NewStringUTF (JNIEnv *env, const char *bytes)
{
{
  try
  try
    {
    {
      // For compatibility with the JDK.
      // For compatibility with the JDK.
      if (!bytes)
      if (!bytes)
        return NULL;
        return NULL;
      jstring result = JvNewStringUTF (bytes);
      jstring result = JvNewStringUTF (bytes);
      return (jstring) wrap_value (env, result);
      return (jstring) wrap_value (env, result);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return NULL;
      return NULL;
    }
    }
}
}
 
 
static jsize JNICALL
static jsize JNICALL
_Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
_Jv_JNI_GetStringUTFLength (JNIEnv *, jstring string)
{
{
  return JvGetStringUTFLength (unwrap (string));
  return JvGetStringUTFLength (unwrap (string));
}
}
 
 
static const char * JNICALL
static const char * JNICALL
_Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string,
_Jv_JNI_GetStringUTFChars (JNIEnv *env, jstring string,
                           jboolean *isCopy)
                           jboolean *isCopy)
{
{
  try
  try
    {
    {
      string = unwrap (string);
      string = unwrap (string);
      if (string == NULL)
      if (string == NULL)
        return NULL;
        return NULL;
      jsize len = JvGetStringUTFLength (string);
      jsize len = JvGetStringUTFLength (string);
      char *r = (char *) _Jv_Malloc (len + 1);
      char *r = (char *) _Jv_Malloc (len + 1);
      JvGetStringUTFRegion (string, 0, string->length(), r);
      JvGetStringUTFRegion (string, 0, string->length(), r);
      r[len] = '\0';
      r[len] = '\0';
 
 
      if (isCopy)
      if (isCopy)
        *isCopy = true;
        *isCopy = true;
 
 
      return (const char *) r;
      return (const char *) r;
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return NULL;
      return NULL;
    }
    }
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
_Jv_JNI_ReleaseStringUTFChars (JNIEnv *, jstring, const char *utf)
{
{
  _Jv_Free ((void *) utf);
  _Jv_Free ((void *) utf);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start,
_Jv_JNI_GetStringRegion (JNIEnv *env, jstring string, jsize start,
                         jsize len, jchar *buf)
                         jsize len, jchar *buf)
{
{
  string = unwrap (string);
  string = unwrap (string);
  jchar *result = _Jv_GetStringChars (string);
  jchar *result = _Jv_GetStringChars (string);
  if (start < 0 || start > string->length ()
  if (start < 0 || start > string->length ()
      || len < 0 || start + len > string->length ())
      || len < 0 || start + len > string->length ())
    {
    {
      try
      try
        {
        {
          env->ex = new java::lang::StringIndexOutOfBoundsException ();
          env->ex = new java::lang::StringIndexOutOfBoundsException ();
        }
        }
      catch (jthrowable t)
      catch (jthrowable t)
        {
        {
          env->ex = t;
          env->ex = t;
        }
        }
    }
    }
  else
  else
    memcpy (buf, &result[start], len * sizeof (jchar));
    memcpy (buf, &result[start], len * sizeof (jchar));
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
_Jv_JNI_GetStringUTFRegion (JNIEnv *env, jstring str, jsize start,
                            jsize len, char *buf)
                            jsize len, char *buf)
{
{
  str = unwrap (str);
  str = unwrap (str);
 
 
  if (start < 0 || start > str->length ()
  if (start < 0 || start > str->length ()
      || len < 0 || start + len > str->length ())
      || len < 0 || start + len > str->length ())
    {
    {
      try
      try
        {
        {
          env->ex = new java::lang::StringIndexOutOfBoundsException ();
          env->ex = new java::lang::StringIndexOutOfBoundsException ();
        }
        }
      catch (jthrowable t)
      catch (jthrowable t)
        {
        {
          env->ex = t;
          env->ex = t;
        }
        }
    }
    }
  else
  else
    _Jv_GetStringUTFRegion (str, start, len, buf);
    _Jv_GetStringUTFRegion (str, start, len, buf);
}
}
 
 
static const jchar * JNICALL
static const jchar * JNICALL
_Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
_Jv_JNI_GetStringCritical (JNIEnv *, jstring str, jboolean *isCopy)
{
{
  jchar *result = _Jv_GetStringChars (unwrap (str));
  jchar *result = _Jv_GetStringChars (unwrap (str));
  if (isCopy)
  if (isCopy)
    *isCopy = false;
    *isCopy = false;
  return result;
  return result;
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
_Jv_JNI_ReleaseStringCritical (JNIEnv *, jstring, const jchar *)
{
{
  // Nothing.
  // Nothing.
}
}
 
 
static jsize JNICALL
static jsize JNICALL
_Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
_Jv_JNI_GetArrayLength (JNIEnv *, jarray array)
{
{
  return unwrap (array)->length;
  return unwrap (array)->length;
}
}
 
 
static jobjectArray JNICALL
static jobjectArray JNICALL
_Jv_JNI_NewObjectArray (JNIEnv *env, jsize length,
_Jv_JNI_NewObjectArray (JNIEnv *env, jsize length,
                        jclass elementClass, jobject init)
                        jclass elementClass, jobject init)
{
{
  try
  try
    {
    {
      elementClass = unwrap (elementClass);
      elementClass = unwrap (elementClass);
      init = unwrap (init);
      init = unwrap (init);
 
 
      _Jv_CheckCast (elementClass, init);
      _Jv_CheckCast (elementClass, init);
      jarray result = JvNewObjectArray (length, elementClass, init);
      jarray result = JvNewObjectArray (length, elementClass, init);
      return (jobjectArray) wrap_value (env, result);
      return (jobjectArray) wrap_value (env, result);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return NULL;
      return NULL;
    }
    }
}
}
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array,
_Jv_JNI_GetObjectArrayElement (JNIEnv *env, jobjectArray array,
                               jsize index)
                               jsize index)
{
{
  if ((unsigned) index >= (unsigned) array->length)
  if ((unsigned) index >= (unsigned) array->length)
    _Jv_ThrowBadArrayIndex (index);
    _Jv_ThrowBadArrayIndex (index);
  jobject *elts = elements (unwrap (array));
  jobject *elts = elements (unwrap (array));
  return wrap_value (env, elts[index]);
  return wrap_value (env, elts[index]);
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_SetObjectArrayElement (JNIEnv *env, jobjectArray array,
_Jv_JNI_SetObjectArrayElement (JNIEnv *env, jobjectArray array,
                               jsize index, jobject value)
                               jsize index, jobject value)
{
{
  try
  try
    {
    {
      array = unwrap (array);
      array = unwrap (array);
      value = unwrap (value);
      value = unwrap (value);
 
 
      _Jv_CheckArrayStore (array, value);
      _Jv_CheckArrayStore (array, value);
      if ((unsigned) index >= (unsigned) array->length)
      if ((unsigned) index >= (unsigned) array->length)
        _Jv_ThrowBadArrayIndex (index);
        _Jv_ThrowBadArrayIndex (index);
      jobject *elts = elements (array);
      jobject *elts = elements (array);
      elts[index] = value;
      elts[index] = value;
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
}
}
 
 
template<typename T, jclass K>
template<typename T, jclass K>
static JArray<T> * JNICALL
static JArray<T> * JNICALL
_Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
_Jv_JNI_NewPrimitiveArray (JNIEnv *env, jsize length)
{
{
  try
  try
    {
    {
      return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
      return (JArray<T> *) wrap_value (env, _Jv_NewPrimArray (K, length));
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
      return NULL;
      return NULL;
    }
    }
}
}
 
 
template<typename T, jclass K>
template<typename T, jclass K>
static T * JNICALL
static T * JNICALL
_Jv_JNI_GetPrimitiveArrayElements (JNIEnv *env, JArray<T> *array,
_Jv_JNI_GetPrimitiveArrayElements (JNIEnv *env, JArray<T> *array,
                                   jboolean *isCopy)
                                   jboolean *isCopy)
{
{
  array = unwrap (array);
  array = unwrap (array);
  if (! _Jv_JNI_check_types (env, array, K))
  if (! _Jv_JNI_check_types (env, array, K))
    return NULL;
    return NULL;
  T *elts = elements (array);
  T *elts = elements (array);
  if (isCopy)
  if (isCopy)
    {
    {
      // We elect never to copy.
      // We elect never to copy.
      *isCopy = false;
      *isCopy = false;
    }
    }
  mark_for_gc (array, global_ref_table);
  mark_for_gc (array, global_ref_table);
  return elts;
  return elts;
}
}
 
 
template<typename T, jclass K>
template<typename T, jclass K>
static void JNICALL
static void JNICALL
_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *env, JArray<T> *array,
_Jv_JNI_ReleasePrimitiveArrayElements (JNIEnv *env, JArray<T> *array,
                                       T *, jint /* mode */)
                                       T *, jint /* mode */)
{
{
  array = unwrap (array);
  array = unwrap (array);
  _Jv_JNI_check_types (env, array, K);
  _Jv_JNI_check_types (env, array, K);
  // Note that we ignore MODE.  We can do this because we never copy
  // Note that we ignore MODE.  We can do this because we never copy
  // the array elements.  My reading of the JNI documentation is that
  // the array elements.  My reading of the JNI documentation is that
  // this is an option for the implementor.
  // this is an option for the implementor.
  unmark_for_gc (array, global_ref_table);
  unmark_for_gc (array, global_ref_table);
}
}
 
 
template<typename T, jclass K>
template<typename T, jclass K>
static void JNICALL
static void JNICALL
_Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
_Jv_JNI_GetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
                                 jsize start, jsize len,
                                 jsize start, jsize len,
                                 T *buf)
                                 T *buf)
{
{
  array = unwrap (array);
  array = unwrap (array);
  if (! _Jv_JNI_check_types (env, array, K))
  if (! _Jv_JNI_check_types (env, array, K))
    return;
    return;
 
 
  // The cast to unsigned lets us save a comparison.
  // The cast to unsigned lets us save a comparison.
  if (start < 0 || len < 0
  if (start < 0 || len < 0
      || (unsigned long) (start + len) > (unsigned long) array->length)
      || (unsigned long) (start + len) > (unsigned long) array->length)
    {
    {
      try
      try
        {
        {
          // FIXME: index.
          // FIXME: index.
          env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
          env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
        }
        }
      catch (jthrowable t)
      catch (jthrowable t)
        {
        {
          // Could have thown out of memory error.
          // Could have thown out of memory error.
          env->ex = t;
          env->ex = t;
        }
        }
    }
    }
  else
  else
    {
    {
      T *elts = elements (array) + start;
      T *elts = elements (array) + start;
      memcpy (buf, elts, len * sizeof (T));
      memcpy (buf, elts, len * sizeof (T));
    }
    }
}
}
 
 
template<typename T, jclass K>
template<typename T, jclass K>
static void JNICALL
static void JNICALL
_Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
_Jv_JNI_SetPrimitiveArrayRegion (JNIEnv *env, JArray<T> *array,
                                 jsize start, jsize len, const T *buf)
                                 jsize start, jsize len, const T *buf)
{
{
  array = unwrap (array);
  array = unwrap (array);
  if (! _Jv_JNI_check_types (env, array, K))
  if (! _Jv_JNI_check_types (env, array, K))
    return;
    return;
 
 
  // The cast to unsigned lets us save a comparison.
  // The cast to unsigned lets us save a comparison.
  if (start < 0 || len < 0
  if (start < 0 || len < 0
      || (unsigned long) (start + len) > (unsigned long) array->length)
      || (unsigned long) (start + len) > (unsigned long) array->length)
    {
    {
      try
      try
        {
        {
          // FIXME: index.
          // FIXME: index.
          env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
          env->ex = new java::lang::ArrayIndexOutOfBoundsException ();
        }
        }
      catch (jthrowable t)
      catch (jthrowable t)
        {
        {
          env->ex = t;
          env->ex = t;
        }
        }
    }
    }
  else
  else
    {
    {
      T *elts = elements (array) + start;
      T *elts = elements (array) + start;
      memcpy (elts, buf, len * sizeof (T));
      memcpy (elts, buf, len * sizeof (T));
    }
    }
}
}
 
 
static void * JNICALL
static void * JNICALL
_Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
_Jv_JNI_GetPrimitiveArrayCritical (JNIEnv *, jarray array,
                                   jboolean *isCopy)
                                   jboolean *isCopy)
{
{
  array = unwrap (array);
  array = unwrap (array);
  // FIXME: does this work?
  // FIXME: does this work?
  jclass klass = array->getClass()->getComponentType();
  jclass klass = array->getClass()->getComponentType();
  JvAssert (klass->isPrimitive ());
  JvAssert (klass->isPrimitive ());
  char *r = _Jv_GetArrayElementFromElementType (array, klass);
  char *r = _Jv_GetArrayElementFromElementType (array, klass);
  if (isCopy)
  if (isCopy)
    *isCopy = false;
    *isCopy = false;
  return r;
  return r;
}
}
 
 
static void JNICALL
static void JNICALL
_Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
_Jv_JNI_ReleasePrimitiveArrayCritical (JNIEnv *, jarray, void *, jint)
{
{
  // Nothing.
  // Nothing.
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_MonitorEnter (JNIEnv *env, jobject obj)
_Jv_JNI_MonitorEnter (JNIEnv *env, jobject obj)
{
{
  try
  try
    {
    {
      _Jv_MonitorEnter (unwrap (obj));
      _Jv_MonitorEnter (unwrap (obj));
      return 0;
      return 0;
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
  return JNI_ERR;
  return JNI_ERR;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_MonitorExit (JNIEnv *env, jobject obj)
_Jv_JNI_MonitorExit (JNIEnv *env, jobject obj)
{
{
  try
  try
    {
    {
      _Jv_MonitorExit (unwrap (obj));
      _Jv_MonitorExit (unwrap (obj));
      return 0;
      return 0;
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
  return JNI_ERR;
  return JNI_ERR;
}
}
 
 
// JDK 1.2
// JDK 1.2
jobject JNICALL
jobject JNICALL
_Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
_Jv_JNI_ToReflectedField (JNIEnv *env, jclass cls, jfieldID fieldID,
                          jboolean)
                          jboolean)
{
{
  try
  try
    {
    {
      cls = unwrap (cls);
      cls = unwrap (cls);
      java::lang::reflect::Field *field = new java::lang::reflect::Field();
      java::lang::reflect::Field *field = new java::lang::reflect::Field();
      field->declaringClass = cls;
      field->declaringClass = cls;
      field->offset = (char*) fieldID - (char *) cls->fields;
      field->offset = (char*) fieldID - (char *) cls->fields;
      field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
      field->name = _Jv_NewStringUtf8Const (fieldID->getNameUtf8Const (cls));
      return wrap_value (env, field);
      return wrap_value (env, field);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
  return NULL;
  return NULL;
}
}
 
 
// JDK 1.2
// JDK 1.2
static jfieldID JNICALL
static jfieldID JNICALL
_Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
_Jv_JNI_FromReflectedField (JNIEnv *, jobject f)
{
{
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
 
 
  f = unwrap (f);
  f = unwrap (f);
  Field *field = reinterpret_cast<Field *> (f);
  Field *field = reinterpret_cast<Field *> (f);
  return _Jv_FromReflectedField (field);
  return _Jv_FromReflectedField (field);
}
}
 
 
jobject JNICALL
jobject JNICALL
_Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
_Jv_JNI_ToReflectedMethod (JNIEnv *env, jclass klass, jmethodID id,
                           jboolean)
                           jboolean)
{
{
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
 
 
  jobject result = NULL;
  jobject result = NULL;
  klass = unwrap (klass);
  klass = unwrap (klass);
 
 
  try
  try
    {
    {
      if (_Jv_equalUtf8Consts (id->name, init_name))
      if (_Jv_equalUtf8Consts (id->name, init_name))
        {
        {
          // A constructor.
          // A constructor.
          Constructor *cons = new Constructor ();
          Constructor *cons = new Constructor ();
          cons->offset = (char *) id - (char *) &klass->methods;
          cons->offset = (char *) id - (char *) &klass->methods;
          cons->declaringClass = klass;
          cons->declaringClass = klass;
          result = cons;
          result = cons;
        }
        }
      else
      else
        {
        {
          Method *meth = new Method ();
          Method *meth = new Method ();
          meth->offset = (char *) id - (char *) &klass->methods;
          meth->offset = (char *) id - (char *) &klass->methods;
          meth->declaringClass = klass;
          meth->declaringClass = klass;
          result = meth;
          result = meth;
        }
        }
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return wrap_value (env, result);
  return wrap_value (env, result);
}
}
 
 
static jmethodID JNICALL
static jmethodID JNICALL
_Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
_Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method)
{
{
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
  method = unwrap (method);
  method = unwrap (method);
  if (Method::class$.isInstance (method))
  if (Method::class$.isInstance (method))
    return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
    return _Jv_FromReflectedMethod (reinterpret_cast<Method *> (method));
  return
  return
    _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
    _Jv_FromReflectedConstructor (reinterpret_cast<Constructor *> (method));
}
}
 
 
// JDK 1.2.
// JDK 1.2.
jweak JNICALL
jweak JNICALL
_Jv_JNI_NewWeakGlobalRef (JNIEnv *env, jobject obj)
_Jv_JNI_NewWeakGlobalRef (JNIEnv *env, jobject obj)
{
{
  using namespace gnu::gcj::runtime;
  using namespace gnu::gcj::runtime;
  JNIWeakRef *ref = NULL;
  JNIWeakRef *ref = NULL;
 
 
  try
  try
    {
    {
      // This seems weird but I think it is correct.
      // This seems weird but I think it is correct.
      obj = unwrap (obj);
      obj = unwrap (obj);
      ref = new JNIWeakRef (obj);
      ref = new JNIWeakRef (obj);
      mark_for_gc (ref, global_ref_table);
      mark_for_gc (ref, global_ref_table);
    }
    }
  catch (jthrowable t)
  catch (jthrowable t)
    {
    {
      env->ex = t;
      env->ex = t;
    }
    }
 
 
  return reinterpret_cast<jweak> (ref);
  return reinterpret_cast<jweak> (ref);
}
}
 
 
void JNICALL
void JNICALL
_Jv_JNI_DeleteWeakGlobalRef (JNIEnv *, jweak obj)
_Jv_JNI_DeleteWeakGlobalRef (JNIEnv *, jweak obj)
{
{
  // JDK compatibility.
  // JDK compatibility.
  if (obj == NULL)
  if (obj == NULL)
    return;
    return;
 
 
  using namespace gnu::gcj::runtime;
  using namespace gnu::gcj::runtime;
  JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
  JNIWeakRef *ref = reinterpret_cast<JNIWeakRef *> (obj);
  unmark_for_gc (ref, global_ref_table);
  unmark_for_gc (ref, global_ref_table);
  ref->clear ();
  ref->clear ();
}
}
 
 


 
 
// Direct byte buffers.
// Direct byte buffers.
 
 
static jobject JNICALL
static jobject JNICALL
_Jv_JNI_NewDirectByteBuffer (JNIEnv *, void *address, jlong length)
_Jv_JNI_NewDirectByteBuffer (JNIEnv *, void *address, jlong length)
{
{
  using namespace gnu::gcj;
  using namespace gnu::gcj;
  using namespace java::nio;
  using namespace java::nio;
  return new DirectByteBufferImpl$ReadWrite
  return new DirectByteBufferImpl$ReadWrite
    (reinterpret_cast<RawData *> (address), length);
    (reinterpret_cast<RawData *> (address), length);
}
}
 
 
static void * JNICALL
static void * JNICALL
_Jv_JNI_GetDirectBufferAddress (JNIEnv *, jobject buffer)
_Jv_JNI_GetDirectBufferAddress (JNIEnv *, jobject buffer)
{
{
  using namespace java::nio;
  using namespace java::nio;
  if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
  if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
    return NULL;
    return NULL;
  Buffer *tmp = static_cast<Buffer *> (buffer);
  Buffer *tmp = static_cast<Buffer *> (buffer);
  return reinterpret_cast<void *> (tmp->address);
  return reinterpret_cast<void *> (tmp->address);
}
}
 
 
static jlong JNICALL
static jlong JNICALL
_Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
_Jv_JNI_GetDirectBufferCapacity (JNIEnv *, jobject buffer)
{
{
  using namespace java::nio;
  using namespace java::nio;
  if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
  if (! _Jv_IsInstanceOf (buffer, &Buffer::class$))
    return -1;
    return -1;
  Buffer *tmp = static_cast<Buffer *> (buffer);
  Buffer *tmp = static_cast<Buffer *> (buffer);
  if (tmp->address == NULL)
  if (tmp->address == NULL)
    return -1;
    return -1;
  return tmp->capacity();
  return tmp->capacity();
}
}
 
 
static jobjectRefType JNICALL
static jobjectRefType JNICALL
_Jv_JNI_GetObjectRefType (JNIEnv *, MAYBE_UNUSED jobject object)
_Jv_JNI_GetObjectRefType (JNIEnv *, MAYBE_UNUSED jobject object)
{
{
  JvFail("GetObjectRefType not implemented");
  JvFail("GetObjectRefType not implemented");
  return JNIInvalidRefType;
  return JNIInvalidRefType;
}
}
 
 


 
 
struct NativeMethodCacheEntry : public JNINativeMethod
struct NativeMethodCacheEntry : public JNINativeMethod
{
{
  char *className;
  char *className;
};
};
 
 
// Hash table of native methods.
// Hash table of native methods.
static NativeMethodCacheEntry *nathash;
static NativeMethodCacheEntry *nathash;
// Number of slots used.
// Number of slots used.
static int nathash_count = 0;
static int nathash_count = 0;
// Number of slots available.  Must be power of 2.
// Number of slots available.  Must be power of 2.
static int nathash_size = 0;
static int nathash_size = 0;
 
 
#define DELETED_ENTRY ((char *) (~0))
#define DELETED_ENTRY ((char *) (~0))
 
 
// Compute a hash value for a native method descriptor.
// Compute a hash value for a native method descriptor.
static int
static int
hash (const NativeMethodCacheEntry *method)
hash (const NativeMethodCacheEntry *method)
{
{
  char *ptr;
  char *ptr;
  int hash = 0;
  int hash = 0;
 
 
  ptr = method->className;
  ptr = method->className;
  while (*ptr)
  while (*ptr)
    hash = (31 * hash) + *ptr++;
    hash = (31 * hash) + *ptr++;
 
 
  ptr = method->name;
  ptr = method->name;
  while (*ptr)
  while (*ptr)
    hash = (31 * hash) + *ptr++;
    hash = (31 * hash) + *ptr++;
 
 
  ptr = method->signature;
  ptr = method->signature;
  while (*ptr)
  while (*ptr)
    hash = (31 * hash) + *ptr++;
    hash = (31 * hash) + *ptr++;
 
 
  return hash;
  return hash;
}
}
 
 
// Find the slot where a native method goes.
// Find the slot where a native method goes.
static NativeMethodCacheEntry *
static NativeMethodCacheEntry *
nathash_find_slot (const NativeMethodCacheEntry *method)
nathash_find_slot (const NativeMethodCacheEntry *method)
{
{
  jint h = hash (method);
  jint h = hash (method);
  int step = (h ^ (h >> 16)) | 1;
  int step = (h ^ (h >> 16)) | 1;
  int w = h & (nathash_size - 1);
  int w = h & (nathash_size - 1);
  int del = -1;
  int del = -1;
 
 
  for (;;)
  for (;;)
    {
    {
      NativeMethodCacheEntry *slotp = &nathash[w];
      NativeMethodCacheEntry *slotp = &nathash[w];
      if (slotp->name == NULL)
      if (slotp->name == NULL)
        {
        {
          if (del >= 0)
          if (del >= 0)
            return &nathash[del];
            return &nathash[del];
          else
          else
            return slotp;
            return slotp;
        }
        }
      else if (slotp->name == DELETED_ENTRY)
      else if (slotp->name == DELETED_ENTRY)
        del = w;
        del = w;
      else if (! strcmp (slotp->name, method->name)
      else if (! strcmp (slotp->name, method->name)
               && ! strcmp (slotp->signature, method->signature)
               && ! strcmp (slotp->signature, method->signature)
               && ! strcmp (slotp->className, method->className))
               && ! strcmp (slotp->className, method->className))
        return slotp;
        return slotp;
      w = (w + step) & (nathash_size - 1);
      w = (w + step) & (nathash_size - 1);
    }
    }
}
}
 
 
// Find a method.  Return NULL if it isn't in the hash table.
// Find a method.  Return NULL if it isn't in the hash table.
static void *
static void *
nathash_find (NativeMethodCacheEntry *method)
nathash_find (NativeMethodCacheEntry *method)
{
{
  if (nathash == NULL)
  if (nathash == NULL)
    return NULL;
    return NULL;
  NativeMethodCacheEntry *slot = nathash_find_slot (method);
  NativeMethodCacheEntry *slot = nathash_find_slot (method);
  if (slot->name == NULL || slot->name == DELETED_ENTRY)
  if (slot->name == NULL || slot->name == DELETED_ENTRY)
    return NULL;
    return NULL;
  return slot->fnPtr;
  return slot->fnPtr;
}
}
 
 
static void
static void
natrehash ()
natrehash ()
{
{
  if (nathash == NULL)
  if (nathash == NULL)
    {
    {
      nathash_size = 1024;
      nathash_size = 1024;
      nathash =
      nathash =
        (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
        (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
                                                   * sizeof (NativeMethodCacheEntry));
                                                   * sizeof (NativeMethodCacheEntry));
    }
    }
  else
  else
    {
    {
      int savesize = nathash_size;
      int savesize = nathash_size;
      NativeMethodCacheEntry *savehash = nathash;
      NativeMethodCacheEntry *savehash = nathash;
      nathash_size *= 2;
      nathash_size *= 2;
      nathash =
      nathash =
        (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
        (NativeMethodCacheEntry *) _Jv_AllocBytes (nathash_size
                                                   * sizeof (NativeMethodCacheEntry));
                                                   * sizeof (NativeMethodCacheEntry));
 
 
      for (int i = 0; i < savesize; ++i)
      for (int i = 0; i < savesize; ++i)
        {
        {
          if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
          if (savehash[i].name != NULL && savehash[i].name != DELETED_ENTRY)
            {
            {
              NativeMethodCacheEntry *slot = nathash_find_slot (&savehash[i]);
              NativeMethodCacheEntry *slot = nathash_find_slot (&savehash[i]);
              *slot = savehash[i];
              *slot = savehash[i];
            }
            }
        }
        }
    }
    }
}
}
 
 
static void
static void
nathash_add (const NativeMethodCacheEntry *method)
nathash_add (const NativeMethodCacheEntry *method)
{
{
  if (3 * nathash_count >= 2 * nathash_size)
  if (3 * nathash_count >= 2 * nathash_size)
    natrehash ();
    natrehash ();
  NativeMethodCacheEntry *slot = nathash_find_slot (method);
  NativeMethodCacheEntry *slot = nathash_find_slot (method);
  // If the slot has a real entry in it, then there is no work to do.
  // If the slot has a real entry in it, then there is no work to do.
  if (slot->name != NULL && slot->name != DELETED_ENTRY)
  if (slot->name != NULL && slot->name != DELETED_ENTRY)
    return;
    return;
  // FIXME: memory leak?
  // FIXME: memory leak?
  slot->name = strdup (method->name);
  slot->name = strdup (method->name);
  slot->className = strdup (method->className);
  slot->className = strdup (method->className);
  // This was already strduped in _Jv_JNI_RegisterNatives.
  // This was already strduped in _Jv_JNI_RegisterNatives.
  slot->signature = method->signature;
  slot->signature = method->signature;
  slot->fnPtr = method->fnPtr;
  slot->fnPtr = method->fnPtr;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
_Jv_JNI_RegisterNatives (JNIEnv *env, jclass klass,
                         const JNINativeMethod *methods,
                         const JNINativeMethod *methods,
                         jint nMethods)
                         jint nMethods)
{
{
  // Synchronize while we do the work.  This must match
  // Synchronize while we do the work.  This must match
  // synchronization in some other functions that manipulate or use
  // synchronization in some other functions that manipulate or use
  // the nathash table.
  // the nathash table.
  JvSynchronize sync (global_ref_table);
  JvSynchronize sync (global_ref_table);
 
 
  NativeMethodCacheEntry dottedMethod;
  NativeMethodCacheEntry dottedMethod;
 
 
  // Look at each descriptor given us, and find the corresponding
  // Look at each descriptor given us, and find the corresponding
  // method in the class.
  // method in the class.
  for (int j = 0; j < nMethods; ++j)
  for (int j = 0; j < nMethods; ++j)
    {
    {
      bool found = false;
      bool found = false;
 
 
      _Jv_Method *imeths = JvGetFirstMethod (klass);
      _Jv_Method *imeths = JvGetFirstMethod (klass);
      for (int i = 0; i < JvNumMethods (klass); ++i)
      for (int i = 0; i < JvNumMethods (klass); ++i)
        {
        {
          _Jv_Method *self = &imeths[i];
          _Jv_Method *self = &imeths[i];
 
 
          // Copy this JNINativeMethod and do a slash to dot
          // Copy this JNINativeMethod and do a slash to dot
          // conversion on the signature.
          // conversion on the signature.
          dottedMethod.name = methods[j].name;
          dottedMethod.name = methods[j].name;
          // FIXME: we leak a little memory here if the method
          // FIXME: we leak a little memory here if the method
          // is not found.
          // is not found.
          dottedMethod.signature = strdup (methods[j].signature);
          dottedMethod.signature = strdup (methods[j].signature);
          dottedMethod.fnPtr = methods[j].fnPtr;
          dottedMethod.fnPtr = methods[j].fnPtr;
          dottedMethod.className = _Jv_GetClassNameUtf8 (klass)->chars();
          dottedMethod.className = _Jv_GetClassNameUtf8 (klass)->chars();
          char *c = dottedMethod.signature;
          char *c = dottedMethod.signature;
          while (*c)
          while (*c)
            {
            {
              if (*c == '/')
              if (*c == '/')
                *c = '.';
                *c = '.';
              c++;
              c++;
            }
            }
 
 
          if (! strcmp (self->name->chars (), dottedMethod.name)
          if (! strcmp (self->name->chars (), dottedMethod.name)
              && ! strcmp (self->signature->chars (), dottedMethod.signature))
              && ! strcmp (self->signature->chars (), dottedMethod.signature))
            {
            {
              if (! (self->accflags & java::lang::reflect::Modifier::NATIVE))
              if (! (self->accflags & java::lang::reflect::Modifier::NATIVE))
                break;
                break;
 
 
              // Found a match that is native.
              // Found a match that is native.
              found = true;
              found = true;
              nathash_add (&dottedMethod);
              nathash_add (&dottedMethod);
 
 
              break;
              break;
            }
            }
        }
        }
 
 
      if (! found)
      if (! found)
        {
        {
          jstring m = JvNewStringUTF (methods[j].name);
          jstring m = JvNewStringUTF (methods[j].name);
          try
          try
            {
            {
              env->ex = new java::lang::NoSuchMethodError (m);
              env->ex = new java::lang::NoSuchMethodError (m);
            }
            }
          catch (jthrowable t)
          catch (jthrowable t)
            {
            {
              env->ex = t;
              env->ex = t;
            }
            }
          return JNI_ERR;
          return JNI_ERR;
        }
        }
    }
    }
 
 
  return JNI_OK;
  return JNI_OK;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_UnregisterNatives (JNIEnv *, jclass)
_Jv_JNI_UnregisterNatives (JNIEnv *, jclass)
{
{
  // FIXME -- we could implement this.
  // FIXME -- we could implement this.
  return JNI_ERR;
  return JNI_ERR;
}
}
 
 


 
 
// Add a character to the buffer, encoding properly.
// Add a character to the buffer, encoding properly.
static void
static void
add_char (char *buf, jchar c, int *here)
add_char (char *buf, jchar c, int *here)
{
{
  if (c == '_')
  if (c == '_')
    {
    {
      buf[(*here)++] = '_';
      buf[(*here)++] = '_';
      buf[(*here)++] = '1';
      buf[(*here)++] = '1';
    }
    }
  else if (c == ';')
  else if (c == ';')
    {
    {
      buf[(*here)++] = '_';
      buf[(*here)++] = '_';
      buf[(*here)++] = '2';
      buf[(*here)++] = '2';
    }
    }
  else if (c == '[')
  else if (c == '[')
    {
    {
      buf[(*here)++] = '_';
      buf[(*here)++] = '_';
      buf[(*here)++] = '3';
      buf[(*here)++] = '3';
    }
    }
 
 
  // Also check for `.' here because we might be passed an internal
  // Also check for `.' here because we might be passed an internal
  // qualified class name like `foo.bar'.
  // qualified class name like `foo.bar'.
  else if (c == '/' || c == '.')
  else if (c == '/' || c == '.')
    buf[(*here)++] = '_';
    buf[(*here)++] = '_';
  else if ((c >= '0' && c <= '9')
  else if ((c >= '0' && c <= '9')
           || (c >= 'a' && c <= 'z')
           || (c >= 'a' && c <= 'z')
           || (c >= 'A' && c <= 'Z'))
           || (c >= 'A' && c <= 'Z'))
    buf[(*here)++] = (char) c;
    buf[(*here)++] = (char) c;
  else
  else
    {
    {
      // "Unicode" character.
      // "Unicode" character.
      buf[(*here)++] = '_';
      buf[(*here)++] = '_';
      buf[(*here)++] = '0';
      buf[(*here)++] = '0';
      for (int i = 0; i < 4; ++i)
      for (int i = 0; i < 4; ++i)
        {
        {
          int val = c & 0x0f;
          int val = c & 0x0f;
          buf[(*here) + 3 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
          buf[(*here) + 3 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
          c >>= 4;
          c >>= 4;
        }
        }
      *here += 4;
      *here += 4;
    }
    }
}
}
 
 
// Compute a mangled name for a native function.  This computes the
// Compute a mangled name for a native function.  This computes the
// long name, and also returns an index which indicates where a NUL
// long name, and also returns an index which indicates where a NUL
// can be placed to create the short name.  This function assumes that
// can be placed to create the short name.  This function assumes that
// the buffer is large enough for its results.
// the buffer is large enough for its results.
static void
static void
mangled_name (jclass klass, _Jv_Utf8Const *func_name,
mangled_name (jclass klass, _Jv_Utf8Const *func_name,
              _Jv_Utf8Const *signature, char *buf, int *long_start)
              _Jv_Utf8Const *signature, char *buf, int *long_start)
{
{
  strcpy (buf, "Java_");
  strcpy (buf, "Java_");
  int here = 5;
  int here = 5;
 
 
  // Add fully qualified class name.
  // Add fully qualified class name.
  jchar *chars = _Jv_GetStringChars (klass->getName ());
  jchar *chars = _Jv_GetStringChars (klass->getName ());
  jint len = klass->getName ()->length ();
  jint len = klass->getName ()->length ();
  for (int i = 0; i < len; ++i)
  for (int i = 0; i < len; ++i)
    add_char (buf, chars[i], &here);
    add_char (buf, chars[i], &here);
 
 
  // Don't use add_char because we need a literal `_'.
  // Don't use add_char because we need a literal `_'.
  buf[here++] = '_';
  buf[here++] = '_';
 
 
  const unsigned char *fn = (const unsigned char *) func_name->chars ();
  const unsigned char *fn = (const unsigned char *) func_name->chars ();
  const unsigned char *limit = fn + func_name->len ();
  const unsigned char *limit = fn + func_name->len ();
  for (int i = 0; ; ++i)
  for (int i = 0; ; ++i)
    {
    {
      int ch = UTF8_GET (fn, limit);
      int ch = UTF8_GET (fn, limit);
      if (ch < 0)
      if (ch < 0)
        break;
        break;
      add_char (buf, ch, &here);
      add_char (buf, ch, &here);
    }
    }
 
 
  // This is where the long signature begins.
  // This is where the long signature begins.
  *long_start = here;
  *long_start = here;
  buf[here++] = '_';
  buf[here++] = '_';
  buf[here++] = '_';
  buf[here++] = '_';
 
 
  const unsigned char *sig = (const unsigned char *) signature->chars ();
  const unsigned char *sig = (const unsigned char *) signature->chars ();
  limit = sig + signature->len ();
  limit = sig + signature->len ();
  JvAssert (sig[0] == '(');
  JvAssert (sig[0] == '(');
  ++sig;
  ++sig;
  while (1)
  while (1)
    {
    {
      int ch = UTF8_GET (sig, limit);
      int ch = UTF8_GET (sig, limit);
      if (ch == ')' || ch < 0)
      if (ch == ')' || ch < 0)
        break;
        break;
      add_char (buf, ch, &here);
      add_char (buf, ch, &here);
    }
    }
 
 
  buf[here] = '\0';
  buf[here] = '\0';
}
}
 
 
JNIEnv *
JNIEnv *
_Jv_GetJNIEnvNewFrameWithLoader (::java::lang::ClassLoader *loader)
_Jv_GetJNIEnvNewFrameWithLoader (::java::lang::ClassLoader *loader)
{
{
  JNIEnv *env = _Jv_GetCurrentJNIEnv ();
  JNIEnv *env = _Jv_GetCurrentJNIEnv ();
  if (__builtin_expect (env == NULL, false))
  if (__builtin_expect (env == NULL, false))
    {
    {
      env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
      env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
      env->functions = &_Jv_JNIFunctions;
      env->functions = &_Jv_JNIFunctions;
      env->locals = NULL;
      env->locals = NULL;
      // We set env->ex below.
      // We set env->ex below.
 
 
      // Set up the bottom, reusable frame.
      // Set up the bottom, reusable frame.
      env->bottom_locals = (_Jv_JNI_LocalFrame *)
      env->bottom_locals = (_Jv_JNI_LocalFrame *)
        _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
        _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
                             + (FRAME_SIZE
                             + (FRAME_SIZE
                                * sizeof (jobject)));
                                * sizeof (jobject)));
 
 
      env->bottom_locals->marker = MARK_SYSTEM;
      env->bottom_locals->marker = MARK_SYSTEM;
      env->bottom_locals->size = FRAME_SIZE;
      env->bottom_locals->size = FRAME_SIZE;
      env->bottom_locals->next = NULL;
      env->bottom_locals->next = NULL;
      env->bottom_locals->allocated_p = false;
      env->bottom_locals->allocated_p = false;
      // We set the klass field below.
      // We set the klass field below.
      memset (&env->bottom_locals->vec[0], 0,
      memset (&env->bottom_locals->vec[0], 0,
              env->bottom_locals->size * sizeof (jobject));
              env->bottom_locals->size * sizeof (jobject));
 
 
      _Jv_SetCurrentJNIEnv (env);
      _Jv_SetCurrentJNIEnv (env);
    }
    }
 
 
  // If we're in a simple JNI call (non-nested), we can just reuse the
  // 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
  // locals frame we allocated many calls ago, back when the env was first
  // built, above.
  // built, above.
 
 
  if (__builtin_expect (env->locals == NULL, true))
  if (__builtin_expect (env->locals == NULL, true))
    {
    {
      env->locals = env->bottom_locals;
      env->locals = env->bottom_locals;
      env->locals->loader = loader;
      env->locals->loader = loader;
    }
    }
  else
  else
    {
    {
      // Alternatively, we might be re-entering JNI, in which case we can't
      // Alternatively, we might be re-entering JNI, in which case we can't
      // reuse the bottom_locals frame, because it is already underneath
      // reuse the bottom_locals frame, because it is already underneath
      // us. So we need to make a new one.
      // us. So we need to make a new one.
      _Jv_JNI_LocalFrame *frame
      _Jv_JNI_LocalFrame *frame
        = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
        = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
                                                      + (FRAME_SIZE
                                                      + (FRAME_SIZE
                                                         * sizeof (jobject)));
                                                         * sizeof (jobject)));
 
 
      frame->marker = MARK_SYSTEM;
      frame->marker = MARK_SYSTEM;
      frame->size = FRAME_SIZE;
      frame->size = FRAME_SIZE;
      frame->allocated_p = false;
      frame->allocated_p = false;
      frame->next = env->locals;
      frame->next = env->locals;
      frame->loader = loader;
      frame->loader = loader;
 
 
      memset (&frame->vec[0], 0,
      memset (&frame->vec[0], 0,
              frame->size * sizeof (jobject));
              frame->size * sizeof (jobject));
 
 
      env->locals = frame;
      env->locals = frame;
    }
    }
 
 
  env->ex = NULL;
  env->ex = NULL;
 
 
  return env;
  return env;
}
}
 
 
// Return the current thread's JNIEnv; if one does not exist, create
// Return the current thread's JNIEnv; if one does not exist, create
// it.  Also create a new system frame for use.  This is `extern "C"'
// it.  Also create a new system frame for use.  This is `extern "C"'
// because the compiler calls it.
// because the compiler calls it.
extern "C" JNIEnv *
extern "C" JNIEnv *
_Jv_GetJNIEnvNewFrame (jclass klass)
_Jv_GetJNIEnvNewFrame (jclass klass)
{
{
  return _Jv_GetJNIEnvNewFrameWithLoader (klass->getClassLoaderInternal());
  return _Jv_GetJNIEnvNewFrameWithLoader (klass->getClassLoaderInternal());
}
}
 
 
// Destroy the env's reusable resources. This is called from the thread
// Destroy the env's reusable resources. This is called from the thread
// destructor "finalize_native" in natThread.cc
// destructor "finalize_native" in natThread.cc
void
void
_Jv_FreeJNIEnv (_Jv_JNIEnv *env)
_Jv_FreeJNIEnv (_Jv_JNIEnv *env)
{
{
  if (env == NULL)
  if (env == NULL)
    return;
    return;
 
 
  if (env->bottom_locals != NULL)
  if (env->bottom_locals != NULL)
    _Jv_Free (env->bottom_locals);
    _Jv_Free (env->bottom_locals);
 
 
  _Jv_Free (env);
  _Jv_Free (env);
}
}
 
 
// Return the function which implements a particular JNI method.  If
// Return the function which implements a particular JNI method.  If
// we can't find the function, we throw the appropriate exception.
// we can't find the function, we throw the appropriate exception.
// This is `extern "C"' because the compiler uses it.
// This is `extern "C"' because the compiler uses it.
extern "C" void *
extern "C" void *
_Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
_Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name,
                     _Jv_Utf8Const *signature, MAYBE_UNUSED int args_size)
                     _Jv_Utf8Const *signature, MAYBE_UNUSED int args_size)
{
{
  int name_length = name->len();
  int name_length = name->len();
  int sig_length = signature->len();
  int sig_length = signature->len();
  char buf[10 + 6 * (name_length + sig_length) + 12];
  char buf[10 + 6 * (name_length + sig_length) + 12];
  int long_start;
  int long_start;
  void *function;
  void *function;
 
 
  // Synchronize on something convenient.  Right now we use the hash.
  // Synchronize on something convenient.  Right now we use the hash.
  JvSynchronize sync (global_ref_table);
  JvSynchronize sync (global_ref_table);
 
 
  // First see if we have an override in the hash table.
  // First see if we have an override in the hash table.
  strncpy (buf, name->chars (), name_length);
  strncpy (buf, name->chars (), name_length);
  buf[name_length] = '\0';
  buf[name_length] = '\0';
  strncpy (buf + name_length + 1, signature->chars (), sig_length);
  strncpy (buf + name_length + 1, signature->chars (), sig_length);
  buf[name_length + sig_length + 1] = '\0';
  buf[name_length + sig_length + 1] = '\0';
  NativeMethodCacheEntry meth;
  NativeMethodCacheEntry meth;
  meth.name = buf;
  meth.name = buf;
  meth.signature = buf + name_length + 1;
  meth.signature = buf + name_length + 1;
  meth.className = _Jv_GetClassNameUtf8(klass)->chars();
  meth.className = _Jv_GetClassNameUtf8(klass)->chars();
  function = nathash_find (&meth);
  function = nathash_find (&meth);
  if (function != NULL)
  if (function != NULL)
    return function;
    return function;
 
 
  // If there was no override, then look in the symbol table.
  // If there was no override, then look in the symbol table.
  buf[0] = '_';
  buf[0] = '_';
  mangled_name (klass, name, signature, buf + 1, &long_start);
  mangled_name (klass, name, signature, buf + 1, &long_start);
  char c = buf[long_start + 1];
  char c = buf[long_start + 1];
  buf[long_start + 1] = '\0';
  buf[long_start + 1] = '\0';
 
 
  function = _Jv_FindSymbolInExecutable (buf + 1);
  function = _Jv_FindSymbolInExecutable (buf + 1);
#ifdef WIN32
#ifdef WIN32
  // On Win32, we use the "stdcall" calling convention (see JNICALL
  // On Win32, we use the "stdcall" calling convention (see JNICALL
  // in jni.h).
  // in jni.h).
  // 
  // 
  // For a function named 'fooBar' that takes 'nn' bytes as arguments,
  // For a function named 'fooBar' that takes 'nn' bytes as arguments,
  // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports it
  // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports it
  // as '_fooBar@nn' and Borland C exports it as 'fooBar'. We try to
  // as '_fooBar@nn' and Borland C exports it as 'fooBar'. We try to
  // take care of all these variations here.
  // take care of all these variations here.
 
 
  char asz_buf[12];    /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */
  char asz_buf[12];    /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */
  char long_nm_sv[11]; /* Ditto, except for the '\0'. */
  char long_nm_sv[11]; /* Ditto, except for the '\0'. */
 
 
  if (function == NULL)
  if (function == NULL)
    {
    {
      // We have tried searching for the 'fooBar' form (BCC) - now
      // We have tried searching for the 'fooBar' form (BCC) - now
      // try the others.
      // try the others.
 
 
      // First, save the part of the long name that will be damaged
      // First, save the part of the long name that will be damaged
      // by appending '@nn'.
      // by appending '@nn'.
      memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv));
      memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv));
 
 
      sprintf (asz_buf, "@%d", args_size);
      sprintf (asz_buf, "@%d", args_size);
      strcat (buf, asz_buf);
      strcat (buf, asz_buf);
 
 
      // Search for the '_fooBar@nn' form (MSVC).
      // Search for the '_fooBar@nn' form (MSVC).
      function = _Jv_FindSymbolInExecutable (buf);
      function = _Jv_FindSymbolInExecutable (buf);
 
 
      if (function == NULL)
      if (function == NULL)
        {
        {
          // Search for the 'fooBar@nn' form (MinGW GCC).
          // Search for the 'fooBar@nn' form (MinGW GCC).
          function = _Jv_FindSymbolInExecutable (buf + 1);
          function = _Jv_FindSymbolInExecutable (buf + 1);
        }
        }
    }
    }
#endif /* WIN32 */
#endif /* WIN32 */
 
 
  if (function == NULL)
  if (function == NULL)
    {
    {
      buf[long_start + 1] = c;
      buf[long_start + 1] = c;
#ifdef WIN32
#ifdef WIN32
      // Restore the part of the long name that was damaged by 
      // Restore the part of the long name that was damaged by 
      // appending the '@nn'.
      // appending the '@nn'.
      memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv));
      memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv));
#endif /* WIN32 */
#endif /* WIN32 */
      function = _Jv_FindSymbolInExecutable (buf + 1);
      function = _Jv_FindSymbolInExecutable (buf + 1);
      if (function == NULL)
      if (function == NULL)
        {
        {
#ifdef WIN32
#ifdef WIN32
          strcat (buf, asz_buf);
          strcat (buf, asz_buf);
          function = _Jv_FindSymbolInExecutable (buf);
          function = _Jv_FindSymbolInExecutable (buf);
          if (function == NULL)
          if (function == NULL)
            function = _Jv_FindSymbolInExecutable (buf + 1);
            function = _Jv_FindSymbolInExecutable (buf + 1);
 
 
          if (function == NULL)
          if (function == NULL)
#endif /* WIN32 */
#endif /* WIN32 */
            {
            {
              jstring str = JvNewStringUTF (name->chars ());
              jstring str = JvNewStringUTF (name->chars ());
              throw new java::lang::UnsatisfiedLinkError (str);
              throw new java::lang::UnsatisfiedLinkError (str);
            }
            }
        }
        }
    }
    }
 
 
  return function;
  return function;
}
}
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
 
 
// This function is the stub which is used to turn an ordinary (CNI)
// This function is the stub which is used to turn an ordinary (CNI)
// method call into a JNI call.
// method call into a JNI call.
void
void
_Jv_JNIMethod::call (ffi_cif *, void *ret, INTERP_FFI_RAW_TYPE *args,
_Jv_JNIMethod::call (ffi_cif *, void *ret, INTERP_FFI_RAW_TYPE *args,
                     void *__this)
                     void *__this)
{
{
  _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
  _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this;
 
 
  JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class);
  JNIEnv *env = _Jv_GetJNIEnvNewFrame (_this->defining_class);
 
 
  // FIXME: we should mark every reference parameter as a local.  For
  // FIXME: we should mark every reference parameter as a local.  For
  // now we assume a conservative GC, and we assume that the
  // now we assume a conservative GC, and we assume that the
  // references are on the stack somewhere.
  // references are on the stack somewhere.
 
 
  // We cache the value that we find, of course, but if we don't find
  // 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
  // a value we don't cache that fact -- we might subsequently load a
  // library which finds the function in question.
  // library which finds the function in question.
  {
  {
    // Synchronize on a convenient object to ensure sanity in case two
    // Synchronize on a convenient object to ensure sanity in case two
    // threads reach this point for the same function at the same
    // threads reach this point for the same function at the same
    // time.
    // time.
    JvSynchronize sync (global_ref_table);
    JvSynchronize sync (global_ref_table);
    if (_this->function == NULL)
    if (_this->function == NULL)
      {
      {
        int args_size = sizeof (JNIEnv *) + _this->args_raw_size;
        int args_size = sizeof (JNIEnv *) + _this->args_raw_size;
 
 
        if (_this->self->accflags & java::lang::reflect::Modifier::STATIC)
        if (_this->self->accflags & java::lang::reflect::Modifier::STATIC)
          args_size += sizeof (_this->defining_class);
          args_size += sizeof (_this->defining_class);
 
 
        _this->function = _Jv_LookupJNIMethod (_this->defining_class,
        _this->function = _Jv_LookupJNIMethod (_this->defining_class,
                                               _this->self->name,
                                               _this->self->name,
                                               _this->self->signature,
                                               _this->self->signature,
                                               args_size);
                                               args_size);
      }
      }
  }
  }
 
 
  JvAssert (_this->args_raw_size % sizeof (INTERP_FFI_RAW_TYPE) == 0);
  JvAssert (_this->args_raw_size % sizeof (INTERP_FFI_RAW_TYPE) == 0);
  INTERP_FFI_RAW_TYPE
  INTERP_FFI_RAW_TYPE
      real_args[2 + _this->args_raw_size / sizeof (INTERP_FFI_RAW_TYPE)];
      real_args[2 + _this->args_raw_size / sizeof (INTERP_FFI_RAW_TYPE)];
  int offset = 0;
  int offset = 0;
 
 
  // First argument is always the environment pointer.
  // First argument is always the environment pointer.
  real_args[offset++].ptr = env;
  real_args[offset++].ptr = env;
 
 
  // For a static method, we pass in the Class.  For non-static
  // For a static method, we pass in the Class.  For non-static
  // methods, the `this' argument is already handled.
  // methods, the `this' argument is already handled.
  if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
  if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
    real_args[offset++].ptr = _this->defining_class;
    real_args[offset++].ptr = _this->defining_class;
 
 
  // In libgcj, the callee synchronizes.
  // In libgcj, the callee synchronizes.
  jobject sync = NULL;
  jobject sync = NULL;
  if ((_this->self->accflags & java::lang::reflect::Modifier::SYNCHRONIZED))
  if ((_this->self->accflags & java::lang::reflect::Modifier::SYNCHRONIZED))
    {
    {
      if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
      if ((_this->self->accflags & java::lang::reflect::Modifier::STATIC))
        sync = _this->defining_class;
        sync = _this->defining_class;
      else
      else
        sync = (jobject) args[0].ptr;
        sync = (jobject) args[0].ptr;
      _Jv_MonitorEnter (sync);
      _Jv_MonitorEnter (sync);
    }
    }
 
 
  // Copy over passed-in arguments.
  // Copy over passed-in arguments.
  memcpy (&real_args[offset], args, _this->args_raw_size);
  memcpy (&real_args[offset], args, _this->args_raw_size);
 
 
  // Add a frame to the composite (interpreted + JNI) call stack
  // Add a frame to the composite (interpreted + JNI) call stack
  java::lang::Thread *thread = java::lang::Thread::currentThread();
  java::lang::Thread *thread = java::lang::Thread::currentThread();
  _Jv_NativeFrame nat_frame (_this, thread);
  _Jv_NativeFrame nat_frame (_this, thread);
 
 
  // The actual call to the JNI function.
  // The actual call to the JNI function.
#if FFI_NATIVE_RAW_API
#if FFI_NATIVE_RAW_API
  ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function,
  ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function,
                ret, real_args);
                ret, real_args);
#else
#else
  ffi_java_raw_call (&_this->jni_cif, (void (*)()) _this->function,
  ffi_java_raw_call (&_this->jni_cif, (void (*)()) _this->function,
                     ret, real_args);
                     ret, real_args);
#endif
#endif
 
 
  // We might need to unwrap a JNI weak reference here.
  // We might need to unwrap a JNI weak reference here.
  if (_this->jni_cif.rtype == &ffi_type_pointer)
  if (_this->jni_cif.rtype == &ffi_type_pointer)
    {
    {
      _Jv_value *val = (_Jv_value *) ret;
      _Jv_value *val = (_Jv_value *) ret;
      val->object_value = unwrap (val->object_value);
      val->object_value = unwrap (val->object_value);
    }
    }
 
 
  if (sync != NULL)
  if (sync != NULL)
    _Jv_MonitorExit (sync);
    _Jv_MonitorExit (sync);
 
 
  _Jv_JNI_PopSystemFrame (env);
  _Jv_JNI_PopSystemFrame (env);
}
}
 
 
#endif /* INTERPRETER */
#endif /* INTERPRETER */
 
 


 
 
//
//
// Invocation API.
// Invocation API.
//
//
 
 
// An internal helper function.
// An internal helper function.
static jint
static jint
_Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
_Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv,
                             void *args, jboolean is_daemon)
                             void *args, jboolean is_daemon)
{
{
  JavaVMAttachArgs *attach = reinterpret_cast<JavaVMAttachArgs *> (args);
  JavaVMAttachArgs *attach = reinterpret_cast<JavaVMAttachArgs *> (args);
  java::lang::ThreadGroup *group = NULL;
  java::lang::ThreadGroup *group = NULL;
 
 
  if (attach)
  if (attach)
    {
    {
      // FIXME: do we really want to support 1.1?
      // FIXME: do we really want to support 1.1?
      if (attach->version != JNI_VERSION_1_4
      if (attach->version != JNI_VERSION_1_4
          && attach->version != JNI_VERSION_1_2
          && attach->version != JNI_VERSION_1_2
          && attach->version != JNI_VERSION_1_1)
          && attach->version != JNI_VERSION_1_1)
        return JNI_EVERSION;
        return JNI_EVERSION;
 
 
      JvAssert (java::lang::ThreadGroup::class$.isInstance (attach->group));
      JvAssert (java::lang::ThreadGroup::class$.isInstance (attach->group));
      group = reinterpret_cast<java::lang::ThreadGroup *> (attach->group);
      group = reinterpret_cast<java::lang::ThreadGroup *> (attach->group);
    }
    }
 
 
  // Attaching an already-attached thread is a no-op.
  // Attaching an already-attached thread is a no-op.
  JNIEnv *env = _Jv_GetCurrentJNIEnv ();
  JNIEnv *env = _Jv_GetCurrentJNIEnv ();
  if (env != NULL)
  if (env != NULL)
    {
    {
      *penv = reinterpret_cast<void *> (env);
      *penv = reinterpret_cast<void *> (env);
      return 0;
      return 0;
    }
    }
 
 
  env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
  env = (JNIEnv *) _Jv_MallocUnchecked (sizeof (JNIEnv));
  if (env == NULL)
  if (env == NULL)
    return JNI_ERR;
    return JNI_ERR;
  env->functions = &_Jv_JNIFunctions;
  env->functions = &_Jv_JNIFunctions;
  env->ex = NULL;
  env->ex = NULL;
  env->bottom_locals
  env->bottom_locals
    = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
    = (_Jv_JNI_LocalFrame *) _Jv_MallocUnchecked (sizeof (_Jv_JNI_LocalFrame)
                                                  + (FRAME_SIZE
                                                  + (FRAME_SIZE
                                                     * sizeof (jobject)));
                                                     * sizeof (jobject)));
  env->locals = env->bottom_locals;
  env->locals = env->bottom_locals;
  if (env->locals == NULL)
  if (env->locals == NULL)
    {
    {
      _Jv_Free (env);
      _Jv_Free (env);
      return JNI_ERR;
      return JNI_ERR;
    }
    }
 
 
  env->locals->allocated_p = false;
  env->locals->allocated_p = false;
  env->locals->marker = MARK_SYSTEM;
  env->locals->marker = MARK_SYSTEM;
  env->locals->size = FRAME_SIZE;
  env->locals->size = FRAME_SIZE;
  env->locals->loader = NULL;
  env->locals->loader = NULL;
  env->locals->next = NULL;
  env->locals->next = NULL;
 
 
  for (int i = 0; i < env->locals->size; ++i)
  for (int i = 0; i < env->locals->size; ++i)
    env->locals->vec[i] = NULL;
    env->locals->vec[i] = NULL;
 
 
  *penv = reinterpret_cast<void *> (env);
  *penv = reinterpret_cast<void *> (env);
 
 
  // This thread might already be a Java thread -- this function might
  // This thread might already be a Java thread -- this function might
  // have been called simply to set the new JNIEnv.
  // have been called simply to set the new JNIEnv.
  if (_Jv_ThreadCurrent () == NULL)
  if (_Jv_ThreadCurrent () == NULL)
    {
    {
      try
      try
        {
        {
          if (is_daemon)
          if (is_daemon)
            _Jv_AttachCurrentThreadAsDaemon (name, group);
            _Jv_AttachCurrentThreadAsDaemon (name, group);
          else
          else
            _Jv_AttachCurrentThread (name, group);
            _Jv_AttachCurrentThread (name, group);
        }
        }
      catch (jthrowable t)
      catch (jthrowable t)
        {
        {
          return JNI_ERR;
          return JNI_ERR;
        }
        }
    }
    }
  _Jv_SetCurrentJNIEnv (env);
  _Jv_SetCurrentJNIEnv (env);
 
 
  return 0;
  return 0;
}
}
 
 
// This is the one actually used by JNI.
// This is the one actually used by JNI.
jint JNICALL
jint JNICALL
_Jv_JNI_AttachCurrentThread (JavaVM *vm, void **penv, void *args)
_Jv_JNI_AttachCurrentThread (JavaVM *vm, void **penv, void *args)
{
{
  return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, false);
  return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, false);
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_AttachCurrentThreadAsDaemon (JavaVM *vm, void **penv,
_Jv_JNI_AttachCurrentThreadAsDaemon (JavaVM *vm, void **penv,
                                     void *args)
                                     void *args)
{
{
  return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, true);
  return _Jv_JNI_AttachCurrentThread (vm, NULL, penv, args, true);
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_DestroyJavaVM (JavaVM *vm)
_Jv_JNI_DestroyJavaVM (JavaVM *vm)
{
{
  JvAssert (_Jv_the_vm && vm == _Jv_the_vm);
  JvAssert (_Jv_the_vm && vm == _Jv_the_vm);
 
 
  union
  union
  {
  {
    JNIEnv *env;
    JNIEnv *env;
    void *env_p;
    void *env_p;
  };
  };
 
 
  if (_Jv_ThreadCurrent () != NULL)
  if (_Jv_ThreadCurrent () != NULL)
    {
    {
      jstring main_name;
      jstring main_name;
      // This sucks.
      // This sucks.
      try
      try
        {
        {
          main_name = JvNewStringLatin1 ("main");
          main_name = JvNewStringLatin1 ("main");
        }
        }
      catch (jthrowable t)
      catch (jthrowable t)
        {
        {
          return JNI_ERR;
          return JNI_ERR;
        }
        }
 
 
      jint r = _Jv_JNI_AttachCurrentThread (vm, main_name, &env_p,
      jint r = _Jv_JNI_AttachCurrentThread (vm, main_name, &env_p,
                                            NULL, false);
                                            NULL, false);
      if (r < 0)
      if (r < 0)
        return r;
        return r;
    }
    }
  else
  else
    env = _Jv_GetCurrentJNIEnv ();
    env = _Jv_GetCurrentJNIEnv ();
 
 
  _Jv_ThreadWait ();
  _Jv_ThreadWait ();
 
 
  // Docs say that this always returns an error code.
  // Docs say that this always returns an error code.
  return JNI_ERR;
  return JNI_ERR;
}
}
 
 
jint JNICALL
jint JNICALL
_Jv_JNI_DetachCurrentThread (JavaVM *)
_Jv_JNI_DetachCurrentThread (JavaVM *)
{
{
  jint code = _Jv_DetachCurrentThread ();
  jint code = _Jv_DetachCurrentThread ();
  return code  ? JNI_EDETACHED : 0;
  return code  ? JNI_EDETACHED : 0;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_GetEnv (JavaVM *, void **penv, jint version)
_Jv_JNI_GetEnv (JavaVM *, void **penv, jint version)
{
{
  if (_Jv_ThreadCurrent () == NULL)
  if (_Jv_ThreadCurrent () == NULL)
    {
    {
      *penv = NULL;
      *penv = NULL;
      return JNI_EDETACHED;
      return JNI_EDETACHED;
    }
    }
 
 
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
  // Handle JVMPI requests.
  // Handle JVMPI requests.
  if (version == JVMPI_VERSION_1)
  if (version == JVMPI_VERSION_1)
    {
    {
      *penv = (void *) &_Jv_JVMPI_Interface;
      *penv = (void *) &_Jv_JVMPI_Interface;
      return 0;
      return 0;
    }
    }
#endif
#endif
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
  // Handle JVMTI requests
  // Handle JVMTI requests
  if (version == JVMTI_VERSION_1_0)
  if (version == JVMTI_VERSION_1_0)
    {
    {
      *penv = (void *) _Jv_GetJVMTIEnv ();
      *penv = (void *) _Jv_GetJVMTIEnv ();
      return 0;
      return 0;
    }
    }
#endif
#endif
 
 
  // FIXME: do we really want to support 1.1?
  // FIXME: do we really want to support 1.1?
  if (version != JNI_VERSION_1_4 && version != JNI_VERSION_1_2
  if (version != JNI_VERSION_1_4 && version != JNI_VERSION_1_2
      && version != JNI_VERSION_1_1)
      && version != JNI_VERSION_1_1)
    {
    {
      *penv = NULL;
      *penv = NULL;
      return JNI_EVERSION;
      return JNI_EVERSION;
    }
    }
 
 
  *penv = (void *) _Jv_GetCurrentJNIEnv ();
  *penv = (void *) _Jv_GetCurrentJNIEnv ();
  return 0;
  return 0;
}
}
 
 
JavaVM *
JavaVM *
_Jv_GetJavaVM ()
_Jv_GetJavaVM ()
{
{
  // FIXME: synchronize
  // FIXME: synchronize
  if (! _Jv_the_vm)
  if (! _Jv_the_vm)
    {
    {
      JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
      JavaVM *nvm = (JavaVM *) _Jv_MallocUnchecked (sizeof (JavaVM));
      if (nvm != NULL)
      if (nvm != NULL)
        nvm->functions = &_Jv_JNI_InvokeFunctions;
        nvm->functions = &_Jv_JNI_InvokeFunctions;
      _Jv_the_vm = nvm;
      _Jv_the_vm = nvm;
    }
    }
 
 
  // If this is a Java thread, we want to make sure it has an
  // If this is a Java thread, we want to make sure it has an
  // associated JNIEnv.
  // associated JNIEnv.
  if (_Jv_ThreadCurrent () != NULL)
  if (_Jv_ThreadCurrent () != NULL)
    {
    {
      void *ignore;
      void *ignore;
      _Jv_JNI_AttachCurrentThread (_Jv_the_vm, &ignore, NULL);
      _Jv_JNI_AttachCurrentThread (_Jv_the_vm, &ignore, NULL);
    }
    }
 
 
  return _Jv_the_vm;
  return _Jv_the_vm;
}
}
 
 
static jint JNICALL
static jint JNICALL
_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
_Jv_JNI_GetJavaVM (JNIEnv *, JavaVM **vm)
{
{
  *vm = _Jv_GetJavaVM ();
  *vm = _Jv_GetJavaVM ();
  return *vm == NULL ? JNI_ERR : JNI_OK;
  return *vm == NULL ? JNI_ERR : JNI_OK;
}
}
 
 


 
 
#define RESERVED NULL
#define RESERVED NULL
 
 
struct JNINativeInterface_ _Jv_JNIFunctions =
struct JNINativeInterface_ _Jv_JNIFunctions =
{
{
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  _Jv_JNI_GetVersion,           // GetVersion
  _Jv_JNI_GetVersion,           // GetVersion
  _Jv_JNI_DefineClass,          // DefineClass
  _Jv_JNI_DefineClass,          // DefineClass
  _Jv_JNI_FindClass,            // FindClass
  _Jv_JNI_FindClass,            // FindClass
  _Jv_JNI_FromReflectedMethod,  // FromReflectedMethod
  _Jv_JNI_FromReflectedMethod,  // FromReflectedMethod
  _Jv_JNI_FromReflectedField,   // FromReflectedField
  _Jv_JNI_FromReflectedField,   // FromReflectedField
  _Jv_JNI_ToReflectedMethod,    // ToReflectedMethod
  _Jv_JNI_ToReflectedMethod,    // ToReflectedMethod
  _Jv_JNI_GetSuperclass,        // GetSuperclass
  _Jv_JNI_GetSuperclass,        // GetSuperclass
  _Jv_JNI_IsAssignableFrom,     // IsAssignableFrom
  _Jv_JNI_IsAssignableFrom,     // IsAssignableFrom
  _Jv_JNI_ToReflectedField,     // ToReflectedField
  _Jv_JNI_ToReflectedField,     // ToReflectedField
  _Jv_JNI_Throw,                // Throw
  _Jv_JNI_Throw,                // Throw
  _Jv_JNI_ThrowNew,             // ThrowNew
  _Jv_JNI_ThrowNew,             // ThrowNew
  _Jv_JNI_ExceptionOccurred,    // ExceptionOccurred
  _Jv_JNI_ExceptionOccurred,    // ExceptionOccurred
  _Jv_JNI_ExceptionDescribe,    // ExceptionDescribe
  _Jv_JNI_ExceptionDescribe,    // ExceptionDescribe
  _Jv_JNI_ExceptionClear,       // ExceptionClear
  _Jv_JNI_ExceptionClear,       // ExceptionClear
  _Jv_JNI_FatalError,           // FatalError
  _Jv_JNI_FatalError,           // FatalError
 
 
  _Jv_JNI_PushLocalFrame,       // PushLocalFrame
  _Jv_JNI_PushLocalFrame,       // PushLocalFrame
  _Jv_JNI_PopLocalFrame,        // PopLocalFrame
  _Jv_JNI_PopLocalFrame,        // PopLocalFrame
  _Jv_JNI_NewGlobalRef,         // NewGlobalRef
  _Jv_JNI_NewGlobalRef,         // NewGlobalRef
  _Jv_JNI_DeleteGlobalRef,      // DeleteGlobalRef
  _Jv_JNI_DeleteGlobalRef,      // DeleteGlobalRef
  _Jv_JNI_DeleteLocalRef,       // DeleteLocalRef
  _Jv_JNI_DeleteLocalRef,       // DeleteLocalRef
 
 
  _Jv_JNI_IsSameObject,         // IsSameObject
  _Jv_JNI_IsSameObject,         // IsSameObject
 
 
  _Jv_JNI_NewLocalRef,          // NewLocalRef
  _Jv_JNI_NewLocalRef,          // NewLocalRef
  _Jv_JNI_EnsureLocalCapacity,  // EnsureLocalCapacity
  _Jv_JNI_EnsureLocalCapacity,  // EnsureLocalCapacity
 
 
  _Jv_JNI_AllocObject,              // AllocObject
  _Jv_JNI_AllocObject,              // AllocObject
  _Jv_JNI_NewObject,                // NewObject
  _Jv_JNI_NewObject,                // NewObject
  _Jv_JNI_NewObjectV,               // NewObjectV
  _Jv_JNI_NewObjectV,               // NewObjectV
  _Jv_JNI_NewObjectA,               // NewObjectA
  _Jv_JNI_NewObjectA,               // NewObjectA
  _Jv_JNI_GetObjectClass,           // GetObjectClass
  _Jv_JNI_GetObjectClass,           // GetObjectClass
  _Jv_JNI_IsInstanceOf,             // IsInstanceOf
  _Jv_JNI_IsInstanceOf,             // IsInstanceOf
  _Jv_JNI_GetAnyMethodID<false>,    // GetMethodID
  _Jv_JNI_GetAnyMethodID<false>,    // GetMethodID
 
 
  _Jv_JNI_CallMethod<jobject>,          // CallObjectMethod
  _Jv_JNI_CallMethod<jobject>,          // CallObjectMethod
  _Jv_JNI_CallMethodV<jobject>,         // CallObjectMethodV
  _Jv_JNI_CallMethodV<jobject>,         // CallObjectMethodV
  _Jv_JNI_CallMethodA<jobject>,         // CallObjectMethodA
  _Jv_JNI_CallMethodA<jobject>,         // CallObjectMethodA
  _Jv_JNI_CallMethod<jboolean>,         // CallBooleanMethod
  _Jv_JNI_CallMethod<jboolean>,         // CallBooleanMethod
  _Jv_JNI_CallMethodV<jboolean>,        // CallBooleanMethodV
  _Jv_JNI_CallMethodV<jboolean>,        // CallBooleanMethodV
  _Jv_JNI_CallMethodA<jboolean>,        // CallBooleanMethodA
  _Jv_JNI_CallMethodA<jboolean>,        // CallBooleanMethodA
  _Jv_JNI_CallMethod<jbyte>,            // CallByteMethod
  _Jv_JNI_CallMethod<jbyte>,            // CallByteMethod
  _Jv_JNI_CallMethodV<jbyte>,           // CallByteMethodV
  _Jv_JNI_CallMethodV<jbyte>,           // CallByteMethodV
  _Jv_JNI_CallMethodA<jbyte>,           // CallByteMethodA
  _Jv_JNI_CallMethodA<jbyte>,           // CallByteMethodA
  _Jv_JNI_CallMethod<jchar>,            // CallCharMethod
  _Jv_JNI_CallMethod<jchar>,            // CallCharMethod
  _Jv_JNI_CallMethodV<jchar>,           // CallCharMethodV
  _Jv_JNI_CallMethodV<jchar>,           // CallCharMethodV
  _Jv_JNI_CallMethodA<jchar>,           // CallCharMethodA
  _Jv_JNI_CallMethodA<jchar>,           // CallCharMethodA
  _Jv_JNI_CallMethod<jshort>,           // CallShortMethod
  _Jv_JNI_CallMethod<jshort>,           // CallShortMethod
  _Jv_JNI_CallMethodV<jshort>,          // CallShortMethodV
  _Jv_JNI_CallMethodV<jshort>,          // CallShortMethodV
  _Jv_JNI_CallMethodA<jshort>,          // CallShortMethodA
  _Jv_JNI_CallMethodA<jshort>,          // CallShortMethodA
  _Jv_JNI_CallMethod<jint>,             // CallIntMethod
  _Jv_JNI_CallMethod<jint>,             // CallIntMethod
  _Jv_JNI_CallMethodV<jint>,            // CallIntMethodV
  _Jv_JNI_CallMethodV<jint>,            // CallIntMethodV
  _Jv_JNI_CallMethodA<jint>,            // CallIntMethodA
  _Jv_JNI_CallMethodA<jint>,            // CallIntMethodA
  _Jv_JNI_CallMethod<jlong>,            // CallLongMethod
  _Jv_JNI_CallMethod<jlong>,            // CallLongMethod
  _Jv_JNI_CallMethodV<jlong>,           // CallLongMethodV
  _Jv_JNI_CallMethodV<jlong>,           // CallLongMethodV
  _Jv_JNI_CallMethodA<jlong>,           // CallLongMethodA
  _Jv_JNI_CallMethodA<jlong>,           // CallLongMethodA
  _Jv_JNI_CallMethod<jfloat>,           // CallFloatMethod
  _Jv_JNI_CallMethod<jfloat>,           // CallFloatMethod
  _Jv_JNI_CallMethodV<jfloat>,          // CallFloatMethodV
  _Jv_JNI_CallMethodV<jfloat>,          // CallFloatMethodV
  _Jv_JNI_CallMethodA<jfloat>,          // CallFloatMethodA
  _Jv_JNI_CallMethodA<jfloat>,          // CallFloatMethodA
  _Jv_JNI_CallMethod<jdouble>,          // CallDoubleMethod
  _Jv_JNI_CallMethod<jdouble>,          // CallDoubleMethod
  _Jv_JNI_CallMethodV<jdouble>,         // CallDoubleMethodV
  _Jv_JNI_CallMethodV<jdouble>,         // CallDoubleMethodV
  _Jv_JNI_CallMethodA<jdouble>,         // CallDoubleMethodA
  _Jv_JNI_CallMethodA<jdouble>,         // CallDoubleMethodA
  _Jv_JNI_CallVoidMethod,               // CallVoidMethod
  _Jv_JNI_CallVoidMethod,               // CallVoidMethod
  _Jv_JNI_CallVoidMethodV,              // CallVoidMethodV
  _Jv_JNI_CallVoidMethodV,              // CallVoidMethodV
  _Jv_JNI_CallVoidMethodA,              // CallVoidMethodA
  _Jv_JNI_CallVoidMethodA,              // CallVoidMethodA
 
 
  // Nonvirtual method invocation functions follow.
  // Nonvirtual method invocation functions follow.
  _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,   // CallNonvirtualObjectMethod
  _Jv_JNI_CallAnyMethod<jobject, nonvirtual>,   // CallNonvirtualObjectMethod
  _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,  // CallNonvirtualObjectMethodV
  _Jv_JNI_CallAnyMethodV<jobject, nonvirtual>,  // CallNonvirtualObjectMethodV
  _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,  // CallNonvirtualObjectMethodA
  _Jv_JNI_CallAnyMethodA<jobject, nonvirtual>,  // CallNonvirtualObjectMethodA
  _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,  // CallNonvirtualBooleanMethod
  _Jv_JNI_CallAnyMethod<jboolean, nonvirtual>,  // CallNonvirtualBooleanMethod
  _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodV
  _Jv_JNI_CallAnyMethodV<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodV
  _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodA
  _Jv_JNI_CallAnyMethodA<jboolean, nonvirtual>, // CallNonvirtualBooleanMethodA
  _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,     // CallNonvirtualByteMethod
  _Jv_JNI_CallAnyMethod<jbyte, nonvirtual>,     // CallNonvirtualByteMethod
  _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,    // CallNonvirtualByteMethodV
  _Jv_JNI_CallAnyMethodV<jbyte, nonvirtual>,    // CallNonvirtualByteMethodV
  _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,    // CallNonvirtualByteMethodA
  _Jv_JNI_CallAnyMethodA<jbyte, nonvirtual>,    // CallNonvirtualByteMethodA
  _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,     // CallNonvirtualCharMethod
  _Jv_JNI_CallAnyMethod<jchar, nonvirtual>,     // CallNonvirtualCharMethod
  _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,    // CallNonvirtualCharMethodV
  _Jv_JNI_CallAnyMethodV<jchar, nonvirtual>,    // CallNonvirtualCharMethodV
  _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,    // CallNonvirtualCharMethodA
  _Jv_JNI_CallAnyMethodA<jchar, nonvirtual>,    // CallNonvirtualCharMethodA
  _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,    // CallNonvirtualShortMethod
  _Jv_JNI_CallAnyMethod<jshort, nonvirtual>,    // CallNonvirtualShortMethod
  _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,   // CallNonvirtualShortMethodV
  _Jv_JNI_CallAnyMethodV<jshort, nonvirtual>,   // CallNonvirtualShortMethodV
  _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,   // CallNonvirtualShortMethodA
  _Jv_JNI_CallAnyMethodA<jshort, nonvirtual>,   // CallNonvirtualShortMethodA
  _Jv_JNI_CallAnyMethod<jint, nonvirtual>,      // CallNonvirtualIntMethod
  _Jv_JNI_CallAnyMethod<jint, nonvirtual>,      // CallNonvirtualIntMethod
  _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,     // CallNonvirtualIntMethodV
  _Jv_JNI_CallAnyMethodV<jint, nonvirtual>,     // CallNonvirtualIntMethodV
  _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,     // CallNonvirtualIntMethodA
  _Jv_JNI_CallAnyMethodA<jint, nonvirtual>,     // CallNonvirtualIntMethodA
  _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,     // CallNonvirtualLongMethod
  _Jv_JNI_CallAnyMethod<jlong, nonvirtual>,     // CallNonvirtualLongMethod
  _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,    // CallNonvirtualLongMethodV
  _Jv_JNI_CallAnyMethodV<jlong, nonvirtual>,    // CallNonvirtualLongMethodV
  _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,    // CallNonvirtualLongMethodA
  _Jv_JNI_CallAnyMethodA<jlong, nonvirtual>,    // CallNonvirtualLongMethodA
  _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,    // CallNonvirtualFloatMethod
  _Jv_JNI_CallAnyMethod<jfloat, nonvirtual>,    // CallNonvirtualFloatMethod
  _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodV
  _Jv_JNI_CallAnyMethodV<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodV
  _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodA
  _Jv_JNI_CallAnyMethodA<jfloat, nonvirtual>,   // CallNonvirtualFloatMethodA
  _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,   // CallNonvirtualDoubleMethod
  _Jv_JNI_CallAnyMethod<jdouble, nonvirtual>,   // CallNonvirtualDoubleMethod
  _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodV
  _Jv_JNI_CallAnyMethodV<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodV
  _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodA
  _Jv_JNI_CallAnyMethodA<jdouble, nonvirtual>,  // CallNonvirtualDoubleMethodA
  _Jv_JNI_CallAnyVoidMethod<nonvirtual>,        // CallNonvirtualVoidMethod
  _Jv_JNI_CallAnyVoidMethod<nonvirtual>,        // CallNonvirtualVoidMethod
  _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,       // CallNonvirtualVoidMethodV
  _Jv_JNI_CallAnyVoidMethodV<nonvirtual>,       // CallNonvirtualVoidMethodV
  _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,       // CallNonvirtualVoidMethodA
  _Jv_JNI_CallAnyVoidMethodA<nonvirtual>,       // CallNonvirtualVoidMethodA
 
 
  _Jv_JNI_GetAnyFieldID<false>, // GetFieldID
  _Jv_JNI_GetAnyFieldID<false>, // GetFieldID
  _Jv_JNI_GetField<jobject>,    // GetObjectField
  _Jv_JNI_GetField<jobject>,    // GetObjectField
  _Jv_JNI_GetField<jboolean>,   // GetBooleanField
  _Jv_JNI_GetField<jboolean>,   // GetBooleanField
  _Jv_JNI_GetField<jbyte>,      // GetByteField
  _Jv_JNI_GetField<jbyte>,      // GetByteField
  _Jv_JNI_GetField<jchar>,      // GetCharField
  _Jv_JNI_GetField<jchar>,      // GetCharField
  _Jv_JNI_GetField<jshort>,     // GetShortField
  _Jv_JNI_GetField<jshort>,     // GetShortField
  _Jv_JNI_GetField<jint>,       // GetIntField
  _Jv_JNI_GetField<jint>,       // GetIntField
  _Jv_JNI_GetField<jlong>,      // GetLongField
  _Jv_JNI_GetField<jlong>,      // GetLongField
  _Jv_JNI_GetField<jfloat>,     // GetFloatField
  _Jv_JNI_GetField<jfloat>,     // GetFloatField
  _Jv_JNI_GetField<jdouble>,    // GetDoubleField
  _Jv_JNI_GetField<jdouble>,    // GetDoubleField
  _Jv_JNI_SetField,             // SetObjectField
  _Jv_JNI_SetField,             // SetObjectField
  _Jv_JNI_SetField,             // SetBooleanField
  _Jv_JNI_SetField,             // SetBooleanField
  _Jv_JNI_SetField,             // SetByteField
  _Jv_JNI_SetField,             // SetByteField
  _Jv_JNI_SetField,             // SetCharField
  _Jv_JNI_SetField,             // SetCharField
  _Jv_JNI_SetField,             // SetShortField
  _Jv_JNI_SetField,             // SetShortField
  _Jv_JNI_SetField,             // SetIntField
  _Jv_JNI_SetField,             // SetIntField
  _Jv_JNI_SetField,             // SetLongField
  _Jv_JNI_SetField,             // SetLongField
  _Jv_JNI_SetField,             // SetFloatField
  _Jv_JNI_SetField,             // SetFloatField
  _Jv_JNI_SetField,             // SetDoubleField
  _Jv_JNI_SetField,             // SetDoubleField
  _Jv_JNI_GetAnyMethodID<true>, // GetStaticMethodID
  _Jv_JNI_GetAnyMethodID<true>, // GetStaticMethodID
 
 
  _Jv_JNI_CallStaticMethod<jobject>,      // CallStaticObjectMethod
  _Jv_JNI_CallStaticMethod<jobject>,      // CallStaticObjectMethod
  _Jv_JNI_CallStaticMethodV<jobject>,     // CallStaticObjectMethodV
  _Jv_JNI_CallStaticMethodV<jobject>,     // CallStaticObjectMethodV
  _Jv_JNI_CallStaticMethodA<jobject>,     // CallStaticObjectMethodA
  _Jv_JNI_CallStaticMethodA<jobject>,     // CallStaticObjectMethodA
  _Jv_JNI_CallStaticMethod<jboolean>,     // CallStaticBooleanMethod
  _Jv_JNI_CallStaticMethod<jboolean>,     // CallStaticBooleanMethod
  _Jv_JNI_CallStaticMethodV<jboolean>,    // CallStaticBooleanMethodV
  _Jv_JNI_CallStaticMethodV<jboolean>,    // CallStaticBooleanMethodV
  _Jv_JNI_CallStaticMethodA<jboolean>,    // CallStaticBooleanMethodA
  _Jv_JNI_CallStaticMethodA<jboolean>,    // CallStaticBooleanMethodA
  _Jv_JNI_CallStaticMethod<jbyte>,        // CallStaticByteMethod
  _Jv_JNI_CallStaticMethod<jbyte>,        // CallStaticByteMethod
  _Jv_JNI_CallStaticMethodV<jbyte>,       // CallStaticByteMethodV
  _Jv_JNI_CallStaticMethodV<jbyte>,       // CallStaticByteMethodV
  _Jv_JNI_CallStaticMethodA<jbyte>,       // CallStaticByteMethodA
  _Jv_JNI_CallStaticMethodA<jbyte>,       // CallStaticByteMethodA
  _Jv_JNI_CallStaticMethod<jchar>,        // CallStaticCharMethod
  _Jv_JNI_CallStaticMethod<jchar>,        // CallStaticCharMethod
  _Jv_JNI_CallStaticMethodV<jchar>,       // CallStaticCharMethodV
  _Jv_JNI_CallStaticMethodV<jchar>,       // CallStaticCharMethodV
  _Jv_JNI_CallStaticMethodA<jchar>,       // CallStaticCharMethodA
  _Jv_JNI_CallStaticMethodA<jchar>,       // CallStaticCharMethodA
  _Jv_JNI_CallStaticMethod<jshort>,       // CallStaticShortMethod
  _Jv_JNI_CallStaticMethod<jshort>,       // CallStaticShortMethod
  _Jv_JNI_CallStaticMethodV<jshort>,      // CallStaticShortMethodV
  _Jv_JNI_CallStaticMethodV<jshort>,      // CallStaticShortMethodV
  _Jv_JNI_CallStaticMethodA<jshort>,      // CallStaticShortMethodA
  _Jv_JNI_CallStaticMethodA<jshort>,      // CallStaticShortMethodA
  _Jv_JNI_CallStaticMethod<jint>,         // CallStaticIntMethod
  _Jv_JNI_CallStaticMethod<jint>,         // CallStaticIntMethod
  _Jv_JNI_CallStaticMethodV<jint>,        // CallStaticIntMethodV
  _Jv_JNI_CallStaticMethodV<jint>,        // CallStaticIntMethodV
  _Jv_JNI_CallStaticMethodA<jint>,        // CallStaticIntMethodA
  _Jv_JNI_CallStaticMethodA<jint>,        // CallStaticIntMethodA
  _Jv_JNI_CallStaticMethod<jlong>,        // CallStaticLongMethod
  _Jv_JNI_CallStaticMethod<jlong>,        // CallStaticLongMethod
  _Jv_JNI_CallStaticMethodV<jlong>,       // CallStaticLongMethodV
  _Jv_JNI_CallStaticMethodV<jlong>,       // CallStaticLongMethodV
  _Jv_JNI_CallStaticMethodA<jlong>,       // CallStaticLongMethodA
  _Jv_JNI_CallStaticMethodA<jlong>,       // CallStaticLongMethodA
  _Jv_JNI_CallStaticMethod<jfloat>,       // CallStaticFloatMethod
  _Jv_JNI_CallStaticMethod<jfloat>,       // CallStaticFloatMethod
  _Jv_JNI_CallStaticMethodV<jfloat>,      // CallStaticFloatMethodV
  _Jv_JNI_CallStaticMethodV<jfloat>,      // CallStaticFloatMethodV
  _Jv_JNI_CallStaticMethodA<jfloat>,      // CallStaticFloatMethodA
  _Jv_JNI_CallStaticMethodA<jfloat>,      // CallStaticFloatMethodA
  _Jv_JNI_CallStaticMethod<jdouble>,      // CallStaticDoubleMethod
  _Jv_JNI_CallStaticMethod<jdouble>,      // CallStaticDoubleMethod
  _Jv_JNI_CallStaticMethodV<jdouble>,     // CallStaticDoubleMethodV
  _Jv_JNI_CallStaticMethodV<jdouble>,     // CallStaticDoubleMethodV
  _Jv_JNI_CallStaticMethodA<jdouble>,     // CallStaticDoubleMethodA
  _Jv_JNI_CallStaticMethodA<jdouble>,     // CallStaticDoubleMethodA
  _Jv_JNI_CallStaticVoidMethod,           // CallStaticVoidMethod
  _Jv_JNI_CallStaticVoidMethod,           // CallStaticVoidMethod
  _Jv_JNI_CallStaticVoidMethodV,          // CallStaticVoidMethodV
  _Jv_JNI_CallStaticVoidMethodV,          // CallStaticVoidMethodV
  _Jv_JNI_CallStaticVoidMethodA,          // CallStaticVoidMethodA
  _Jv_JNI_CallStaticVoidMethodA,          // CallStaticVoidMethodA
 
 
  _Jv_JNI_GetAnyFieldID<true>,         // GetStaticFieldID
  _Jv_JNI_GetAnyFieldID<true>,         // GetStaticFieldID
  _Jv_JNI_GetStaticField<jobject>,     // GetStaticObjectField
  _Jv_JNI_GetStaticField<jobject>,     // GetStaticObjectField
  _Jv_JNI_GetStaticField<jboolean>,    // GetStaticBooleanField
  _Jv_JNI_GetStaticField<jboolean>,    // GetStaticBooleanField
  _Jv_JNI_GetStaticField<jbyte>,       // GetStaticByteField
  _Jv_JNI_GetStaticField<jbyte>,       // GetStaticByteField
  _Jv_JNI_GetStaticField<jchar>,       // GetStaticCharField
  _Jv_JNI_GetStaticField<jchar>,       // GetStaticCharField
  _Jv_JNI_GetStaticField<jshort>,      // GetStaticShortField
  _Jv_JNI_GetStaticField<jshort>,      // GetStaticShortField
  _Jv_JNI_GetStaticField<jint>,        // GetStaticIntField
  _Jv_JNI_GetStaticField<jint>,        // GetStaticIntField
  _Jv_JNI_GetStaticField<jlong>,       // GetStaticLongField
  _Jv_JNI_GetStaticField<jlong>,       // GetStaticLongField
  _Jv_JNI_GetStaticField<jfloat>,      // GetStaticFloatField
  _Jv_JNI_GetStaticField<jfloat>,      // GetStaticFloatField
  _Jv_JNI_GetStaticField<jdouble>,     // GetStaticDoubleField
  _Jv_JNI_GetStaticField<jdouble>,     // GetStaticDoubleField
  _Jv_JNI_SetStaticField,              // SetStaticObjectField
  _Jv_JNI_SetStaticField,              // SetStaticObjectField
  _Jv_JNI_SetStaticField,              // SetStaticBooleanField
  _Jv_JNI_SetStaticField,              // SetStaticBooleanField
  _Jv_JNI_SetStaticField,              // SetStaticByteField
  _Jv_JNI_SetStaticField,              // SetStaticByteField
  _Jv_JNI_SetStaticField,              // SetStaticCharField
  _Jv_JNI_SetStaticField,              // SetStaticCharField
  _Jv_JNI_SetStaticField,              // SetStaticShortField
  _Jv_JNI_SetStaticField,              // SetStaticShortField
  _Jv_JNI_SetStaticField,              // SetStaticIntField
  _Jv_JNI_SetStaticField,              // SetStaticIntField
  _Jv_JNI_SetStaticField,              // SetStaticLongField
  _Jv_JNI_SetStaticField,              // SetStaticLongField
  _Jv_JNI_SetStaticField,              // SetStaticFloatField
  _Jv_JNI_SetStaticField,              // SetStaticFloatField
  _Jv_JNI_SetStaticField,              // SetStaticDoubleField
  _Jv_JNI_SetStaticField,              // SetStaticDoubleField
  _Jv_JNI_NewString,                   // NewString
  _Jv_JNI_NewString,                   // NewString
  _Jv_JNI_GetStringLength,             // GetStringLength
  _Jv_JNI_GetStringLength,             // GetStringLength
  _Jv_JNI_GetStringChars,              // GetStringChars
  _Jv_JNI_GetStringChars,              // GetStringChars
  _Jv_JNI_ReleaseStringChars,          // ReleaseStringChars
  _Jv_JNI_ReleaseStringChars,          // ReleaseStringChars
  _Jv_JNI_NewStringUTF,                // NewStringUTF
  _Jv_JNI_NewStringUTF,                // NewStringUTF
  _Jv_JNI_GetStringUTFLength,          // GetStringUTFLength
  _Jv_JNI_GetStringUTFLength,          // GetStringUTFLength
  _Jv_JNI_GetStringUTFChars,           // GetStringUTFChars
  _Jv_JNI_GetStringUTFChars,           // GetStringUTFChars
  _Jv_JNI_ReleaseStringUTFChars,       // ReleaseStringUTFChars
  _Jv_JNI_ReleaseStringUTFChars,       // ReleaseStringUTFChars
  _Jv_JNI_GetArrayLength,              // GetArrayLength
  _Jv_JNI_GetArrayLength,              // GetArrayLength
  _Jv_JNI_NewObjectArray,              // NewObjectArray
  _Jv_JNI_NewObjectArray,              // NewObjectArray
  _Jv_JNI_GetObjectArrayElement,       // GetObjectArrayElement
  _Jv_JNI_GetObjectArrayElement,       // GetObjectArrayElement
  _Jv_JNI_SetObjectArrayElement,       // SetObjectArrayElement
  _Jv_JNI_SetObjectArrayElement,       // SetObjectArrayElement
  _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
  _Jv_JNI_NewPrimitiveArray<jboolean, JvPrimClass (boolean)>,
                                                            // NewBooleanArray
                                                            // NewBooleanArray
  _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,     // NewByteArray
  _Jv_JNI_NewPrimitiveArray<jbyte, JvPrimClass (byte)>,     // NewByteArray
  _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,     // NewCharArray
  _Jv_JNI_NewPrimitiveArray<jchar, JvPrimClass (char)>,     // NewCharArray
  _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,   // NewShortArray
  _Jv_JNI_NewPrimitiveArray<jshort, JvPrimClass (short)>,   // NewShortArray
  _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,       // NewIntArray
  _Jv_JNI_NewPrimitiveArray<jint, JvPrimClass (int)>,       // NewIntArray
  _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,     // NewLongArray
  _Jv_JNI_NewPrimitiveArray<jlong, JvPrimClass (long)>,     // NewLongArray
  _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,   // NewFloatArray
  _Jv_JNI_NewPrimitiveArray<jfloat, JvPrimClass (float)>,   // NewFloatArray
  _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>, // NewDoubleArray
  _Jv_JNI_NewPrimitiveArray<jdouble, JvPrimClass (double)>, // NewDoubleArray
  _Jv_JNI_GetPrimitiveArrayElements<jboolean, JvPrimClass (boolean)>,
  _Jv_JNI_GetPrimitiveArrayElements<jboolean, JvPrimClass (boolean)>,
                                            // GetBooleanArrayElements
                                            // GetBooleanArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jbyte, JvPrimClass (byte)>,
  _Jv_JNI_GetPrimitiveArrayElements<jbyte, JvPrimClass (byte)>,
                                            // GetByteArrayElements
                                            // GetByteArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jchar, JvPrimClass (char)>,
  _Jv_JNI_GetPrimitiveArrayElements<jchar, JvPrimClass (char)>,
                                            // GetCharArrayElements
                                            // GetCharArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jshort, JvPrimClass (short)>,
  _Jv_JNI_GetPrimitiveArrayElements<jshort, JvPrimClass (short)>,
                                            // GetShortArrayElements
                                            // GetShortArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jint, JvPrimClass (int)>,
  _Jv_JNI_GetPrimitiveArrayElements<jint, JvPrimClass (int)>,
                                            // GetIntArrayElements
                                            // GetIntArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jlong, JvPrimClass (long)>,
  _Jv_JNI_GetPrimitiveArrayElements<jlong, JvPrimClass (long)>,
                                            // GetLongArrayElements
                                            // GetLongArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jfloat, JvPrimClass (float)>,
  _Jv_JNI_GetPrimitiveArrayElements<jfloat, JvPrimClass (float)>,
                                            // GetFloatArrayElements
                                            // GetFloatArrayElements
  _Jv_JNI_GetPrimitiveArrayElements<jdouble, JvPrimClass (double)>,
  _Jv_JNI_GetPrimitiveArrayElements<jdouble, JvPrimClass (double)>,
                                            // GetDoubleArrayElements
                                            // GetDoubleArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jboolean, JvPrimClass (boolean)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jboolean, JvPrimClass (boolean)>,
                                            // ReleaseBooleanArrayElements
                                            // ReleaseBooleanArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jbyte, JvPrimClass (byte)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jbyte, JvPrimClass (byte)>,
                                            // ReleaseByteArrayElements
                                            // ReleaseByteArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jchar, JvPrimClass (char)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jchar, JvPrimClass (char)>,
                                            // ReleaseCharArrayElements
                                            // ReleaseCharArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jshort, JvPrimClass (short)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jshort, JvPrimClass (short)>,
                                            // ReleaseShortArrayElements
                                            // ReleaseShortArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jint, JvPrimClass (int)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jint, JvPrimClass (int)>,
                                            // ReleaseIntArrayElements
                                            // ReleaseIntArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jlong, JvPrimClass (long)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jlong, JvPrimClass (long)>,
                                            // ReleaseLongArrayElements
                                            // ReleaseLongArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jfloat, JvPrimClass (float)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jfloat, JvPrimClass (float)>,
                                            // ReleaseFloatArrayElements
                                            // ReleaseFloatArrayElements
  _Jv_JNI_ReleasePrimitiveArrayElements<jdouble, JvPrimClass (double)>,
  _Jv_JNI_ReleasePrimitiveArrayElements<jdouble, JvPrimClass (double)>,
                                            // ReleaseDoubleArrayElements
                                            // ReleaseDoubleArrayElements
  _Jv_JNI_GetPrimitiveArrayRegion<jboolean, JvPrimClass (boolean)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jboolean, JvPrimClass (boolean)>,
                                            // GetBooleanArrayRegion
                                            // GetBooleanArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jbyte, JvPrimClass (byte)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jbyte, JvPrimClass (byte)>,
                                            // GetByteArrayRegion
                                            // GetByteArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jchar, JvPrimClass (char)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jchar, JvPrimClass (char)>,
                                            // GetCharArrayRegion
                                            // GetCharArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jshort, JvPrimClass (short)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jshort, JvPrimClass (short)>,
                                            // GetShortArrayRegion
                                            // GetShortArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jint, JvPrimClass (int)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jint, JvPrimClass (int)>,
                                            // GetIntArrayRegion
                                            // GetIntArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jlong, JvPrimClass (long)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jlong, JvPrimClass (long)>,
                                            // GetLongArrayRegion
                                            // GetLongArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jfloat, JvPrimClass (float)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jfloat, JvPrimClass (float)>,
                                            // GetFloatArrayRegion
                                            // GetFloatArrayRegion
  _Jv_JNI_GetPrimitiveArrayRegion<jdouble, JvPrimClass (double)>,
  _Jv_JNI_GetPrimitiveArrayRegion<jdouble, JvPrimClass (double)>,
                                            // GetDoubleArrayRegion
                                            // GetDoubleArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jboolean, JvPrimClass (boolean)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jboolean, JvPrimClass (boolean)>,
                                            // SetBooleanArrayRegion
                                            // SetBooleanArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jbyte, JvPrimClass (byte)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jbyte, JvPrimClass (byte)>,
                                            // SetByteArrayRegion
                                            // SetByteArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jchar, JvPrimClass (char)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jchar, JvPrimClass (char)>,
                                            // SetCharArrayRegion
                                            // SetCharArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jshort, JvPrimClass (short)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jshort, JvPrimClass (short)>,
                                            // SetShortArrayRegion
                                            // SetShortArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jint, JvPrimClass (int)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jint, JvPrimClass (int)>,
                                            // SetIntArrayRegion
                                            // SetIntArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jlong, JvPrimClass (long)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jlong, JvPrimClass (long)>,
                                            // SetLongArrayRegion
                                            // SetLongArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jfloat, JvPrimClass (float)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jfloat, JvPrimClass (float)>,
                                            // SetFloatArrayRegion
                                            // SetFloatArrayRegion
  _Jv_JNI_SetPrimitiveArrayRegion<jdouble, JvPrimClass (double)>,
  _Jv_JNI_SetPrimitiveArrayRegion<jdouble, JvPrimClass (double)>,
                                            // SetDoubleArrayRegion
                                            // SetDoubleArrayRegion
  _Jv_JNI_RegisterNatives,                  // RegisterNatives
  _Jv_JNI_RegisterNatives,                  // RegisterNatives
  _Jv_JNI_UnregisterNatives,                // UnregisterNatives
  _Jv_JNI_UnregisterNatives,                // UnregisterNatives
  _Jv_JNI_MonitorEnter,                     // MonitorEnter
  _Jv_JNI_MonitorEnter,                     // MonitorEnter
  _Jv_JNI_MonitorExit,                      // MonitorExit
  _Jv_JNI_MonitorExit,                      // MonitorExit
  _Jv_JNI_GetJavaVM,                        // GetJavaVM
  _Jv_JNI_GetJavaVM,                        // GetJavaVM
 
 
  _Jv_JNI_GetStringRegion,                  // GetStringRegion
  _Jv_JNI_GetStringRegion,                  // GetStringRegion
  _Jv_JNI_GetStringUTFRegion,               // GetStringUTFRegion
  _Jv_JNI_GetStringUTFRegion,               // GetStringUTFRegion
  _Jv_JNI_GetPrimitiveArrayCritical,        // GetPrimitiveArrayCritical
  _Jv_JNI_GetPrimitiveArrayCritical,        // GetPrimitiveArrayCritical
  _Jv_JNI_ReleasePrimitiveArrayCritical,    // ReleasePrimitiveArrayCritical
  _Jv_JNI_ReleasePrimitiveArrayCritical,    // ReleasePrimitiveArrayCritical
  _Jv_JNI_GetStringCritical,                // GetStringCritical
  _Jv_JNI_GetStringCritical,                // GetStringCritical
  _Jv_JNI_ReleaseStringCritical,            // ReleaseStringCritical
  _Jv_JNI_ReleaseStringCritical,            // ReleaseStringCritical
 
 
  _Jv_JNI_NewWeakGlobalRef,                 // NewWeakGlobalRef
  _Jv_JNI_NewWeakGlobalRef,                 // NewWeakGlobalRef
  _Jv_JNI_DeleteWeakGlobalRef,              // DeleteWeakGlobalRef
  _Jv_JNI_DeleteWeakGlobalRef,              // DeleteWeakGlobalRef
 
 
  _Jv_JNI_ExceptionCheck,                   // ExceptionCheck
  _Jv_JNI_ExceptionCheck,                   // ExceptionCheck
 
 
  _Jv_JNI_NewDirectByteBuffer,              // NewDirectByteBuffer
  _Jv_JNI_NewDirectByteBuffer,              // NewDirectByteBuffer
  _Jv_JNI_GetDirectBufferAddress,           // GetDirectBufferAddress
  _Jv_JNI_GetDirectBufferAddress,           // GetDirectBufferAddress
  _Jv_JNI_GetDirectBufferCapacity,          // GetDirectBufferCapacity
  _Jv_JNI_GetDirectBufferCapacity,          // GetDirectBufferCapacity
 
 
  _Jv_JNI_GetObjectRefType                  // GetObjectRefType
  _Jv_JNI_GetObjectRefType                  // GetObjectRefType
};
};
 
 
struct JNIInvokeInterface_ _Jv_JNI_InvokeFunctions =
struct JNIInvokeInterface_ _Jv_JNI_InvokeFunctions =
{
{
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
  RESERVED,
 
 
  _Jv_JNI_DestroyJavaVM,
  _Jv_JNI_DestroyJavaVM,
  _Jv_JNI_AttachCurrentThread,
  _Jv_JNI_AttachCurrentThread,
  _Jv_JNI_DetachCurrentThread,
  _Jv_JNI_DetachCurrentThread,
  _Jv_JNI_GetEnv,
  _Jv_JNI_GetEnv,
  _Jv_JNI_AttachCurrentThreadAsDaemon
  _Jv_JNI_AttachCurrentThreadAsDaemon
};
};
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.