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/] [prims.cc] - Diff between revs 753 and 783

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

Rev 753 Rev 783
// prims.cc - Code for core of runtime environment.
// prims.cc - Code for core of runtime environment.
 
 
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  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 <platform.h>
#include <platform.h>
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <signal.h>
#include <signal.h>
 
 
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
 
 
#include <gcj/cni.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <jvm.h>
#include <java-signal.h>
#include <java-signal.h>
#include <java-threads.h>
#include <java-threads.h>
#include <java-interp.h>
#include <java-interp.h>
 
 
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
#include <jvmpi.h>
#include <jvmpi.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/ThreadGroup.h>
#endif
#endif
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
#include <jvmti.h>
#include <jvmti.h>
#include "jvmti-int.h"
#include "jvmti-int.h"
#endif
#endif
 
 
#ifndef DISABLE_GETENV_PROPERTIES
#ifndef DISABLE_GETENV_PROPERTIES
#include <java-props.h>
#include <java-props.h>
#define PROCESS_GCJ_PROPERTIES process_gcj_properties()
#define PROCESS_GCJ_PROPERTIES process_gcj_properties()
#else
#else
#define PROCESS_GCJ_PROPERTIES
#define PROCESS_GCJ_PROPERTIES
#endif // DISABLE_GETENV_PROPERTIES
#endif // DISABLE_GETENV_PROPERTIES
 
 
#include <java/lang/Class.h>
#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/ClassLoader.h>
#include <java/lang/Runtime.h>
#include <java/lang/Runtime.h>
#include <java/lang/String.h>
#include <java/lang/String.h>
#include <java/lang/Thread.h>
#include <java/lang/Thread.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/ArithmeticException.h>
#include <java/lang/ArithmeticException.h>
#include <java/lang/ClassFormatError.h>
#include <java/lang/ClassFormatError.h>
#include <java/lang/ClassNotFoundException.h>
#include <java/lang/ClassNotFoundException.h>
#include <java/lang/InternalError.h>
#include <java/lang/InternalError.h>
#include <java/lang/NegativeArraySizeException.h>
#include <java/lang/NegativeArraySizeException.h>
#include <java/lang/NoClassDefFoundError.h>
#include <java/lang/NoClassDefFoundError.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/NullPointerException.h>
#include <java/lang/OutOfMemoryError.h>
#include <java/lang/OutOfMemoryError.h>
#include <java/lang/System.h>
#include <java/lang/System.h>
#include <java/lang/VMClassLoader.h>
#include <java/lang/VMClassLoader.h>
#include <java/lang/reflect/Modifier.h>
#include <java/lang/reflect/Modifier.h>
#include <java/io/PrintStream.h>
#include <java/io/PrintStream.h>
#include <java/lang/UnsatisfiedLinkError.h>
#include <java/lang/UnsatisfiedLinkError.h>
#include <java/lang/VirtualMachineError.h>
#include <java/lang/VirtualMachineError.h>
#include <gnu/gcj/runtime/ExtensionClassLoader.h>
#include <gnu/gcj/runtime/ExtensionClassLoader.h>
#include <gnu/gcj/runtime/FinalizerThread.h>
#include <gnu/gcj/runtime/FinalizerThread.h>
#include <execution.h>
#include <execution.h>
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
#include <gnu/classpath/jdwp/Jdwp.h>
#include <gnu/classpath/jdwp/Jdwp.h>
#include <gnu/classpath/jdwp/VMVirtualMachine.h>
#include <gnu/classpath/jdwp/VMVirtualMachine.h>
#endif // INTERPRETER
#endif // INTERPRETER
 
 
#include <gnu/java/lang/MainThread.h>
#include <gnu/java/lang/MainThread.h>
 
 
#ifdef USE_LTDL
#ifdef USE_LTDL
#include <ltdl.h>
#include <ltdl.h>
#endif
#endif
 
 
// Execution engine for compiled code.
// Execution engine for compiled code.
_Jv_CompiledEngine _Jv_soleCompiledEngine;
_Jv_CompiledEngine _Jv_soleCompiledEngine;
 
 
// Execution engine for code compiled with -findirect-classes
// Execution engine for code compiled with -findirect-classes
_Jv_IndirectCompiledEngine _Jv_soleIndirectCompiledEngine;
_Jv_IndirectCompiledEngine _Jv_soleIndirectCompiledEngine;
 
 
// We allocate a single OutOfMemoryError exception which we keep
// We allocate a single OutOfMemoryError exception which we keep
// around for use if we run out of memory.
// around for use if we run out of memory.
static java::lang::OutOfMemoryError *no_memory;
static java::lang::OutOfMemoryError *no_memory;
 
 
// Number of bytes in largest array object we create.  This could be
// Number of bytes in largest array object we create.  This could be
// increased to the largest size_t value, so long as the appropriate
// increased to the largest size_t value, so long as the appropriate
// functions are changed to take a size_t argument instead of jint.
// functions are changed to take a size_t argument instead of jint.
#define MAX_OBJECT_SIZE (((size_t)1<<31) - 1)
#define MAX_OBJECT_SIZE (((size_t)1<<31) - 1)
 
 
// Properties set at compile time.
// Properties set at compile time.
const char **_Jv_Compiler_Properties = NULL;
const char **_Jv_Compiler_Properties = NULL;
int _Jv_Properties_Count = 0;
int _Jv_Properties_Count = 0;
 
 
#ifndef DISABLE_GETENV_PROPERTIES
#ifndef DISABLE_GETENV_PROPERTIES
// Property key/value pairs.
// Property key/value pairs.
property_pair *_Jv_Environment_Properties;
property_pair *_Jv_Environment_Properties;
#endif
#endif
 
 
// Stash the argv pointer to benefit native libraries that need it.
// Stash the argv pointer to benefit native libraries that need it.
const char **_Jv_argv;
const char **_Jv_argv;
int _Jv_argc;
int _Jv_argc;
 
 
// Debugging options
// Debugging options
static bool remoteDebug = false;
static bool remoteDebug = false;
#ifdef INTERPRETER
#ifdef INTERPRETER
static char defaultJdwpOptions[] = "";
static char defaultJdwpOptions[] = "";
static char *jdwpOptions = defaultJdwpOptions;
static char *jdwpOptions = defaultJdwpOptions;
 
 
// Typedefs for JVMTI agent functions.
// Typedefs for JVMTI agent functions.
typedef jint jvmti_agent_onload_func (JavaVM *vm, char *options,
typedef jint jvmti_agent_onload_func (JavaVM *vm, char *options,
                                      void *reserved);
                                      void *reserved);
typedef jint jvmti_agent_onunload_func (JavaVM *vm);
typedef jint jvmti_agent_onunload_func (JavaVM *vm);
 
 
// JVMTI agent function pointers.
// JVMTI agent function pointers.
static jvmti_agent_onload_func *jvmti_agentonload = NULL;
static jvmti_agent_onload_func *jvmti_agentonload = NULL;
static jvmti_agent_onunload_func *jvmti_agentonunload = NULL;
static jvmti_agent_onunload_func *jvmti_agentonunload = NULL;
static char *jvmti_agent_opts;
static char *jvmti_agent_opts;
#endif // INTERPRETER
#endif // INTERPRETER
 
 
// Argument support.
// Argument support.
int
int
_Jv_GetNbArgs (void)
_Jv_GetNbArgs (void)
{
{
  // _Jv_argc is 0 if not explicitly initialized.
  // _Jv_argc is 0 if not explicitly initialized.
  return _Jv_argc;
  return _Jv_argc;
}
}
 
 
const char *
const char *
_Jv_GetSafeArg (int index)
_Jv_GetSafeArg (int index)
{
{
  if (index >=0 && index < _Jv_GetNbArgs ())
  if (index >=0 && index < _Jv_GetNbArgs ())
    return _Jv_argv[index];
    return _Jv_argv[index];
  else
  else
    return "";
    return "";
}
}
 
 
void
void
_Jv_SetArgs (int argc, const char **argv)
_Jv_SetArgs (int argc, const char **argv)
{
{
  _Jv_argc = argc;
  _Jv_argc = argc;
  _Jv_argv = argv;
  _Jv_argv = argv;
}
}
 
 
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
// Pointer to JVMPI notification functions.
// Pointer to JVMPI notification functions.
void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event);
void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event);
void (*_Jv_JVMPI_Notify_THREAD_START) (JVMPI_Event *event);
void (*_Jv_JVMPI_Notify_THREAD_START) (JVMPI_Event *event);
void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
#endif
#endif


 
 
#if defined (HANDLE_SEGV) || defined(HANDLE_FPE)
#if defined (HANDLE_SEGV) || defined(HANDLE_FPE)
/* Unblock a signal.  Unless we do this, the signal may only be sent
/* Unblock a signal.  Unless we do this, the signal may only be sent
   once.  */
   once.  */
