OSDN Git Service

2007-01-31 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / prims.cc
index 0352669..a419120 100644 (file)
@@ -32,6 +32,9 @@ details.  */
 #include <java/lang/ThreadGroup.h>
 #endif
 
+#include <jvmti.h>
+#include "jvmti-int.h"
+
 #ifndef DISABLE_GETENV_PROPERTIES
 #include <ctype.h>
 #include <java-props.h>
@@ -56,7 +59,6 @@ details.  */
 #include <java/lang/NullPointerException.h>
 #include <java/lang/OutOfMemoryError.h>
 #include <java/lang/System.h>
-#include <java/lang/VMThrowable.h>
 #include <java/lang/VMClassLoader.h>
 #include <java/lang/reflect/Modifier.h>
 #include <java/io/PrintStream.h>
@@ -65,6 +67,8 @@ details.  */
 #include <gnu/gcj/runtime/ExtensionClassLoader.h>
 #include <gnu/gcj/runtime/FinalizerThread.h>
 #include <execution.h>
+#include <gnu/classpath/jdwp/Jdwp.h>
+#include <gnu/classpath/jdwp/VMVirtualMachine.h>
 #include <gnu/java/lang/MainThread.h>
 
 #ifdef USE_LTDL
@@ -74,6 +78,9 @@ details.  */
 // Execution engine for compiled code.
 _Jv_CompiledEngine _Jv_soleCompiledEngine;
 
+// Execution engine for code compiled with -findirect-classes
+_Jv_IndirectCompiledEngine _Jv_soleIndirectCompiledEngine;
+
 // We allocate a single OutOfMemoryError exception which we keep
 // around for use if we run out of memory.
 static java::lang::OutOfMemoryError *no_memory;
@@ -81,7 +88,7 @@ static java::lang::OutOfMemoryError *no_memory;
 // Number of bytes in largest array object we create.  This could be
 // increased to the largest size_t value, so long as the appropriate
 // functions are changed to take a size_t argument instead of jint.
-#define MAX_OBJECT_SIZE ((1<<31) - 1)
+#define MAX_OBJECT_SIZE (((size_t)1<<31) - 1)
 
 // Properties set at compile time.
 const char **_Jv_Compiler_Properties = NULL;
@@ -96,6 +103,11 @@ property_pair *_Jv_Environment_Properties;
 const char **_Jv_argv;
 int _Jv_argc;
 
+// Debugging options
+static bool remoteDebug = false;
+static char defaultJdwpOptions[] = "";
+static char *jdwpOptions = defaultJdwpOptions;
+
 // Argument support.
 int
 _Jv_GetNbArgs (void)
@@ -353,7 +365,7 @@ _Jv_equalUtf8Classnames (const Utf8Const *a, const Utf8Const *b)
 
 /* Count the number of Unicode chars encoded in a given Ut8 string. */
 int
