// natClass.cc - Implementation of java.lang.Class native methods.

/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
   2010 Free Software Foundation

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

#include <config.h>

#include <limits.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>

#pragma implementation "Class.h"

#include <gcj/cni.h>
#include <jvm.h>
#include <java-threads.h>

#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/String.h>
#include <java/lang/reflect/Modifier.h>
#include <java/lang/reflect/Member.h>
#include <java/lang/reflect/Method.h>
#include <java/lang/reflect/Field.h>
#include <java/lang/reflect/Proxy.h>
#include <java/lang/reflect/Constructor.h>
#include <java/lang/AbstractMethodError.h>
#include <java/lang/ArrayStoreException.h>
#include <java/lang/ClassCastException.h>
#include <java/lang/ClassNotFoundException.h>
#include <java/lang/ExceptionInInitializerError.h>
#include <java/lang/IllegalAccessException.h>
#include <java/lang/IllegalAccessError.h>
#include <java/lang/IllegalArgumentException.h>
#include <java/lang/IncompatibleClassChangeError.h>
#include <java/lang/NoSuchFieldError.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/InstantiationException.h>
#include <java/lang/NoClassDefFoundError.h>
#include <java/lang/NoSuchFieldException.h>
#include <java/lang/NoSuchMethodError.h>
#include <java/lang/NoSuchMethodException.h>
#include <java/lang/Thread.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/RuntimePermission.h>
#include <java/lang/System.h>
#include <java/lang/SecurityException.h>
#include <java/lang/SecurityManager.h>
#include <java/lang/StringBuffer.h>
#include <java/lang/VMClassLoader.h>
#include <gcj/method.h>
#include <gnu/gcj/RawData.h>
#include <java/lang/VerifyError.h>
#include <java/lang/InternalError.h>
#include <java/lang/TypeNotPresentException.h>
#include <java/lang/Byte.h>
#include <java/lang/Short.h>
#include <java/lang/Integer.h>
#include <java/lang/Float.h>
#include <java/lang/Double.h>
#include <java/lang/Long.h>
#include <java/lang/Character.h>
#include <java/lang/Boolean.h>
#include <java/lang/annotation/Annotation.h>
#include <java/util/HashMap.h>
#include <java/util/Map.h>
#include <sun/reflect/annotation/AnnotationInvocationHandler.h>
#include <java/lang/Enum.h>

#include <java-cpool.h>
#include <java-interp.h>
#include <java-assert.h>
#include <java-stack.h>
#include <execution.h>



using namespace gcj;

jclass
java::lang::Class::forName (jstring className, jboolean initialize,
                            java::lang::ClassLoader *loader)
{
  if (! className)
    throw new java::lang::NullPointerException;

  jsize length = _Jv_GetStringUTFLength (className);
  char buffer[length];
  _Jv_GetStringUTFRegion (className, 0, className->length(), buffer);

  _Jv_Utf8Const *name = _Jv_makeUtf8Const (buffer, length);

  if (! _Jv_VerifyClassName (name))
    throw new java::lang::ClassNotFoundException (className);

  jclass klass = (buffer[0] == '[' 
		  ? _Jv_FindClassFromSignature (name->chars(), loader)
		  : _Jv_FindClass (name, loader));

  if (klass == NULL)
    throw new java::lang::ClassNotFoundException (className);

  if (initialize)
    _Jv_InitClass (klass);

  return klass;
}

jclass
java::lang::Class::forName (jstring className)
{
  java::lang::ClassLoader *loader = NULL;

  jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
  if (caller)
    loader = caller->getClassLoaderInternal();

  return forName (className, true, loader);
}

java::lang::ClassLoader *
java::lang::Class::getClassLoader (void)
{
  java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
  if (s != NULL)
    {
      jclass caller = _Jv_StackTrace::GetCallingClass (&Class::class$);
      return getClassLoader (caller);
   }

  return loader;
}

java::lang::ClassLoader *
java::lang::Class::getClassLoader (jclass caller)
{
  java::lang::SecurityManager *s = java::lang::System::getSecurityManager();
  if (s != NULL)
    {
      ClassLoader *caller_loader = caller->getClassLoaderInternal();

      // If the caller has a non-null class loader, and that loader
      // is not this class' loader or an ancestor thereof, then do a
      // security check.
      if (caller_loader != NULL && ! caller_loader->isAncestorOf(loader))
	s->checkPermission (new RuntimePermission (JvNewStringLatin1 ("getClassLoader")));
    }

  return loader;
}

java::lang::reflect::Constructor *
java::lang::Class::getConstructor (JArray<jclass> *param_types)
{
  memberAccessCheck(java::lang::reflect::Member::PUBLIC);

  jstring partial_sig = getSignature (param_types, true);
  jint hash = partial_sig->hashCode ();

  int i = isPrimitive () ? 0 : method_count;
  while (--i >= 0)
    {
      if (_Jv_equalUtf8Consts (methods[i].name, init_name)
	  && _Jv_equal (methods[i].signature, partial_sig, hash))
	{
	  // Found it.  For getConstructor, the constructor must be
	  // public.
	  using namespace java::lang::reflect;
	  if (! Modifier::isPublic(methods[i].accflags))
	    break;
	  Constructor *cons = new Constructor ();
	  cons->offset = (char *) (&methods[i]) - (char *) methods;
	  cons->declaringClass = this;
	  return cons;
	}
    }
  throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
}

JArray<java::lang::reflect::Constructor *> *
java::lang::Class::getDeclaredConstructors (jboolean publicOnly)
{
  int numConstructors = 0;
  int max = isPrimitive () ? 0 : method_count;
  int i;
  for (i = max; --i >= 0; )
    {
      _Jv_Method *method = &methods[i];
      if (method->name == NULL
	  || ! _Jv_equalUtf8Consts (method->name, init_name))
	continue;
      if (publicOnly
	  && ! java::lang::reflect::Modifier::isPublic(method->accflags))
	continue;
      numConstructors++;
    }
  JArray<java::lang::reflect::Constructor *> *result
    = (JArray<java::lang::reflect::Constructor *> *)
    JvNewObjectArray (numConstructors,
		      &java::lang::reflect::Constructor::class$,
		      NULL);
  java::lang::reflect::Constructor** cptr = elements (result);
  for (i = 0;  i < max;  i++)
    {
      _Jv_Method *method = &methods[i];
      if (method->name == NULL
	  || ! _Jv_equalUtf8Consts (method->name, init_name))
	continue;
      if (publicOnly
	  && ! java::lang::reflect::Modifier::isPublic(method->accflags))
	continue;
      java::lang::reflect::Constructor *cons
	= new java::lang::reflect::Constructor ();
      cons->offset = (char *) method - (char *) methods;
      cons->declaringClass = this;
      *cptr++ = cons;
    }
  return result;
}

java::lang::reflect::Constructor *
java::lang::Class::getDeclaredConstructor (JArray<jclass> *param_types)
{
  memberAccessCheck(java::lang::reflect::Member::DECLARED);

  jstring partial_sig = getSignature (param_types, true);
  jint hash = partial_sig->hashCode ();

  int i = isPrimitive () ? 0 : method_count;
  while (--i >= 0)
    {
      if (_Jv_equalUtf8Consts (methods[i].name, init_name)
	  && _Jv_equal (methods[i].signature, partial_sig, hash))
	{
	  // Found it.
	  using namespace java::lang::reflect;
	  Constructor *cons = new Constructor ();
	  cons->offset = (char *) (&methods[i]) - (char *) methods;
	  cons->declaringClass = this;
	  return cons;
	}
    }
  throw new java::lang::NoSuchMethodException (_Jv_NewStringUtf8Const (init_name));
}