static void
static void
unblock_signal (int signum __attribute__ ((__unused__)))
unblock_signal (int signum __attribute__ ((__unused__)))
{
{
#ifdef _POSIX_VERSION
#ifdef _POSIX_VERSION
  sigset_t sigs;
  sigset_t sigs;
 
 
  sigemptyset (&sigs);
  sigemptyset (&sigs);
  sigaddset (&sigs, signum);
  sigaddset (&sigs, signum);
  sigprocmask (SIG_UNBLOCK, &sigs, NULL);
  sigprocmask (SIG_UNBLOCK, &sigs, NULL);
#endif
#endif
}
}
#endif
#endif
 
 
#ifdef HANDLE_SEGV
#ifdef HANDLE_SEGV
SIGNAL_HANDLER (catch_segv)
SIGNAL_HANDLER (catch_segv)
{
{
  unblock_signal (SIGSEGV);
  unblock_signal (SIGSEGV);
  MAKE_THROW_FRAME (nullp);
  MAKE_THROW_FRAME (nullp);
  java::lang::NullPointerException *nullp
  java::lang::NullPointerException *nullp
    = new java::lang::NullPointerException;
    = new java::lang::NullPointerException;
  throw nullp;
  throw nullp;
}
}
#endif
#endif
 
 
#ifdef HANDLE_FPE
#ifdef HANDLE_FPE
SIGNAL_HANDLER (catch_fpe)
SIGNAL_HANDLER (catch_fpe)
{
{
  unblock_signal (SIGFPE);
  unblock_signal (SIGFPE);
#ifdef HANDLE_DIVIDE_OVERFLOW
#ifdef HANDLE_DIVIDE_OVERFLOW
  HANDLE_DIVIDE_OVERFLOW;
  HANDLE_DIVIDE_OVERFLOW;
#else
#else
  MAKE_THROW_FRAME (arithexception);
  MAKE_THROW_FRAME (arithexception);
#endif
#endif
  java::lang::ArithmeticException *arithexception
  java::lang::ArithmeticException *arithexception
    = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
    = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
  throw arithexception;
  throw arithexception;
}
}
#endif
#endif
 
 
 
 
jboolean
jboolean
_Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
_Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
{
{
  int len;
  int len;
  const _Jv_ushort *aptr, *bptr;
  const _Jv_ushort *aptr, *bptr;
  if (a == b)
  if (a == b)
    return true;
    return true;
  if (a->hash != b->hash)
  if (a->hash != b->hash)
    return false;
    return false;
  len = a->length;
  len = a->length;
  if (b->length != len)
  if (b->length != len)
    return false;
    return false;
  aptr = (const _Jv_ushort *)a->data;
  aptr = (const _Jv_ushort *)a->data;
  bptr = (const _Jv_ushort *)b->data;
  bptr = (const _Jv_ushort *)b->data;
  len = (len + 1) >> 1;
  len = (len + 1) >> 1;
  while (--len >= 0)
  while (--len >= 0)
    if (*aptr++ != *bptr++)
    if (*aptr++ != *bptr++)
      return false;
      return false;
  return true;
  return true;
}
}
 
 
/* True iff A is equal to STR.
/* True iff A is equal to STR.
   HASH is STR->hashCode().
   HASH is STR->hashCode().
*/
*/
 
 
jboolean
jboolean
_Jv_equal (Utf8Const* a, jstring str, jint hash)
_Jv_equal (Utf8Const* a, jstring str, jint hash)
{
{
  if (a->hash != (_Jv_ushort) hash)
  if (a->hash != (_Jv_ushort) hash)
    return false;
    return false;
  jint len = str->length();
  jint len = str->length();
  jint i = 0;
  jint i = 0;
  jchar *sptr = _Jv_GetStringChars (str);
  jchar *sptr = _Jv_GetStringChars (str);
  unsigned char* ptr = (unsigned char*) a->data;
  unsigned char* ptr = (unsigned char*) a->data;
  unsigned char* limit = ptr + a->length;
  unsigned char* limit = ptr + a->length;
  for (;; i++, sptr++)
  for (;; i++, sptr++)
    {
    {
      int ch = UTF8_GET (ptr, limit);
      int ch = UTF8_GET (ptr, limit);
      if (i == len)
      if (i == len)
        return ch < 0;
        return ch < 0;
      if (ch != *sptr)
      if (ch != *sptr)
        return false;
        return false;
    }
    }
  return true;
  return true;
}
}
 
 
/* Like _Jv_equal, but stop after N characters.  */
/* Like _Jv_equal, but stop after N characters.  */
jboolean
jboolean
_Jv_equaln (Utf8Const *a, jstring str, jint n)
_Jv_equaln (Utf8Const *a, jstring str, jint n)
{
{
  jint len = str->length();
  jint len = str->length();
  jint i = 0;
  jint i = 0;
  jchar *sptr = _Jv_GetStringChars (str);
  jchar *sptr = _Jv_GetStringChars (str);
  unsigned char* ptr = (unsigned char*) a->data;
  unsigned char* ptr = (unsigned char*) a->data;
  unsigned char* limit = ptr + a->length;
  unsigned char* limit = ptr + a->length;
  for (; n-- > 0; i++, sptr++)
  for (; n-- > 0; i++, sptr++)
    {
    {
      int ch = UTF8_GET (ptr, limit);
      int ch = UTF8_GET (ptr, limit);
      if (i == len)
      if (i == len)
        return ch < 0;
        return ch < 0;
      if (ch != *sptr)
      if (ch != *sptr)
        return false;
        return false;
    }
    }
  return true;
  return true;
}
}
 
 
// Determines whether the given Utf8Const object contains
// Determines whether the given Utf8Const object contains
// a type which is primitive or some derived form of it, eg.
// a type which is primitive or some derived form of it, eg.
// an array or multi-dimensional array variant.
// an array or multi-dimensional array variant.
jboolean
jboolean
_Jv_isPrimitiveOrDerived(const Utf8Const *a)
_Jv_isPrimitiveOrDerived(const Utf8Const *a)
{
{
  unsigned char *aptr = (unsigned char *) a->data;
  unsigned char *aptr = (unsigned char *) a->data;
  unsigned char *alimit = aptr + a->length;
  unsigned char *alimit = aptr + a->length;
  int ac = UTF8_GET(aptr, alimit);
  int ac = UTF8_GET(aptr, alimit);
 
 
  // Skips any leading array marks.
  // Skips any leading array marks.
  while (ac == '[')
  while (ac == '[')
    ac = UTF8_GET(aptr, alimit);
    ac = UTF8_GET(aptr, alimit);
 
 
  // There should not be another character. This implies that
  // There should not be another character. This implies that
  // the type name is only one character long.
  // the type name is only one character long.
  if (UTF8_GET(aptr, alimit) == -1)
  if (UTF8_GET(aptr, alimit) == -1)
    switch ( ac )
    switch ( ac )
      {
      {
        case 'Z':
        case 'Z':
        case 'B':
        case 'B':
        case 'C':
        case 'C':
        case 'S':
        case 'S':
        case 'I':
        case 'I':
        case 'J':
        case 'J':
        case 'F':
        case 'F':
        case 'D':
        case 'D':
          return true;
          return true;
        default:
        default:
          break;
          break;
       }
       }
 
 
   return false;
   return false;
}
}
 
 
// Find out whether two _Jv_Utf8Const candidates contain the same
// Find out whether two _Jv_Utf8Const candidates contain the same
// classname.
// classname.
// The method is written to handle the different formats of classnames.
// The method is written to handle the different formats of classnames.
// Eg. "Ljava/lang/Class;", "Ljava.lang.Class;", "java/lang/Class" and
// Eg. "Ljava/lang/Class;", "Ljava.lang.Class;", "java/lang/Class" and
// "java.lang.Class" will be seen as equal.
// "java.lang.Class" will be seen as equal.
// Warning: This function is not smart enough to declare "Z" and "boolean"
// Warning: This function is not smart enough to declare "Z" and "boolean"
// and similar cases as equal (and is not meant to be used this way)!
// and similar cases as equal (and is not meant to be used this way)!
jboolean
jboolean
_Jv_equalUtf8Classnames (const Utf8Const *a, const Utf8Const *b)
_Jv_equalUtf8Classnames (const Utf8Const *a, const Utf8Const *b)
{
{
  // If the class name's length differs by two characters
  // If the class name's length differs by two characters
  // it is possible that we have candidates which are given
  // it is possible that we have candidates which are given
  // in the two different formats ("Lp1/p2/cn;" vs. "p1/p2/cn")
  // in the two different formats ("Lp1/p2/cn;" vs. "p1/p2/cn")
  switch (a->length - b->length)
  switch (a->length - b->length)
    {
    {
      case -2:
      case -2:
      case 0:
      case 0:
      case 2:
      case 2:
        break;
        break;
      default:
      default:
        return false;
        return false;
    }
    }
 
 
  unsigned char *aptr = (unsigned char *) a->data;
  unsigned char *aptr = (unsigned char *) a->data;
  unsigned char *alimit = aptr + a->length;
  unsigned char *alimit = aptr + a->length;
  unsigned char *bptr = (unsigned char *) b->data;
  unsigned char *bptr = (unsigned char *) b->data;
  unsigned char *blimit = bptr + b->length;
  unsigned char *blimit = bptr + b->length;
 
 
  if (alimit[-1] == ';')
  if (alimit[-1] == ';')
    alimit--;
    alimit--;
 
 
  if (blimit[-1] == ';')
  if (blimit[-1] == ';')
    blimit--;
    blimit--;
 
 
  int ac = UTF8_GET(aptr, alimit);
  int ac = UTF8_GET(aptr, alimit);
  int bc = UTF8_GET(bptr, blimit);
  int bc = UTF8_GET(bptr, blimit);
 
 
  // Checks whether both strings have the same amount of leading [ characters.
  // Checks whether both strings have the same amount of leading [ characters.
  while (ac == '[')
  while (ac == '[')
    {
    {
      if (bc == '[')
      if (bc == '[')
        {
        {
          ac = UTF8_GET(aptr, alimit);
          ac = UTF8_GET(aptr, alimit);
          bc = UTF8_GET(bptr, blimit);
          bc = UTF8_GET(bptr, blimit);
          continue;
          continue;
        }
        }
 
 
      return false;
      return false;
    }
    }
 
 
  // Skips leading L character.
  // Skips leading L character.
  if (ac == 'L')
  if (ac == 'L')
    ac = UTF8_GET(aptr, alimit);
    ac = UTF8_GET(aptr, alimit);
 
 
  if (bc == 'L')
  if (bc == 'L')
    bc = UTF8_GET(bptr, blimit);
    bc = UTF8_GET(bptr, blimit);
 
 
  // Compares the remaining characters.
  // Compares the remaining characters.
  while (ac != -1 && bc != -1)
  while (ac != -1 && bc != -1)
    {
    {
      // Replaces package separating dots with slashes.
      // Replaces package separating dots with slashes.
      if (ac == '.')
      if (ac == '.')
        ac = '/';
        ac = '/';
 
 
      if (bc == '.')
      if (bc == '.')
        bc = '/';
        bc = '/';
 
 
      // Now classnames differ if there is at least one non-matching
      // Now classnames differ if there is at least one non-matching
      // character.
      // character.
      if (ac != bc)
      if (ac != bc)
        return false;
        return false;
 
 
      ac = UTF8_GET(aptr, alimit);
      ac = UTF8_GET(aptr, alimit);
      bc = UTF8_GET(bptr, blimit);
      bc = UTF8_GET(bptr, blimit);
    }
    }
 
 
  return (ac == bc);
  return (ac == bc);
}
}
 
 
/* Count the number of Unicode chars encoded in a given Ut8 string. */
/* Count the number of Unicode chars encoded in a given Ut8 string. */
int
int
_Jv_strLengthUtf8(const char* str, int len)
_Jv_strLengthUtf8(const char* str, int len)
{
{
  unsigned char* ptr;
  unsigned char* ptr;
  unsigned char* limit;
  unsigned char* limit;
  int str_length;
  int str_length;
 
 
  ptr = (unsigned char*) str;
  ptr = (unsigned char*) str;
  limit = ptr + len;
  limit = ptr + len;
  str_length = 0;
  str_length = 0;
  for (; ptr < limit; str_length++)
  for (; ptr < limit; str_length++)
    {
    {
      if (UTF8_GET (ptr, limit) < 0)
      if (UTF8_GET (ptr, limit) < 0)
        return (-1);
        return (-1);
    }
    }
  return (str_length);
  return (str_length);
}
}
 
 
/* Calculate a hash value for a string encoded in Utf8 format.
/* Calculate a hash value for a string encoded in Utf8 format.
 * This returns the same hash value as specified or java.lang.String.hashCode.
 * This returns the same hash value as specified or java.lang.String.hashCode.
 */
 */
jint
jint
_Jv_hashUtf8String (const char* str, int len)
_Jv_hashUtf8String (const char* str, int len)
{
{
  unsigned char* ptr = (unsigned char*) str;
  unsigned char* ptr = (unsigned char*) str;
  unsigned char* limit = ptr + len;
  unsigned char* limit = ptr + len;
  jint hash = 0;
  jint hash = 0;
 
 
  for (; ptr < limit;)
  for (; ptr < limit;)
    {
    {
      int ch = UTF8_GET (ptr, limit);
      int ch = UTF8_GET (ptr, limit);
      /* Updated specification from
      /* Updated specification from
         http://www.javasoft.com/docs/books/jls/clarify.html. */
         http://www.javasoft.com/docs/books/jls/clarify.html. */
      hash = (31 * hash) + ch;
      hash = (31 * hash) + ch;
    }
    }
  return hash;
  return hash;
}
}
 
 
void
void
_Jv_Utf8Const::init(const char *s, int len)
_Jv_Utf8Const::init(const char *s, int len)
{
{
  ::memcpy (data, s, len);
  ::memcpy (data, s, len);
  data[len] = 0;
  data[len] = 0;
  length = len;
  length = len;
  hash = _Jv_hashUtf8String (s, len) & 0xFFFF;
  hash = _Jv_hashUtf8String (s, len) & 0xFFFF;
}
}
 
 
_Jv_Utf8Const *
_Jv_Utf8Const *
_Jv_makeUtf8Const (const char* s, int len)
_Jv_makeUtf8Const (const char* s, int len)
{
{
  if (len < 0)
  if (len < 0)
    len = strlen (s);
    len = strlen (s);
  Utf8Const* m
  Utf8Const* m
    = (Utf8Const*) _Jv_AllocBytes (_Jv_Utf8Const::space_needed(s, len));
    = (Utf8Const*) _Jv_AllocBytes (_Jv_Utf8Const::space_needed(s, len));
  m->init(s, len);
  m->init(s, len);
  return m;
  return m;
}
}
 
 
_Jv_Utf8Const *
_Jv_Utf8Const *
_Jv_makeUtf8Const (jstring string)
_Jv_makeUtf8Const (jstring string)
{
{
  jint hash = string->hashCode ();
  jint hash = string->hashCode ();
  jint len = _Jv_GetStringUTFLength (string);
  jint len = _Jv_GetStringUTFLength (string);
 
 
  Utf8Const* m = (Utf8Const*)
  Utf8Const* m = (Utf8Const*)
    _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
    _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
 
 
  m->hash = hash;
  m->hash = hash;
  m->length = len;
  m->length = len;
 
 
  _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
  _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
  m->data[len] = 0;
  m->data[len] = 0;
 
 
  return m;
  return m;
}
}
 
 


 
 
#ifdef __GCJ_DEBUG
#ifdef __GCJ_DEBUG
void
void
_Jv_Abort (const char *function, const char *file, int line,
_Jv_Abort (const char *function, const char *file, int line,
           const char *message)
           const char *message)
#else
#else
void
void
_Jv_Abort (const char *, const char *, int, const char *message)
_Jv_Abort (const char *, const char *, int, const char *message)
#endif
#endif
{
{
#ifdef __GCJ_DEBUG
#ifdef __GCJ_DEBUG
  fprintf (stderr,
  fprintf (stderr,
           "libgcj failure: %s\n   in function %s, file %s, line %d\n",
           "libgcj failure: %s\n   in function %s, file %s, line %d\n",
           message, function, file, line);
           message, function, file, line);
#else
#else
  fprintf (stderr, "libgcj failure: %s\n", message);
  fprintf (stderr, "libgcj failure: %s\n", message);
#endif
#endif
  fflush (stderr);
  fflush (stderr);
  abort ();
  abort ();
}
}
 
 
static void
static void
fail_on_finalization (jobject)
fail_on_finalization (jobject)
{
{
  JvFail ("object was finalized");
  JvFail ("object was finalized");
}
}
 
 
void
void
_Jv_GCWatch (jobject obj)
_Jv_GCWatch (jobject obj)
{
{
  _Jv_RegisterFinalizer (obj, fail_on_finalization);
  _Jv_RegisterFinalizer (obj, fail_on_finalization);
}
}
 
 
void
void
_Jv_ThrowBadArrayIndex(jint bad_index)
_Jv_ThrowBadArrayIndex(jint bad_index)
{
{
  throw new java::lang::ArrayIndexOutOfBoundsException
  throw new java::lang::ArrayIndexOutOfBoundsException
    (java::lang::String::valueOf (bad_index));
    (java::lang::String::valueOf (bad_index));
}
}
 
 
void
void
_Jv_ThrowNullPointerException ()
_Jv_ThrowNullPointerException ()
{
{
  throw new java::lang::NullPointerException;
  throw new java::lang::NullPointerException;
}
}
 
 
// Resolve an entry in the constant pool and return the target
// Resolve an entry in the constant pool and return the target
// address.
// address.
void *
void *
_Jv_ResolvePoolEntry (jclass this_class, jint index)
_Jv_ResolvePoolEntry (jclass this_class, jint index)
{
{
  _Jv_Constants *pool = &this_class->constants;
  _Jv_Constants *pool = &this_class->constants;
 
 
  if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
  if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
    return pool->data[index].field->u.addr;
    return pool->data[index].field->u.addr;
 
 
  JvSynchronize sync (this_class);
  JvSynchronize sync (this_class);
  return (_Jv_Linker::resolve_pool_entry (this_class, index))
  return (_Jv_Linker::resolve_pool_entry (this_class, index))
    .field->u.addr;
    .field->u.addr;
}
}
 
 
 
 
// Explicitly throw a no memory exception.
// Explicitly throw a no memory exception.
// The collector calls this when it encounters an out-of-memory condition.
// The collector calls this when it encounters an out-of-memory condition.
void _Jv_ThrowNoMemory()
void _Jv_ThrowNoMemory()
{
{
  throw no_memory;
  throw no_memory;
}
}
 
 
#ifdef ENABLE_JVMPI
#ifdef ENABLE_JVMPI
# define JVMPI_NOTIFY_ALLOC(klass,size,obj) \
# define JVMPI_NOTIFY_ALLOC(klass,size,obj) \
    if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false)) \
    if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false)) \
      jvmpi_notify_alloc(klass,size,obj);
      jvmpi_notify_alloc(klass,size,obj);
