OSDN Git Service

00d547017f46ae35466c715261ec49dc7eea6393
[pf3gnuchains/gcc-fork.git] / libjava / prims.cc
1 // prims.cc - Code for core of runtime environment.
2
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12 #include <platform.h>
13
14 #include <stdlib.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <signal.h>
19
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23
24 #include <gcj/cni.h>
25 #include <jvm.h>
26 #include <java-signal.h>
27 #include <java-threads.h>
28 #include <java-interp.h>
29
30 #ifdef ENABLE_JVMPI
31 #include <jvmpi.h>
32 #include <java/lang/ThreadGroup.h>
33 #endif
34
35 #ifndef DISABLE_GETENV_PROPERTIES
36 #include <ctype.h>
37 #include <java-props.h>
38 #define PROCESS_GCJ_PROPERTIES process_gcj_properties()
39 #else
40 #define PROCESS_GCJ_PROPERTIES
41 #endif // DISABLE_GETENV_PROPERTIES
42
43 #include <java/lang/Class.h>
44 #include <java/lang/ClassLoader.h>
45 #include <java/lang/Runtime.h>
46 #include <java/lang/String.h>
47 #include <java/lang/Thread.h>
48 #include <java/lang/ThreadGroup.h>
49 #include <java/lang/ArrayIndexOutOfBoundsException.h>
50 #include <java/lang/ArithmeticException.h>
51 #include <java/lang/ClassFormatError.h>
52 #include <java/lang/ClassNotFoundException.h>
53 #include <java/lang/InternalError.h>
54 #include <java/lang/NegativeArraySizeException.h>
55 #include <java/lang/NoClassDefFoundError.h>
56 #include <java/lang/NullPointerException.h>
57 #include <java/lang/OutOfMemoryError.h>
58 #include <java/lang/System.h>
59 #include <java/lang/VMClassLoader.h>
60 #include <java/lang/reflect/Modifier.h>
61 #include <java/io/PrintStream.h>
62 #include <java/lang/UnsatisfiedLinkError.h>
63 #include <java/lang/VirtualMachineError.h>
64 #include <gnu/gcj/runtime/ExtensionClassLoader.h>
65 #include <gnu/gcj/runtime/FinalizerThread.h>
66 #include <execution.h>
67 #include <gnu/classpath/jdwp/Jdwp.h>
68 #include <gnu/classpath/jdwp/VMVirtualMachine.h>
69 #include <gnu/classpath/jdwp/event/VmDeathEvent.h>
70 #include <gnu/classpath/jdwp/event/VmInitEvent.h>
71 #include <gnu/java/lang/MainThread.h>
72
73 #ifdef USE_LTDL
74 #include <ltdl.h>
75 #endif
76
77 // Execution engine for compiled code.
78 _Jv_CompiledEngine _Jv_soleCompiledEngine;
79
80 // Execution engine for code compiled with -findirect-classes
81 _Jv_IndirectCompiledEngine _Jv_soleIndirectCompiledEngine;
82
83 // We allocate a single OutOfMemoryError exception which we keep
84 // around for use if we run out of memory.
85 static java::lang::OutOfMemoryError *no_memory;
86
87 // Number of bytes in largest array object we create.  This could be
88 // increased to the largest size_t value, so long as the appropriate
89 // functions are changed to take a size_t argument instead of jint.
90 #define MAX_OBJECT_SIZE (((size_t)1<<31) - 1)
91
92 // Properties set at compile time.
93 const char **_Jv_Compiler_Properties = NULL;
94 int _Jv_Properties_Count = 0;
95
96 #ifndef DISABLE_GETENV_PROPERTIES
97 // Property key/value pairs.
98 property_pair *_Jv_Environment_Properties;
99 #endif
100
101 // Stash the argv pointer to benefit native libraries that need it.
102 const char **_Jv_argv;
103 int _Jv_argc;
104
105 // Debugging options
106 static bool remoteDebug = false;
107 static char defaultJdwpOptions[] = "";
108 static char *jdwpOptions = defaultJdwpOptions;
109
110 // Argument support.
111 int
112 _Jv_GetNbArgs (void)
113 {
114   // _Jv_argc is 0 if not explicitly initialized.
115   return _Jv_argc;
116 }
117
118 const char *
119 _Jv_GetSafeArg (int index)
120 {
121   if (index >=0 && index < _Jv_GetNbArgs ())
122     return _Jv_argv[index];
123   else
124     return "";
125 }
126
127 void
128 _Jv_SetArgs (int argc, const char **argv)
129 {
130   _Jv_argc = argc;
131   _Jv_argv = argv;
132 }
133
134 #ifdef ENABLE_JVMPI
135 // Pointer to JVMPI notification functions.
136 void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event);
137 void (*_Jv_JVMPI_Notify_THREAD_START) (JVMPI_Event *event);
138 void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
139 #endif
140 \f
141
142 #if defined (HANDLE_SEGV) || defined(HANDLE_FPE)
143 /* Unblock a signal.  Unless we do this, the signal may only be sent
144    once.  */
145 static void 
146 unblock_signal (int signum __attribute__ ((__unused__)))
147 {
148 #ifdef _POSIX_VERSION
149   sigset_t sigs;
150
151   sigemptyset (&sigs);
152   sigaddset (&sigs, signum);
153   sigprocmask (SIG_UNBLOCK, &sigs, NULL);
154 #endif
155 }
156 #endif
157
158 #ifdef HANDLE_SEGV
159 SIGNAL_HANDLER (catch_segv)
160 {
161   unblock_signal (SIGSEGV);
162   MAKE_THROW_FRAME (nullp);
163   java::lang::NullPointerException *nullp 
164     = new java::lang::NullPointerException;
165   throw nullp;
166 }
167 #endif
168
169 #ifdef HANDLE_FPE
170 SIGNAL_HANDLER (catch_fpe)
171 {
172   unblock_signal (SIGFPE);
173 #ifdef HANDLE_DIVIDE_OVERFLOW
174   HANDLE_DIVIDE_OVERFLOW;
175 #else
176   MAKE_THROW_FRAME (arithexception);
177 #endif
178   java::lang::ArithmeticException *arithexception 
179     = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
180   throw arithexception;
181 }
182 #endif
183
184
185 jboolean
186 _Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
187 {
188   int len;
189   const _Jv_ushort *aptr, *bptr;
190   if (a == b)
191     return true;
192   if (a->hash != b->hash)
193     return false;
194   len = a->length;
195   if (b->length != len)
196     return false;
197   aptr = (const _Jv_ushort *)a->data;
198   bptr = (const _Jv_ushort *)b->data;
199   len = (len + 1) >> 1;
200   while (--len >= 0)
201     if (*aptr++ != *bptr++)
202       return false;
203   return true;
204 }
205
206 /* True iff A is equal to STR.
207    HASH is STR->hashCode().  
208 */
209
210 jboolean
211 _Jv_equal (Utf8Const* a, jstring str, jint hash)
212 {
213   if (a->hash != (_Jv_ushort) hash)
214     return false;
215   jint len = str->length();
216   jint i = 0;
217   jchar *sptr = _Jv_GetStringChars (str);
218   unsigned char* ptr = (unsigned char*) a->data;
219   unsigned char* limit = ptr + a->length;
220   for (;; i++, sptr++)
221     {
222       int ch = UTF8_GET (ptr, limit);
223       if (i == len)
224         return ch < 0;
225       if (ch != *sptr)
226         return false;
227     }
228   return true;
229 }
230
231 /* Like _Jv_equal, but stop after N characters.  */
232 jboolean
233 _Jv_equaln (Utf8Const *a, jstring str, jint n)
234 {
235   jint len = str->length();
236   jint i = 0;
237   jchar *sptr = _Jv_GetStringChars (str);
238   unsigned char* ptr = (unsigned char*) a->data;
239   unsigned char* limit = ptr + a->length;
240   for (; n-- > 0; i++, sptr++)
241     {
242       int ch = UTF8_GET (ptr, limit);
243       if (i == len)
244         return ch < 0;
245       if (ch != *sptr)
246         return false;
247     }
248   return true;
249 }
250
251 // Determines whether the given Utf8Const object contains
252 // a type which is primitive or some derived form of it, eg.
253 // an array or multi-dimensional array variant.
254 jboolean
255 _Jv_isPrimitiveOrDerived(const Utf8Const *a)
256 {
257   unsigned char *aptr = (unsigned char *) a->data;
258   unsigned char *alimit = aptr + a->length;
259   int ac = UTF8_GET(aptr, alimit);
260
261   // Skips any leading array marks.
262   while (ac == '[')
263     ac = UTF8_GET(aptr, alimit);
264
265   // There should not be another character. This implies that
266   // the type name is only one character long.
267   if (UTF8_GET(aptr, alimit) == -1)
268     switch ( ac )
269       {
270         case 'Z':
271         case 'B':
272         case 'C':
273         case 'S':
274         case 'I':
275         case 'J':
276         case 'F':
277         case 'D':
278           return true;
279         default:
280           break;
281        }
282
283    return false;
284 }
285
286 // Find out whether two _Jv_Utf8Const candidates contain the same
287 // classname.
288 // The method is written to handle the different formats of classnames.
289 // Eg. "Ljava/lang/Class;", "Ljava.lang.Class;", "java/lang/Class" and
290 // "java.lang.Class" will be seen as equal.
291 // Warning: This function is not smart enough to declare "Z" and "boolean"
292 // and similar cases as equal (and is not meant to be used this way)!
293 jboolean
294 _Jv_equalUtf8Classnames (const Utf8Const *a, const Utf8Const *b)
295 {
296   // If the class name's length differs by two characters
297   // it is possible that we have candidates which are given
298   // in the two different formats ("Lp1/p2/cn;" vs. "p1/p2/cn")
299   switch (a->length - b->length)
300     {
301       case -2:
302       case 0:
303       case 2:
304         break;
305       default:
306         return false;
307     }
308
309   unsigned char *aptr = (unsigned char *) a->data;
310   unsigned char *alimit = aptr + a->length;
311   unsigned char *bptr = (unsigned char *) b->data;
312   unsigned char *blimit = bptr + b->length;
313
314   if (alimit[-1] == ';')
315     alimit--;
316
317   if (blimit[-1] == ';')
318     blimit--;
319
320   int ac = UTF8_GET(aptr, alimit);
321   int bc = UTF8_GET(bptr, blimit);
322
323   // Checks whether both strings have the same amount of leading [ characters.
324   while (ac == '[')
325     {
326       if (bc == '[')
327         {
328           ac = UTF8_GET(aptr, alimit);
329           bc = UTF8_GET(bptr, blimit);
330           continue;
331         }
332
333       return false;
334     }
335
336   // Skips leading L character.
337   if (ac == 'L')
338     ac = UTF8_GET(aptr, alimit);
339         
340   if (bc == 'L')
341     bc = UTF8_GET(bptr, blimit);
342
343   // Compares the remaining characters.
344   while (ac != -1 && bc != -1)
345     {
346       // Replaces package separating dots with slashes.
347       if (ac == '.')
348         ac = '/';
349
350       if (bc == '.')
351         bc = '/';
352       
353       // Now classnames differ if there is at least one non-matching
354       // character.
355       if (ac != bc)
356         return false;
357
358       ac = UTF8_GET(aptr, alimit);
359       bc = UTF8_GET(bptr, blimit);
360     }
361
362   return (ac == bc);
363 }
364
365 /* Count the number of Unicode chars encoded in a given Ut8 string. */
366 int
367 _Jv_strLengthUtf8(const char* str, int len)
368 {
369   unsigned char* ptr;
370   unsigned char* limit;
371   int str_length;
372
373   ptr = (unsigned char*) str;
374   limit = ptr + len;
375   str_length = 0;
376   for (; ptr < limit; str_length++)
377     {
378       if (UTF8_GET (ptr, limit) < 0)
379         return (-1);
380     }
381   return (str_length);
382 }
383
384 /* Calculate a hash value for a string encoded in Utf8 format.
385  * This returns the same hash value as specified or java.lang.String.hashCode.
386  */
387 jint
388 _Jv_hashUtf8String (const char* str, int len)
389 {
390   unsigned char* ptr = (unsigned char*) str;
391   unsigned char* limit = ptr + len;
392   jint hash = 0;
393
394   for (; ptr < limit;)
395     {
396       int ch = UTF8_GET (ptr, limit);
397       /* Updated specification from
398          http://www.javasoft.com/docs/books/jls/clarify.html. */
399       hash = (31 * hash) + ch;
400     }
401   return hash;
402 }
403
404 void
405 _Jv_Utf8Const::init(const char *s, int len)
406 {
407   ::memcpy (data, s, len);
408   data[len] = 0;
409   length = len;
410   hash = _Jv_hashUtf8String (s, len) & 0xFFFF;
411 }
412
413 _Jv_Utf8Const *
414 _Jv_makeUtf8Const (const char* s, int len)
415 {
416   if (len < 0)
417     len = strlen (s);
418   Utf8Const* m
419     = (Utf8Const*) _Jv_AllocBytes (_Jv_Utf8Const::space_needed(s, len));
420   m->init(s, len);
421   return m;
422 }
423
424 _Jv_Utf8Const *
425 _Jv_makeUtf8Const (jstring string)
426 {
427   jint hash = string->hashCode ();
428   jint len = _Jv_GetStringUTFLength (string);
429
430   Utf8Const* m = (Utf8Const*)
431     _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
432
433   m->hash = hash;
434   m->length = len;
435
436   _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
437   m->data[len] = 0;
438   
439   return m;
440 }
441
442 \f
443
444 #ifdef DEBUG
445 void
446 _Jv_Abort (const char *function, const char *file, int line,
447            const char *message)
448 #else
449 void
450 _Jv_Abort (const char *, const char *, int, const char *message)
451 #endif
452 {
453 #ifdef DEBUG
454   fprintf (stderr,
455            "libgcj failure: %s\n   in function %s, file %s, line %d\n",
456            message, function, file, line);
457 #else
458   fprintf (stderr, "libgcj failure: %s\n", message);
459 #endif
460   abort ();
461 }
462
463 static void
464 fail_on_finalization (jobject)
465 {
466   JvFail ("object was finalized");
467 }
468
469 void
470 _Jv_GCWatch (jobject obj)
471 {
472   _Jv_RegisterFinalizer (obj, fail_on_finalization);
473 }
474
475 void
476 _Jv_ThrowBadArrayIndex(jint bad_index)
477 {
478   throw new java::lang::ArrayIndexOutOfBoundsException
479     (java::lang::String::valueOf (bad_index));
480 }
481
482 void
483 _Jv_ThrowNullPointerException ()
484 {
485   throw new java::lang::NullPointerException;
486 }
487
488 // Resolve an entry in the constant pool and return the target
489 // address.
490 void *
491 _Jv_ResolvePoolEntry (jclass this_class, jint index)
492 {
493   _Jv_Constants *pool = &this_class->constants;
494
495   if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
496     return pool->data[index].field->u.addr;
497
498   JvSynchronize sync (this_class);
499   return (_Jv_Linker::resolve_pool_entry (this_class, index))
500     .field->u.addr;
501 }
502
503
504 // Explicitly throw a no memory exception.
505 // The collector calls this when it encounters an out-of-memory condition.
506 void _Jv_ThrowNoMemory()
507 {
508   throw no_memory;
509 }
510
511 #ifdef ENABLE_JVMPI
512 # define JVMPI_NOTIFY_ALLOC(klass,size,obj) \
513     if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false)) \
514       jvmpi_notify_alloc(klass,size,obj);
515 static void
516 jvmpi_notify_alloc(jclass klass, jint size, jobject obj)
517 {
518   // Service JVMPI allocation request.
519   JVMPI_Event event;
520
521   event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
522   event.env_id = NULL;
523   event.u.obj_alloc.arena_id = 0;
524   event.u.obj_alloc.class_id = (jobjectID) klass;
525   event.u.obj_alloc.is_array = 0;
526   event.u.obj_alloc.size = size;
527   event.u.obj_alloc.obj_id = (jobjectID) obj;
528
529   // FIXME:  This doesn't look right for the Boehm GC.  A GC may
530   // already be in progress.  _Jv_DisableGC () doesn't wait for it.
531   // More importantly, I don't see the need for disabling GC, since we
532   // blatantly have a pointer to obj on our stack, ensuring that the
533   // object can't be collected.  Even for a nonconservative collector,
534   // it appears to me that this must be true, since we are about to
535   // return obj. Isn't this whole approach way too intrusive for
536   // a useful profiling interface?                      - HB
537   _Jv_DisableGC ();
538   (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
539   _Jv_EnableGC ();
540 }
541 #else /* !ENABLE_JVMPI */
542 # define JVMPI_NOTIFY_ALLOC(klass,size,obj) /* do nothing */
543 #endif
544
545 // Allocate a new object of class KLASS.
546 // First a version that assumes that we have no finalizer, and that
547 // the class is already initialized.
548 // If we know that JVMPI is disabled, this can be replaced by a direct call
549 // to the allocator for the appropriate GC.
550 jobject
551 _Jv_AllocObjectNoInitNoFinalizer (jclass klass)
552 {
553   jint size = klass->size ();
554   jobject obj = (jobject) _Jv_AllocObj (size, klass);
555   JVMPI_NOTIFY_ALLOC (klass, size, obj);
556   return obj;
557 }
558
559 // And now a version that initializes if necessary.
560 jobject
561 _Jv_AllocObjectNoFinalizer (jclass klass)
562 {
563   if (_Jv_IsPhantomClass(klass) )
564     throw new java::lang::NoClassDefFoundError(klass->getName());
565
566   _Jv_InitClass (klass);
567   jint size = klass->size ();
568   jobject obj = (jobject) _Jv_AllocObj (size, klass);
569   JVMPI_NOTIFY_ALLOC (klass, size, obj);
570   return obj;
571 }
572
573 // And now the general version that registers a finalizer if necessary.
574 jobject
575 _Jv_AllocObject (jclass klass)
576 {
577   jobject obj = _Jv_AllocObjectNoFinalizer (klass);
578   
579   // We assume that the compiler only generates calls to this routine
580   // if there really is an interesting finalizer.
581   // Unfortunately, we still have to the dynamic test, since there may
582   // be cni calls to this routine.
583   // Note that on IA64 get_finalizer() returns the starting address of the
584   // function, not a function pointer.  Thus this still works.
585   if (klass->vtable->get_finalizer ()
586       != java::lang::Object::class$.vtable->get_finalizer ())
587     _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
588   return obj;
589 }
590
591 // Allocate a String, including variable length storage.
592 jstring
593 _Jv_AllocString(jsize len)
594 {
595   using namespace java::lang;
596
597   jsize sz = sizeof(java::lang::String) + len * sizeof(jchar);
598
599   // We assert that for strings allocated this way, the data field
600   // will always point to the object itself.  Thus there is no reason
601   // for the garbage collector to scan any of it.
602   // Furthermore, we're about to overwrite the string data, so
603   // initialization of the object is not an issue.
604
605   // String needs no initialization, and there is no finalizer, so
606   // we can go directly to the collector's allocator interface.
607   jstring obj = (jstring) _Jv_AllocPtrFreeObj(sz, &String::class$);
608
609   obj->data = obj;
610   obj->boffset = sizeof(java::lang::String);
611   obj->count = len;
612   obj->cachedHashCode = 0;
613
614   JVMPI_NOTIFY_ALLOC (&String::class$, sz, obj);
615   
616   return obj;
617 }
618
619 // A version of the above that assumes the object contains no pointers,
620 // and requires no finalization.  This can't happen if we need pointers
621 // to locks.
622 #ifdef JV_HASH_SYNCHRONIZATION
623 jobject
624 _Jv_AllocPtrFreeObject (jclass klass)
625 {
626   _Jv_InitClass (klass);
627   jint size = klass->size ();
628
629   jobject obj = (jobject) _Jv_AllocPtrFreeObj (size, klass);
630
631   JVMPI_NOTIFY_ALLOC (klass, size, obj);
632
633   return obj;
634 }
635 #endif /* JV_HASH_SYNCHRONIZATION */
636
637
638 // Allocate a new array of Java objects.  Each object is of type
639 // `elementClass'.  `init' is used to initialize each slot in the
640 // array.
641 jobjectArray
642 _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
643 {
644   // Creating an array of an unresolved type is impossible. So we throw
645   // the NoClassDefFoundError.
646   if ( _Jv_IsPhantomClass(elementClass) )
647     throw new java::lang::NoClassDefFoundError(elementClass->getName());
648
649   if (__builtin_expect (count < 0, false))
650     throw new java::lang::NegativeArraySizeException;
651
652   JvAssert (! elementClass->isPrimitive ());
653
654   // Ensure that elements pointer is properly aligned.
655   jobjectArray obj = NULL;
656   size_t size = (size_t) elements (obj);
657   // Check for overflow.
658   if (__builtin_expect ((size_t) count > 
659                         (MAX_OBJECT_SIZE - 1 - size) / sizeof (jobject), false))
660     throw no_memory;
661
662   size += count * sizeof (jobject);
663
664   jclass klass = _Jv_GetArrayClass (elementClass,
665                                     elementClass->getClassLoaderInternal());
666
667   obj = (jobjectArray) _Jv_AllocArray (size, klass);
668   // Cast away const.
669   jsize *lp = const_cast<jsize *> (&obj->length);
670   *lp = count;
671   // We know the allocator returns zeroed memory.  So don't bother
672   // zeroing it again.
673   if (init)
674     {
675       jobject *ptr = elements(obj);
676       while (--count >= 0)
677         *ptr++ = init;
678     }
679   return obj;
680 }
681
682 // Allocate a new array of primitives.  ELTYPE is the type of the
683 // element, COUNT is the size of the array.
684 jobject
685 _Jv_NewPrimArray (jclass eltype, jint count)
686 {
687   int elsize = eltype->size();
688   if (__builtin_expect (count < 0, false))
689     throw new java::lang::NegativeArraySizeException;
690
691   JvAssert (eltype->isPrimitive ());
692   jobject dummy = NULL;
693   size_t size = (size_t) _Jv_GetArrayElementFromElementType (dummy, eltype);
694
695   // Check for overflow.
696   if (__builtin_expect ((size_t) count > 
697                         (MAX_OBJECT_SIZE - size) / elsize, false))
698     throw no_memory;
699
700   jclass klass = _Jv_GetArrayClass (eltype, 0);
701
702 # ifdef JV_HASH_SYNCHRONIZATION
703   // Since the vtable is always statically allocated,
704   // these are completely pointerfree!  Make sure the GC doesn't touch them.
705   __JArray *arr =
706     (__JArray*) _Jv_AllocPtrFreeObj (size + elsize * count, klass);
707   memset((char *)arr + size, 0, elsize * count);
708 # else
709   __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
710   // Note that we assume we are given zeroed memory by the allocator.
711 # endif
712   // Cast away const.
713   jsize *lp = const_cast<jsize *> (&arr->length);
714   *lp = count;
715
716   return arr;
717 }
718
719 jobject
720 _Jv_NewArray (jint type, jint size)
721 {
722   switch (type)
723     {
724       case  4:  return JvNewBooleanArray (size);
725       case  5:  return JvNewCharArray (size);
726       case  6:  return JvNewFloatArray (size);
727       case  7:  return JvNewDoubleArray (size);
728       case  8:  return JvNewByteArray (size);
729       case  9:  return JvNewShortArray (size);
730       case 10:  return JvNewIntArray (size);
731       case 11:  return JvNewLongArray (size);
732     }
733   throw new java::lang::InternalError
734     (JvNewStringLatin1 ("invalid type code in _Jv_NewArray"));
735 }
736
737 // Allocate a possibly multi-dimensional array but don't check that
738 // any array length is <0.
739 static jobject
740 _Jv_NewMultiArrayUnchecked (jclass type, jint dimensions, jint *sizes)
741 {
742   JvAssert (type->isArray());
743   jclass element_type = type->getComponentType();
744   jobject result;
745   if (element_type->isPrimitive())
746     result = _Jv_NewPrimArray (element_type, sizes[0]);
747   else
748     result = _Jv_NewObjectArray (sizes[0], element_type, NULL);
749
750   if (dimensions > 1)
751     {
752       JvAssert (! element_type->isPrimitive());
753       JvAssert (element_type->isArray());
754       jobject *contents = elements ((jobjectArray) result);
755       for (int i = 0; i < sizes[0]; ++i)
756         contents[i] = _Jv_NewMultiArrayUnchecked (element_type, dimensions - 1,
757                                                   sizes + 1);
758     }
759
760   return result;
761 }
762
763 jobject
764 _Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
765 {
766   for (int i = 0; i < dimensions; ++i)
767     if (sizes[i] < 0)
768       throw new java::lang::NegativeArraySizeException;
769
770   return _Jv_NewMultiArrayUnchecked (type, dimensions, sizes);
771 }
772
773 jobject
774 _Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
775 {
776   // Creating an array of an unresolved type is impossible. So we throw
777   // the NoClassDefFoundError.
778   if (_Jv_IsPhantomClass(array_type))
779     throw new java::lang::NoClassDefFoundError(array_type->getName());
780
781   va_list args;
782   jint sizes[dimensions];
783   va_start (args, dimensions);
784   for (int i = 0; i < dimensions; ++i)
785     {
786       jint size = va_arg (args, jint);
787       if (size < 0)
788         throw new java::lang::NegativeArraySizeException;
789       sizes[i] = size;
790     }
791   va_end (args);
792
793   return _Jv_NewMultiArrayUnchecked (array_type, dimensions, sizes);
794 }
795
796 \f
797
798 // Ensure 8-byte alignment, for hash synchronization.
799 #define DECLARE_PRIM_TYPE(NAME)                 \
800   java::lang::Class _Jv_##NAME##Class __attribute__ ((aligned (8)));
801
802 DECLARE_PRIM_TYPE(byte)
803 DECLARE_PRIM_TYPE(short)
804 DECLARE_PRIM_TYPE(int)
805 DECLARE_PRIM_TYPE(long)
806 DECLARE_PRIM_TYPE(boolean)
807 DECLARE_PRIM_TYPE(char)
808 DECLARE_PRIM_TYPE(float)
809 DECLARE_PRIM_TYPE(double)
810 DECLARE_PRIM_TYPE(void)
811
812 void
813 _Jv_InitPrimClass (jclass cl, const char *cname, char sig, int len)
814 {    
815   using namespace java::lang::reflect;
816
817   // We must set the vtable for the class; the Java constructor
818   // doesn't do this.
819   (*(_Jv_VTable **) cl) = java::lang::Class::class$.vtable;
820
821   // Initialize the fields we care about.  We do this in the same
822   // order they are declared in Class.h.
823   cl->name = _Jv_makeUtf8Const ((char *) cname, -1);
824   cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
825   cl->method_count = sig;
826   cl->size_in_bytes = len;
827   cl->vtable = JV_PRIMITIVE_VTABLE;
828   cl->state = JV_STATE_DONE;
829   cl->depth = -1;
830 }
831
832 jclass
833 _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader,
834                             char **endp)
835 {
836   // First count arrays.
837   int array_count = 0;
838   while (*sig == '[')
839     {
840       ++sig;
841       ++array_count;
842     }
843
844   jclass result = NULL;
845   switch (*sig)
846     {
847     case 'B':
848       result = JvPrimClass (byte);
849       break;
850     case 'S':
851       result = JvPrimClass (short);
852       break;
853     case 'I':
854       result = JvPrimClass (int);
855       break;
856     case 'J':
857       result = JvPrimClass (long);
858       break;
859     case 'Z':
860       result = JvPrimClass (boolean);
861       break;
862     case 'C':
863       result = JvPrimClass (char);
864       break;
865     case 'F':
866       result = JvPrimClass (float);
867       break;
868     case 'D':
869       result = JvPrimClass (double);
870       break;
871     case 'V':
872       result = JvPrimClass (void);
873       break;
874     case 'L':
875       {
876         char *save = ++sig;
877         while (*sig && *sig != ';')
878           ++sig;
879         // Do nothing if signature appears to be malformed.
880         if (*sig == ';')
881           {
882             _Jv_Utf8Const *name = _Jv_makeUtf8Const (save, sig - save);
883             result = _Jv_FindClass (name, loader);
884           }
885         break;
886       }
887     default:
888       // Do nothing -- bad signature.
889       break;
890     }
891
892   if (endp)
893     {
894       // Not really the "end", but the last valid character that we
895       // looked at.
896       *endp = sig;
897     }
898
899   if (! result)
900     return NULL;
901
902   // Find arrays.
903   while (array_count-- > 0)
904     result = _Jv_GetArrayClass (result, loader);
905   return result;
906 }
907
908
909 jclass
910 _Jv_FindClassFromSignatureNoException (char *sig, java::lang::ClassLoader *loader,
911                                        char **endp)
912 {
913   jclass klass;
914
915   try
916     {
917       klass = _Jv_FindClassFromSignature(sig, loader, endp);
918     }
919   catch (java::lang::NoClassDefFoundError *ncdfe)
920     {
921       return NULL;
922     }
923   catch (java::lang::ClassNotFoundException *cnfe)
924     {
925       return NULL;
926     }
927
928   return klass;
929 }
930
931 JArray<jstring> *
932 JvConvertArgv (int argc, const char **argv)
933 {
934   if (argc < 0)
935     argc = 0;
936   jobjectArray ar = JvNewObjectArray(argc, &java::lang::String::class$, NULL);
937   jobject *ptr = elements(ar);
938   jbyteArray bytes = NULL;
939   for (int i = 0;  i < argc;  i++)
940     {
941       const char *arg = argv[i];
942       int len = strlen (arg);
943       if (bytes == NULL || bytes->length < len)
944         bytes = JvNewByteArray (len);
945       jbyte *bytePtr = elements (bytes);
946       // We assume jbyte == char.
947       memcpy (bytePtr, arg, len);
948
949       // Now convert using the default encoding.
950       *ptr++ = new java::lang::String (bytes, 0, len);
951     }
952   return (JArray<jstring>*) ar;
953 }
954
955 // FIXME: These variables are static so that they will be
956 // automatically scanned by the Boehm collector.  This is needed
957 // because with qthreads the collector won't scan the initial stack --
958 // it will only scan the qthreads stacks.
959
960 // Command line arguments.
961 static JArray<jstring> *arg_vec;
962
963 // The primary thread.
964 static java::lang::Thread *main_thread;
965
966 #ifndef DISABLE_GETENV_PROPERTIES
967
968 static char *
969 next_property_key (char *s, size_t *length)
970 {
971   size_t l = 0;
972
973   JvAssert (s);
974
975   // Skip over whitespace
976   while (isspace (*s))
977     s++;
978
979   // If we've reached the end, return NULL.  Also return NULL if for
980   // some reason we've come across a malformed property string.
981   if (*s == 0
982       || *s == ':'
983       || *s == '=')
984     return NULL;
985
986   // Determine the length of the property key.
987   while (s[l] != 0
988          && ! isspace (s[l])
989          && s[l] != ':'
990          && s[l] != '=')
991     {
992       if (s[l] == '\\'
993           && s[l+1] != 0)
994         l++;
995       l++;
996     }
997
998   *length = l;
999
1000   return s;
1001 }
1002
1003 static char *
1004 next_property_value (char *s, size_t *length)
1005 {
1006   size_t l = 0;
1007
1008   JvAssert (s);
1009
1010   while (isspace (*s))
1011     s++;
1012
1013   if (*s == ':'
1014       || *s == '=')
1015     s++;
1016
1017   while (isspace (*s))
1018     s++;
1019
1020   // Determine the length of the property value.
1021   while (s[l] != 0
1022          && ! isspace (s[l])
1023          && s[l] != ':'
1024          && s[l] != '=')
1025     {
1026       if (s[l] == '\\'
1027           && s[l+1] != 0)
1028         l += 2;
1029       else
1030         l++;
1031     }
1032
1033   *length = l;
1034
1035   return s;
1036 }
1037
1038 static void
1039 process_gcj_properties ()
1040 {
1041   char *props = getenv("GCJ_PROPERTIES");
1042
1043   if (NULL == props)
1044     return;
1045
1046   // Later on we will write \0s into this string.  It is simplest to
1047   // just duplicate it here.
1048   props = strdup (props);
1049
1050   char *p = props;
1051   size_t length;
1052   size_t property_count = 0;
1053
1054   // Whip through props quickly in order to count the number of
1055   // property values.
1056   while (p && (p = next_property_key (p, &length)))
1057     {
1058       // Skip to the end of the key
1059       p += length;
1060
1061       p = next_property_value (p, &length);
1062       if (p)
1063         p += length;
1064       
1065       property_count++;
1066     }
1067
1068   // Allocate an array of property value/key pairs.
1069   _Jv_Environment_Properties = 
1070     (property_pair *) malloc (sizeof(property_pair) 
1071                               * (property_count + 1));
1072
1073   // Go through the properties again, initializing _Jv_Properties
1074   // along the way.
1075   p = props;
1076   property_count = 0;
1077   while (p && (p = next_property_key (p, &length)))
1078     {
1079       _Jv_Environment_Properties[property_count].key = p;
1080       _Jv_Environment_Properties[property_count].key_length = length;
1081
1082       // Skip to the end of the key
1083       p += length;
1084
1085       p = next_property_value (p, &length);
1086       
1087       _Jv_Environment_Properties[property_count].value = p;
1088       _Jv_Environment_Properties[property_count].value_length = length;
1089
1090       if (p)
1091         p += length;
1092
1093       property_count++;
1094     }
1095   memset ((void *) &_Jv_Environment_Properties[property_count], 
1096           0, sizeof (property_pair));
1097
1098   // Null terminate the strings.
1099   for (property_pair *prop = &_Jv_Environment_Properties[0];
1100        prop->key != NULL;
1101        prop++)
1102     {
1103       prop->key[prop->key_length] = 0;
1104       prop->value[prop->value_length] = 0;
1105     }
1106 }
1107 #endif // DISABLE_GETENV_PROPERTIES
1108
1109 namespace gcj
1110 {
1111   _Jv_Utf8Const *void_signature;
1112   _Jv_Utf8Const *clinit_name;
1113   _Jv_Utf8Const *init_name;
1114   _Jv_Utf8Const *finit_name;
1115   
1116   bool runtimeInitialized = false;
1117   
1118   // When true, print debugging information about class loading.
1119   bool verbose_class_flag;
1120   
1121   // When true, enable the bytecode verifier and BC-ABI type verification. 
1122   bool verifyClasses = true;
1123
1124   // Thread stack size specified by the -Xss runtime argument.
1125   size_t stack_size = 0;
1126
1127   // Start time of the VM
1128   jlong startTime = 0;
1129
1130   // Arguments passed to the VM
1131   JArray<jstring>* vmArgs;
1132
1133   // Currently loaded classes
1134   jint loadedClasses = 0;
1135
1136   // Unloaded classes
1137   jlong unloadedClasses = 0;
1138 }
1139
1140 // We accept all non-standard options accepted by Sun's java command,
1141 // for compatibility with existing application launch scripts.
1142 static jint
1143 parse_x_arg (char* option_string)
1144 {
1145   if (strlen (option_string) <= 0)
1146     return -1;
1147
1148   if (! strcmp (option_string, "int"))
1149     {
1150       // FIXME: this should cause the vm to never load shared objects
1151     }
1152   else if (! strcmp (option_string, "mixed"))
1153     {
1154       // FIXME: allow interpreted and native code
1155     }
1156   else if (! strcmp (option_string, "batch"))
1157     {
1158       // FIXME: disable background JIT'ing
1159     }
1160   else if (! strcmp (option_string, "debug"))
1161     {
1162       remoteDebug = true;
1163     }
1164   else if (! strncmp (option_string, "runjdwp:", 8))
1165     {
1166       if (strlen (option_string) > 8)
1167           jdwpOptions = &option_string[8];
1168       else
1169         {
1170           fprintf (stderr,
1171                    "libgcj: argument required for JDWP options");
1172           return -1;
1173         }
1174     }
1175   else if (! strncmp (option_string, "bootclasspath:", 14))
1176     {
1177       // FIXME: add a parse_bootclasspath_arg function
1178     }
1179   else if (! strncmp (option_string, "bootclasspath/a:", 16))
1180     {
1181     }
1182   else if (! strncmp (option_string, "bootclasspath/p:", 16))
1183     {
1184     }
1185   else if (! strcmp (option_string, "check:jni"))
1186     {
1187       // FIXME: enable strict JNI checking
1188     }
1189   else if (! strcmp (option_string, "future"))
1190     {
1191       // FIXME: enable strict class file format checks
1192     }
1193   else if (! strcmp (option_string, "noclassgc"))
1194     {
1195       // FIXME: disable garbage collection for classes
1196     }
1197   else if (! strcmp (option_string, "incgc"))
1198     {
1199       // FIXME: incremental garbage collection
1200     }
1201   else if (! strncmp (option_string, "loggc:", 6))
1202     {
1203       if (option_string[6] == '\0')
1204         {
1205           fprintf (stderr,
1206                    "libgcj: filename argument expected for loggc option\n");
1207           return -1;
1208         }
1209       // FIXME: set gc logging filename
1210     }
1211   else if (! strncmp (option_string, "ms", 2))
1212     {
1213       // FIXME: ignore this option until PR 20699 is fixed.
1214       // _Jv_SetInitialHeapSize (option_string + 2);
1215     }
1216   else if (! strncmp (option_string, "mx", 2))
1217     _Jv_SetMaximumHeapSize (option_string + 2);
1218   else if (! strcmp (option_string, "prof"))
1219     {
1220       // FIXME: enable profiling of program running in vm
1221     }
1222   else if (! strncmp (option_string, "runhprof:", 9))
1223     {
1224       // FIXME: enable specific type of vm profiling.  add a
1225       // parse_runhprof_arg function
1226     }
1227   else if (! strcmp (option_string, "rs"))
1228     {
1229       // FIXME: reduced system signal usage.  disable thread dumps,
1230       // only terminate in response to user-initiated calls,
1231       // e.g. System.exit()
1232     }
1233   else if (! strncmp (option_string, "ss", 2))
1234     {
1235       _Jv_SetStackSize (option_string + 2);
1236     }
1237   else if (! strcmp (option_string, "X:+UseAltSigs"))
1238     {
1239       // FIXME: use signals other than SIGUSR1 and SIGUSR2
1240     }
1241   else if (! strcmp (option_string, "share:off"))
1242     {
1243       // FIXME: don't share class data
1244     }
1245   else if (! strcmp (option_string, "share:auto"))
1246     {
1247       // FIXME: share class data where possible
1248     }
1249   else if (! strcmp (option_string, "share:on"))
1250     {
1251       // FIXME: fail if impossible to share class data
1252     }
1253
1254   return 0;
1255 }
1256
1257 static jint
1258 parse_verbose_args (char* option_string,
1259                     bool ignore_unrecognized)
1260 {
1261   size_t len = sizeof ("-verbose") - 1;
1262
1263   if (strlen (option_string) < len)
1264     return -1;
1265
1266   if (option_string[len] == ':'
1267       && option_string[len + 1] != '\0')
1268     {
1269       char* verbose_args = option_string + len + 1;
1270
1271       do
1272         {
1273           if (! strncmp (verbose_args,
1274                          "gc", sizeof ("gc") - 1))
1275             {
1276               if (verbose_args[sizeof ("gc") - 1] == '\0'
1277                   || verbose_args[sizeof ("gc") - 1] == ',')
1278                 {
1279                   // FIXME: we should add functions to boehm-gc that
1280                   // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
1281                   // GC_print_back_height.
1282                   verbose_args += sizeof ("gc") - 1;
1283                 }
1284               else
1285                 {
1286                 verbose_arg_err:
1287                   fprintf (stderr, "libgcj: unknown verbose option: %s\n",
1288                            option_string);
1289                   return -1;
1290                 }
1291             }
1292           else if (! strncmp (verbose_args,
1293                               "class",
1294                               sizeof ("class") - 1))
1295             {
1296               if (verbose_args[sizeof ("class") - 1] == '\0'
1297                   || verbose_args[sizeof ("class") - 1] == ',')
1298                 {
1299                   gcj::verbose_class_flag = true;
1300                   verbose_args += sizeof ("class") - 1;
1301                 }
1302               else
1303                 goto verbose_arg_err;
1304             }
1305           else if (! strncmp (verbose_args, "jni",
1306                               sizeof ("jni") - 1))
1307             {
1308               if (verbose_args[sizeof ("jni") - 1] == '\0'
1309                   || verbose_args[sizeof ("jni") - 1] == ',')
1310                 {
1311                   // FIXME: enable JNI messages.
1312                   verbose_args += sizeof ("jni") - 1;
1313                 }
1314               else
1315                 goto verbose_arg_err;
1316             }
1317           else if (ignore_unrecognized
1318                    && verbose_args[0] == 'X')
1319             {
1320               // ignore unrecognized non-standard verbose option
1321               while (verbose_args[0] != '\0'
1322                      && verbose_args[0] != ',')
1323                 verbose_args++;
1324             }
1325           else if (verbose_args[0] == ',')
1326             {
1327               verbose_args++;
1328             }
1329           else
1330             goto verbose_arg_err;
1331
1332           if (verbose_args[0] == ',')
1333             verbose_args++;
1334         }
1335       while (verbose_args[0] != '\0');
1336     }
1337   else if (option_string[len] == 'g'
1338            && option_string[len + 1] == 'c'
1339            && option_string[len + 2] == '\0')
1340     {
1341       // FIXME: we should add functions to boehm-gc that
1342       // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
1343       // GC_print_back_height.
1344       return 0;
1345     }
1346   else if (option_string[len] == '\0')
1347     {
1348       gcj::verbose_class_flag = true;
1349       return 0;
1350     }
1351   else
1352     {
1353       // unrecognized option beginning with -verbose
1354       return -1;
1355     }
1356   return 0;
1357 }
1358
1359 static jint
1360 parse_init_args (JvVMInitArgs* vm_args)
1361 {
1362   // if _Jv_Compiler_Properties is non-NULL then it needs to be
1363   // re-allocated dynamically.
1364   if (_Jv_Compiler_Properties)
1365     {
1366       const char** props = _Jv_Compiler_Properties;
1367       _Jv_Compiler_Properties = NULL;
1368
1369       for (int i = 0; props[i]; i++)
1370         {
1371           _Jv_Compiler_Properties = (const char**) _Jv_Realloc
1372             (_Jv_Compiler_Properties,
1373              (_Jv_Properties_Count + 1) * sizeof (const char*));
1374           _Jv_Compiler_Properties[_Jv_Properties_Count++] = props[i];
1375         }
1376     }
1377
1378   if (vm_args == NULL)
1379     return 0;
1380
1381   for (int i = 0; i < vm_args->nOptions; ++i)
1382     {
1383       char* option_string = vm_args->options[i].optionString;
1384       if (! strcmp (option_string, "vfprintf")
1385           || ! strcmp (option_string, "exit")
1386           || ! strcmp (option_string, "abort"))
1387         {
1388           // FIXME: we are required to recognize these, but for
1389           // now we don't handle them in any way.
1390           continue;
1391         }
1392       else if (! strncmp (option_string,
1393                           "-verbose", sizeof ("-verbose") - 1))
1394         {
1395           jint result = parse_verbose_args (option_string,
1396                                             vm_args->ignoreUnrecognized);
1397           if (result < 0)
1398             return result;
1399         }
1400       else if (! strncmp (option_string, "-D", 2))
1401         {
1402           _Jv_Compiler_Properties = (const char**) _Jv_Realloc
1403             (_Jv_Compiler_Properties,
1404              (_Jv_Properties_Count + 1) * sizeof (char*));
1405
1406           _Jv_Compiler_Properties[_Jv_Properties_Count++] =
1407             strdup (option_string + 2);
1408
1409           continue;
1410         }
1411       else if (vm_args->ignoreUnrecognized)
1412         {
1413           if (option_string[0] == '_')
1414             parse_x_arg (option_string + 1);
1415           else if (! strncmp (option_string, "-X", 2))
1416             parse_x_arg (option_string + 2);
1417           else
1418             {
1419             unknown_option:
1420               fprintf (stderr, "libgcj: unknown option: %s\n", option_string);
1421               return -1;
1422             }
1423         }
1424       else
1425         goto unknown_option;
1426     }
1427   return 0;
1428 }
1429
1430 jint
1431 _Jv_CreateJavaVM (JvVMInitArgs* vm_args)
1432 {
1433   using namespace gcj;
1434
1435   if (runtimeInitialized)
1436     return -1;
1437
1438   runtimeInitialized = true;
1439   startTime = _Jv_platform_gettimeofday();
1440
1441   jint result = parse_init_args (vm_args);
1442   if (result < 0)
1443     return -1;
1444
1445   PROCESS_GCJ_PROPERTIES;
1446
1447   /* Threads must be initialized before the GC, so that it inherits the
1448      signal mask.  */
1449   _Jv_InitThreads ();
1450   _Jv_InitGC ();
1451   _Jv_InitializeSyncMutex ();
1452   
1453 #ifdef INTERPRETER
1454   _Jv_InitInterpreter ();
1455 #endif  
1456
1457 #ifdef HANDLE_SEGV
1458   INIT_SEGV;
1459 #endif
1460
1461 #ifdef HANDLE_FPE
1462   INIT_FPE;
1463 #endif
1464
1465   /* Initialize Utf8 constants declared in jvm.h. */
1466   void_signature = _Jv_makeUtf8Const ("()V", 3);
1467   clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
1468   init_name = _Jv_makeUtf8Const ("<init>", 6);
1469   finit_name = _Jv_makeUtf8Const ("finit$", 6);
1470
1471   /* Initialize built-in classes to represent primitive TYPEs. */
1472   _Jv_InitPrimClass (&_Jv_byteClass,    "byte",    'B', 1);
1473   _Jv_InitPrimClass (&_Jv_shortClass,   "short",   'S', 2);
1474   _Jv_InitPrimClass (&_Jv_intClass,     "int",     'I', 4);
1475   _Jv_InitPrimClass (&_Jv_longClass,    "long",    'J', 8);
1476   _Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1);
1477   _Jv_InitPrimClass (&_Jv_charClass,    "char",    'C', 2);
1478   _Jv_InitPrimClass (&_Jv_floatClass,   "float",   'F', 4);
1479   _Jv_InitPrimClass (&_Jv_doubleClass,  "double",  'D', 8);
1480   _Jv_InitPrimClass (&_Jv_voidClass,    "void",    'V', 0);
1481
1482   // We have to initialize this fairly early, to avoid circular class
1483   // initialization.  In particular we want to start the
1484   // initialization of ClassLoader before we start the initialization
1485   // of VMClassLoader.
1486   _Jv_InitClass (&java::lang::ClassLoader::class$);
1487
1488   // Set up the system class loader and the bootstrap class loader.
1489   gnu::gcj::runtime::ExtensionClassLoader::initialize();
1490   java::lang::VMClassLoader::initialize(JvNewStringLatin1(TOOLEXECLIBDIR));
1491
1492   _Jv_RegisterBootstrapPackages();
1493
1494   no_memory = new java::lang::OutOfMemoryError;
1495
1496 #ifdef USE_LTDL
1497   LTDL_SET_PRELOADED_SYMBOLS ();
1498 #endif
1499
1500   _Jv_platform_initialize ();
1501
1502   _Jv_JNI_Init ();
1503   _Jv_JVMTI_Init ();
1504
1505   _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
1506
1507   // Start the GC finalizer thread.  A VirtualMachineError can be
1508   // thrown by the runtime if, say, threads aren't available.
1509   try
1510     {
1511       using namespace gnu::gcj::runtime;
1512       FinalizerThread *ft = new FinalizerThread ();
1513       ft->start ();
1514     }
1515   catch (java::lang::VirtualMachineError *ignore)
1516     {
1517     }
1518
1519   runtimeInitialized = true;
1520
1521   return 0;
1522 }
1523
1524 void
1525 _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
1526              const char **argv, bool is_jar)
1527 {
1528 #ifndef DISABLE_MAIN_ARGS
1529   _Jv_SetArgs (argc, argv);
1530 #endif
1531
1532   java::lang::Runtime *runtime = NULL;
1533
1534   try
1535     {
1536       if (_Jv_CreateJavaVM (vm_args) < 0)
1537         {
1538           fprintf (stderr, "libgcj: couldn't create virtual machine\n");
1539           exit (1);
1540         }
1541       
1542       if (vm_args == NULL)
1543         gcj::vmArgs = JvConvertArgv(0, NULL);
1544       else
1545         {
1546           const char* vmArgs[vm_args->nOptions];
1547           const char** vmPtr = vmArgs;
1548           struct _Jv_VMOption* optionPtr = vm_args->options;
1549           for (int i = 0; i < vm_args->nOptions; ++i)
1550             *vmPtr++ = (*optionPtr++).optionString;
1551           gcj::vmArgs = JvConvertArgv(vm_args->nOptions, vmArgs);
1552         }
1553
1554       // Get the Runtime here.  We want to initialize it before searching
1555       // for `main'; that way it will be set up if `main' is a JNI method.
1556       runtime = java::lang::Runtime::getRuntime ();
1557
1558 #ifdef DISABLE_MAIN_ARGS
1559       arg_vec = JvConvertArgv (0, 0);
1560 #else      
1561       arg_vec = JvConvertArgv (argc - 1, argv + 1);
1562 #endif
1563
1564       using namespace gnu::java::lang;
1565       if (klass)
1566         main_thread = new MainThread (klass, arg_vec);
1567       else
1568         main_thread = new MainThread (JvNewStringUTF (name),
1569                                       arg_vec, is_jar);
1570       _Jv_AttachCurrentThread (main_thread);
1571
1572       // Start JDWP
1573       if (remoteDebug)
1574         {
1575           using namespace gnu::classpath::jdwp;
1576           VMVirtualMachine::initialize ();
1577           Jdwp *jdwp = new Jdwp ();
1578           jdwp->setDaemon (true);
1579           jdwp->configure (JvNewStringLatin1 (jdwpOptions));
1580           jdwp->start ();
1581
1582           // Wait for JDWP to initialize and start
1583           jdwp->join ();
1584         }
1585
1586       // Send VmInit
1587       gnu::classpath::jdwp::event::VmInitEvent *event;
1588       event = new gnu::classpath::jdwp::event::VmInitEvent (main_thread);
1589       gnu::classpath::jdwp::Jdwp::notify (event);
1590     }
1591   catch (java::lang::Throwable *t)
1592     {
1593       java::lang::System::err->println (JvNewStringLatin1 
1594         ("Exception during runtime initialization"));
1595       t->printStackTrace();
1596       if (runtime)
1597         java::lang::Runtime::exitNoChecksAccessor (1);
1598       // In case the runtime creation failed.
1599       ::exit (1);
1600     }
1601
1602   _Jv_ThreadRun (main_thread);
1603
1604   // Notify debugger of VM's death
1605   if (gnu::classpath::jdwp::Jdwp::isDebugging)
1606     {
1607       using namespace gnu::classpath::jdwp;
1608       event::VmDeathEvent *event = new event::VmDeathEvent ();
1609       Jdwp::notify (event);
1610     }
1611
1612   // If we got here then something went wrong, as MainThread is not
1613   // supposed to terminate.
1614   ::exit (1);
1615 }
1616
1617 void
1618 _Jv_RunMain (jclass klass, const char *name, int argc, const char **argv, 
1619              bool is_jar)
1620 {
1621   _Jv_RunMain (NULL, klass, name, argc, argv, is_jar);
1622 }
1623
1624 void
1625 JvRunMain (jclass klass, int argc, const char **argv)
1626 {
1627   _Jv_RunMain (klass, NULL, argc, argv, false);
1628 }
1629
1630 void
1631 JvRunMainName (const char *name, int argc, const char **argv)
1632 {
1633   _Jv_RunMain (NULL, name, argc, argv, false);
1634 }
1635
1636 \f
1637
1638 // Parse a string and return a heap size.
1639 static size_t
1640 parse_memory_size (const char *spec)
1641 {
1642   char *end;
1643   unsigned long val = strtoul (spec, &end, 10);
1644   if (*end == 'k' || *end == 'K')
1645     val *= 1024;
1646   else if (*end == 'm' || *end == 'M')
1647     val *= 1048576;
1648   return (size_t) val;
1649 }
1650
1651 // Set the initial heap size.  This might be ignored by the GC layer.
1652 // This must be called before _Jv_RunMain.
1653 void
1654 _Jv_SetInitialHeapSize (const char *arg)
1655 {
1656   size_t size = parse_memory_size (arg);
1657   _Jv_GCSetInitialHeapSize (size);
1658 }
1659
1660 // Set the maximum heap size.  This might be ignored by the GC layer.
1661 // This must be called before _Jv_RunMain.
1662 void
1663 _Jv_SetMaximumHeapSize (const char *arg)
1664 {
1665   size_t size = parse_memory_size (arg);
1666   _Jv_GCSetMaximumHeapSize (size);
1667 }
1668
1669 void
1670 _Jv_SetStackSize (const char *arg)
1671 {
1672   size_t size = parse_memory_size (arg);
1673   gcj::stack_size = size;
1674 }
1675
1676 void *
1677 _Jv_Malloc (jsize size)
1678 {
1679   if (__builtin_expect (size == 0, false))
1680     size = 1;
1681   void *ptr = malloc ((size_t) size);
1682   if (__builtin_expect (ptr == NULL, false))
1683     throw no_memory;
1684   return ptr;
1685 }
1686
1687 void *
1688 _Jv_Realloc (void *ptr, jsize size)
1689 {
1690   if (__builtin_expect (size == 0, false))
1691     size = 1;
1692   ptr = realloc (ptr, (size_t) size);
1693   if (__builtin_expect (ptr == NULL, false))
1694     throw no_memory;
1695   return ptr;
1696 }
1697
1698 void *
1699 _Jv_MallocUnchecked (jsize size)
1700 {
1701   if (__builtin_expect (size == 0, false))
1702     size = 1;
1703   return malloc ((size_t) size);
1704 }
1705
1706 void
1707 _Jv_Free (void* ptr)
1708 {
1709   return free (ptr);
1710 }
1711
1712 \f
1713
1714 // In theory, these routines can be #ifdef'd away on machines which
1715 // support divide overflow signals.  However, we never know if some
1716 // code might have been compiled with "-fuse-divide-subroutine", so we
1717 // always include them in libgcj.
1718
1719 jint
1720 _Jv_divI (jint dividend, jint divisor)
1721 {
1722   if (__builtin_expect (divisor == 0, false))
1723     {
1724       java::lang::ArithmeticException *arithexception 
1725         = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));      
1726       throw arithexception;
1727     }
1728   
1729   if (dividend == (jint) 0x80000000L && divisor == -1)
1730     return dividend;
1731
1732   return dividend / divisor;
1733 }
1734
1735 jint
1736 _Jv_remI (jint dividend, jint divisor)
1737 {
1738   if (__builtin_expect (divisor == 0, false))
1739     {
1740       java::lang::ArithmeticException *arithexception 
1741         = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));      
1742       throw arithexception;
1743     }
1744   
1745   if (dividend == (jint) 0x80000000L && divisor == -1)
1746     return 0;
1747   
1748   return dividend % divisor;
1749 }
1750
1751 jlong
1752 _Jv_divJ (jlong dividend, jlong divisor)
1753 {
1754   if (__builtin_expect (divisor == 0, false))
1755     {
1756       java::lang::ArithmeticException *arithexception 
1757         = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));      
1758       throw arithexception;
1759     }
1760
1761   if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
1762     return dividend;
1763
1764   return dividend / divisor;
1765 }
1766
1767 jlong
1768 _Jv_remJ (jlong dividend, jlong divisor)
1769 {
1770   if (__builtin_expect (divisor == 0, false))
1771     {
1772       java::lang::ArithmeticException *arithexception 
1773         = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));      
1774       throw arithexception;
1775     }
1776
1777   if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
1778     return 0;
1779
1780   return dividend % divisor;
1781 }
1782
1783 \f
1784
1785 // Return true if SELF_KLASS can access a field or method in
1786 // OTHER_KLASS.  The field or method's access flags are specified in
1787 // FLAGS.
1788 jboolean
1789 _Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
1790 {
1791   using namespace java::lang::reflect;
1792   return ((self_klass == other_klass)
1793           || ((flags & Modifier::PUBLIC) != 0)
1794           || (((flags & Modifier::PROTECTED) != 0)
1795               && _Jv_IsAssignableFromSlow (self_klass, other_klass))
1796           || (((flags & Modifier::PRIVATE) == 0)
1797               && _Jv_ClassNameSamePackage (self_klass->name,
1798                                            other_klass->name)));
1799 }
1800
1801 // Prepend GCJ_VERSIONED_LIBDIR to a module search path stored in a C
1802 // char array, if the path is not already prefixed by
1803 // GCJ_VERSIONED_LIBDIR.  Return a newly JvMalloc'd char buffer.  The
1804 // result should be freed using JvFree.
1805 char*
1806 _Jv_PrependVersionedLibdir (char* libpath)
1807 {
1808   char* retval = 0;
1809
1810   if (libpath && libpath[0] != '\0')
1811     {
1812       if (! strncmp (libpath,
1813                      GCJ_VERSIONED_LIBDIR,
1814                      sizeof (GCJ_VERSIONED_LIBDIR) - 1))
1815         {
1816           // LD_LIBRARY_PATH is already prefixed with
1817           // GCJ_VERSIONED_LIBDIR.
1818           retval = (char*) _Jv_Malloc (strlen (libpath) + 1);
1819           strcpy (retval, libpath);
1820         }
1821       else
1822         {
1823           // LD_LIBRARY_PATH is not prefixed with
1824           // GCJ_VERSIONED_LIBDIR.
1825           char path_sep[2];
1826           path_sep[0] = (char) _Jv_platform_path_separator;
1827           path_sep[1] = '\0';
1828           jsize total = ((sizeof (GCJ_VERSIONED_LIBDIR) - 1)
1829                          + 1 /* path separator */ + strlen (libpath) + 1);
1830           retval = (char*) _Jv_Malloc (total);
1831           strcpy (retval, GCJ_VERSIONED_LIBDIR);
1832           strcat (retval, path_sep);
1833           strcat (retval, libpath);
1834         }
1835     }
1836   else
1837     {
1838       // LD_LIBRARY_PATH was not specified or is empty.
1839       retval = (char*) _Jv_Malloc (sizeof (GCJ_VERSIONED_LIBDIR));
1840       strcpy (retval, GCJ_VERSIONED_LIBDIR);
1841     }
1842
1843   return retval;
1844 }