java::lang::reflect::Field *
java::lang::Class::getField (jstring name, jint hash)
{
  java::lang::reflect::Field* rfield;
  for (int i = 0;  i < field_count;  i++)
    {
      _Jv_Field *field = &fields[i];
      if (! _Jv_equal (field->name, name, hash))
	continue;
      if (! (field->getModifiers() & java::lang::reflect::Modifier::PUBLIC))
	continue;
      rfield = new java::lang::reflect::Field ();
      rfield->offset = (char*) field - (char*) fields;
      rfield->declaringClass = this;
      rfield->name = name;
      return rfield;
    }
  jclass superclass = getSuperclass();
  if (superclass == NULL)
    return NULL;
  rfield = superclass->getField(name, hash);
  for (int i = 0; i < interface_count && rfield == NULL; ++i)
    rfield = interfaces[i]->getField (name, hash);
  return rfield;
}

java::lang::reflect::Field *
java::lang::Class::getDeclaredField (jstring name)
{
  memberAccessCheck(java::lang::reflect::Member::DECLARED);
  int hash = name->hashCode();
  for (int i = 0;  i < field_count;  i++)
    {
      _Jv_Field *field = &fields[i];
      if (! _Jv_equal (field->name, name, hash))
	continue;
      java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
      rfield->offset = (char*) field - (char*) fields;
      rfield->declaringClass = this;
      rfield->name = name;
      return rfield;
    }
  throw new java::lang::NoSuchFieldException (name);
}

JArray<java::lang::reflect::Field *> *
java::lang::Class::getDeclaredFields (jboolean public_only)
{
  int size;
  if (public_only)
    {
      size = 0;
      for (int i = 0; i < field_count; ++i)
	{
	  _Jv_Field *field = &fields[i];
	  if ((field->flags & java::lang::reflect::Modifier::PUBLIC))
	    ++size;
	}
    }
  else
    size = field_count;

  JArray<java::lang::reflect::Field *> *result
    = (JArray<java::lang::reflect::Field *> *)
    JvNewObjectArray (size, &java::lang::reflect::Field::class$, NULL);
  java::lang::reflect::Field** fptr = elements (result);
  for (int i = 0;  i < field_count;  i++)
    {
      _Jv_Field *field = &fields[i];
      if (public_only
	  && ! (field->flags & java::lang::reflect::Modifier::PUBLIC))
	continue;
      java::lang::reflect::Field* rfield = new java::lang::reflect::Field ();
      rfield->offset = (char*) field - (char*) fields;
      rfield->declaringClass = this;
      *fptr++ = rfield;
    }
  return result;
}

void
java::lang::Class::getSignature (java::lang::StringBuffer *buffer)
{
  if (isPrimitive())
    buffer->append((jchar) method_count);
  else
    {
      jstring name = getName();
      if (name->charAt(0) != '[')
	buffer->append((jchar) 'L');
      buffer->append(name);
      if (name->charAt(0) != '[')
	buffer->append((jchar) ';');
    }
}

// This doesn't have to be native.  It is an implementation detail
// only called from the C++ code, though, so maybe this is clearer.
jstring
java::lang::Class::getSignature (JArray<jclass> *param_types,
				 jboolean is_constructor)
{
  java::lang::StringBuffer *buf = new java::lang::StringBuffer ();
  buf->append((jchar) '(');
  // A NULL param_types means "no parameters".
  if (param_types != NULL)
    {
      jclass *v = elements (param_types);
      for (int i = 0; i < param_types->length; ++i)
	v[i]->getSignature(buf);
    }
  buf->append((jchar) ')');
  if (is_constructor)
    buf->append((jchar) 'V');
  return buf->toString();
}

java::lang::reflect::Method *
java::lang::Class::_getDeclaredMethod (jstring name,
				       JArray<jclass> *param_types)
{
  jstring partial_sig = getSignature (param_types, false);
  jint p_len = partial_sig->length();
  _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
  int i = isPrimitive () ? 0 : method_count;
  while (--i >= 0)
    {
      if (_Jv_equalUtf8Consts (methods[i].name, utf_name)
	  && _Jv_equaln (methods[i].signature, partial_sig, p_len)
	  && (methods[i].accflags
	      & java::lang::reflect::Modifier::INVISIBLE) == 0)
	{
	  // Found it.
	  using namespace java::lang::reflect;
	  Method *rmethod = new Method ();
	  rmethod->offset = (char*) (&methods[i]) - (char*) methods;
	  rmethod->declaringClass = this;
	  return rmethod;
	}
    }
  return NULL;
}

JArray<java::lang::reflect::Method *> *
java::lang::Class::getDeclaredMethods (void)
{
  memberAccessCheck(java::lang::reflect::Member::DECLARED);

  int numMethods = 0;
  int max = isPrimitive () ? 0 : method_count;
  int i;
  for (i = max; --i >= 0; )
    {
      _Jv_Method *method = &methods[i];
      if (method->name == NULL
	  || _Jv_equalUtf8Consts (method->name, clinit_name)
	  || _Jv_equalUtf8Consts (method->name, init_name)
	  || _Jv_equalUtf8Consts (method->name, finit_name)
	  || (methods[i].accflags
	      & java::lang::reflect::Modifier::INVISIBLE) != 0)
	continue;
      numMethods++;
    }
  JArray<java::lang::reflect::Method *> *result
    = (JArray<java::lang::reflect::Method *> *)
    JvNewObjectArray (numMethods, &java::lang::reflect::Method::class$, NULL);
  java::lang::reflect::Method** mptr = elements (result);
  for (i = 0;  i < max;  i++)
    {
      _Jv_Method *method = &methods[i];
      if (method->name == NULL
	  || _Jv_equalUtf8Consts (method->name, clinit_name)
	  || _Jv_equalUtf8Consts (method->name, init_name)
	  || _Jv_equalUtf8Consts (method->name, finit_name)
	  || (methods[i].accflags
	      & java::lang::reflect::Modifier::INVISIBLE) != 0)
	continue;
      java::lang::reflect::Method* rmethod
	= new java::lang::reflect::Method ();
      rmethod->offset = (char*) method - (char*) methods;
      rmethod->declaringClass = this;
      *mptr++ = rmethod;
    }
  return result;
}

jstring
java::lang::Class::getName (void)
{
  return name->toString();
}

JArray<jclass> *
java::lang::Class::getInterfaces (void)
{
  jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
  jobject *data = elements (r);
  for (int i = 0; i < interface_count; ++i)
    {
      typedef unsigned int uaddr __attribute__ ((mode (pointer)));
      data[i] = interfaces[i];
      if ((uaddr)data[i] < (uaddr)constants.size)
	fprintf (stderr, "ERROR !!!\n");
    }
  return reinterpret_cast<JArray<jclass> *> (r);
}