static void
static void
jvmpi_notify_alloc(jclass klass, jint size, jobject obj)
jvmpi_notify_alloc(jclass klass, jint size, jobject obj)
{
{
  // Service JVMPI allocation request.
  // Service JVMPI allocation request.
  JVMPI_Event event;
  JVMPI_Event event;
 
 
  event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
  event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
  event.env_id = NULL;
  event.env_id = NULL;
  event.u.obj_alloc.arena_id = 0;
  event.u.obj_alloc.arena_id = 0;
  event.u.obj_alloc.class_id = (jobjectID) klass;
  event.u.obj_alloc.class_id = (jobjectID) klass;
  event.u.obj_alloc.is_array = 0;
  event.u.obj_alloc.is_array = 0;
  event.u.obj_alloc.size = size;
  event.u.obj_alloc.size = size;
  event.u.obj_alloc.obj_id = (jobjectID) obj;
  event.u.obj_alloc.obj_id = (jobjectID) obj;
 
 
  // FIXME:  This doesn't look right for the Boehm GC.  A GC may
  // FIXME:  This doesn't look right for the Boehm GC.  A GC may
  // already be in progress.  _Jv_DisableGC () doesn't wait for it.
  // already be in progress.  _Jv_DisableGC () doesn't wait for it.
  // More importantly, I don't see the need for disabling GC, since we
  // More importantly, I don't see the need for disabling GC, since we
  // blatantly have a pointer to obj on our stack, ensuring that the
  // blatantly have a pointer to obj on our stack, ensuring that the
  // object can't be collected.  Even for a nonconservative collector,
  // object can't be collected.  Even for a nonconservative collector,
  // it appears to me that this must be true, since we are about to
  // it appears to me that this must be true, since we are about to
  // return obj. Isn't this whole approach way too intrusive for
  // return obj. Isn't this whole approach way too intrusive for
  // a useful profiling interface?                      - HB
  // a useful profiling interface?                      - HB
  _Jv_DisableGC ();
  _Jv_DisableGC ();
  (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
  (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
  _Jv_EnableGC ();
  _Jv_EnableGC ();
}
}
#else /* !ENABLE_JVMPI */
#else /* !ENABLE_JVMPI */
# define JVMPI_NOTIFY_ALLOC(klass,size,obj) /* do nothing */
# define JVMPI_NOTIFY_ALLOC(klass,size,obj) /* do nothing */
#endif
#endif
 
 
// Allocate a new object of class KLASS.
// Allocate a new object of class KLASS.
// First a version that assumes that we have no finalizer, and that
// First a version that assumes that we have no finalizer, and that
// the class is already initialized.
// the class is already initialized.
// If we know that JVMPI is disabled, this can be replaced by a direct call
// If we know that JVMPI is disabled, this can be replaced by a direct call
// to the allocator for the appropriate GC.
// to the allocator for the appropriate GC.
jobject
jobject
_Jv_AllocObjectNoInitNoFinalizer (jclass klass)
_Jv_AllocObjectNoInitNoFinalizer (jclass klass)
{
{
  jint size = klass->size ();
  jint size = klass->size ();
  jobject obj = (jobject) _Jv_AllocObj (size, klass);
  jobject obj = (jobject) _Jv_AllocObj (size, klass);
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
  return obj;
  return obj;
}
}
 
 
// And now a version that initializes if necessary.
// And now a version that initializes if necessary.
jobject
jobject
_Jv_AllocObjectNoFinalizer (jclass klass)
_Jv_AllocObjectNoFinalizer (jclass klass)
{
{
  if (_Jv_IsPhantomClass(klass) )
  if (_Jv_IsPhantomClass(klass) )
    throw new java::lang::NoClassDefFoundError(klass->getName());
    throw new java::lang::NoClassDefFoundError(klass->getName());
 
 
  _Jv_InitClass (klass);
  _Jv_InitClass (klass);
  jint size = klass->size ();
  jint size = klass->size ();
  jobject obj = (jobject) _Jv_AllocObj (size, klass);
  jobject obj = (jobject) _Jv_AllocObj (size, klass);
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
  return obj;
  return obj;
}
}
 
 
// And now the general version that registers a finalizer if necessary.
// And now the general version that registers a finalizer if necessary.
jobject
jobject
_Jv_AllocObject (jclass klass)
_Jv_AllocObject (jclass klass)
{
{
  jobject obj = _Jv_AllocObjectNoFinalizer (klass);
  jobject obj = _Jv_AllocObjectNoFinalizer (klass);
 
 
  // We assume that the compiler only generates calls to this routine
  // We assume that the compiler only generates calls to this routine
  // if there really is an interesting finalizer.
  // if there really is an interesting finalizer.
  // Unfortunately, we still have to the dynamic test, since there may
  // Unfortunately, we still have to the dynamic test, since there may
  // be cni calls to this routine.
  // be cni calls to this routine.
  // Note that on IA64 get_finalizer() returns the starting address of the
  // Note that on IA64 get_finalizer() returns the starting address of the
  // function, not a function pointer.  Thus this still works.
  // function, not a function pointer.  Thus this still works.
  if (klass->vtable->get_finalizer ()
  if (klass->vtable->get_finalizer ()
      != java::lang::Object::class$.vtable->get_finalizer ())
      != java::lang::Object::class$.vtable->get_finalizer ())
    _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
    _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
  return obj;
  return obj;
}
}
 
 
// Allocate a String, including variable length storage.
// Allocate a String, including variable length storage.
jstring
jstring
_Jv_AllocString(jsize len)
_Jv_AllocString(jsize len)
{
{
  using namespace java::lang;
  using namespace java::lang;
 
 
  jsize sz = sizeof(java::lang::String) + len * sizeof(jchar);
  jsize sz = sizeof(java::lang::String) + len * sizeof(jchar);
 
 
  // We assert that for strings allocated this way, the data field
  // We assert that for strings allocated this way, the data field
  // will always point to the object itself.  Thus there is no reason
  // will always point to the object itself.  Thus there is no reason
  // for the garbage collector to scan any of it.
  // for the garbage collector to scan any of it.
  // Furthermore, we're about to overwrite the string data, so
  // Furthermore, we're about to overwrite the string data, so
  // initialization of the object is not an issue.
  // initialization of the object is not an issue.
 
 
  // String needs no initialization, and there is no finalizer, so
  // String needs no initialization, and there is no finalizer, so
  // we can go directly to the collector's allocator interface.
  // we can go directly to the collector's allocator interface.
  jstring obj = (jstring) _Jv_AllocPtrFreeObj(sz, &String::class$);
  jstring obj = (jstring) _Jv_AllocPtrFreeObj(sz, &String::class$);
 
 
  obj->data = obj;
  obj->data = obj;
  obj->boffset = sizeof(java::lang::String);
  obj->boffset = sizeof(java::lang::String);
  obj->count = len;
  obj->count = len;
  obj->cachedHashCode = 0;
  obj->cachedHashCode = 0;
 
 
  JVMPI_NOTIFY_ALLOC (&String::class$, sz, obj);
  JVMPI_NOTIFY_ALLOC (&String::class$, sz, obj);
 
 
  return obj;
  return obj;
}
}
 
 
// A version of the above that assumes the object contains no pointers,
// A version of the above that assumes the object contains no pointers,
// and requires no finalization.  This can't happen if we need pointers
// and requires no finalization.  This can't happen if we need pointers
// to locks.
// to locks.
#ifdef JV_HASH_SYNCHRONIZATION
#ifdef JV_HASH_SYNCHRONIZATION
jobject
jobject
_Jv_AllocPtrFreeObject (jclass klass)
_Jv_AllocPtrFreeObject (jclass klass)
{
{
  _Jv_InitClass (klass);
  _Jv_InitClass (klass);
  jint size = klass->size ();
  jint size = klass->size ();
 
 
  jobject obj = (jobject) _Jv_AllocPtrFreeObj (size, klass);
  jobject obj = (jobject) _Jv_AllocPtrFreeObj (size, klass);
 
 
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
 
 
  return obj;
  return obj;
}
}
#endif /* JV_HASH_SYNCHRONIZATION */
#endif /* JV_HASH_SYNCHRONIZATION */
 
 
 
 
// Allocate a new array of Java objects.  Each object is of type
// Allocate a new array of Java objects.  Each object is of type
// `elementClass'.  `init' is used to initialize each slot in the
// `elementClass'.  `init' is used to initialize each slot in the
// array.
// array.
jobjectArray
jobjectArray
_Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
_Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
{
{
  // Creating an array of an unresolved type is impossible. So we throw
  // Creating an array of an unresolved type is impossible. So we throw
  // the NoClassDefFoundError.
  // the NoClassDefFoundError.
  if ( _Jv_IsPhantomClass(elementClass) )
  if ( _Jv_IsPhantomClass(elementClass) )
    throw new java::lang::NoClassDefFoundError(elementClass->getName());
    throw new java::lang::NoClassDefFoundError(elementClass->getName());
 
 
  if (__builtin_expect (count < 0, false))
  if (__builtin_expect (count < 0, false))
    throw new java::lang::NegativeArraySizeException;
    throw new java::lang::NegativeArraySizeException;
 
 
  JvAssert (! elementClass->isPrimitive ());
  JvAssert (! elementClass->isPrimitive ());
 
 
  // Ensure that elements pointer is properly aligned.
  // Ensure that elements pointer is properly aligned.
  jobjectArray obj = NULL;
  jobjectArray obj = NULL;
  size_t size = (size_t) elements (obj);
  size_t size = (size_t) elements (obj);
  // Check for overflow.
  // Check for overflow.
  if (__builtin_expect ((size_t) count >
  if (__builtin_expect ((size_t) count >
                        (MAX_OBJECT_SIZE - 1 - size) / sizeof (jobject), false))
                        (MAX_OBJECT_SIZE - 1 - size) / sizeof (jobject), false))
    throw no_memory;
    throw no_memory;
 
 
  size += count * sizeof (jobject);
  size += count * sizeof (jobject);
 
 
  jclass klass = _Jv_GetArrayClass (elementClass,
  jclass klass = _Jv_GetArrayClass (elementClass,
                                    elementClass->getClassLoaderInternal());
                                    elementClass->getClassLoaderInternal());
 
 
  obj = (jobjectArray) _Jv_AllocArray (size, klass);
  obj = (jobjectArray) _Jv_AllocArray (size, klass);
  // Cast away const.
  // Cast away const.
  jsize *lp = const_cast<jsize *> (&obj->length);
  jsize *lp = const_cast<jsize *> (&obj->length);
  *lp = count;
  *lp = count;
  // We know the allocator returns zeroed memory.  So don't bother
  // We know the allocator returns zeroed memory.  So don't bother
  // zeroing it again.
  // zeroing it again.
  if (init)
  if (init)
    {
    {
      jobject *ptr = elements(obj);
      jobject *ptr = elements(obj);
      while (--count >= 0)
      while (--count >= 0)
        *ptr++ = init;
        *ptr++ = init;
    }
    }
  return obj;
  return obj;
}
}
 
 
// Allocate a new array of primitives.  ELTYPE is the type of the
// Allocate a new array of primitives.  ELTYPE is the type of the
// element, COUNT is the size of the array.
// element, COUNT is the size of the array.
jobject
jobject
_Jv_NewPrimArray (jclass eltype, jint count)
_Jv_NewPrimArray (jclass eltype, jint count)
{
{
  int elsize = eltype->size();
  int elsize = eltype->size();
  if (__builtin_expect (count < 0, false))
  if (__builtin_expect (count < 0, false))
    throw new java::lang::NegativeArraySizeException;
    throw new java::lang::NegativeArraySizeException;
 
 
  JvAssert (eltype->isPrimitive ());
  JvAssert (eltype->isPrimitive ());
  jobject dummy = NULL;
  jobject dummy = NULL;
  size_t size = (size_t) _Jv_GetArrayElementFromElementType (dummy, eltype);
  size_t size = (size_t) _Jv_GetArrayElementFromElementType (dummy, eltype);
 
 
  // Check for overflow.
  // Check for overflow.
  if (__builtin_expect ((size_t) count >
  if (__builtin_expect ((size_t) count >
                        (MAX_OBJECT_SIZE - size) / elsize, false))
                        (MAX_OBJECT_SIZE - size) / elsize, false))
    throw no_memory;
    throw no_memory;
 
 
  jclass klass = _Jv_GetArrayClass (eltype, 0);
  jclass klass = _Jv_GetArrayClass (eltype, 0);
 
 
# ifdef JV_HASH_SYNCHRONIZATION
# ifdef JV_HASH_SYNCHRONIZATION
  // Since the vtable is always statically allocated,
  // Since the vtable is always statically allocated,
  // these are completely pointerfree!  Make sure the GC doesn't touch them.
  // these are completely pointerfree!  Make sure the GC doesn't touch them.
  __JArray *arr =
  __JArray *arr =
    (__JArray*) _Jv_AllocPtrFreeObj (size + elsize * count, klass);
    (__JArray*) _Jv_AllocPtrFreeObj (size + elsize * count, klass);
  memset((char *)arr + size, 0, elsize * count);
  memset((char *)arr + size, 0, elsize * count);
# else
# else
  __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
  __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
  // Note that we assume we are given zeroed memory by the allocator.
  // Note that we assume we are given zeroed memory by the allocator.
# endif
# endif
  // Cast away const.
  // Cast away const.
  jsize *lp = const_cast<jsize *> (&arr->length);
  jsize *lp = const_cast<jsize *> (&arr->length);
  *lp = count;
  *lp = count;
 
 
  return arr;
  return arr;
}
}
 
 
jobject
jobject
_Jv_NewArray (jint type, jint size)
_Jv_NewArray (jint type, jint size)
{
{
  switch (type)
  switch (type)
    {
    {
      case  4:  return JvNewBooleanArray (size);
      case  4:  return JvNewBooleanArray (size);
      case  5:  return JvNewCharArray (size);
      case  5:  return JvNewCharArray (size);
      case  6:  return JvNewFloatArray (size);
      case  6:  return JvNewFloatArray (size);
      case  7:  return JvNewDoubleArray (size);
      case  7:  return JvNewDoubleArray (size);
      case  8:  return JvNewByteArray (size);
      case  8:  return JvNewByteArray (size);
      case  9:  return JvNewShortArray (size);
      case  9:  return JvNewShortArray (size);
      case 10:  return JvNewIntArray (size);
      case 10:  return JvNewIntArray (size);
      case 11:  return JvNewLongArray (size);
      case 11:  return JvNewLongArray (size);
    }
    }
  throw new java::lang::InternalError
  throw new java::lang::InternalError
    (JvNewStringLatin1 ("invalid type code in _Jv_NewArray"));
    (JvNewStringLatin1 ("invalid type code in _Jv_NewArray"));
}
}
 
 
// Allocate a possibly multi-dimensional array but don't check that
// Allocate a possibly multi-dimensional array but don't check that
// any array length is <0.
// any array length is <0.
static jobject
static jobject
_Jv_NewMultiArrayUnchecked (jclass type, jint dimensions, jint *sizes)
_Jv_NewMultiArrayUnchecked (jclass type, jint dimensions, jint *sizes)
{
{
  JvAssert (type->isArray());
  JvAssert (type->isArray());
  jclass element_type = type->getComponentType();
  jclass element_type = type->getComponentType();
  jobject result;
  jobject result;
  if (element_type->isPrimitive())
  if (element_type->isPrimitive())
    result = _Jv_NewPrimArray (element_type, sizes[0]);
    result = _Jv_NewPrimArray (element_type, sizes[0]);
  else
  else
    result = _Jv_NewObjectArray (sizes[0], element_type, NULL);
    result = _Jv_NewObjectArray (sizes[0], element_type, NULL);
 
 
  if (dimensions > 1)
  if (dimensions > 1)
    {
    {
      JvAssert (! element_type->isPrimitive());
      JvAssert (! element_type->isPrimitive());
      JvAssert (element_type->isArray());
      JvAssert (element_type->isArray());
      jobject *contents = elements ((jobjectArray) result);
      jobject *contents = elements ((jobjectArray) result);
      for (int i = 0; i < sizes[0]; ++i)
      for (int i = 0; i < sizes[0]; ++i)
        contents[i] = _Jv_NewMultiArrayUnchecked (element_type, dimensions - 1,
        contents[i] = _Jv_NewMultiArrayUnchecked (element_type, dimensions - 1,
                                                  sizes + 1);
                                                  sizes + 1);
    }
    }
 
 
  return result;
  return result;
}
}
 
 
jobject
jobject
_Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
_Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
{
{
  for (int i = 0; i < dimensions; ++i)
  for (int i = 0; i < dimensions; ++i)
    if (sizes[i] < 0)
    if (sizes[i] < 0)
      throw new java::lang::NegativeArraySizeException;
      throw new java::lang::NegativeArraySizeException;
 
 
  return _Jv_NewMultiArrayUnchecked (type, dimensions, sizes);
  return _Jv_NewMultiArrayUnchecked (type, dimensions, sizes);
}
}
 
 
jobject
jobject
_Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
_Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
{
{
  // Creating an array of an unresolved type is impossible. So we throw
  // Creating an array of an unresolved type is impossible. So we throw
  // the NoClassDefFoundError.
  // the NoClassDefFoundError.
  if (_Jv_IsPhantomClass(array_type))
  if (_Jv_IsPhantomClass(array_type))
    throw new java::lang::NoClassDefFoundError(array_type->getName());
    throw new java::lang::NoClassDefFoundError(array_type->getName());
 
 
  va_list args;
  va_list args;
  jint sizes[dimensions];
  jint sizes[dimensions];
  va_start (args, dimensions);
  va_start (args, dimensions);
  for (int i = 0; i < dimensions; ++i)
  for (int i = 0; i < dimensions; ++i)
    {
    {
      jint size = va_arg (args, jint);
      jint size = va_arg (args, jint);
      if (size < 0)
      if (size < 0)
        throw new java::lang::NegativeArraySizeException;
        throw new java::lang::NegativeArraySizeException;
      sizes[i] = size;
      sizes[i] = size;
    }
    }
  va_end (args);
  va_end (args);
 
 
  return _Jv_NewMultiArrayUnchecked (array_type, dimensions, sizes);
  return _Jv_NewMultiArrayUnchecked (array_type, dimensions, sizes);
}
}
 
 


 
 
// Ensure 8-byte alignment, for hash synchronization.
// Ensure 8-byte alignment, for hash synchronization.
#define DECLARE_PRIM_TYPE(NAME)                 \
#define DECLARE_PRIM_TYPE(NAME)                 \
  java::lang::Class _Jv_##NAME##Class __attribute__ ((aligned (8)));
  java::lang::Class _Jv_##NAME##Class __attribute__ ((aligned (8)));
 
 
DECLARE_PRIM_TYPE(byte)
DECLARE_PRIM_TYPE(byte)
DECLARE_PRIM_TYPE(short)
DECLARE_PRIM_TYPE(short)
DECLARE_PRIM_TYPE(int)
DECLARE_PRIM_TYPE(int)
DECLARE_PRIM_TYPE(long)
DECLARE_PRIM_TYPE(long)
DECLARE_PRIM_TYPE(boolean)
DECLARE_PRIM_TYPE(boolean)
DECLARE_PRIM_TYPE(char)
DECLARE_PRIM_TYPE(char)
DECLARE_PRIM_TYPE(float)
DECLARE_PRIM_TYPE(float)
DECLARE_PRIM_TYPE(double)
DECLARE_PRIM_TYPE(double)
DECLARE_PRIM_TYPE(void)
DECLARE_PRIM_TYPE(void)
 
 
void
void
_Jv_InitPrimClass (jclass cl, const char *cname, char sig, int len)
_Jv_InitPrimClass (jclass cl, const char *cname, char sig, int len)
{
{
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
 
 
  // We must set the vtable for the class; the Java constructor
  // We must set the vtable for the class; the Java constructor
  // doesn't do this.
  // doesn't do this.
  (*(_Jv_VTable **) cl) = java::lang::Class::class$.vtable;
  (*(_Jv_VTable **) cl) = java::lang::Class::class$.vtable;
 
 
  // Initialize the fields we care about.  We do this in the same
  // Initialize the fields we care about.  We do this in the same
  // order they are declared in Class.h.
  // order they are declared in Class.h.
  cl->name = _Jv_makeUtf8Const ((char *) cname, -1);
  cl->name = _Jv_makeUtf8Const ((char *) cname, -1);
  cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
  cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
  cl->method_count = sig;
  cl->method_count = sig;
  cl->size_in_bytes = len;
  cl->size_in_bytes = len;
  cl->vtable = JV_PRIMITIVE_VTABLE;
  cl->vtable = JV_PRIMITIVE_VTABLE;
  cl->state = JV_STATE_DONE;
  cl->state = JV_STATE_DONE;
  cl->depth = -1;
  cl->depth = -1;
}
}
 
 
jclass
jclass
_Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader,
_Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader,
                            char **endp)
                            char **endp)
{
{
  // First count arrays.
  // First count arrays.
  int array_count = 0;
  int array_count = 0;
  while (*sig == '[')
  while (*sig == '[')
    {
    {
      ++sig;
      ++sig;
      ++array_count;
      ++array_count;
    }
    }
 
 
  jclass result = NULL;
  jclass result = NULL;
  switch (*sig)
  switch (*sig)
    {
    {
    case 'B':
    case 'B':
      result = JvPrimClass (byte);
      result = JvPrimClass (byte);
      break;
      break;
    case 'S':
    case 'S':
      result = JvPrimClass (short);
      result = JvPrimClass (short);
      break;
      break;
    case 'I':
    case 'I':
      result = JvPrimClass (int);
      result = JvPrimClass (int);
      break;
      break;
    case 'J':
    case 'J':
      result = JvPrimClass (long);
      result = JvPrimClass (long);
      break;
      break;
    case 'Z':
    case 'Z':
      result = JvPrimClass (boolean);
      result = JvPrimClass (boolean);
      break;
      break;
    case 'C':
    case 'C':
      result = JvPrimClass (char);
      result = JvPrimClass (char);
      break;
      break;
    case 'F':
    case 'F':
      result = JvPrimClass (float);
      result = JvPrimClass (float);
      break;
      break;
    case 'D':
    case 'D':
      result = JvPrimClass (double);
      result = JvPrimClass (double);
      break;
      break;
    case 'V':
    case 'V':
      result = JvPrimClass (void);
      result = JvPrimClass (void);
      break;
      break;
    case 'L':
    case 'L':
      {
      {
        char *save = ++sig;
        char *save = ++sig;
        while (*sig && *sig != ';')
        while (*sig && *sig != ';')
          ++sig;
          ++sig;
        // Do nothing if signature appears to be malformed.
        // Do nothing if signature appears to be malformed.
        if (*sig == ';')
        if (*sig == ';')
          {
          {
            _Jv_Utf8Const *name = _Jv_makeUtf8Const (save, sig - save);
            _Jv_Utf8Const *name = _Jv_makeUtf8Const (save, sig - save);
            result = _Jv_FindClass (name, loader);
            result = _Jv_FindClass (name, loader);
          }
          }
        break;
        break;
      }
      }
    default:
    default:
      // Do nothing -- bad signature.
      // Do nothing -- bad signature.
      break;
      break;
    }
    }
 
 
  if (endp)
  if (endp)
    {
    {
      // Not really the "end", but the last valid character that we
      // Not really the "end", but the last valid character that we
      // looked at.
      // looked at.
      *endp = sig;
      *endp = sig;
    }
    }
 
 
  if (! result)
  if (! result)
    return NULL;
    return NULL;
 
 
  // Find arrays.
  // Find arrays.
  while (array_count-- > 0)
  while (array_count-- > 0)
    result = _Jv_GetArrayClass (result, loader);
    result = _Jv_GetArrayClass (result, loader);
  return result;
  return result;
}
}
 
 
 
 
jclass
jclass
_Jv_FindClassFromSignatureNoException (char *sig, java::lang::ClassLoader *loader,
_Jv_FindClassFromSignatureNoException (char *sig, java::lang::ClassLoader *loader,
                                       char **endp)
                                       char **endp)
{
{
  jclass klass;
  jclass klass;
 
 
  try
  try
    {
    {
      klass = _Jv_FindClassFromSignature(sig, loader, endp);
      klass = _Jv_FindClassFromSignature(sig, loader, endp);
    }
    }
  catch (java::lang::NoClassDefFoundError *ncdfe)
  catch (java::lang::NoClassDefFoundError *ncdfe)
    {
    {
      return NULL;
      return NULL;
    }
    }
  catch (java::lang::ClassNotFoundException *cnfe)
  catch (java::lang::ClassNotFoundException *cnfe)
    {
    {
      return NULL;
      return NULL;
    }
    }
 
 
  return klass;
  return klass;
}
}
 
 
JArray<jstring> *
JArray<jstring> *
JvConvertArgv (int argc, const char **argv)
JvConvertArgv (int argc, const char **argv)
{
{
  if (argc < 0)
  if (argc < 0)
    argc = 0;
    argc = 0;
  jobjectArray ar = JvNewObjectArray(argc, &java::lang::String::class$, NULL);
  jobjectArray ar = JvNewObjectArray(argc, &java::lang::String::class$, NULL);
  jobject *ptr = elements(ar);
  jobject *ptr = elements(ar);
  jbyteArray bytes = NULL;
  jbyteArray bytes = NULL;
  for (int i = 0;  i < argc;  i++)
  for (int i = 0;  i < argc;  i++)
    {
    {
      const char *arg = argv[i];
      const char *arg = argv[i];
      int len = strlen (arg);
      int len = strlen (arg);
      if (bytes == NULL || bytes->length < len)
      if (bytes == NULL || bytes->length < len)
        bytes = JvNewByteArray (len);
        bytes = JvNewByteArray (len);
      jbyte *bytePtr = elements (bytes);
      jbyte *bytePtr = elements (bytes);
      // We assume jbyte == char.
      // We assume jbyte == char.
      memcpy (bytePtr, arg, len);
      memcpy (bytePtr, arg, len);
 
 
      // Now convert using the default encoding.
      // Now convert using the default encoding.
      *ptr++ = new java::lang::String (bytes, 0, len);
      *ptr++ = new java::lang::String (bytes, 0, len);
    }
    }
  return (JArray<jstring>*) ar;
  return (JArray<jstring>*) ar;
}
}
 
 
// FIXME: These variables are static so that they will be
// FIXME: These variables are static so that they will be
// automatically scanned by the Boehm collector.  This is needed
// automatically scanned by the Boehm collector.  This is needed
// because with qthreads the collector won't scan the initial stack --
// because with qthreads the collector won't scan the initial stack --
// it will only scan the qthreads stacks.
// it will only scan the qthreads stacks.
 
 
// Command line arguments.
// Command line arguments.
static JArray<jstring> *arg_vec;
static JArray<jstring> *arg_vec;
 
 
// The primary thread.
// The primary thread.
static java::lang::Thread *main_thread;
static java::lang::Thread *main_thread;
 
 
#ifndef DISABLE_GETENV_PROPERTIES
#ifndef DISABLE_GETENV_PROPERTIES
 
 
#define c_isspace(c) (memchr (" \t\n\r\v\f", c, 6) != NULL)
#define c_isspace(c) (memchr (" \t\n\r\v\f", c, 6) != NULL)
 
 
static char *
static char *
next_property_key (char *s, size_t *length)
next_property_key (char *s, size_t *length)
{
{
  size_t l = 0;
  size_t l = 0;
 
 
  JvAssert (s);
  JvAssert (s);
 
 
  // Skip over whitespace
  // Skip over whitespace
  while (c_isspace (*s))
  while (c_isspace (*s))
    s++;
    s++;
 
 
  // If we've reached the end, return NULL.  Also return NULL if for
  // If we've reached the end, return NULL.  Also return NULL if for
  // some reason we've come across a malformed property string.
  // some reason we've come across a malformed property string.
  if (*s == 0
  if (*s == 0
      || *s == ':'
      || *s == ':'
      || *s == '=')
      || *s == '=')
    return NULL;
    return NULL;
 
 
  // Determine the length of the property key.
  // Determine the length of the property key.
  while (s[l] != 0
  while (s[l] != 0
         && ! c_isspace (s[l])
         && ! c_isspace (s[l])
         && s[l] != ':'
         && s[l] != ':'
         && s[l] != '=')
         && s[l] != '=')
    {
    {
      if (s[l] == '\\'
      if (s[l] == '\\'
          && s[l+1] != 0)
          && s[l+1] != 0)
        l++;
        l++;
      l++;
      l++;
    }
    }
 
 
  *length = l;
  *length = l;
 
 
  return s;
  return s;
}
}
 
 
static char *
static char *
next_property_value (char *s, size_t *length)
next_property_value (char *s, size_t *length)
{
{
  size_t l = 0;
  size_t l = 0;
 
 
  JvAssert (s);
  JvAssert (s);
 
 
  while (c_isspace (*s))
  while (c_isspace (*s))
    s++;
    s++;
 
 
  if (*s == ':'
  if (*s == ':'
      || *s == '=')
      || *s == '=')
    s++;
    s++;
 
 
  while (c_isspace (*s))
  while (c_isspace (*s))
    s++;
    s++;
 
 
  // Determine the length of the property value.
  // Determine the length of the property value.
  while (s[l] != 0
  while (s[l] != 0
         && ! c_isspace (s[l])
         && ! c_isspace (s[l])
         && s[l] != ':'
         && s[l] != ':'
         && s[l] != '=')
         && s[l] != '=')
    {
    {
      if (s[l] == '\\'
      if (s[l] == '\\'
          && s[l+1] != 0)
          && s[l+1] != 0)
        l += 2;
        l += 2;
      else
      else
        l++;
        l++;
    }
    }
 
 
  *length = l;
  *length = l;
 
 
  return s;
  return s;
}
}
 
 
static void
static void
process_gcj_properties ()
process_gcj_properties ()
{
{
  char *props = getenv("GCJ_PROPERTIES");
  char *props = getenv("GCJ_PROPERTIES");
 
 
  if (NULL == props)
  if (NULL == props)
    return;
    return;
 
 
  // Later on we will write \0s into this string.  It is simplest to
  // Later on we will write \0s into this string.  It is simplest to
  // just duplicate it here.
  // just duplicate it here.
  props = strdup (props);
  props = strdup (props);
 
 
  char *p = props;
  char *p = props;
  size_t length;
  size_t length;
  size_t property_count = 0;
  size_t property_count = 0;
 
 
  // Whip through props quickly in order to count the number of
  // Whip through props quickly in order to count the number of
  // property values.
  // property values.
  while (p && (p = next_property_key (p, &length)))
  while (p && (p = next_property_key (p, &length)))
    {
    {
      // Skip to the end of the key
      // Skip to the end of the key
      p += length;
      p += length;
 
 
      p = next_property_value (p, &length);
      p = next_property_value (p, &length);
      if (p)
      if (p)
        p += length;
        p += length;
 
 
      property_count++;
      property_count++;
    }
    }
 
 
  // Allocate an array of property value/key pairs.
  // Allocate an array of property value/key pairs.
  _Jv_Environment_Properties =
  _Jv_Environment_Properties =
    (property_pair *) malloc (sizeof(property_pair)
    (property_pair *) malloc (sizeof(property_pair)
                              * (property_count + 1));
                              * (property_count + 1));
 
 
  // Go through the properties again, initializing _Jv_Properties
  // Go through the properties again, initializing _Jv_Properties
  // along the way.
  // along the way.
  p = props;
  p = props;
  property_count = 0;
  property_count = 0;
  while (p && (p = next_property_key (p, &length)))
  while (p && (p = next_property_key (p, &length)))
    {
    {
      _Jv_Environment_Properties[property_count].key = p;
      _Jv_Environment_Properties[property_count].key = p;
      _Jv_Environment_Properties[property_count].key_length = length;
      _Jv_Environment_Properties[property_count].key_length = length;
 
 
      // Skip to the end of the key
      // Skip to the end of the key
      p += length;
      p += length;
 
 
      p = next_property_value (p, &length);
      p = next_property_value (p, &length);
 
 
      _Jv_Environment_Properties[property_count].value = p;
      _Jv_Environment_Properties[property_count].value = p;
      _Jv_Environment_Properties[property_count].value_length = length;
      _Jv_Environment_Properties[property_count].value_length = length;
 
 
      if (p)
      if (p)
        p += length;
        p += length;
 
 
      property_count++;
      property_count++;
    }
    }
  memset ((void *) &_Jv_Environment_Properties[property_count],
  memset ((void *) &_Jv_Environment_Properties[property_count],
          0, sizeof (property_pair));
          0, sizeof (property_pair));
 
 
  // Null terminate the strings.
  // Null terminate the strings.
  for (property_pair *prop = &_Jv_Environment_Properties[0];
  for (property_pair *prop = &_Jv_Environment_Properties[0];
       prop->key != NULL;
       prop->key != NULL;
       prop++)
       prop++)
    {
    {
      prop->key[prop->key_length] = 0;
      prop->key[prop->key_length] = 0;
      prop->value[prop->value_length] = 0;
      prop->value[prop->value_length] = 0;
    }
    }
}
}
#endif // DISABLE_GETENV_PROPERTIES
#endif // DISABLE_GETENV_PROPERTIES
 
 
namespace gcj
namespace gcj
{
{
  _Jv_Utf8Const *void_signature;
  _Jv_Utf8Const *void_signature;
  _Jv_Utf8Const *clinit_name;
  _Jv_Utf8Const *clinit_name;
  _Jv_Utf8Const *init_name;
  _Jv_Utf8Const *init_name;
  _Jv_Utf8Const *finit_name;
  _Jv_Utf8Const *finit_name;
 
 
  bool runtimeInitialized = false;
  bool runtimeInitialized = false;
 
 
  // When true, print debugging information about class loading.
  // When true, print debugging information about class loading.
  bool verbose_class_flag;
  bool verbose_class_flag;
 
 
  // When true, enable the bytecode verifier and BC-ABI type verification. 
  // When true, enable the bytecode verifier and BC-ABI type verification. 
  bool verifyClasses = true;
  bool verifyClasses = true;
 
 
  // Thread stack size specified by the -Xss runtime argument.
  // Thread stack size specified by the -Xss runtime argument.
  size_t stack_size = 0;
  size_t stack_size = 0;
 
 
  // Start time of the VM
  // Start time of the VM
  jlong startTime = 0;
  jlong startTime = 0;
 
 
  // Arguments passed to the VM
  // Arguments passed to the VM
  JArray<jstring>* vmArgs;
  JArray<jstring>* vmArgs;
 
 
  // Currently loaded classes
  // Currently loaded classes
  jint loadedClasses = 0;
  jint loadedClasses = 0;
 
 
  // Unloaded classes
  // Unloaded classes
  jlong unloadedClasses = 0;
  jlong unloadedClasses = 0;
}
}
 
 
// We accept all non-standard options accepted by Sun's java command,
// We accept all non-standard options accepted by Sun's java command,
// for compatibility with existing application launch scripts.
// for compatibility with existing application launch scripts.
static jint
static jint
parse_x_arg (char* option_string)
parse_x_arg (char* option_string)
{
{
  if (strlen (option_string) <= 0)
  if (strlen (option_string) <= 0)
    return -1;
    return -1;
 
 
  if (! strcmp (option_string, "int"))
  if (! strcmp (option_string, "int"))
    {
    {
      // FIXME: this should cause the vm to never load shared objects
      // FIXME: this should cause the vm to never load shared objects
    }
    }
  else if (! strcmp (option_string, "mixed"))
  else if (! strcmp (option_string, "mixed"))
    {
    {
      // FIXME: allow interpreted and native code
      // FIXME: allow interpreted and native code
    }
    }
  else if (! strcmp (option_string, "batch"))
  else if (! strcmp (option_string, "batch"))
    {
    {
      // FIXME: disable background JIT'ing
      // FIXME: disable background JIT'ing
    }
    }
  else if (! strcmp (option_string, "debug"))
  else if (! strcmp (option_string, "debug"))
    {
    {
      remoteDebug = true;
      remoteDebug = true;
    }
    }
#ifdef INTERPRETER
#ifdef INTERPRETER
  else if (! strncmp (option_string, "runjdwp:", 8))
  else if (! strncmp (option_string, "runjdwp:", 8))
    {
    {
      if (strlen (option_string) > 8)
      if (strlen (option_string) > 8)
          jdwpOptions = &option_string[8];
          jdwpOptions = &option_string[8];
      else
      else
        {
        {
          fprintf (stderr,
          fprintf (stderr,
                   "libgcj: argument required for JDWP options");
                   "libgcj: argument required for JDWP options");
          return -1;
          return -1;
        }
        }
    }
    }
#endif // INTERPRETER
#endif // INTERPRETER
  else if (! strncmp (option_string, "bootclasspath:", 14))
  else if (! strncmp (option_string, "bootclasspath:", 14))
    {
    {
      // FIXME: add a parse_bootclasspath_arg function
      // FIXME: add a parse_bootclasspath_arg function
    }
    }
  else if (! strncmp (option_string, "bootclasspath/a:", 16))
  else if (! strncmp (option_string, "bootclasspath/a:", 16))
    {
    {
    }
    }
  else if (! strncmp (option_string, "bootclasspath/p:", 16))
  else if (! strncmp (option_string, "bootclasspath/p:", 16))
    {
    {
    }
    }
  else if (! strcmp (option_string, "check:jni"))
  else if (! strcmp (option_string, "check:jni"))
    {
    {
      // FIXME: enable strict JNI checking
      // FIXME: enable strict JNI checking
    }
    }
  else if (! strcmp (option_string, "future"))
  else if (! strcmp (option_string, "future"))
    {
    {
      // FIXME: enable strict class file format checks
      // FIXME: enable strict class file format checks
    }
    }
  else if (! strcmp (option_string, "noclassgc"))
  else if (! strcmp (option_string, "noclassgc"))
    {
    {
      // FIXME: disable garbage collection for classes
      // FIXME: disable garbage collection for classes
    }
    }
  else if (! strcmp (option_string, "incgc"))
  else if (! strcmp (option_string, "incgc"))
    {
    {
      // FIXME: incremental garbage collection
      // FIXME: incremental garbage collection
    }
    }
  else if (! strncmp (option_string, "loggc:", 6))
  else if (! strncmp (option_string, "loggc:", 6))
    {
    {
      if (option_string[6] == '\0')
      if (option_string[6] == '\0')
        {
        {
          fprintf (stderr,
          fprintf (stderr,
                   "libgcj: filename argument expected for loggc option\n");
                   "libgcj: filename argument expected for loggc option\n");
          return -1;
          return -1;
        }
        }
      // FIXME: set gc logging filename
      // FIXME: set gc logging filename
    }
    }
  else if (! strncmp (option_string, "ms", 2))
  else if (! strncmp (option_string, "ms", 2))
    {
    {
      // FIXME: ignore this option until PR 20699 is fixed.
      // FIXME: ignore this option until PR 20699 is fixed.
      // _Jv_SetInitialHeapSize (option_string + 2);
      // _Jv_SetInitialHeapSize (option_string + 2);
    }
    }
  else if (! strncmp (option_string, "mx", 2))
  else if (! strncmp (option_string, "mx", 2))
    _Jv_SetMaximumHeapSize (option_string + 2);
    _Jv_SetMaximumHeapSize (option_string + 2);
  else if (! strcmp (option_string, "prof"))
  else if (! strcmp (option_string, "prof"))
    {
    {
      // FIXME: enable profiling of program running in vm
      // FIXME: enable profiling of program running in vm
    }
    }
  else if (! strncmp (option_string, "runhprof:", 9))
  else if (! strncmp (option_string, "runhprof:", 9))
    {
    {
      // FIXME: enable specific type of vm profiling.  add a
      // FIXME: enable specific type of vm profiling.  add a
      // parse_runhprof_arg function
      // parse_runhprof_arg function
    }
    }
  else if (! strcmp (option_string, "rs"))
  else if (! strcmp (option_string, "rs"))
    {
    {
      // FIXME: reduced system signal usage.  disable thread dumps,
      // FIXME: reduced system signal usage.  disable thread dumps,
      // only terminate in response to user-initiated calls,
      // only terminate in response to user-initiated calls,
      // e.g. System.exit()
      // e.g. System.exit()
    }
    }
  else if (! strncmp (option_string, "ss", 2))
  else if (! strncmp (option_string, "ss", 2))
    {
    {
      _Jv_SetStackSize (option_string + 2);
      _Jv_SetStackSize (option_string + 2);
    }
    }
  else if (! strcmp (option_string, "X:+UseAltSigs"))
  else if (! strcmp (option_string, "X:+UseAltSigs"))
    {
    {
      // FIXME: use signals other than SIGUSR1 and SIGUSR2
      // FIXME: use signals other than SIGUSR1 and SIGUSR2
    }
    }
  else if (! strcmp (option_string, "share:off"))
  else if (! strcmp (option_string, "share:off"))
    {
    {
      // FIXME: don't share class data
      // FIXME: don't share class data
    }
    }
  else if (! strcmp (option_string, "share:auto"))
  else if (! strcmp (option_string, "share:auto"))
    {
    {
      // FIXME: share class data where possible
      // FIXME: share class data where possible
    }
    }
  else if (! strcmp (option_string, "share:on"))
  else if (! strcmp (option_string, "share:on"))
    {
    {
      // FIXME: fail if impossible to share class data
      // FIXME: fail if impossible to share class data
    }
    }
  else
  else
    {
    {
      // Unrecognized.
      // Unrecognized.
      return -1;
      return -1;
    }
    }
  return 0;
  return 0;
}
}
 
 
static jint
static jint
parse_verbose_args (char* option_string,
parse_verbose_args (char* option_string,
                    bool ignore_unrecognized)
                    bool ignore_unrecognized)
{
{
  size_t len = sizeof ("-verbose") - 1;
  size_t len = sizeof ("-verbose") - 1;
 
 
  if (strlen (option_string) < len)
  if (strlen (option_string) < len)
    return -1;
    return -1;
 
 
  if (option_string[len] == ':'
  if (option_string[len] == ':'
      && option_string[len + 1] != '\0')
      && option_string[len + 1] != '\0')
    {
    {
      char* verbose_args = option_string + len + 1;
      char* verbose_args = option_string + len + 1;
 
 
      do
      do
        {
        {
          if (! strncmp (verbose_args,
          if (! strncmp (verbose_args,
                         "gc", sizeof ("gc") - 1))
                         "gc", sizeof ("gc") - 1))
            {
            {
              if (verbose_args[sizeof ("gc") - 1] == '\0'
              if (verbose_args[sizeof ("gc") - 1] == '\0'
                  || verbose_args[sizeof ("gc") - 1] == ',')
                  || verbose_args[sizeof ("gc") - 1] == ',')
                {
                {
                  // FIXME: we should add functions to boehm-gc that
                  // FIXME: we should add functions to boehm-gc that
                  // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
                  // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
                  // GC_print_back_height.
                  // GC_print_back_height.
                  verbose_args += sizeof ("gc") - 1;
                  verbose_args += sizeof ("gc") - 1;
                }
                }
              else
              else
                {
                {
                verbose_arg_err:
                verbose_arg_err:
                  fprintf (stderr, "libgcj: unknown verbose option: %s\n",
                  fprintf (stderr, "libgcj: unknown verbose option: %s\n",
                           option_string);
                           option_string);
                  return -1;
                  return -1;
                }
                }
            }
            }
          else if (! strncmp (verbose_args,
          else if (! strncmp (verbose_args,
                              "class",
                              "class",
                              sizeof ("class") - 1))
                              sizeof ("class") - 1))
            {
            {
              if (verbose_args[sizeof ("class") - 1] == '\0'
              if (verbose_args[sizeof ("class") - 1] == '\0'
                  || verbose_args[sizeof ("class") - 1] == ',')
                  || verbose_args[sizeof ("class") - 1] == ',')
                {
                {
                  gcj::verbose_class_flag = true;
                  gcj::verbose_class_flag = true;
                  verbose_args += sizeof ("class") - 1;
                  verbose_args += sizeof ("class") - 1;
                }
                }
              else
              else
                goto verbose_arg_err;
                goto verbose_arg_err;
            }
            }
          else if (! strncmp (verbose_args, "jni",
          else if (! strncmp (verbose_args, "jni",
                              sizeof ("jni") - 1))
                              sizeof ("jni") - 1))
            {
            {
              if (verbose_args[sizeof ("jni") - 1] == '\0'
              if (verbose_args[sizeof ("jni") - 1] == '\0'
                  || verbose_args[sizeof ("jni") - 1] == ',')
                  || verbose_args[sizeof ("jni") - 1] == ',')
                {
                {
                  // FIXME: enable JNI messages.
                  // FIXME: enable JNI messages.
                  verbose_args += sizeof ("jni") - 1;
                  verbose_args += sizeof ("jni") - 1;
                }
                }
              else
              else
                goto verbose_arg_err;
                goto verbose_arg_err;
            }
            }
          else if (ignore_unrecognized
          else if (ignore_unrecognized
                   && verbose_args[0] == 'X')
                   && verbose_args[0] == 'X')
            {
            {
              // ignore unrecognized non-standard verbose option
              // ignore unrecognized non-standard verbose option
              while (verbose_args[0] != '\0'
              while (verbose_args[0] != '\0'
                     && verbose_args[0] != ',')
                     && verbose_args[0] != ',')
                verbose_args++;
                verbose_args++;
            }
            }
          else if (verbose_args[0] == ',')
          else if (verbose_args[0] == ',')
            {
            {
              verbose_args++;
              verbose_args++;
            }
            }
          else
          else
            goto verbose_arg_err;
            goto verbose_arg_err;
 
 
          if (verbose_args[0] == ',')
          if (verbose_args[0] == ',')
            verbose_args++;
            verbose_args++;
        }
        }
      while (verbose_args[0] != '\0');
      while (verbose_args[0] != '\0');
    }
    }
  else if (option_string[len] == 'g'
  else if (option_string[len] == 'g'
           && option_string[len + 1] == 'c'
           && option_string[len + 1] == 'c'
           && option_string[len + 2] == '\0')
           && option_string[len + 2] == '\0')
    {
    {
      // FIXME: we should add functions to boehm-gc that
      // FIXME: we should add functions to boehm-gc that
      // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
      // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
      // GC_print_back_height.
      // GC_print_back_height.
      return 0;
      return 0;
    }
    }
  else if (option_string[len] == '\0')
  else if (option_string[len] == '\0')
    {
    {
      gcj::verbose_class_flag = true;
      gcj::verbose_class_flag = true;
      return 0;
      return 0;
    }
    }
  else
  else
    {
    {
      // unrecognized option beginning with -verbose
      // unrecognized option beginning with -verbose
      return -1;
      return -1;
    }
    }
  return 0;
  return 0;
}
}
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
// This function loads the agent functions for JVMTI from the library indicated
// This function loads the agent functions for JVMTI from the library indicated
// by name.  It returns a negative value on failure, the value of which
// by name.  It returns a negative value on failure, the value of which
// indicates where ltdl failed, it also prints an error message.
// indicates where ltdl failed, it also prints an error message.
static jint
static jint
load_jvmti_agent (const char *name)
load_jvmti_agent (const char *name)
{
{
#ifdef USE_LTDL
#ifdef USE_LTDL
  if (lt_dlinit ())
  if (lt_dlinit ())
    {
    {
      fprintf (stderr,
      fprintf (stderr,
              "libgcj: Error in ltdl init while loading agent library.\n");
              "libgcj: Error in ltdl init while loading agent library.\n");
      return -1;
      return -1;
    }
    }
 
 
  lt_dlhandle lib = lt_dlopenext (name);
  lt_dlhandle lib = lt_dlopenext (name);
  if (!lib)
  if (!lib)
    {
    {
      fprintf (stderr,
      fprintf (stderr,
               "libgcj: Error opening agent library.\n");
               "libgcj: Error opening agent library.\n");
      return -2;
      return -2;
    }
    }
 
 
  if (lib)
  if (lib)
    {
    {
      jvmti_agentonload
      jvmti_agentonload
        = (jvmti_agent_onload_func *) lt_dlsym (lib, "Agent_OnLoad");
        = (jvmti_agent_onload_func *) lt_dlsym (lib, "Agent_OnLoad");
 
 
      if (!jvmti_agentonload)
      if (!jvmti_agentonload)
        {
        {
          fprintf (stderr,
          fprintf (stderr,
                   "libgcj: Error finding agent function in library %s.\n",
                   "libgcj: Error finding agent function in library %s.\n",
                   name);
                   name);
          lt_dlclose (lib);
          lt_dlclose (lib);
          lib = NULL;
          lib = NULL;
          return -4;
          return -4;
        }
        }
      else
      else
        {
        {
          jvmti_agentonunload
          jvmti_agentonunload
            = (jvmti_agent_onunload_func *) lt_dlsym (lib, "Agent_OnUnload");
            = (jvmti_agent_onunload_func *) lt_dlsym (lib, "Agent_OnUnload");
 
 
          return 0;
          return 0;
        }
        }
    }
    }
  else
  else
    {
    {
      fprintf (stderr, "libgcj: Library %s not found in library path.\n", name);
      fprintf (stderr, "libgcj: Library %s not found in library path.\n", name);
      return -3;
      return -3;
    }
    }
 
 
#endif /* USE_LTDL */
#endif /* USE_LTDL */
 
 
  // If LTDL cannot be used, return an error code indicating this.
  // If LTDL cannot be used, return an error code indicating this.
  return -99;
  return -99;
}
}
#endif // INTERPRETER
#endif // INTERPRETER
 
 
static jint
static jint
parse_init_args (JvVMInitArgs* vm_args)
parse_init_args (JvVMInitArgs* vm_args)
{
{
  // if _Jv_Compiler_Properties is non-NULL then it needs to be
  // if _Jv_Compiler_Properties is non-NULL then it needs to be
  // re-allocated dynamically.
  // re-allocated dynamically.
  if (_Jv_Compiler_Properties)
  if (_Jv_Compiler_Properties)
    {
    {
      const char** props = _Jv_Compiler_Properties;
      const char** props = _Jv_Compiler_Properties;
      _Jv_Compiler_Properties = NULL;
      _Jv_Compiler_Properties = NULL;
 
 
      for (int i = 0; props[i]; i++)
      for (int i = 0; props[i]; i++)
        {
        {
          _Jv_Compiler_Properties = (const char**) _Jv_Realloc
          _Jv_Compiler_Properties = (const char**) _Jv_Realloc
            (_Jv_Compiler_Properties,
            (_Jv_Compiler_Properties,
             (_Jv_Properties_Count + 1) * sizeof (const char*));
             (_Jv_Properties_Count + 1) * sizeof (const char*));
          _Jv_Compiler_Properties[_Jv_Properties_Count++] = props[i];
          _Jv_Compiler_Properties[_Jv_Properties_Count++] = props[i];
        }
        }
    }
    }
 
 
  if (vm_args == NULL)
  if (vm_args == NULL)
    return 0;
    return 0;
 
 
  for (int i = 0; i < vm_args->nOptions; ++i)
  for (int i = 0; i < vm_args->nOptions; ++i)
    {
    {
      char* option_string = vm_args->options[i].optionString;
      char* option_string = vm_args->options[i].optionString;
 
 
      if (! strcmp (option_string, "vfprintf")
      if (! strcmp (option_string, "vfprintf")
          || ! strcmp (option_string, "exit")
          || ! strcmp (option_string, "exit")
          || ! strcmp (option_string, "abort"))
          || ! strcmp (option_string, "abort"))
        {
        {
          // FIXME: we are required to recognize these, but for
          // FIXME: we are required to recognize these, but for
          // now we don't handle them in any way.
          // now we don't handle them in any way.
          continue;
          continue;
        }
        }
      else if (! strncmp (option_string,
      else if (! strncmp (option_string,
                          "-verbose", sizeof ("-verbose") - 1))
                          "-verbose", sizeof ("-verbose") - 1))
        {
        {
          jint result = parse_verbose_args (option_string,
          jint result = parse_verbose_args (option_string,
                                            vm_args->ignoreUnrecognized);
                                            vm_args->ignoreUnrecognized);
          if (result < 0)
          if (result < 0)
            return result;
            return result;
        }
        }
      else if (! strncmp (option_string, "-D", 2))
      else if (! strncmp (option_string, "-D", 2))
        {
        {
          _Jv_Compiler_Properties = (const char**) _Jv_Realloc
          _Jv_Compiler_Properties = (const char**) _Jv_Realloc
            (_Jv_Compiler_Properties,
            (_Jv_Compiler_Properties,
             (_Jv_Properties_Count + 1) * sizeof (char*));
             (_Jv_Properties_Count + 1) * sizeof (char*));
 
 
          _Jv_Compiler_Properties[_Jv_Properties_Count++] =
          _Jv_Compiler_Properties[_Jv_Properties_Count++] =
            strdup (option_string + 2);
            strdup (option_string + 2);
 
 
          continue;
          continue;
        }
        }
#ifdef INTERPRETER
#ifdef INTERPRETER
      else if (! strncmp (option_string, "-agentlib", sizeof ("-agentlib") - 1))
      else if (! strncmp (option_string, "-agentlib", sizeof ("-agentlib") - 1))
        {
        {
          char *strPtr;
          char *strPtr;
 
 
          if (strlen(option_string) > (sizeof ("-agentlib:") - 1))
          if (strlen(option_string) > (sizeof ("-agentlib:") - 1))
            strPtr = &option_string[sizeof ("-agentlib:") - 1];
            strPtr = &option_string[sizeof ("-agentlib:") - 1];
          else
          else
            {
            {
              fprintf (stderr,
              fprintf (stderr,
                "libgcj: Malformed agentlib argument %s: expected lib name\n",
                "libgcj: Malformed agentlib argument %s: expected lib name\n",
                option_string);
                option_string);
              return -1;
              return -1;
            }
            }
 
 
          // These are optional arguments to pass to the agent library.
          // These are optional arguments to pass to the agent library.
          jvmti_agent_opts = strchr (strPtr, '=');
          jvmti_agent_opts = strchr (strPtr, '=');
 
 
          if (! strncmp (strPtr, "jdwp", 4))
          if (! strncmp (strPtr, "jdwp", 4))
            {
            {
              // We want to run JDWP here so set the correct variables.
              // We want to run JDWP here so set the correct variables.
              remoteDebug = true;
              remoteDebug = true;
              jdwpOptions = ++jvmti_agent_opts;
              jdwpOptions = ++jvmti_agent_opts;
            }
            }
          else
          else
            {
            {
              jint nameLength;
              jint nameLength;
 
 
              if (jvmti_agent_opts == NULL)
              if (jvmti_agent_opts == NULL)
                nameLength = strlen (strPtr);
                nameLength = strlen (strPtr);
              else
              else
                {
                {
                  nameLength = jvmti_agent_opts - strPtr;
                  nameLength = jvmti_agent_opts - strPtr;
                  jvmti_agent_opts++;
                  jvmti_agent_opts++;
                }
                }
 
 
              char lib_name[nameLength + 3 + 1];
              char lib_name[nameLength + 3 + 1];
              strcpy (lib_name, "lib");
              strcpy (lib_name, "lib");
              strncat (lib_name, strPtr, nameLength);
              strncat (lib_name, strPtr, nameLength);
 
 
              jint result = load_jvmti_agent (lib_name);
              jint result = load_jvmti_agent (lib_name);
 
 
              if (result < 0)
              if (result < 0)
                {
                {
                  return -1;
                  return -1;
                }
                }
 
 
              // Mark JVMTI active
              // Mark JVMTI active
              JVMTI::enabled = true;
              JVMTI::enabled = true;
            }
            }
 
 
          continue;
          continue;
        }
        }
      else if (! strncmp (option_string, "-agentpath:",
      else if (! strncmp (option_string, "-agentpath:",
                          sizeof ("-agentpath:") - 1))
                          sizeof ("-agentpath:") - 1))
        {
        {
          char *strPtr;
          char *strPtr;
 
 
          if (strlen(option_string) > 10)
          if (strlen(option_string) > 10)
            strPtr = &option_string[10];
            strPtr = &option_string[10];
          else
          else
            {
            {
              fprintf (stderr,
              fprintf (stderr,
                "libgcj: Malformed agentlib argument %s: expected lib path\n",
                "libgcj: Malformed agentlib argument %s: expected lib path\n",
                option_string);
                option_string);
              return -1;
              return -1;
            }
            }
 
 
          // These are optional arguments to pass to the agent library.
          // These are optional arguments to pass to the agent library.
          jvmti_agent_opts = strchr (strPtr, '=');
          jvmti_agent_opts = strchr (strPtr, '=');
 
 
          jint nameLength;
          jint nameLength;
 
 
          if (jvmti_agent_opts == NULL)
          if (jvmti_agent_opts == NULL)
            nameLength = strlen (strPtr);
            nameLength = strlen (strPtr);
          else
          else
            {
            {
              nameLength = jvmti_agent_opts - strPtr;
              nameLength = jvmti_agent_opts - strPtr;
              jvmti_agent_opts++;
              jvmti_agent_opts++;
            }
            }
 
 
          char lib_name[nameLength + 3 + 1];
          char lib_name[nameLength + 3 + 1];
          strcpy (lib_name, "lib");
          strcpy (lib_name, "lib");
          strncat (lib_name, strPtr, nameLength);
          strncat (lib_name, strPtr, nameLength);
          jint result = load_jvmti_agent (strPtr);
          jint result = load_jvmti_agent (strPtr);
 
 
          if (result < 0)
          if (result < 0)
            {
            {
              return -1;
              return -1;
            }
            }
 
 
          // Mark JVMTI active
          // Mark JVMTI active
          JVMTI::enabled = true;
          JVMTI::enabled = true;
          continue;
          continue;
        }
        }
#endif // INTERPRETER
#endif // INTERPRETER
      else
      else
        {
        {
          int r = -1;
          int r = -1;
          if (option_string[0] == '_')
          if (option_string[0] == '_')
            r = parse_x_arg (option_string + 1);
            r = parse_x_arg (option_string + 1);
          else if (! strncmp (option_string, "-X", 2))
          else if (! strncmp (option_string, "-X", 2))
            r = parse_x_arg (option_string + 2);
            r = parse_x_arg (option_string + 2);
 
 
          if (r == -1 && ! vm_args->ignoreUnrecognized)
          if (r == -1 && ! vm_args->ignoreUnrecognized)
            {
            {
              fprintf (stderr, "libgcj: unknown option: %s\n", option_string);
              fprintf (stderr, "libgcj: unknown option: %s\n", option_string);
              return -1;
              return -1;
            }
            }
        }
        }
    }
    }
  return 0;
  return 0;
}
}
 
 
jint
jint
_Jv_CreateJavaVM (JvVMInitArgs* vm_args)
_Jv_CreateJavaVM (JvVMInitArgs* vm_args)
{
{
  using namespace gcj;
  using namespace gcj;
 
 
  if (runtimeInitialized)
  if (runtimeInitialized)
    return -1;
    return -1;
 
 
  runtimeInitialized = true;
  runtimeInitialized = true;
  startTime = _Jv_platform_gettimeofday();
  startTime = _Jv_platform_gettimeofday();
 
 
  jint result = parse_init_args (vm_args);
  jint result = parse_init_args (vm_args);
  if (result < 0)
  if (result < 0)
    return -1;
    return -1;
 
 
  PROCESS_GCJ_PROPERTIES;
  PROCESS_GCJ_PROPERTIES;
 
 
  /* Threads must be initialized before the GC, so that it inherits the
  /* Threads must be initialized before the GC, so that it inherits the
     signal mask.  */
     signal mask.  */
  _Jv_InitThreads ();
  _Jv_InitThreads ();
  _Jv_InitGC ();
  _Jv_InitGC ();
  _Jv_InitializeSyncMutex ();
  _Jv_InitializeSyncMutex ();
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
  _Jv_InitInterpreter ();
  _Jv_InitInterpreter ();
#endif  
#endif  
 
 
#ifdef HANDLE_SEGV
#ifdef HANDLE_SEGV
  INIT_SEGV;
  INIT_SEGV;
#endif
#endif
 
 
#ifdef HANDLE_FPE
#ifdef HANDLE_FPE
  INIT_FPE;
  INIT_FPE;
#endif
#endif
 
 
  /* Initialize Utf8 constants declared in jvm.h. */
  /* Initialize Utf8 constants declared in jvm.h. */
  void_signature = _Jv_makeUtf8Const ("()V", 3);
  void_signature = _Jv_makeUtf8Const ("()V", 3);
  clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
  clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
  init_name = _Jv_makeUtf8Const ("<init>", 6);
  init_name = _Jv_makeUtf8Const ("<init>", 6);
  finit_name = _Jv_makeUtf8Const ("finit$", 6);
  finit_name = _Jv_makeUtf8Const ("finit$", 6);
 
 
  /* Initialize built-in classes to represent primitive TYPEs. */
  /* Initialize built-in classes to represent primitive TYPEs. */
  _Jv_InitPrimClass (&_Jv_byteClass,    "byte",    'B', 1);
  _Jv_InitPrimClass (&_Jv_byteClass,    "byte",    'B', 1);
  _Jv_InitPrimClass (&_Jv_shortClass,   "short",   'S', 2);
  _Jv_InitPrimClass (&_Jv_shortClass,   "short",   'S', 2);
  _Jv_InitPrimClass (&_Jv_intClass,     "int",     'I', 4);
  _Jv_InitPrimClass (&_Jv_intClass,     "int",     'I', 4);
  _Jv_InitPrimClass (&_Jv_longClass,    "long",    'J', 8);
  _Jv_InitPrimClass (&_Jv_longClass,    "long",    'J', 8);
  _Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1);
  _Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1);
  _Jv_InitPrimClass (&_Jv_charClass,    "char",    'C', 2);
  _Jv_InitPrimClass (&_Jv_charClass,    "char",    'C', 2);
  _Jv_InitPrimClass (&_Jv_floatClass,   "float",   'F', 4);
  _Jv_InitPrimClass (&_Jv_floatClass,   "float",   'F', 4);
  _Jv_InitPrimClass (&_Jv_doubleClass,  "double",  'D', 8);
  _Jv_InitPrimClass (&_Jv_doubleClass,  "double",  'D', 8);
  _Jv_InitPrimClass (&_Jv_voidClass,    "void",    'V', 0);
  _Jv_InitPrimClass (&_Jv_voidClass,    "void",    'V', 0);
 
 
  // We have to initialize this fairly early, to avoid circular class
  // We have to initialize this fairly early, to avoid circular class
  // initialization.  In particular we want to start the
  // initialization.  In particular we want to start the
  // initialization of ClassLoader before we start the initialization
  // initialization of ClassLoader before we start the initialization
  // of VMClassLoader.
  // of VMClassLoader.
  _Jv_InitClass (&java::lang::ClassLoader::class$);
  _Jv_InitClass (&java::lang::ClassLoader::class$);
 
 
  // Set up the system class loader and the bootstrap class loader.
  // Set up the system class loader and the bootstrap class loader.
  gnu::gcj::runtime::ExtensionClassLoader::initialize();
  gnu::gcj::runtime::ExtensionClassLoader::initialize();
  java::lang::VMClassLoader::initialize(JvNewStringLatin1(TOOLEXECLIBDIR));
  java::lang::VMClassLoader::initialize(JvNewStringLatin1(TOOLEXECLIBDIR));
 
 
  _Jv_RegisterBootstrapPackages();
  _Jv_RegisterBootstrapPackages();
 
 
  no_memory = new java::lang::OutOfMemoryError;
  no_memory = new java::lang::OutOfMemoryError;
 
 
