OSDN Git Service

2004-07-22 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / libjava / prims.cc
index 71cd8c3..a0ad08e 100644 (file)
@@ -1,6 +1,6 @@
 // prims.cc - Code for core of runtime environment.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -25,6 +25,7 @@ details.  */
 #include <jvm.h>
 #include <java-signal.h>
 #include <java-threads.h>
+#include <java-interp.h>
 
 #ifdef ENABLE_JVMPI
 #include <jvmpi.h>
@@ -60,7 +61,7 @@ details.  */
 #include <java/lang/VirtualMachineError.h>
 #include <gnu/gcj/runtime/VMClassLoader.h>
 #include <gnu/gcj/runtime/FinalizerThread.h>
-#include <gnu/gcj/runtime/FirstThread.h>
+#include <gnu/java/lang/MainThread.h>
 
 #ifdef USE_LTDL
 #include <ltdl.h>
@@ -70,8 +71,10 @@ details.  */
 // around for use if we run out of memory.
 static java::lang::OutOfMemoryError *no_memory;
 
-// Largest representable size_t.
-#define SIZE_T_MAX ((size_t) (~ (size_t) 0))
+// 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)
 
 static const char *no_properties[] = { NULL };
 
@@ -387,16 +390,15 @@ jvmpi_notify_alloc(jclass klass, jint size, jobject obj)
 # define jvmpi_notify_alloc(klass,size,obj) /* do nothing */
 #endif
 
-// Allocate a new object of class KLASS.  SIZE is the size of the object
-// to allocate.  You might think this is redundant, but it isn't; some
-// classes, such as String, aren't of fixed size.
+// Allocate a new object of class KLASS.
 // First a version that assumes that we have no finalizer, and that
 // the class is already initialized.
 // If we know that JVMPI is disabled, this can be replaced by a direct call
 // to the allocator for the appropriate GC.
 jobject
-_Jv_AllocObjectNoInitNoFinalizer (jclass klass, jint size)
+_Jv_AllocObjectNoInitNoFinalizer (jclass klass)
 {
+  jint size = klass->size ();
   jobject obj = (jobject) _Jv_AllocObj (size, klass);
   jvmpi_notify_alloc (klass, size, obj);
   return obj;
@@ -404,9 +406,10 @@ _Jv_AllocObjectNoInitNoFinalizer (jclass klass, jint size)
 
 // And now a version that initializes if necessary.
 jobject
-_Jv_AllocObjectNoFinalizer (jclass klass, jint size)
+_Jv_AllocObjectNoFinalizer (jclass klass)
 {
   _Jv_InitClass (klass);
+  jint size = klass->size ();
   jobject obj = (jobject) _Jv_AllocObj (size, klass);
   jvmpi_notify_alloc (klass, size, obj);
   return obj;
@@ -414,10 +417,10 @@ _Jv_AllocObjectNoFinalizer (jclass klass, jint size)
 
 // And now the general version that registers a finalizer if necessary.
 jobject
-_Jv_AllocObject (jclass klass, jint size)
+_Jv_AllocObject (jclass klass)
 {
-  jobject obj = _Jv_AllocObjectNoFinalizer (klass, size);
-
+  jobject obj = _Jv_AllocObjectNoFinalizer (klass);
+  
   // We assume that the compiler only generates calls to this routine
   // if there really is an interesting finalizer.
   // Unfortunately, we still have to the dynamic test, since there may
@@ -430,14 +433,62 @@ _Jv_AllocObject (jclass klass, jint size)
   return obj;
 }
 
+// Allocate a String, including variable length storage.
+jstring
+_Jv_AllocString(jsize len)
+{
+  using namespace java::lang;
+
+  jsize sz = sizeof(java::lang::String) + len * sizeof(jchar);
+
+  // We assert that for strings allocated this way, the data field
+  // will always point to the object itself.  Thus there is no reason
+  // for the garbage collector to scan any of it.
+  // Furthermore, we're about to overwrite the string data, so
+  // initialization of the object is not an issue.
+
+  // String needs no initialization, and there is no finalizer, so
+  // we can go directly to the collector's allocator interface.
+  jstring obj = (jstring) _Jv_AllocPtrFreeObj(sz, &String::class$);
+
+  obj->data = obj;
+  obj->boffset = sizeof(java::lang::String);
+  obj->count = len;
+  obj->cachedHashCode = 0;
+  
+#ifdef ENABLE_JVMPI
+  // Service JVMPI request.
+
+  if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false))
+    {
+      JVMPI_Event event;
+
+      event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
+      event.env_id = NULL;
+      event.u.obj_alloc.arena_id = 0;
+      event.u.obj_alloc.class_id = (jobjectID) &String::class$;
+      event.u.obj_alloc.is_array = 0;
+      event.u.obj_alloc.size = sz;
+      event.u.obj_alloc.obj_id = (jobjectID) obj;
+
+      _Jv_DisableGC ();
+      (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
+      _Jv_EnableGC ();
+    }
+#endif  
+  
+  return obj;
+}
+
 // A version of the above that assumes the object contains no pointers,
 // and requires no finalization.  This can't happen if we need pointers
 // to locks.
 #ifdef JV_HASH_SYNCHRONIZATION
 jobject
-_Jv_AllocPtrFreeObject (jclass klass, jint size)
+_Jv_AllocPtrFreeObject (jclass klass)
 {
   _Jv_InitClass (klass);
+  jint size = klass->size ();
 
   jobject obj = (jobject) _Jv_AllocPtrFreeObj (size, klass);
 
@@ -481,6 +532,11 @@ _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
   // Ensure that elements pointer is properly aligned.
   jobjectArray obj = NULL;
   size_t size = (size_t) elements (obj);
+  // Check for overflow.
+  if (__builtin_expect ((size_t) count > 
+                       (MAX_OBJECT_SIZE - 1 - size) / sizeof (jobject), false))
+    throw no_memory;
+
   size += count * sizeof (jobject);
 
   jclass klass = _Jv_GetArrayClass (elementClass,
@@ -516,7 +572,7 @@ _Jv_NewPrimArray (jclass eltype, jint count)
 
   // Check for overflow.
   if (__builtin_expect ((size_t) count > 
-                       (SIZE_T_MAX - size) / elsize, false))
+                       (MAX_OBJECT_SIZE - size) / elsize, false))
     throw no_memory;
 
   jclass klass = _Jv_GetArrayClass (eltype, 0);
@@ -866,8 +922,10 @@ process_gcj_properties ()
     // Null terminate the strings.
     while (_Jv_Environment_Properties[i].key)
       {
-       _Jv_Environment_Properties[i].key[_Jv_Environment_Properties[i].key_length] = 0;
-       _Jv_Environment_Properties[i++].value[_Jv_Environment_Properties[i].value_length] = 0;
+        property_pair *prop = &_Jv_Environment_Properties[i];
+       prop->key[prop->key_length] = 0;
+       prop->value[prop->value_length] = 0;
+       i++;
       }
   }
 }