java::lang::reflect::Method *
java::lang::Class::_getMethod (jstring name, JArray<jclass> *param_types)
{
  jstring partial_sig = getSignature (param_types, false);
  jint p_len = partial_sig->length();
  _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);

   for (Class *klass = this; klass; klass = klass->getSuperclass())
    {
      int i = klass->isPrimitive () ? 0 : klass->method_count;
      while (--i >= 0)
	{
	  if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
	      && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len)
	      && (klass->methods[i].accflags
		  & java::lang::reflect::Modifier::INVISIBLE) == 0)
	    {
	      // Found it.
	      using namespace java::lang::reflect;

	      // Method must be public.
	      if (! Modifier::isPublic (klass->methods[i].accflags))
		break;

	      Method *rmethod = new Method ();
	      rmethod->offset = ((char *) (&klass->methods[i])
				 - (char *) klass->methods);
	      rmethod->declaringClass = klass;
	      return rmethod;
	    }
	}
    }

  // If we haven't found a match, and this class is an interface, then
  // check all the superinterfaces.
  if (isInterface())
    {
      for (int i = 0; i < interface_count; ++i)
	{
	  using namespace java::lang::reflect;
	  Method *rmethod = interfaces[i]->_getMethod (name, param_types);
	  if (rmethod != NULL)
	    return rmethod;
	}
    }

  return NULL;
}

// This is a very slow implementation, since it re-scans all the
// methods we've already listed to make sure we haven't duplicated a
// method.  It also over-estimates the required size, so we have to
// shrink the result array later.
jint
java::lang::Class::_getMethods (JArray<java::lang::reflect::Method *> *result,
				jint offset)
{
  jint count = 0;

  // First examine all local methods
  for (int i = isPrimitive () ? 0 : method_count; --i >= 0; )
    {
      _Jv_Method *method = &methods[i];
      if (method->name == NULL
	  || _Jv_equalUtf8Consts (method->name, clinit_name)
	  || _Jv_equalUtf8Consts (method->name, init_name)
	  || _Jv_equalUtf8Consts (method->name, finit_name)
	  || (method->accflags
	      & java::lang::reflect::Modifier::INVISIBLE) != 0)
	continue;
      // Only want public methods.
      if (! java::lang::reflect::Modifier::isPublic (method->accflags))
	continue;

      // This is where we over-count the slots required if we aren't
      // filling the result for real.
      if (result != NULL)
	{
	  jboolean add = true;
	  java::lang::reflect::Method **mp = elements (result);
	  // If we already have a method with this name and signature,
	  // then ignore this one.  This can happen with virtual
	  // methods.
	  for (int j = 0; j < offset; ++j)
	    {
	      _Jv_Method *meth_2 = _Jv_FromReflectedMethod (mp[j]);
	      if (_Jv_equalUtf8Consts (method->name, meth_2->name)
		  && _Jv_equalUtf8Consts (method->signature,
					  meth_2->signature))
		{
		  add = false;
		  break;
		}
	    }
	  if (! add)
	    continue;
	}

      if (result != NULL)
	{
	  using namespace java::lang::reflect;
	  Method *rmethod = new Method ();
	  rmethod->offset = (char *) method - (char *) methods;
	  rmethod->declaringClass = this;
	  Method **mp = elements (result);
	  mp[offset + count] = rmethod;
	}
      ++count;
    }
  offset += count;

  // Now examine superclasses.
  if (getSuperclass () != NULL)
    {
      jint s_count = getSuperclass()->_getMethods (result, offset);
      offset += s_count;
      count += s_count;
    }

  // Finally, examine interfaces.
  for (int i = 0; i < interface_count; ++i)
    {
      int f_count = interfaces[i]->_getMethods (result, offset);
      count += f_count;
      offset += f_count;
    }

  return count;
}

JArray<java::lang::reflect::Method *> *
java::lang::Class::getMethods (void)
{
  using namespace java::lang::reflect;

  memberAccessCheck(Member::PUBLIC);

  // This will overestimate the size we need.
  jint count = _getMethods (NULL, 0);

  JArray<Method *> *result
    = ((JArray<Method *> *) JvNewObjectArray (count,
					      &Method::class$,
					      NULL));

  // When filling the array for real, we get the actual count.  Then
  // we resize the array.
  jint real_count = _getMethods (result, 0);

  if (real_count != count)
    {
      JArray<Method *> *r2
	= ((JArray<Method *> *) JvNewObjectArray (real_count,
						  &Method::class$,
						  NULL));
      
      Method **destp = elements (r2);
      Method **srcp = elements (result);

      for (int i = 0; i < real_count; ++i)
	*destp++ = *srcp++;

      result = r2;
    }

  return result;
}

jboolean
java::lang::Class::isAssignableFrom (jclass klass)
{
  // Arguments may not have been initialized, given ".class" syntax.
  // This ensures we can at least look at their superclasses.
  _Jv_Linker::wait_for_state (this, JV_STATE_LOADING);
  _Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
  return _Jv_IsAssignableFrom (klass, this);
}

jboolean
java::lang::Class::isInstance (jobject obj)
{
  if (! obj)
    return false;
  return _Jv_IsAssignableFrom (JV_CLASS (obj), this);
}

jobject
java::lang::Class::newInstance (void)
{
  memberAccessCheck(java::lang::reflect::Member::PUBLIC);

  if (isPrimitive ()
      || isInterface ()
      || isArray ()
      || java::lang::reflect::Modifier::isAbstract(accflags))
    throw new java::lang::InstantiationException (getName ());

  _Jv_InitClass (this);

  _Jv_Method *meth = _Jv_GetMethodLocal (this, init_name, void_signature);
  if (! meth)
    throw new java::lang::InstantiationException (getName());

  jobject r = _Jv_AllocObject (this);
  /* Class constructors/destructors have __thiscall calling
     convention for 32-bit native Windows ABI.  */
#if defined (__MINGW32__) && defined (__i386__)
  ((void (__thiscall *) (jobject)) meth->ncode) (r);
#else
  ((void (*) (jobject)) meth->ncode) (r);
#endif
  return r;
}

void
java::lang::Class::finalize (void)
{
  // Array classes don't have an engine, and don't need to be finalized.
   if (engine)
     engine->unregister(this);
}

#ifdef INTERPRETER
void
_Jv_ClosureList::releaseClosures (_Jv_ClosureList **closures)
{
  if (!closures)
    return;

  while (_Jv_ClosureList *current = *closures)
    {
      *closures = current->next;
      ffi_closure_free (current->ptr);
    }
}

void
_Jv_ClosureList::registerClosure (jclass klass, void *ptr)
{
  _Jv_ClosureList **closures = klass->engine->get_closure_list (klass);
  if (closures)
    {
      this->ptr = ptr;
      this->next = *closures;
      *closures = this;
    }
}
#endif