-_Jv_strLengthUtf8(char* str, int len)
+_Jv_strLengthUtf8(const char* str, int len)
 {
   unsigned char* ptr;
   unsigned char* limit;
@@ -374,7 +386,7 @@ _Jv_strLengthUtf8(char* str, int len)
  * This returns the same hash value as specified or java.lang.String.hashCode.
  */
 jint
-_Jv_hashUtf8String (char* str, int len)
+_Jv_hashUtf8String (const char* str, int len)
 {
   unsigned char* ptr = (unsigned char*) str;
   unsigned char* limit = ptr + len;
@@ -391,7 +403,7 @@ _Jv_hashUtf8String (char* str, int len)
 }
 
 void
-_Jv_Utf8Const::init(char *s, int len)
+_Jv_Utf8Const::init(const char *s, int len)
 {
   ::memcpy (data, s, len);
   data[len] = 0;
@@ -400,7 +412,7 @@ _Jv_Utf8Const::init(char *s, int len)
 }
 
 _Jv_Utf8Const *
-_Jv_makeUtf8Const (char* s, int len)
+_Jv_makeUtf8Const (const char* s, int len)
 {
   if (len < 0)
     len = strlen (s);
@@ -446,6 +458,7 @@ _Jv_Abort (const char *, const char *, int, const char *message)
 #else
   fprintf (stderr, "libgcj failure: %s\n", message);
 #endif
+  fflush (stderr);
   abort ();
 }
 
@@ -762,6 +775,11 @@ _Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
 jobject
 _Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
 {
+  // Creating an array of an unresolved type is impossible. So we throw
+  // the NoClassDefFoundError.
+  if (_Jv_IsPhantomClass(array_type))
+    throw new java::lang::NoClassDefFoundError(array_type->getName());
+
   va_list args;
   jint sizes[dimensions];
   va_start (args, dimensions);
@@ -794,7 +812,7 @@ DECLARE_PRIM_TYPE(double)
 DECLARE_PRIM_TYPE(void)
 
 void
-_Jv_InitPrimClass (jclass cl, char *cname, char sig, int len)
+_Jv_InitPrimClass (jclass cl, const char *cname, char sig, int len)
 {    
   using namespace java::lang::reflect;
 
@@ -1107,6 +1125,18 @@ namespace gcj
 
   // Thread stack size specified by the -Xss runtime argument.
   size_t stack_size = 0;
+
+  // Start time of the VM
+  jlong startTime = 0;
+
+  // Arguments passed to the VM
+  JArray<jstring>* vmArgs;
+
+  // Currently loaded classes
+  jint loadedClasses = 0;
+
+  // Unloaded classes
+  jlong unloadedClasses = 0;
 }
 
 // We accept all non-standard options accepted by Sun's java command,
@@ -1131,7 +1161,18 @@ parse_x_arg (char* option_string)
     }
   else if (! strcmp (option_string, "debug"))
     {
-      // FIXME: add JDWP/JVMDI support
+      remoteDebug = true;
+    }
+  else if (! strncmp (option_string, "runjdwp:", 8))
+    {
+      if (strlen (option_string) > 8)
+         jdwpOptions = &option_string[8];
+      else
+       {
+         fprintf (stderr,
+                  "libgcj: argument required for JDWP options");
+         return -1;
+       }
     }
   else if (! strncmp (option_string, "bootclasspath:", 14))
     {
@@ -1397,6 +1438,7 @@ _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
     return -1;
 
   runtimeInitialized = true;
+  startTime = _Jv_platform_gettimeofday();
 
   jint result = parse_init_args (vm_args);
   if (result < 0)
@@ -1439,10 +1481,6 @@ _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
   _Jv_InitPrimClass (&_Jv_doubleClass,  "double",  'D', 8);
   _Jv_InitPrimClass (&_Jv_voidClass,    "void",    'V', 0);
 
-  // Turn stack trace generation off while creating exception objects.
-  _Jv_InitClass (&java::lang::VMThrowable::class$);
-  java::lang::VMThrowable::trace_enabled = 0;
-  
   // We have to initialize this fairly early, to avoid circular class
   // initialization.  In particular we want to start the
   // initialization of ClassLoader before we start the initialization
@@ -1457,8 +1495,6 @@ _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
 
   no_memory = new java::lang::OutOfMemoryError;
 
-  java::lang::VMThrowable::trace_enabled = 1;
-
 #ifdef USE_LTDL
   LTDL_SET_PRELOADED_SYMBOLS ();
 #endif
@@ -1466,6 +1502,7 @@ _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
   _Jv_platform_initialize ();
 
   _Jv_JNI_Init ();
+  _Jv_JVMTI_Init ();
 
   _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
 
@@ -1481,6 +1518,8 @@ _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
     {
     }
 
+  runtimeInitialized = true;
+
   return 0;
 }
 
@@ -1501,6 +1540,18 @@ _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
          fprintf (stderr, "libgcj: couldn't create virtual machine\n");
          exit (1);
        }
+      
+      if (vm_args == NULL)
+       gcj::vmArgs = JvConvertArgv(0, NULL);
+      else
+       {
+         const char* vmArgs[vm_args->nOptions];
+         const char** vmPtr = vmArgs;
+         struct _Jv_VMOption* optionPtr = vm_args->options;
+         for (int i = 0; i < vm_args->nOptions; ++i)
+           *vmPtr++ = (*optionPtr++).optionString;
+         gcj::vmArgs = JvConvertArgv(vm_args->nOptions, vmArgs);
+       }
 
       // 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.