@@ -898,6 +956,18 @@ _Jv_CreateJavaVM (void* /*vm_args*/)
   _Jv_InitThreads ();
   _Jv_InitGC ();
   _Jv_InitializeSyncMutex ();
+  
+#ifdef INTERPRETER
+  _Jv_InitInterpreter ();
+#endif  
+
+#ifdef HANDLE_SEGV
+  INIT_SEGV;
+#endif
+
+#ifdef HANDLE_FPE
+  INIT_FPE;
+#endif
 
   /* Initialize Utf8 constants declared in jvm.h. */
   void_signature = _Jv_makeUtf8Const ("()V", 3);
@@ -920,15 +990,20 @@ _Jv_CreateJavaVM (void* /*vm_args*/)
   _Jv_InitClass (&java::lang::VMThrowable::class$);
   java::lang::VMThrowable::trace_enabled = 0;
   
-  INIT_SEGV;
-#ifdef HANDLE_FPE
-  INIT_FPE;
-#endif
-  
+  // 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
+  // of VMClassLoader.
+  _Jv_InitClass (&java::lang::ClassLoader::class$);
+
+  // Once the bootstrap loader is in place, change it into a kind of
+  // system loader, by having it read the class path.
+  gnu::gcj::runtime::VMClassLoader::initialize();
+
   no_memory = new java::lang::OutOfMemoryError;
-  
+
   java::lang::VMThrowable::trace_enabled = 1;
-  
+
 #ifdef USE_LTDL
   LTDL_SET_PRELOADED_SYMBOLS ();
 #endif
@@ -940,8 +1015,7 @@ _Jv_CreateJavaVM (void* /*vm_args*/)
   _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
 
   // Start the GC finalizer thread.  A VirtualMachineError can be
-  // thrown by the runtime if, say, threads aren't available.  In this
-  // case finalizers simply won't run.
+  // thrown by the runtime if, say, threads aren't available.
   try
     {
       using namespace gnu::gcj::runtime;
@@ -959,7 +1033,9 @@ void
 _Jv_RunMain (jclass klass, const char *name, int argc, const char **argv, 
             bool is_jar)
 {
+#ifndef DISABLE_MAIN_ARGS
   _Jv_SetArgs (argc, argv);
+#endif
 
   java::lang::Runtime *runtime = NULL;
 
@@ -981,18 +1057,12 @@ _Jv_RunMain (jclass klass, const char *name, int argc, const char **argv,
       arg_vec = JvConvertArgv (argc - 1, argv + 1);
 #endif
 
-      // 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 of VMClassLoader.
-      _Jv_InitClass (&java::lang::ClassLoader::class$);
-
-      using namespace gnu::gcj::runtime;
+      using namespace gnu::java::lang;
       if (klass)
-       main_thread = new FirstThread (klass, arg_vec);
+       main_thread = new MainThread (klass, arg_vec);
       else
-       main_thread = new FirstThread (JvNewStringLatin1 (name),
-                                      arg_vec, is_jar);
+       main_thread = new MainThread (JvNewStringLatin1 (name),
+                                     arg_vec, is_jar);
     }
   catch (java::lang::Throwable *t)
     {