// This implements the initialization process for a class.  From Spec
// section 12.4.2.
void
java::lang::Class::initializeClass (void)
{
  // Short-circuit to avoid needless locking (expression includes
  // JV_STATE_PHANTOM and JV_STATE_DONE).
  if (state >= JV_STATE_PHANTOM)
    return;

  // Step 1.  We introduce a new scope so we can synchronize more
  // easily.
  {
    JvSynchronize sync (this);

    if (state < JV_STATE_LINKED)
      {
	try
	  {
	    _Jv_Linker::wait_for_state(this, JV_STATE_LINKED);
	  }
	catch (java::lang::SecurityException *x)
	  {
	    throw x;
	  }
	catch (java::lang::Throwable *x)
	  {
	    // Turn into a NoClassDefFoundError.
	    java::lang::NoClassDefFoundError *result
	      = new java::lang::NoClassDefFoundError(getName());
	    result->initCause(x);
	    throw result;
	  }
      }

    // Step 2.
    java::lang::Thread *self = java::lang::Thread::currentThread();
    self = (java::lang::Thread *) ((long) self | 1);
    while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
      wait ();

    // Steps 3 &  4.
    if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
      return;

    // Step 5.
    if (state == JV_STATE_ERROR)
      throw new java::lang::NoClassDefFoundError (getName());

    // Step 6.
    thread = self;
    _Jv_Linker::wait_for_state (this, JV_STATE_LINKED);
    state = JV_STATE_IN_PROGRESS;
  }

  // Step 7.
  if (! isInterface () && superclass)
    {
      try
	{
	  _Jv_InitClass (superclass);
	}
      catch (java::lang::SecurityException *x)
	{
	  throw x;
	}
      catch (java::lang::Throwable *except)
	{
	  // Caught an exception.
	  JvSynchronize sync (this);
	  state = JV_STATE_ERROR;
	  notifyAll ();
	  throw except;
	}
    }

  // Steps 8, 9, 10, 11.
  try
    {
      _Jv_Method *meth = _Jv_GetMethodLocal (this, clinit_name,
					     void_signature);
      if (meth)
	((void (*) (void)) meth->ncode) ();
    }
  catch (java::lang::SecurityException *x)
    {
      throw x;
    }
  catch (java::lang::Throwable *except)
    {
      if (! java::lang::Error::class$.isInstance(except))
	{
	  try
	    {
	      except = new ExceptionInInitializerError (except);
	    }
	  catch (java::lang::Throwable *t)
	    {
	      except = t;
	    }
	}

      JvSynchronize sync (this);
      state = JV_STATE_ERROR;
      notifyAll ();
      throw except;
    }

  JvSynchronize sync (this);
  state = JV_STATE_DONE;
  notifyAll ();
}

// Only used by serialization
java::lang::reflect::Field *
java::lang::Class::getPrivateField (jstring name)
{
  int hash = name->hashCode ();

  java::lang::reflect::Field* rfield;
  for (int i = 0;  i < field_count;  i++)
    {
      _Jv_Field *field = &fields[i];
      if (! _Jv_equal (field->name, name, hash))
	continue;
      rfield = new java::lang::reflect::Field ();
      rfield->offset = (char*) field - (char*) fields;
      rfield->declaringClass = this;
      rfield->name = name;
      return rfield;
    }
  jclass superclass = getSuperclass();
  if (superclass == NULL)
    return NULL;
  rfield = superclass->getPrivateField(name);
  for (int i = 0; i < interface_count && rfield == NULL; ++i)
    rfield = interfaces[i]->getPrivateField (name);
  return rfield;
}

// Only used by serialization
java::lang::reflect::Method *
java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
{
  jstring partial_sig = getSignature (param_types, false);
  jint p_len = partial_sig->length();
  _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
  for (Class *klass = this; klass; klass = klass->getSuperclass())
    {
      int i = klass->isPrimitive () ? 0 : klass->method_count;
      while (--i >= 0)
	{
	  if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
	      && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
	    {
	      // Found it.
	      using namespace java::lang::reflect;

	      Method *rmethod = new Method ();
	      rmethod->offset = ((char *) (&klass->methods[i])
				 - (char *) klass->methods);
	      rmethod->declaringClass = klass;
	      return rmethod;
	    }
	}
    }
  throw new java::lang::NoSuchMethodException (name);
}

// Private accessor method for Java code to retrieve the protection domain.
java::security::ProtectionDomain *
java::lang::Class::getProtectionDomain0 ()
{
  return protectionDomain;
}

JArray<jobject> *
java::lang::Class::getSigners()
{
  return hack_signers;
}

void
java::lang::Class::setSigners(JArray<jobject> *s)
{
  hack_signers = s;
}



static unsigned char
read_u1 (unsigned char *&p)
{
  return *p++;
}

static unsigned char
read_u1 (unsigned char *&p, unsigned char *next)
{
  if (next - p < 1)
    throw new java::lang::InternalError();
  return *p++;
}

static unsigned int
read_u2 (unsigned char *&p)
{
  unsigned int b1 = *p++;
  unsigned int b2 = *p++;
  return (b1 << 8) | b2;
}

static unsigned int
read_u2 (unsigned char *&p, unsigned char *next)
{
  if (next - p < 2)
    throw new java::lang::InternalError();
  return read_u2 (p);
}

static int
read_4 (unsigned char *&p)
{
  int b1 = *p++;
  int b2 = *p++;
  int b3 = *p++;
  int b4 = *p++;
  return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
}

jstring
java::lang::Class::getReflectionSignature (jint /*jv_attr_type*/ type,
					   jint obj_index)
{
  // We just re-parse the bytecode for this data each time.  If
  // necessary we can cache results, but I suspect this is not
  // performance sensitive.
  unsigned char *bytes = reflection_data;
  if (bytes == NULL)
    return NULL;
  while (true)
    {
      int kind = read_u1 (bytes);
      if (kind == JV_DONE_ATTR)
	return NULL;
      int len = read_4 (bytes);
      unsigned char *next = bytes + len;
      if (kind != type)
	{
	  bytes = next;
	  continue;
	}
      if (type != JV_CLASS_ATTR)
	{
	  unsigned short index = read_u2 (bytes, next);
	  if (index != obj_index)
	    {
	      bytes = next;
	      continue;
	    }
	}
      int nt = read_u1 (bytes, next);
      if (nt != JV_SIGNATURE_KIND)
	{
	  bytes = next;
	  continue;
	}
      unsigned int cpool_idx = read_u2 (bytes, next);
      if (cpool_idx >= (unsigned int) constants.size
	  || constants.tags[cpool_idx] != JV_CONSTANT_Utf8)
	{
	  // We just ignore errors for now.  It isn't clear what is
	  // best to do here, as an encoding error here means a bug
	  // either in the compiler or in defineclass.cc.
	  return NULL;
	}
      return _Jv_NewStringUtf8Const (constants.data[cpool_idx].utf8);
    }
}

jstring
java::lang::Class::getReflectionSignature (::java::lang::reflect::Constructor *c)
{
  _Jv_Method *meth = _Jv_FromReflectedConstructor (c);
  unsigned short meth_index = meth - methods;
  return getReflectionSignature (JV_METHOD_ATTR, meth_index);
}

jstring
java::lang::Class::getReflectionSignature (::java::lang::reflect::Method *m)
{
  _Jv_Method *meth = _Jv_FromReflectedMethod (m);
  unsigned short meth_index = meth - methods;
  return getReflectionSignature (JV_METHOD_ATTR, meth_index);
}

jstring
java::lang::Class::getReflectionSignature (::java::lang::reflect::Field *f)
{
  _Jv_Field *fld = _Jv_FromReflectedField (f);
  unsigned short fld_index = fld - fields;
  return getReflectionSignature (JV_FIELD_ATTR, fld_index);
}

jstring
java::lang::Class::getClassSignature()
{
  return getReflectionSignature (JV_CLASS_ATTR, 0);
}

jint
java::lang::Class::getEnclosingMethodData()
{
  unsigned char *bytes = reflection_data;
  if (bytes == NULL)
    return 0;
  while (true)
    {
      int kind = read_u1 (bytes);
      if (kind == JV_DONE_ATTR)
	return 0;
      int len = read_4 (bytes);
      unsigned char *next = bytes + len;
      if (kind != JV_CLASS_ATTR)
	{
	  bytes = next;
	  continue;
	}
      int type = read_u1 (bytes, next);
      if (type != JV_ENCLOSING_METHOD_KIND)
	{
	  bytes = next;
	  continue;
	}
      int class_index = read_u2 (bytes, next);
      int method_index = read_u2 (bytes, next);
      _Jv_word result;
      _Jv_storeIndexes (&result, class_index, method_index);
      return result.i;
    }
}

