OSDN Git Service

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