#ifdef USE_LTDL
#ifdef USE_LTDL
  LTDL_SET_PRELOADED_SYMBOLS ();
  LTDL_SET_PRELOADED_SYMBOLS ();
#endif
#endif
 
 
  _Jv_platform_initialize ();
  _Jv_platform_initialize ();
 
 
  _Jv_JNI_Init ();
  _Jv_JNI_Init ();
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
  _Jv_JVMTI_Init ();
  _Jv_JVMTI_Init ();
#endif
#endif
 
 
  _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
  _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
 
 
  // Start the GC finalizer thread.  A VirtualMachineError can be
  // Start the GC finalizer thread.  A VirtualMachineError can be
  // thrown by the runtime if, say, threads aren't available.
  // thrown by the runtime if, say, threads aren't available.
  try
  try
    {
    {
      using namespace gnu::gcj::runtime;
      using namespace gnu::gcj::runtime;
      FinalizerThread *ft = new FinalizerThread ();
      FinalizerThread *ft = new FinalizerThread ();
      ft->start ();
      ft->start ();
    }
    }
  catch (java::lang::VirtualMachineError *ignore)
  catch (java::lang::VirtualMachineError *ignore)
    {
    {
    }
    }
 
 
  runtimeInitialized = true;
  runtimeInitialized = true;
 
 
  return 0;
  return 0;
}
}
 
 
void
void
_Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
_Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
             const char **argv, bool is_jar)
             const char **argv, bool is_jar)
{
{
#ifndef DISABLE_MAIN_ARGS
#ifndef DISABLE_MAIN_ARGS
  _Jv_SetArgs (argc, argv);
  _Jv_SetArgs (argc, argv);
#endif
#endif
 
 
  java::lang::Runtime *runtime = NULL;
  java::lang::Runtime *runtime = NULL;
 
 
  try
  try
    {
    {
      if (_Jv_CreateJavaVM (vm_args) < 0)
      if (_Jv_CreateJavaVM (vm_args) < 0)
        {
        {
          fprintf (stderr, "libgcj: couldn't create virtual machine\n");
          fprintf (stderr, "libgcj: couldn't create virtual machine\n");
          exit (1);
          exit (1);
        }
        }
 
 
      if (vm_args == NULL)
      if (vm_args == NULL)
        gcj::vmArgs = JvConvertArgv(0, NULL);
        gcj::vmArgs = JvConvertArgv(0, NULL);
      else
      else
        {
        {
          const char* vmArgs[vm_args->nOptions];
          const char* vmArgs[vm_args->nOptions];
          const char** vmPtr = vmArgs;
          const char** vmPtr = vmArgs;
          struct _Jv_VMOption* optionPtr = vm_args->options;
          struct _Jv_VMOption* optionPtr = vm_args->options;
          for (int i = 0; i < vm_args->nOptions; ++i)
          for (int i = 0; i < vm_args->nOptions; ++i)
            *vmPtr++ = (*optionPtr++).optionString;
            *vmPtr++ = (*optionPtr++).optionString;
          gcj::vmArgs = JvConvertArgv(vm_args->nOptions, vmArgs);
          gcj::vmArgs = JvConvertArgv(vm_args->nOptions, vmArgs);
        }
        }
 
 
      // Get the Runtime here.  We want to initialize it before searching
      // Get the Runtime here.  We want to initialize it before searching
      // for `main'; that way it will be set up if `main' is a JNI method.
      // for `main'; that way it will be set up if `main' is a JNI method.
      runtime = java::lang::Runtime::getRuntime ();
      runtime = java::lang::Runtime::getRuntime ();
 
 
#ifdef DISABLE_MAIN_ARGS
#ifdef DISABLE_MAIN_ARGS
      arg_vec = JvConvertArgv (0, 0);
      arg_vec = JvConvertArgv (0, 0);
#else      
#else      
      arg_vec = JvConvertArgv (argc - 1, argv + 1);
      arg_vec = JvConvertArgv (argc - 1, argv + 1);
#endif
#endif
 
 
      using namespace gnu::java::lang;
      using namespace gnu::java::lang;
      if (klass)
      if (klass)
        main_thread = new MainThread (klass, arg_vec);
        main_thread = new MainThread (klass, arg_vec);
      else
      else
        main_thread = new MainThread (JvNewStringUTF (name),
        main_thread = new MainThread (JvNewStringUTF (name),
                                      arg_vec, is_jar);
                                      arg_vec, is_jar);
      _Jv_AttachCurrentThread (main_thread);
      _Jv_AttachCurrentThread (main_thread);
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
      // Start JVMTI if an agent function has been found.
      // Start JVMTI if an agent function has been found.
      if (jvmti_agentonload)
      if (jvmti_agentonload)
        (*jvmti_agentonload) (_Jv_GetJavaVM (), jvmti_agent_opts, NULL);
        (*jvmti_agentonload) (_Jv_GetJavaVM (), jvmti_agent_opts, NULL);
 
 
      // Start JDWP
      // Start JDWP
      if (remoteDebug)
      if (remoteDebug)
        {
        {
          using namespace gnu::classpath::jdwp;
          using namespace gnu::classpath::jdwp;
          VMVirtualMachine::initialize ();
          VMVirtualMachine::initialize ();
          Jdwp *jdwp = new Jdwp ();
          Jdwp *jdwp = new Jdwp ();
          jdwp->setDaemon (true);
          jdwp->setDaemon (true);
          jdwp->configure (JvNewStringLatin1 (jdwpOptions));
          jdwp->configure (JvNewStringLatin1 (jdwpOptions));
          jdwp->start ();
          jdwp->start ();
 
 
          // Wait for JDWP to initialize and start
          // Wait for JDWP to initialize and start
          jdwp->join ();
          jdwp->join ();
        }
        }
      // Send VMInit
      // Send VMInit
      if (JVMTI_REQUESTED_EVENT (VMInit))
      if (JVMTI_REQUESTED_EVENT (VMInit))
        _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_INIT, main_thread);
        _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_INIT, main_thread);
#endif // INTERPRETER
#endif // INTERPRETER
    }
    }
  catch (java::lang::Throwable *t)
  catch (java::lang::Throwable *t)
    {
    {
      java::lang::System::err->println (JvNewStringLatin1
      java::lang::System::err->println (JvNewStringLatin1
        ("Exception during runtime initialization"));
        ("Exception during runtime initialization"));
      t->printStackTrace();
      t->printStackTrace();
      if (runtime)
      if (runtime)
        java::lang::Runtime::exitNoChecksAccessor (1);
        java::lang::Runtime::exitNoChecksAccessor (1);
      // In case the runtime creation failed.
      // In case the runtime creation failed.
      ::exit (1);
      ::exit (1);
    }
    }
 
 
  _Jv_ThreadRun (main_thread);
  _Jv_ThreadRun (main_thread);
 
 