jclass
java::lang::Class::getEnclosingClass()
{
  _Jv_word indexes;
  indexes.i = getEnclosingMethodData();
  if (indexes.i == 0)
    // No enclosing method, but perhaps a member or anonymous class
    return getDeclaringClass();
  _Jv_ushort class_index, method_index;
  _Jv_loadIndexes (&indexes, class_index, method_index);
  return _Jv_Linker::resolve_pool_entry (this, class_index).clazz;
}

::java::lang::reflect::Method *
java::lang::Class::getEnclosingMethod()
{
  _Jv_word indexes;
  indexes.i = getEnclosingMethodData();
  if (indexes.i == 0)
    return NULL;
  _Jv_ushort class_index, method_index;
  _Jv_loadIndexes (&indexes, class_index, method_index);
  jclass found_class;
  _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class,
							 class_index,
							 method_index,
							 false, false);
  using namespace java::lang::reflect;
  Method *rmethod = new Method ();
  rmethod->offset = (char *) method - (char *) found_class->methods;
  rmethod->declaringClass = found_class;
  return rmethod;
}

::java::lang::reflect::Constructor *
java::lang::Class::getEnclosingConstructor()
{
  _Jv_word indexes;
  indexes.i = getEnclosingMethodData();
  if (indexes.i == 0)
    return NULL;
  _Jv_ushort class_index, method_index;
  _Jv_loadIndexes (&indexes, class_index, method_index);
  jclass found_class;
  _Jv_Method *method = _Jv_Linker::resolve_method_entry (this, found_class,
							 class_index,
							 method_index,
							 false, false);
  using namespace java::lang::reflect;
  Constructor *cons = new Constructor ();
  cons->offset = (char *) method - (char *) found_class->methods;
  cons->declaringClass = this;
  return cons;
}

static void
check_constant (_Jv_Constants *pool, jint cpool_index, jint type)
{
  if (cpool_index <= 0 || cpool_index >= pool->size)
    throw new InternalError(JvNewStringLatin1("invalid constant pool index"));
  if ((pool->tags[cpool_index] & 
	~(JV_CONSTANT_ResolvedFlag|JV_CONSTANT_LazyFlag)) != type)
    {
      ::java::lang::StringBuffer *sb = new ::java::lang::StringBuffer();
      sb->append(JvNewStringLatin1("expected pool constant "));
      sb->append(type);
      sb->append(JvNewStringLatin1(" but got "));
      sb->append(jint (pool->tags[cpool_index]));
      throw new InternalError(sb->toString());
    }
}

// Forward declaration
static ::java::lang::annotation::Annotation *
parseAnnotation(jclass klass, _Jv_Constants *pool,
		unsigned char *&bytes, unsigned char *last);

static jobject
parseAnnotationElement(jclass klass, _Jv_Constants *pool,
		       unsigned char *&bytes, unsigned char *last)
{
  int tag = read_u1 (bytes, last);
  jobject result;
  switch (tag)
    {
    case 'B':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Integer);
	result = Byte::valueOf (pool->data[cindex].i);
      }
      break;
    case 'C':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Integer);
	result = Character::valueOf (pool->data[cindex].i);
      }
      break;
    case 'S':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Integer);
	result = Short::valueOf (pool->data[cindex].i);
      }
      break;
    case 'Z':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Integer);
	result = Boolean::valueOf (jboolean (pool->data[cindex].i));
      }
      break;
    case 'I':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Integer);
	result = Integer::valueOf (pool->data[cindex].i);
      }
      break;
    case 'D':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Double);
	_Jv_word2 word;
	memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word));
	result = Double::valueOf (word.d);
      }
      break;
    case 'F':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Float);
	result = Float::valueOf (pool->data[cindex].f);
      }
      break;
    case 'J':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Long);
	_Jv_word2 word;
	memcpy (&word, &pool->data[cindex], 2 * sizeof (_Jv_word));
	result = Long::valueOf (word.l);
      }
      break;
    case 's':
      {
	int cindex = read_u2 (bytes, last);
	// Despite what the JVM spec says, compilers generate a Utf8
	// constant here, not a String.
	check_constant (pool, cindex, JV_CONSTANT_Utf8);
	result = pool->data[cindex].utf8->toString();
      }
      break;
    case 'e':
      {
	int type_name_index = read_u2 (bytes, last);
	check_constant (pool, type_name_index, JV_CONSTANT_Utf8);
 	int const_name_index = read_u2 (bytes, last);
	check_constant (pool, const_name_index, JV_CONSTANT_Utf8);

	_Jv_Utf8Const *u_name = pool->data[type_name_index].utf8;
	_Jv_Utf8Const *e_name = pool->data[const_name_index].utf8;

	// FIXME: throw correct exceptions at the correct times.
	jclass e_class = _Jv_FindClassFromSignature(u_name->chars(),
						    klass->getClassLoaderInternal());
	result = ::java::lang::Enum::valueOf(e_class, e_name->toString());
      }
      break;
    case 'c':
      {
	int cindex = read_u2 (bytes, last);
	check_constant (pool, cindex, JV_CONSTANT_Utf8);
	_Jv_Utf8Const *u_name = pool->data[cindex].utf8;
	jclass anno_class
	  = _Jv_FindClassFromSignatureNoException(u_name->chars(),
						  klass->getClassLoaderInternal());
	// FIXME: not correct: we should lazily do this when trying to
	// read the element.  This means that
	// AnnotationInvocationHandler needs to have a special case.
	if (! anno_class)
	  // FIXME: original exception...
	  throw new TypeNotPresentException(u_name->toString(), NULL);
	result = anno_class;
      }
      break;
    case '@':
      result = parseAnnotation (klass, pool, bytes, last);
      break;
    case '[':
      {
	int n_array_elts = read_u2 (bytes, last);
	jobjectArray aresult = _Jv_NewObjectArray (n_array_elts,
						   &Object::class$, NULL);
	jobject *elts = elements (aresult);
	for (int i = 0; i < n_array_elts; ++i)
	  elts[i] = parseAnnotationElement(klass, pool, bytes, last);
	result = aresult;
      }
      break;
    default:
      throw new java::lang::InternalError();
    }
  return result;
}

static ::java::lang::annotation::Annotation *
parseAnnotation(jclass klass, _Jv_Constants *pool,
		unsigned char *&bytes, unsigned char *last)
{
  int type_index = read_u2 (bytes, last);
  check_constant (pool, type_index, JV_CONSTANT_Utf8);

  _Jv_Utf8Const *u_name = pool->data[type_index].utf8;
  jclass anno_class = _Jv_FindClassFromSignatureNoException(u_name->chars(),
							    klass->getClassLoaderInternal());
  // FIXME: what to do if anno_class==NULL?

  ::java::util::HashMap *hmap = new ::java::util::HashMap();
  int npairs = read_u2 (bytes, last);
  for (int i = 0; i < npairs; ++i)
    {
      int name_index = read_u2 (bytes, last);
      check_constant (pool, name_index, JV_CONSTANT_Utf8);
      jstring name = _Jv_NewStringUtf8Const (pool->data[name_index].utf8);
      jobject value = parseAnnotationElement (klass, pool, bytes, last);
      // FIXME: any checks needed for name?
      hmap->put(name, value);
    }
  using namespace ::sun::reflect::annotation;
  return AnnotationInvocationHandler::create (anno_class,
					      (::java::util::Map *) hmap);
}