@@ -1516,8 +1567,27 @@ _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
       if (klass)
        main_thread = new MainThread (klass, arg_vec);
       else
-       main_thread = new MainThread (JvNewStringLatin1 (name),
+       main_thread = new MainThread (JvNewStringUTF (name),
                                      arg_vec, is_jar);
+      _Jv_AttachCurrentThread (main_thread);
+
+      // Start JDWP
+      if (remoteDebug)
+       {
+         using namespace gnu::classpath::jdwp;
+         VMVirtualMachine::initialize ();
+         Jdwp *jdwp = new Jdwp ();
+         jdwp->setDaemon (true);
+         jdwp->configure (JvNewStringLatin1 (jdwpOptions));
+         jdwp->start ();
+
+         // Wait for JDWP to initialize and start
+         jdwp->join ();
+       }
+
+      // Send VMInit
+      if (JVMTI_REQUESTED_EVENT (VMInit))
+       _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_INIT, main_thread);
     }
   catch (java::lang::Throwable *t)
     {
@@ -1525,14 +1595,21 @@ _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
         ("Exception during runtime initialization"));
       t->printStackTrace();
       if (runtime)
-       runtime->exit (1);
+       java::lang::Runtime::exitNoChecksAccessor (1);
       // In case the runtime creation failed.
       ::exit (1);
     }
 
-  _Jv_AttachCurrentThread (main_thread);
   _Jv_ThreadRun (main_thread);
 
+  // Send VMDeath
+  if (JVMTI_REQUESTED_EVENT (VMDeath))
+    {
+      java::lang::Thread *thread = java::lang::Thread::currentThread ();
+      JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
+      _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_DEATH, thread, jni_env);
+    }
+
   // If we got here then something went wrong, as MainThread is not
   // supposed to terminate.
   ::exit (1);
@@ -1551,6 +1628,12 @@ JvRunMain (jclass klass, int argc, const char **argv)
   _Jv_RunMain (klass, NULL, argc, argv, false);
 }
 
+void
+JvRunMainName (const char *name, int argc, const char **argv)
+{
+  _Jv_RunMain (NULL, name, argc, argv, false);
+}
+
 \f
 
 // Parse a string and return a heap size.
@@ -1715,3 +1798,48 @@ _Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
              && _Jv_ClassNameSamePackage (self_klass->name,
                                           other_klass->name)));
 }
+
+// Prepend GCJ_VERSIONED_LIBDIR to a module search path stored in a C
+// char array, if the path is not already prefixed by
+// GCJ_VERSIONED_LIBDIR.  Return a newly JvMalloc'd char buffer.  The
+// result should be freed using JvFree.
+char*
+_Jv_PrependVersionedLibdir (char* libpath)
+{
+  char* retval = 0;
+
+  if (libpath && libpath[0] != '\0')
+    {
+      if (! strncmp (libpath,
+                     GCJ_VERSIONED_LIBDIR,
+                     sizeof (GCJ_VERSIONED_LIBDIR) - 1))
+        {
+          // LD_LIBRARY_PATH is already prefixed with
+          // GCJ_VERSIONED_LIBDIR.
+          retval = (char*) _Jv_Malloc (strlen (libpath) + 1);
+          strcpy (retval, libpath);
+        }
+      else
+        {
+          // LD_LIBRARY_PATH is not prefixed with
+          // GCJ_VERSIONED_LIBDIR.
+         char path_sep[2];
+         path_sep[0] = (char) _Jv_platform_path_separator;
+         path_sep[1] = '\0';
+          jsize total = ((sizeof (GCJ_VERSIONED_LIBDIR) - 1)
+                        + 1 /* path separator */ + strlen (libpath) + 1);
+          retval = (char*) _Jv_Malloc (total);
+          strcpy (retval, GCJ_VERSIONED_LIBDIR);
+          strcat (retval, path_sep);
+          strcat (retval, libpath);
+        }
+    }
+  else
+    {
+      // LD_LIBRARY_PATH was not specified or is empty.
+      retval = (char*) _Jv_Malloc (sizeof (GCJ_VERSIONED_LIBDIR));
+      strcpy (retval, GCJ_VERSIONED_LIBDIR);
+    }
+
+  return retval;
+}