#ifdef INTERPRETER
#ifdef INTERPRETER
  // Send VMDeath
  // Send VMDeath
  if (JVMTI_REQUESTED_EVENT (VMDeath))
  if (JVMTI_REQUESTED_EVENT (VMDeath))
    {
    {
      java::lang::Thread *thread = java::lang::Thread::currentThread ();
      java::lang::Thread *thread = java::lang::Thread::currentThread ();
      JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
      JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
      _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_DEATH, thread, jni_env);
      _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_DEATH, thread, jni_env);
    }
    }
 
 
  // Run JVMTI AgentOnUnload if it exists and an agent is loaded.
  // Run JVMTI AgentOnUnload if it exists and an agent is loaded.
  if (jvmti_agentonunload)
  if (jvmti_agentonunload)
    (*jvmti_agentonunload) (_Jv_GetJavaVM ());
    (*jvmti_agentonunload) (_Jv_GetJavaVM ());
#endif // INTERPRETER
#endif // INTERPRETER
 
 
  // If we got here then something went wrong, as MainThread is not
  // If we got here then something went wrong, as MainThread is not
  // supposed to terminate.
  // supposed to terminate.
  ::exit (1);
  ::exit (1);
}
}
 
 
void
void
_Jv_RunMain (jclass klass, const char *name, int argc, const char **argv,
_Jv_RunMain (jclass klass, const char *name, int argc, const char **argv,
             bool is_jar)
             bool is_jar)
{
{
  _Jv_RunMain (NULL, klass, name, argc, argv, is_jar);
  _Jv_RunMain (NULL, klass, name, argc, argv, is_jar);
}
}
 
 
void
void
JvRunMain (jclass klass, int argc, const char **argv)
JvRunMain (jclass klass, int argc, const char **argv)
{
{
  _Jv_RunMain (klass, NULL, argc, argv, false);
  _Jv_RunMain (klass, NULL, argc, argv, false);
}
}
 
 
void
void
JvRunMainName (const char *name, int argc, const char **argv)
JvRunMainName (const char *name, int argc, const char **argv)
{
{
  _Jv_RunMain (NULL, name, argc, argv, false);
  _Jv_RunMain (NULL, name, argc, argv, false);
}
}
 
 


 
 