static jobjectArray
parseAnnotations(jclass klass, _Jv_Constants *pool,
		 unsigned char *&bytes, unsigned char *last)
{
  int num = read_u2 (bytes, last);
  jobjectArray result = _Jv_NewObjectArray (num,
					    &::java::lang::annotation::Annotation::class$,
					    NULL);
  jobject *elts = elements (result);
  for (int i = 0; i < num; ++i)
    elts[i] = parseAnnotation(klass, pool, bytes, last);
  return result;
}

static jobjectArray
parseParameterAnnotations(jclass klass, _Jv_Constants *pool,
			  unsigned char *&bytes, unsigned char *last)
{
  jclass anno = &::java::lang::annotation::Annotation::class$;
  jclass annoary = _Jv_GetArrayClass (anno, anno->getClassLoaderInternal());

  // FIXME: something should check the number of params versus the
  // method
  int n_params = read_u1 (bytes, last);
  jobjectArray result = _Jv_NewObjectArray (n_params, annoary, NULL);
  jobject *elts = elements (result);
  for (int i = 0; i < n_params; ++i)
    elts[i] = parseAnnotations(klass, pool, bytes, last);
  return result;
}

jobject
java::lang::Class::getMethodDefaultValue(::java::lang::reflect::Method *meth)
{
  // FIXME: could cache the value here...

  unsigned char *bytes = reflection_data;
  if (bytes == NULL)
    return 0;

  unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods;

  while (true)
    {
      int type = read_u1 (bytes);
      if (type == JV_DONE_ATTR)
	return NULL;
      int len = read_4 (bytes);
      unsigned char *next = bytes + len;
      if (type != JV_METHOD_ATTR)
	{
	  bytes = next;
	  continue;
	}
      int kind = read_u1 (bytes, next);
      if (kind != JV_ANNOTATION_DEFAULT_KIND)
	{
	  bytes = next;
	  continue;
	}
      int index = read_u2 (bytes, next);
      if (meth_index != index)
	{
	  bytes = next;
	  continue;
	}

      // FIXME: could cache here.  If we do then we have to clone any
      // array result.
      return parseAnnotationElement(this, &this->constants, bytes, next);
    }
}

jobjectArray
java::lang::Class::getDeclaredAnnotations(jint /* jv_attr_type */ member_type,
					  jint member_index,
					  jint /* jv_attr_kind */ kind_req)
{
  using namespace java::lang::annotation;
  jobjectArray result;

  unsigned char *bytes = reflection_data;
  if (bytes == NULL)
    return 0;

  if (loader == NULL)
    loader = (ClassLoader *)VMClassLoader::bootLoader;

  result = (loader->getDeclaredAnnotations
	    (this, member_type, member_index, kind_req));
  if (result)
    return result;

  for (;;)
    {
      int type = read_u1 (bytes);
      if (type == JV_DONE_ATTR)
	return NULL;
      int len = read_4 (bytes);
      unsigned char *next = bytes + len;
      if (type != member_type)
	{
	  bytes = next;
	  continue;
	}
      int kind = read_u1 (bytes, next);
      if (kind != kind_req)
	{
	  bytes = next;
	  continue;
	}
      if (member_type != JV_CLASS_ATTR)
	{
	  int index = read_u2 (bytes, next);
	  if (member_index != index)
	    {
	      bytes = next;
	      continue;
	    }
	}

      if (kind_req == JV_PARAMETER_ANNOTATIONS_KIND)
	result = ((parseParameterAnnotations 
		   (this, &this->constants, bytes, next)));
      else
	result = ((parseAnnotations (this, &this->constants, bytes, next)));
      break;
    }

  return (loader->putDeclaredAnnotations
	  (this, member_type, member_index, kind_req, result));
}

jobjectArray
java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Method *meth,
					  jboolean is_param)
{
  unsigned short meth_index = _Jv_FromReflectedMethod (meth) - methods;
  return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index,
				(is_param
				 ? JV_PARAMETER_ANNOTATIONS_KIND
				 : JV_ANNOTATIONS_KIND));
}

jobjectArray
java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Constructor *cons,
					  jboolean is_param)
{
  unsigned short meth_index = _Jv_FromReflectedConstructor (cons) - methods;
  return getDeclaredAnnotations(JV_METHOD_ATTR, meth_index,
				(is_param
				 ? JV_PARAMETER_ANNOTATIONS_KIND
				 : JV_ANNOTATIONS_KIND));
}

jobjectArray
java::lang::Class::getDeclaredAnnotations(::java::lang::reflect::Field *fld)
{
  unsigned short field_index = _Jv_FromReflectedField (fld) - fields;
  return getDeclaredAnnotations(JV_FIELD_ATTR, field_index,
				JV_ANNOTATIONS_KIND);
}

JArray< ::java::lang::annotation::Annotation *> *
java::lang::Class::getDeclaredAnnotationsInternal()
{
  return (JArray< ::java::lang::annotation::Annotation *> *) getDeclaredAnnotations(JV_CLASS_ATTR, 0, JV_ANNOTATIONS_KIND);
}

static jclass
resolve_class_constant (jclass klass, _Jv_Constants *pool, int cpool_index)
{
  check_constant (pool, cpool_index, JV_CONSTANT_Class);
  // FIXME: what is the correct thing to do with an exception here?
  return _Jv_Linker::resolve_pool_entry (klass, cpool_index, false).clazz;
}

jint
java::lang::Class::findInnerClassAttribute()
{
  unsigned char *bytes = reflection_data;
  if (bytes == NULL)
    return -1;
  while (true)
    {
      int type = read_u1 (bytes);
      if (type == JV_DONE_ATTR)
	break;
      // After the type but before the length.
      unsigned char *save = bytes;
      int len = read_4 (bytes);
      unsigned char *next = bytes + len;
      if (type != JV_CLASS_ATTR)
	{
	  bytes = next;
	  continue;
	}
      int kind = read_u1 (bytes, next);
      if (kind != JV_INNER_CLASSES_KIND)
	{
	  bytes = next;
	  continue;
	}
      return save - reflection_data;
    }
  return -1;
}

jint
java::lang::Class::findDeclaredClasses(JArray<jclass> *result,
				       jboolean publicOnly,
				       jint offset)
{
  unsigned char *bytes = reflection_data + offset;
  int len = read_4 (bytes);
  unsigned char *next = bytes + len;
  // Skip a byte.
  read_u1 (bytes, next);
  int n_classes = read_u2 (bytes, next);
  int count = 0;
  for (int i = 0; i < n_classes; ++i)
    {
      int inner_class_index = read_u2 (bytes, next);
      int outer_class_index = read_u2 (bytes, next);
      /*int inner_name_index = */ read_u2 (bytes, next);
      int inner_flags = read_u2 (bytes, next);

      if (inner_class_index == 0 || outer_class_index == 0)
	continue;
      if (resolve_class_constant (this, &constants, outer_class_index) == this)
	{
	  jclass inner = resolve_class_constant (this, &constants,
						 inner_class_index);
	  if (! publicOnly
	      || ((inner_flags
		   & java::lang::reflect::Modifier::PUBLIC) != 0))
	    {
	      if (result)
		{
		  jclass *elts = elements (result);
		  elts[count] = inner;
		}
	      ++count;
	    }
	}
    }

  return count;
}

JArray<jclass> *
java::lang::Class::getDeclaredClasses (jboolean publicOnly)
{
  int offset = findInnerClassAttribute();
  int count;
  if (offset == -1)
    {
      // No InnerClasses attribute, so no declared classes.
      count = 0;
    }
  else
    count = findDeclaredClasses(NULL, publicOnly, offset);
  JArray<jclass> *result
    = (JArray<jclass> *) JvNewObjectArray (count, &java::lang::Class::class$,
					   NULL);
  if (count > 0)
    findDeclaredClasses(result, publicOnly, offset);
  return result;
}

jclass
java::lang::Class::getDeclaringClass (void)
{
  int offset = findInnerClassAttribute();
  if (offset == -1)
    return NULL;

  unsigned char *bytes = reflection_data + offset;
  int len = read_4 (bytes);
  unsigned char *next = bytes + len;
  // Skip a byte.
  read_u1 (bytes, next);
  int n_classes = read_u2 (bytes, next);
  for (int i = 0; i < n_classes; ++i)
    {
      int inner_class_index = read_u2 (bytes, next);
      int outer_class_index = read_u2 (bytes, next);
      /*int inner_name_index = */read_u2 (bytes, next);
      /*int inner_flags = */read_u2 (bytes, next);

      if (inner_class_index == 0 || outer_class_index == 0)
	continue;
      if (resolve_class_constant (this, &constants, inner_class_index) == this)
	return resolve_class_constant (this, &constants, outer_class_index);
    }

  return NULL;
}

jboolean
java::lang::Class::isAnonymousClass()
{
  int offset = findInnerClassAttribute();
  if (offset == -1)
    return false;

  unsigned char *bytes = reflection_data + offset;
  int len = read_4 (bytes);
  unsigned char *next = bytes + len;
  // Skip a byte.
  read_u1 (bytes, next);
  int n_classes = read_u2 (bytes, next);
  for (int i = 0; i < n_classes; ++i)
    {
      int inner_class_index = read_u2 (bytes, next);
      /*int outer_class_index = */read_u2 (bytes, next);
      int inner_name_index = read_u2 (bytes, next);
      /*int inner_flags = */read_u2 (bytes, next);

      if (inner_class_index == 0)
	continue;
      if (resolve_class_constant (this, &constants, inner_class_index) == this)
	return inner_name_index == 0;
    }

  return false;
}

jboolean
java::lang::Class::isLocalClass()
{
  _Jv_word indexes;
  indexes.i = getEnclosingMethodData();
  return indexes.i != 0;
}

jboolean
java::lang::Class::isMemberClass()
{
  // FIXME: is this correct?
  return !isLocalClass() && getDeclaringClass() != NULL;
}



//
// Some class-related convenience functions.
//

// Find a method declared in the class.  If it is not declared locally
// (or if it is inherited), return NULL.
_Jv_Method *
_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
		    _Jv_Utf8Const *signature)
{
  for (int i = 0; i < klass->method_count; ++i)
    {
      if (_Jv_equalUtf8Consts (name, klass->methods[i].name)
	  && _Jv_equalUtf8Consts (signature, klass->methods[i].signature))
	return &klass->methods[i];
    }
  return NULL;
}

_Jv_Method *
_Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
                          _Jv_Utf8Const *signature,
			  jclass *declarer_result)
{
  for (; klass; klass = klass->getSuperclass())
    {
      _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);

      if (meth)
	{
	  if (declarer_result)
	    *declarer_result = klass;
	  return meth;
	}
    }

  return NULL;
}

java::lang::reflect::Method *
_Jv_GetReflectedMethod (jclass klass, _Jv_Utf8Const *name,
		       _Jv_Utf8Const *signature)
{
  for (; klass; klass = klass->getSuperclass())
    {
      _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
      if (meth)
	{
	  using namespace java::lang::reflect;
	  Method *rmethod = new Method ();
	  rmethod->offset = (char*) meth - (char*) klass->methods;
	  rmethod->declaringClass = klass;
	  return rmethod;
	}
    }
  
  return NULL;
}

#ifdef HAVE_TLS

// NOTE: MCACHE_SIZE should be a power of 2 minus one.
#define MCACHE_SIZE 31

struct _Jv_mcache
{
  jclass klass;
  _Jv_Method *method;
};

static __thread _Jv_mcache *method_cache;
#endif // HAVE_TLS

static void *
_Jv_FindMethodInCache (jclass klass MAYBE_UNUSED,
		       _Jv_Utf8Const *name MAYBE_UNUSED,
		       _Jv_Utf8Const *signature MAYBE_UNUSED)
{
#ifdef HAVE_TLS
  _Jv_mcache *cache = method_cache;
  if (cache)
    {
      int index = name->hash16 () & MCACHE_SIZE;
      _Jv_mcache *mc = &cache[index];
      _Jv_Method *m = mc->method;

      if (mc->klass == klass
	  && _Jv_equalUtf8Consts (m->name, name)
	  && _Jv_equalUtf8Consts (m->signature, signature))
	return mc->method->ncode;
    }
#endif // HAVE_TLS
  return NULL;
}

static void
_Jv_AddMethodToCache (jclass klass MAYBE_UNUSED,
		      _Jv_Method *method MAYBE_UNUSED)
{
#ifdef HAVE_TLS
  if (method_cache == NULL)
    method_cache = (_Jv_mcache *) _Jv_MallocUnchecked((MCACHE_SIZE + 1)
						      * sizeof (_Jv_mcache));
  // If the allocation failed, just keep going.
  if (method_cache != NULL)
    {
      int index = method->name->hash16 () & MCACHE_SIZE;
      method_cache[index].method = method;
      method_cache[index].klass = klass;
    }
#endif // HAVE_TLS
}

// Free this thread's method cache.  We explicitly manage this memory
// as the GC does not yet know how to scan TLS on all platforms.
void
_Jv_FreeMethodCache ()
{
#ifdef HAVE_TLS
  if (method_cache != NULL)
    {
      _Jv_Free(method_cache);
      method_cache = NULL;
    }
#endif // HAVE_TLS
}

void *
_Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name,
                           _Jv_Utf8Const *signature)
{
  using namespace java::lang::reflect;

  void *ncode = _Jv_FindMethodInCache (klass, name, signature);
  if (ncode != 0)
    return ncode;

  for (; klass; klass = klass->getSuperclass())
    {
      _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
      if (! meth)
        continue;

      if (Modifier::isStatic(meth->accflags))
	throw new java::lang::IncompatibleClassChangeError
	  (_Jv_GetMethodString (klass, meth));
      if (Modifier::isAbstract(meth->accflags))
	throw new java::lang::AbstractMethodError
	  (_Jv_GetMethodString (klass, meth));
      if (! Modifier::isPublic(meth->accflags))
	throw new java::lang::IllegalAccessError
	  (_Jv_GetMethodString (klass, meth));

      _Jv_AddMethodToCache (klass, meth);

      return meth->ncode;
    }
  throw new java::lang::IncompatibleClassChangeError;
}

// Fast interface method lookup by index.
void *
_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
{
  _Jv_IDispatchTable *cldt = klass->idt;
  int idx = iface->ioffsets[cldt->iindex] + method_idx;
  return cldt->itable[idx];
}