// Parse a string and return a heap size.
// Parse a string and return a heap size.
static size_t
static size_t
parse_memory_size (const char *spec)
parse_memory_size (const char *spec)
{
{
  char *end;
  char *end;
  unsigned long val = strtoul (spec, &end, 10);
  unsigned long val = strtoul (spec, &end, 10);
  if (*end == 'k' || *end == 'K')
  if (*end == 'k' || *end == 'K')
    val *= 1024;
    val *= 1024;
  else if (*end == 'm' || *end == 'M')
  else if (*end == 'm' || *end == 'M')
    val *= 1048576;
    val *= 1048576;
  return (size_t) val;
  return (size_t) val;
}
}
 
 
// Set the initial heap size.  This might be ignored by the GC layer.
// Set the initial heap size.  This might be ignored by the GC layer.
// This must be called before _Jv_RunMain.
// This must be called before _Jv_RunMain.
void
void
_Jv_SetInitialHeapSize (const char *arg)
_Jv_SetInitialHeapSize (const char *arg)
{
{
  size_t size = parse_memory_size (arg);
  size_t size = parse_memory_size (arg);
  _Jv_GCSetInitialHeapSize (size);
  _Jv_GCSetInitialHeapSize (size);
}
}
 
 
// Set the maximum heap size.  This might be ignored by the GC layer.
// Set the maximum heap size.  This might be ignored by the GC layer.
// This must be called before _Jv_RunMain.
// This must be called before _Jv_RunMain.
void
void
_Jv_SetMaximumHeapSize (const char *arg)
_Jv_SetMaximumHeapSize (const char *arg)
{
{
  size_t size = parse_memory_size (arg);
  size_t size = parse_memory_size (arg);
  _Jv_GCSetMaximumHeapSize (size);
  _Jv_GCSetMaximumHeapSize (size);
}
}
 
 
void
void
_Jv_SetStackSize (const char *arg)
_Jv_SetStackSize (const char *arg)
{
{
  size_t size = parse_memory_size (arg);
  size_t size = parse_memory_size (arg);
  gcj::stack_size = size;
  gcj::stack_size = size;
}
}
 
 
void *
void *
_Jv_Malloc (jsize size)
_Jv_Malloc (jsize size)
{
{
  if (__builtin_expect (size == 0, false))
  if (__builtin_expect (size == 0, false))
    size = 1;
    size = 1;
  void *ptr = malloc ((size_t) size);
  void *ptr = malloc ((size_t) size);
  if (__builtin_expect (ptr == NULL, false))
  if (__builtin_expect (ptr == NULL, false))
    throw no_memory;
    throw no_memory;
  return ptr;
  return ptr;
}
}
 
 
void *
void *
_Jv_Realloc (void *ptr, jsize size)
_Jv_Realloc (void *ptr, jsize size)
{
{
  if (__builtin_expect (size == 0, false))
  if (__builtin_expect (size == 0, false))
    size = 1;
    size = 1;
  ptr = realloc (ptr, (size_t) size);
  ptr = realloc (ptr, (size_t) size);
  if (__builtin_expect (ptr == NULL, false))
  if (__builtin_expect (ptr == NULL, false))
    throw no_memory;
    throw no_memory;
  return ptr;
  return ptr;
}
}
 
 
void *
void *
_Jv_MallocUnchecked (jsize size)
_Jv_MallocUnchecked (jsize size)
{
{
  if (__builtin_expect (size == 0, false))
  if (__builtin_expect (size == 0, false))
    size = 1;
    size = 1;
  return malloc ((size_t) size);
  return malloc ((size_t) size);
}
}
 
 
void
void
_Jv_Free (void* ptr)
_Jv_Free (void* ptr)
{
{
  return free (ptr);
  return free (ptr);
}
}
 
 


 
 