jboolean
_Jv_IsAssignableFrom (jclass source, jclass target)
{
  if (source == target)
    return true;

  // If target is array, so must source be.  
  while (target->isArray ())
    {
      if (! source->isArray())
	return false;
      target = target->getComponentType();
      source = source->getComponentType();
    }

  if (target->isInterface())
    {
      // Abstract classes have no IDT, and IDTs provide no way to check
      // two interfaces for assignability.
      if (__builtin_expect 
          (source->idt == NULL || source->isInterface(), false))
        return _Jv_InterfaceAssignableFrom (source, target);

      _Jv_IDispatchTable *cl_idt = source->idt;

      if (__builtin_expect ((target->ioffsets == NULL), false))
	return false; // No class implementing TARGET has been loaded.    
      jshort cl_iindex = cl_idt->iindex;
      if (cl_iindex < target->ioffsets[0])
        {
	  jshort offset = target->ioffsets[cl_iindex];
	  if (offset != -1 && offset < cl_idt->itable_length
	      && cl_idt->itable[offset] == target)
	    return true;
	}
      return false;
    }

  // Primitive TYPE classes are only assignable to themselves.
  if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false))
    return false;

  if (target == &java::lang::Object::class$)
    return true;
  else if (source->ancestors == NULL || target->ancestors == NULL)
    {
      // We need this case when either SOURCE or TARGET has not has
      // its constant-time tables prepared.

      // At this point we know that TARGET can't be Object, so it is
      // safe to use that as the termination point.
      while (source && source != &java::lang::Object::class$)
	{
	  if (source == target)
	    return true;
	  source = source->getSuperclass();
	}
    }
  else if (source->depth >= target->depth
	   && source->ancestors[source->depth - target->depth] == target)
    return true;

  return false;
}

// Interface type checking, the slow way. Returns TRUE if IFACE is a 
// superinterface of SOURCE. This is used when SOURCE is also an interface,
// or a class with no interface dispatch table.
jboolean
_Jv_InterfaceAssignableFrom (jclass source, jclass iface)
{
  for (int i = 0; i < source->interface_count; i++)
    {
      jclass source_interface = source->interfaces[i];
      if (iface == source_interface
          || _Jv_InterfaceAssignableFrom (source_interface, iface))
        return true;      
    }
    
  if (!source->isInterface()
      && source->superclass 
      && _Jv_InterfaceAssignableFrom (source->superclass, iface))
    return true;
        
  return false;
}

jboolean
_Jv_IsInstanceOf(jobject obj, jclass cl)
{
  if (__builtin_expect (!obj, false))
    return false;
  return _Jv_IsAssignableFrom (JV_CLASS (obj), cl);
}

void *
_Jv_CheckCast (jclass c, jobject obj)
{
  if (__builtin_expect 
      (obj != NULL && ! _Jv_IsAssignableFrom(JV_CLASS (obj), c), false))
    throw new java::lang::ClassCastException
      ((new java::lang::StringBuffer
	(obj->getClass()->getName()))->append
       (JvNewStringUTF(" cannot be cast to "))->append
       (c->getName())->toString());

  return obj;
}

void
_Jv_CheckArrayStore (jobject arr, jobject obj)
{
  if (obj)
    {
      JvAssert (arr != NULL);
      jclass elt_class = (JV_CLASS (arr))->getComponentType();
      if (elt_class == &java::lang::Object::class$)
	return;
      jclass obj_class = JV_CLASS (obj);
      if (__builtin_expect 
          (! _Jv_IsAssignableFrom (obj_class, elt_class), false))
	throw new java::lang::ArrayStoreException
		((new java::lang::StringBuffer
		 (JvNewStringUTF("Cannot store ")))->append
		 (obj_class->getName())->append
		 (JvNewStringUTF(" in array of type "))->append
		 (elt_class->getName())->toString());
    }
}

jboolean
_Jv_IsAssignableFromSlow (jclass source, jclass target)
{
  // First, strip arrays.
  while (target->isArray ())
    {
      // If target is array, source must be as well.
      if (! source->isArray ())
       return false;
      target = target->getComponentType ();
      source = source->getComponentType ();
    }

  // Quick success.
  if (target == &java::lang::Object::class$)
    return true;

  // Ensure that the classes have their supers installed.
  _Jv_Linker::wait_for_state (source, JV_STATE_LOADING);
  _Jv_Linker::wait_for_state (target, JV_STATE_LOADING);

  do
    {
      if (source == target)
       return true;

      if (target->isPrimitive () || source->isPrimitive ())
       return false;

      if (target->isInterface ())
       {
         for (int i = 0; i < source->interface_count; ++i)
           {
             // We use a recursive call because we also need to
             // check superinterfaces.
             if (_Jv_IsAssignableFromSlow (source->getInterface (i), target))
               return true;
           }
       }
      source = source->getSuperclass ();
    }
  while (source != NULL);

  return false;
}

// Lookup an interface method by name.  This is very similar to
// purpose to _getMethod, but the interfaces are quite different.  It
// might be a good idea for _getMethod to call this function.
//
// Return true of the method is found, with the class in FOUND_CLASS
// and the index in INDEX.
bool
_Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
			const _Jv_Utf8Const *utf_name,  
			const _Jv_Utf8Const *utf_sig)
{
   for (jclass klass = search_class; klass; klass = klass->getSuperclass())
    {
      // FIXME: Throw an exception?
      if (!klass->isInterface ())
	return false;
      
      int max = klass->method_count;
      int offset = 0;
      for (int i = 0; i < max; ++i)
	{
	  // Skip <clinit> here, as it will not be in the IDT.
	  if (klass->methods[i].name->first() == '<')
	    continue;

	  if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
	      && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
	    {
	      // Found it.
	      using namespace java::lang::reflect;

	      // FIXME: Method must be public.  Throw an exception?
	      if (! Modifier::isPublic (klass->methods[i].accflags))
		break;

	      found_class = klass;
	      // Interface method indexes count from 1.
	      index = offset + 1;
	      return true;
	    }

	  ++offset;
	}
    }

  // If we haven't found a match, and this class is an interface, then
  // check all the superinterfaces.
  if (search_class->isInterface())
    {
      for (int i = 0; i < search_class->interface_count; ++i)
	{
	  using namespace java::lang::reflect;
	  bool found = _Jv_getInterfaceMethod (search_class->interfaces[i], 
					       found_class, index,
					       utf_name, utf_sig);
	  if (found)
	    return true;
	}
    }

  return false;
}

#ifdef INTERPRETER
_Jv_MethodBase *
_Jv_FindInterpreterMethod (jclass klass, jmethodID desired_method)
{
  using namespace java::lang::reflect;

  _Jv_InterpClass *iclass
    = reinterpret_cast<_Jv_InterpClass *> (klass->aux_info);
  _Jv_MethodBase **imethods = _Jv_GetFirstMethod (iclass);

  for (int i = 0; i < JvNumMethods (klass); ++i)
    {
      _Jv_MethodBase *imeth = imethods[i];
      if (imeth->get_method () == desired_method)
	return imeth;
    }

  return NULL;
}
#endif

// Return Utf8 name of a class. This function is here for code that
// can't access klass->name directly.
_Jv_Utf8Const*
_Jv_GetClassNameUtf8 (jclass klass)
{
  return klass->name;
}

jclass
_Jv_GetMethodDeclaringClass (jmethodID method)
{
  _Jv_StackTrace::UpdateNCodeMap ();
  jobject obj = reinterpret_cast<jobject> (method->ncode);
  return reinterpret_cast<jclass> (_Jv_StackTrace::ncodeMap->get (obj));
}

jbyte
_Jv_GetClassState (jclass klass)
{
  return klass->state;
}

#ifdef INTERPRETER
jstring
_Jv_GetInterpClassSourceFile (jclass klass)
{
  if (_Jv_IsInterpretedClass (klass))
    {
      _Jv_InterpClass *iclass =
	reinterpret_cast<_Jv_InterpClass *> (klass->aux_info);
      return iclass->source_file_name;
    }

  return NULL;
}
#endif