// In theory, these routines can be #ifdef'd away on machines which
// In theory, these routines can be #ifdef'd away on machines which
// support divide overflow signals.  However, we never know if some
// support divide overflow signals.  However, we never know if some
// code might have been compiled with "-fuse-divide-subroutine", so we
// code might have been compiled with "-fuse-divide-subroutine", so we
// always include them in libgcj.
// always include them in libgcj.
 
 
jint
jint
_Jv_divI (jint dividend, jint divisor)
_Jv_divI (jint dividend, jint divisor)
{
{
  if (__builtin_expect (divisor == 0, false))
  if (__builtin_expect (divisor == 0, false))
    {
    {
      java::lang::ArithmeticException *arithexception
      java::lang::ArithmeticException *arithexception
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
      throw arithexception;
      throw arithexception;
    }
    }
 
 
  if (dividend == (jint) 0x80000000L && divisor == -1)
  if (dividend == (jint) 0x80000000L && divisor == -1)
    return dividend;
    return dividend;
 
 
  return dividend / divisor;
  return dividend / divisor;
}
}
 
 
jint
jint
_Jv_remI (jint dividend, jint divisor)
_Jv_remI (jint dividend, jint divisor)
{
{
  if (__builtin_expect (divisor == 0, false))
  if (__builtin_expect (divisor == 0, false))
    {
    {
      java::lang::ArithmeticException *arithexception
      java::lang::ArithmeticException *arithexception
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
      throw arithexception;
      throw arithexception;
    }
    }
 
 
  if (dividend == (jint) 0x80000000L && divisor == -1)
  if (dividend == (jint) 0x80000000L && divisor == -1)
    return 0;
    return 0;
 
 
  return dividend % divisor;
  return dividend % divisor;
}
}
 
 
jlong
jlong
_Jv_divJ (jlong dividend, jlong divisor)
_Jv_divJ (jlong dividend, jlong divisor)
{
{
  if (__builtin_expect (divisor == 0, false))
  if (__builtin_expect (divisor == 0, false))
    {
    {
      java::lang::ArithmeticException *arithexception
      java::lang::ArithmeticException *arithexception
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
      throw arithexception;
      throw arithexception;
    }
    }
 
 
  if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
  if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
    return dividend;
    return dividend;
 
 
  return dividend / divisor;
  return dividend / divisor;
}
}
 
 
jlong
jlong
_Jv_remJ (jlong dividend, jlong divisor)
_Jv_remJ (jlong dividend, jlong divisor)
{
{
  if (__builtin_expect (divisor == 0, false))
  if (__builtin_expect (divisor == 0, false))
    {
    {
      java::lang::ArithmeticException *arithexception
      java::lang::ArithmeticException *arithexception
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
      throw arithexception;
      throw arithexception;
    }
    }
 
 
  if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
  if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
    return 0;
    return 0;
 
 
  return dividend % divisor;
  return dividend % divisor;
}
}
 
 


 
 
// Return true if SELF_KLASS can access a field or method in
// Return true if SELF_KLASS can access a field or method in
// OTHER_KLASS.  The field or method's access flags are specified in
// OTHER_KLASS.  The field or method's access flags are specified in
// FLAGS.
// FLAGS.
jboolean
jboolean
_Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
_Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
{
{
  using namespace java::lang::reflect;
  using namespace java::lang::reflect;
  return ((self_klass == other_klass)
  return ((self_klass == other_klass)
          || ((flags & Modifier::PUBLIC) != 0)
          || ((flags & Modifier::PUBLIC) != 0)
          || (((flags & Modifier::PROTECTED) != 0)
          || (((flags & Modifier::PROTECTED) != 0)
              && _Jv_IsAssignableFromSlow (self_klass, other_klass))
              && _Jv_IsAssignableFromSlow (self_klass, other_klass))
          || (((flags & Modifier::PRIVATE) == 0)
          || (((flags & Modifier::PRIVATE) == 0)
              && _Jv_ClassNameSamePackage (self_klass->name,
              && _Jv_ClassNameSamePackage (self_klass->name,
                                           other_klass->name)));
                                           other_klass->name)));
}
}
 
 
// Prepend GCJ_VERSIONED_LIBDIR to a module search path stored in a C
// Prepend GCJ_VERSIONED_LIBDIR to a module search path stored in a C
// char array, if the path is not already prefixed by
// char array, if the path is not already prefixed by
// GCJ_VERSIONED_LIBDIR.  Return a newly JvMalloc'd char buffer.  The
// GCJ_VERSIONED_LIBDIR.  Return a newly JvMalloc'd char buffer.  The
// result should be freed using JvFree.
// result should be freed using JvFree.
char*
char*
_Jv_PrependVersionedLibdir (char* libpath)
_Jv_PrependVersionedLibdir (char* libpath)
{
{
  char* retval = 0;
  char* retval = 0;
 
 
  if (libpath && libpath[0] != '\0')
  if (libpath && libpath[0] != '\0')
    {
    {
      if (! strncmp (libpath,
      if (! strncmp (libpath,
                     GCJ_VERSIONED_LIBDIR,
                     GCJ_VERSIONED_LIBDIR,
                     sizeof (GCJ_VERSIONED_LIBDIR) - 1))
                     sizeof (GCJ_VERSIONED_LIBDIR) - 1))
        {
        {
          // LD_LIBRARY_PATH is already prefixed with
          // LD_LIBRARY_PATH is already prefixed with
          // GCJ_VERSIONED_LIBDIR.
          // GCJ_VERSIONED_LIBDIR.
          retval = (char*) _Jv_Malloc (strlen (libpath) + 1);
          retval = (char*) _Jv_Malloc (strlen (libpath) + 1);
          strcpy (retval, libpath);
          strcpy (retval, libpath);
        }
        }
      else
      else
        {
        {
          // LD_LIBRARY_PATH is not prefixed with
          // LD_LIBRARY_PATH is not prefixed with
          // GCJ_VERSIONED_LIBDIR.
          // GCJ_VERSIONED_LIBDIR.
          char path_sep[2];
          char path_sep[2];
          path_sep[0] = (char) _Jv_platform_path_separator;
          path_sep[0] = (char) _Jv_platform_path_separator;
          path_sep[1] = '\0';
          path_sep[1] = '\0';
          jsize total = ((sizeof (GCJ_VERSIONED_LIBDIR) - 1)
          jsize total = ((sizeof (GCJ_VERSIONED_LIBDIR) - 1)
                         + 1 /* path separator */ + strlen (libpath) + 1);
                         + 1 /* path separator */ + strlen (libpath) + 1);
          retval = (char*) _Jv_Malloc (total);
          retval = (char*) _Jv_Malloc (total);
          strcpy (retval, GCJ_VERSIONED_LIBDIR);
          strcpy (retval, GCJ_VERSIONED_LIBDIR);
          strcat (retval, path_sep);
          strcat (retval, path_sep);
          strcat (retval, libpath);
          strcat (retval, libpath);
        }
        }
    }
    }
  else
  else
    {
    {
      // LD_LIBRARY_PATH was not specified or is empty.
      // LD_LIBRARY_PATH was not specified or is empty.
      retval = (char*) _Jv_Malloc (sizeof (GCJ_VERSIONED_LIBDIR));
      retval = (char*) _Jv_Malloc (sizeof (GCJ_VERSIONED_LIBDIR));
      strcpy (retval, GCJ_VERSIONED_LIBDIR);
      strcpy (retval, GCJ_VERSIONED_LIBDIR);
    }
    }
 
 
  return retval;
  return retval;
}
}
 
 

powered by: WebSVN 2.1.0

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