OSDN Git Service

* config/h8300/h8300.md (a peephole2): Tighten the condition.
[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  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
29 #ifdef ENABLE_JVMPI
30 #include <jvmpi.h>
31 #include <java/lang/ThreadGroup.h>
32 #endif
33
34 #ifndef DISABLE_GETENV_PROPERTIES
35 #include <ctype.h>
36 #include <java-props.h>
37 #define PROCESS_GCJ_PROPERTIES process_gcj_properties()
38 #else
39 #define PROCESS_GCJ_PROPERTIES
40 #endif // DISABLE_GETENV_PROPERTIES
41
42 #include <java/lang/Class.h>
43 #include <java/lang/ClassLoader.h>
44 #include <java/lang/Runtime.h>
45 #include <java/lang/String.h>
46 #include <java/lang/Thread.h>
47 #include <java/lang/ThreadGroup.h>
48 #include <java/lang/ArrayIndexOutOfBoundsException.h>
49 #include <java/lang/ArithmeticException.h>
50 #include <java/lang/ClassFormatError.h>
51 #include <java/lang/InternalError.h>
52 #include <java/lang/NegativeArraySizeException.h>
53 #include <java/lang/NullPointerException.h>
54 #include <java/lang/OutOfMemoryError.h>
55 #include <java/lang/System.h>
56 #include <java/lang/VMThrowable.h>
57 #include <java/lang/reflect/Modifier.h>
58 #include <java/io/PrintStream.h>
59 #include <java/lang/UnsatisfiedLinkError.h>
60 #include <java/lang/VirtualMachineError.h>
61 #include <gnu/gcj/runtime/VMClassLoader.h>
62 #include <gnu/gcj/runtime/FinalizerThread.h>
63 #include <gnu/gcj/runtime/FirstThread.h>
64
65 #ifdef USE_LTDL
66 #include <ltdl.h>
67 #endif
68
69 // We allocate a single OutOfMemoryError exception which we keep
70 // around for use if we run out of memory.
71 static java::lang::OutOfMemoryError *no_memory;
72
73 // Largest representable size_t.
74 #define SIZE_T_MAX ((size_t) (~ (size_t) 0))
75
76 static const char *no_properties[] = { NULL };
77
78 // Properties set at compile time.
79 const char **_Jv_Compiler_Properties = no_properties;
80
81 // The JAR file to add to the beginning of java.class.path.
82 const char *_Jv_Jar_Class_Path;
83
84 #ifndef DISABLE_GETENV_PROPERTIES
85 // Property key/value pairs.
86 property_pair *_Jv_Environment_Properties;
87 #endif
88
89 // Stash the argv pointer to benefit native libraries that need it.
90 const char **_Jv_argv;
91 int _Jv_argc;
92
93 #ifdef ENABLE_JVMPI
94 // Pointer to JVMPI notification functions.
95 void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event);
96 void (*_Jv_JVMPI_Notify_THREAD_START) (JVMPI_Event *event);
97 void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
98 #endif
99 \f
100
101 extern "C" void _Jv_ThrowSignal (jthrowable) __attribute ((noreturn));
102
103 // Just like _Jv_Throw, but fill in the stack trace first.  Although
104 // this is declared extern in order that its name not be mangled, it
105 // is not intended to be used outside this file.
106 void 
107 _Jv_ThrowSignal (jthrowable throwable)
108 {
109   throwable->fillInStackTrace ();
110   throw throwable;
111 }
112  
113 #ifdef HANDLE_SEGV
114 static java::lang::NullPointerException *nullp;
115
116 SIGNAL_HANDLER (catch_segv)
117 {
118   MAKE_THROW_FRAME (nullp);
119   _Jv_ThrowSignal (nullp);
120 }
121 #endif
122
123 static java::lang::ArithmeticException *arithexception;
124
125 #ifdef HANDLE_FPE
126 SIGNAL_HANDLER (catch_fpe)
127 {
128 #ifdef HANDLE_DIVIDE_OVERFLOW
129   HANDLE_DIVIDE_OVERFLOW;
130 #else
131   MAKE_THROW_FRAME (arithexception);
132 #endif
133   _Jv_ThrowSignal (arithexception);
134 }
135 #endif
136
137 \f
138
139 jboolean
140 _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
141 {
142   int len;
143   _Jv_ushort *aptr, *bptr;
144   if (a == b)
145     return true;
146   if (a->hash != b->hash)
147     return false;
148   len = a->length;
149   if (b->length != len)
150     return false;
151   aptr = (_Jv_ushort *)a->data;
152   bptr = (_Jv_ushort *)b->data;
153   len = (len + 1) >> 1;
154   while (--len >= 0)
155     if (*aptr++ != *bptr++)
156       return false;
157   return true;
158 }
159
160 /* True iff A is equal to STR.
161    HASH is STR->hashCode().  
162 */
163
164 jboolean
165 _Jv_equal (Utf8Const* a, jstring str, jint hash)
166 {
167   if (a->hash != (_Jv_ushort) hash)
168     return false;
169   jint len = str->length();
170   jint i = 0;
171   jchar *sptr = _Jv_GetStringChars (str);
172   unsigned char* ptr = (unsigned char*) a->data;
173   unsigned char* limit = ptr + a->length;
174   for (;; i++, sptr++)
175     {
176       int ch = UTF8_GET (ptr, limit);
177       if (i == len)
178         return ch < 0;
179       if (ch != *sptr)
180         return false;
181     }
182   return true;
183 }
184
185 /* Like _Jv_equal, but stop after N characters.  */
186 jboolean
187 _Jv_equaln (Utf8Const *a, jstring str, jint n)
188 {
189   jint len = str->length();
190   jint i = 0;
191   jchar *sptr = _Jv_GetStringChars (str);
192   unsigned char* ptr = (unsigned char*) a->data;
193   unsigned char* limit = ptr + a->length;
194   for (; n-- > 0; i++, sptr++)
195     {
196       int ch = UTF8_GET (ptr, limit);
197       if (i == len)
198         return ch < 0;
199       if (ch != *sptr)
200         return false;
201     }
202   return true;
203 }
204
205 /* Count the number of Unicode chars encoded in a given Ut8 string. */
206 int
207 _Jv_strLengthUtf8(char* str, int len)
208 {
209   unsigned char* ptr;
210   unsigned char* limit;
211   int str_length;
212
213   ptr = (unsigned char*) str;
214   limit = ptr + len;
215   str_length = 0;
216   for (; ptr < limit; str_length++)
217     {
218       if (UTF8_GET (ptr, limit) < 0)
219         return (-1);
220     }
221   return (str_length);
222 }
223
224 /* Calculate a hash value for a string encoded in Utf8 format.
225  * This returns the same hash value as specified or java.lang.String.hashCode.
226  */
227 static jint
228 hashUtf8String (char* str, int len)
229 {
230   unsigned char* ptr = (unsigned char*) str;
231   unsigned char* limit = ptr + len;
232   jint hash = 0;
233
234   for (; ptr < limit;)
235     {
236       int ch = UTF8_GET (ptr, limit);
237       /* Updated specification from
238          http://www.javasoft.com/docs/books/jls/clarify.html. */
239       hash = (31 * hash) + ch;
240     }
241   return hash;
242 }
243
244 _Jv_Utf8Const *
245 _Jv_makeUtf8Const (char* s, int len)
246 {
247   if (len < 0)
248     len = strlen (s);
249   Utf8Const* m = (Utf8Const*) _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
250   memcpy (m->data, s, len);
251   m->data[len] = 0;
252   m->length = len;
253   m->hash = hashUtf8String (s, len) & 0xFFFF;
254   return (m);
255 }
256
257 _Jv_Utf8Const *
258 _Jv_makeUtf8Const (jstring string)
259 {
260   jint hash = string->hashCode ();
261   jint len = _Jv_GetStringUTFLength (string);
262
263   Utf8Const* m = (Utf8Const*)
264     _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
265
266   m->hash = hash;
267   m->length = len;
268
269   _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
270   m->data[len] = 0;
271   
272   return m;
273 }
274
275 \f
276
277 #ifdef DEBUG
278 void
279 _Jv_Abort (const char *function, const char *file, int line,
280            const char *message)
281 #else
282 void
283 _Jv_Abort (const char *, const char *, int, const char *message)
284 #endif
285 {
286 #ifdef DEBUG
287   fprintf (stderr,
288            "libgcj failure: %s\n   in function %s, file %s, line %d\n",
289            message, function, file, line);
290 #else
291   fprintf (stderr, "libgcj failure: %s\n", message);
292 #endif
293   abort ();
294 }
295
296 static void
297 fail_on_finalization (jobject)
298 {
299   JvFail ("object was finalized");
300 }
301
302 void
303 _Jv_GCWatch (jobject obj)
304 {
305   _Jv_RegisterFinalizer (obj, fail_on_finalization);
306 }
307
308 void
309 _Jv_ThrowBadArrayIndex(jint bad_index)
310 {
311   throw new java::lang::ArrayIndexOutOfBoundsException
312     (java::lang::String::valueOf (bad_index));
313 }
314
315 void
316 _Jv_ThrowNullPointerException ()
317 {
318   throw new java::lang::NullPointerException;
319 }
320
321 // Explicitly throw a no memory exception.
322 // The collector calls this when it encounters an out-of-memory condition.
323 void _Jv_ThrowNoMemory()
324 {
325   throw no_memory;
326 }
327
328 #ifdef ENABLE_JVMPI
329 static void
330 jvmpi_notify_alloc(jclass klass, jint size, jobject obj)
331 {
332   // Service JVMPI allocation request.
333   if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false))
334     {
335       JVMPI_Event event;
336
337       event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
338       event.env_id = NULL;
339       event.u.obj_alloc.arena_id = 0;
340       event.u.obj_alloc.class_id = (jobjectID) klass;
341       event.u.obj_alloc.is_array = 0;
342       event.u.obj_alloc.size = size;
343       event.u.obj_alloc.obj_id = (jobjectID) obj;
344
345       // FIXME:  This doesn't look right for the Boehm GC.  A GC may
346       // already be in progress.  _Jv_DisableGC () doesn't wait for it.
347       // More importantly, I don't see the need for disabling GC, since we
348       // blatantly have a pointer to obj on our stack, ensuring that the
349       // object can't be collected.  Even for a nonconservative collector,
350       // it appears to me that this must be true, since we are about to
351       // return obj. Isn't this whole approach way too intrusive for
352       // a useful profiling interface?                  - HB
353       _Jv_DisableGC ();
354       (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
355       _Jv_EnableGC ();
356     }
357 }
358 #else /* !ENABLE_JVMPI */
359 # define jvmpi_notify_alloc(klass,size,obj) /* do nothing */
360 #endif
361
362 // Allocate a new object of class KLASS.  SIZE is the size of the object
363 // to allocate.  You might think this is redundant, but it isn't; some
364 // classes, such as String, aren't of fixed size.
365 // First a version that assumes that we have no finalizer, and that
366 // the class is already initialized.
367 // If we know that JVMPI is disabled, this can be replaced by a direct call
368 // to the allocator for the appropriate GC.
369 jobject
370 _Jv_AllocObjectNoInitNoFinalizer (jclass klass, jint size)
371 {
372   jobject obj = (jobject) _Jv_AllocObj (size, klass);
373   jvmpi_notify_alloc (klass, size, obj);
374   return obj;
375 }
376
377 // And now a version that initializes if necessary.
378 jobject
379 _Jv_AllocObjectNoFinalizer (jclass klass, jint size)
380 {
381   _Jv_InitClass (klass);
382   jobject obj = (jobject) _Jv_AllocObj (size, klass);
383   jvmpi_notify_alloc (klass, size, obj);
384   return obj;
385 }
386
387 // And now the general version that registers a finalizer if necessary.
388 jobject
389 _Jv_AllocObject (jclass klass, jint size)
390 {
391   jobject obj = _Jv_AllocObjectNoFinalizer (klass, size);
392
393   // We assume that the compiler only generates calls to this routine
394   // if there really is an interesting finalizer.
395   // Unfortunately, we still have to the dynamic test, since there may
396   // be cni calls to this routine.
397   // Note that on IA64 get_finalizer() returns the starting address of the
398   // function, not a function pointer.  Thus this still works.
399   if (klass->vtable->get_finalizer ()
400       != java::lang::Object::class$.vtable->get_finalizer ())
401     _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
402   return obj;
403 }
404
405 // A version of the above that assumes the object contains no pointers,
406 // and requires no finalization.  This can't happen if we need pointers
407 // to locks.
408 #ifdef JV_HASH_SYNCHRONIZATION
409 jobject
410 _Jv_AllocPtrFreeObject (jclass klass, jint size)
411 {
412   _Jv_InitClass (klass);
413
414   jobject obj = (jobject) _Jv_AllocPtrFreeObj (size, klass);
415
416 #ifdef ENABLE_JVMPI
417   // Service JVMPI request.
418
419   if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false))
420     {
421       JVMPI_Event event;
422
423       event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
424       event.env_id = NULL;
425       event.u.obj_alloc.arena_id = 0;
426       event.u.obj_alloc.class_id = (jobjectID) klass;
427       event.u.obj_alloc.is_array = 0;
428       event.u.obj_alloc.size = size;
429       event.u.obj_alloc.obj_id = (jobjectID) obj;
430
431       _Jv_DisableGC ();
432       (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
433       _Jv_EnableGC ();
434     }
435 #endif
436
437   return obj;
438 }
439 #endif /* JV_HASH_SYNCHRONIZATION */
440
441
442 // Allocate a new array of Java objects.  Each object is of type
443 // `elementClass'.  `init' is used to initialize each slot in the
444 // array.
445 jobjectArray
446 _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
447 {
448   if (__builtin_expect (count < 0, false))
449     throw new java::lang::NegativeArraySizeException;
450
451   JvAssert (! elementClass->isPrimitive ());
452
453   // Ensure that elements pointer is properly aligned.
454   jobjectArray obj = NULL;
455   size_t size = (size_t) elements (obj);
456   size += count * sizeof (jobject);
457
458   jclass klass = _Jv_GetArrayClass (elementClass,
459                                     elementClass->getClassLoaderInternal());
460
461   obj = (jobjectArray) _Jv_AllocArray (size, klass);
462   // Cast away const.
463   jsize *lp = const_cast<jsize *> (&obj->length);
464   *lp = count;
465   // We know the allocator returns zeroed memory.  So don't bother
466   // zeroing it again.
467   if (init)
468     {
469       jobject *ptr = elements(obj);
470       while (--count >= 0)
471         *ptr++ = init;
472     }
473   return obj;
474 }
475
476 // Allocate a new array of primitives.  ELTYPE is the type of the
477 // element, COUNT is the size of the array.
478 jobject
479 _Jv_NewPrimArray (jclass eltype, jint count)
480 {
481   int elsize = eltype->size();
482   if (__builtin_expect (count < 0, false))
483     throw new java::lang::NegativeArraySizeException;
484
485   JvAssert (eltype->isPrimitive ());
486   jobject dummy = NULL;
487   size_t size = (size_t) _Jv_GetArrayElementFromElementType (dummy, eltype);
488
489   // Check for overflow.
490   if (__builtin_expect ((size_t) count > 
491                         (SIZE_T_MAX - size) / elsize, false))
492     throw no_memory;
493
494   jclass klass = _Jv_GetArrayClass (eltype, 0);
495
496 # ifdef JV_HASH_SYNCHRONIZATION
497   // Since the vtable is always statically allocated,
498   // these are completely pointerfree!  Make sure the GC doesn't touch them.
499   __JArray *arr =
500     (__JArray*) _Jv_AllocPtrFreeObj (size + elsize * count, klass);
501   memset((char *)arr + size, 0, elsize * count);
502 # else
503   __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
504   // Note that we assume we are given zeroed memory by the allocator.
505 # endif
506   // Cast away const.
507   jsize *lp = const_cast<jsize *> (&arr->length);
508   *lp = count;
509
510   return arr;
511 }
512
513 jobject
514 _Jv_NewArray (jint type, jint size)
515 {
516   switch (type)
517     {
518       case  4:  return JvNewBooleanArray (size);
519       case  5:  return JvNewCharArray (size);
520       case  6:  return JvNewFloatArray (size);
521       case  7:  return JvNewDoubleArray (size);
522       case  8:  return JvNewByteArray (size);
523       case  9:  return JvNewShortArray (size);
524       case 10:  return JvNewIntArray (size);
525       case 11:  return JvNewLongArray (size);
526     }
527   throw new java::lang::InternalError
528     (JvNewStringLatin1 ("invalid type code in _Jv_NewArray"));
529 }
530
531 // Allocate a possibly multi-dimensional array but don't check that
532 // any array length is <0.
533 static jobject
534 _Jv_NewMultiArrayUnchecked (jclass type, jint dimensions, jint *sizes)
535 {
536   JvAssert (type->isArray());
537   jclass element_type = type->getComponentType();
538   jobject result;
539   if (element_type->isPrimitive())
540     result = _Jv_NewPrimArray (element_type, sizes[0]);
541   else
542     result = _Jv_NewObjectArray (sizes[0], element_type, NULL);
543
544   if (dimensions > 1)
545     {
546       JvAssert (! element_type->isPrimitive());
547       JvAssert (element_type->isArray());
548       jobject *contents = elements ((jobjectArray) result);
549       for (int i = 0; i < sizes[0]; ++i)
550         contents[i] = _Jv_NewMultiArrayUnchecked (element_type, dimensions - 1,
551                                                   sizes + 1);
552     }
553
554   return result;
555 }
556
557 jobject
558 _Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
559 {
560   for (int i = 0; i < dimensions; ++i)
561     if (sizes[i] < 0)
562       throw new java::lang::NegativeArraySizeException;
563
564   return _Jv_NewMultiArrayUnchecked (type, dimensions, sizes);
565 }
566
567 jobject
568 _Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
569 {
570   va_list args;
571   jint sizes[dimensions];
572   va_start (args, dimensions);
573   for (int i = 0; i < dimensions; ++i)
574     {
575       jint size = va_arg (args, jint);
576       if (size < 0)
577         throw new java::lang::NegativeArraySizeException;
578       sizes[i] = size;
579     }
580   va_end (args);
581
582   return _Jv_NewMultiArrayUnchecked (array_type, dimensions, sizes);
583 }
584
585 \f
586
587 // Ensure 8-byte alignment, for hash synchronization.
588 #define DECLARE_PRIM_TYPE(NAME)                 \
589   _Jv_ArrayVTable _Jv_##NAME##VTable;           \
590   java::lang::Class _Jv_##NAME##Class __attribute__ ((aligned (8)));
591
592 DECLARE_PRIM_TYPE(byte)
593 DECLARE_PRIM_TYPE(short)
594 DECLARE_PRIM_TYPE(int)
595 DECLARE_PRIM_TYPE(long)
596 DECLARE_PRIM_TYPE(boolean)
597 DECLARE_PRIM_TYPE(char)
598 DECLARE_PRIM_TYPE(float)
599 DECLARE_PRIM_TYPE(double)
600 DECLARE_PRIM_TYPE(void)
601
602 void
603 _Jv_InitPrimClass (jclass cl, char *cname, char sig, int len, 
604                    _Jv_ArrayVTable *array_vtable)
605 {    
606   using namespace java::lang::reflect;
607
608   _Jv_InitNewClassFields (cl);
609
610   // We must set the vtable for the class; the Java constructor
611   // doesn't do this.
612   (*(_Jv_VTable **) cl) = java::lang::Class::class$.vtable;
613
614   // Initialize the fields we care about.  We do this in the same
615   // order they are declared in Class.h.
616   cl->name = _Jv_makeUtf8Const ((char *) cname, -1);
617   cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
618   cl->method_count = sig;
619   cl->size_in_bytes = len;
620   cl->vtable = JV_PRIMITIVE_VTABLE;
621   cl->state = JV_STATE_DONE;
622   cl->depth = -1;
623   if (sig != 'V')
624     _Jv_NewArrayClass (cl, NULL, (_Jv_VTable *) array_vtable);
625 }
626
627 jclass
628 _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader)
629 {
630   switch (*sig)
631     {
632     case 'B':
633       return JvPrimClass (byte);
634     case 'S':
635       return JvPrimClass (short);
636     case 'I':
637       return JvPrimClass (int);
638     case 'J':
639       return JvPrimClass (long);
640     case 'Z':
641       return JvPrimClass (boolean);
642     case 'C':
643       return JvPrimClass (char);
644     case 'F':
645       return JvPrimClass (float);
646     case 'D':
647       return JvPrimClass (double);
648     case 'V':
649       return JvPrimClass (void);
650     case 'L':
651       {
652         int i;
653         for (i = 1; sig[i] && sig[i] != ';'; ++i)
654           ;
655         _Jv_Utf8Const *name = _Jv_makeUtf8Const (&sig[1], i - 1);
656         return _Jv_FindClass (name, loader);
657       }
658     case '[':
659       {
660         jclass klass = _Jv_FindClassFromSignature (&sig[1], loader);
661         if (! klass)
662           return NULL;
663         return _Jv_GetArrayClass (klass, loader);
664       }
665     }
666
667   return NULL;                  // Placate compiler.
668 }
669
670 \f
671
672 JArray<jstring> *
673 JvConvertArgv (int argc, const char **argv)
674 {
675   if (argc < 0)
676     argc = 0;
677   jobjectArray ar = JvNewObjectArray(argc, &StringClass, NULL);
678   jobject *ptr = elements(ar);
679   jbyteArray bytes = NULL;
680   for (int i = 0;  i < argc;  i++)
681     {
682       const char *arg = argv[i];
683       int len = strlen (arg);
684       if (bytes == NULL || bytes->length < len)
685         bytes = JvNewByteArray (len);
686       jbyte *bytePtr = elements (bytes);
687       // We assume jbyte == char.
688       memcpy (bytePtr, arg, len);
689
690       // Now convert using the default encoding.
691       *ptr++ = new java::lang::String (bytes, 0, len);
692     }
693   return (JArray<jstring>*) ar;
694 }
695
696 // FIXME: These variables are static so that they will be
697 // automatically scanned by the Boehm collector.  This is needed
698 // because with qthreads the collector won't scan the initial stack --
699 // it will only scan the qthreads stacks.
700
701 // Command line arguments.
702 static JArray<jstring> *arg_vec;
703
704 // The primary thread.
705 static java::lang::Thread *main_thread;
706
707 #ifndef DISABLE_GETENV_PROPERTIES
708
709 static char *
710 next_property_key (char *s, size_t *length)
711 {
712   size_t l = 0;
713
714   JvAssert (s);
715
716   // Skip over whitespace
717   while (isspace (*s))
718     s++;
719
720   // If we've reached the end, return NULL.  Also return NULL if for
721   // some reason we've come across a malformed property string.
722   if (*s == 0
723       || *s == ':'
724       || *s == '=')
725     return NULL;
726
727   // Determine the length of the property key.
728   while (s[l] != 0
729          && ! isspace (s[l])
730          && s[l] != ':'
731          && s[l] != '=')
732     {
733       if (s[l] == '\\'
734           && s[l+1] != 0)
735         l++;
736       l++;
737     }
738
739   *length = l;
740
741   return s;
742 }
743
744 static char *
745 next_property_value (char *s, size_t *length)
746 {
747   size_t l = 0;
748
749   JvAssert (s);
750
751   while (isspace (*s))
752     s++;
753
754   if (*s == ':'
755       || *s == '=')
756     s++;
757
758   while (isspace (*s))
759     s++;
760
761   // If we've reached the end, return NULL.
762   if (*s == 0)
763     return NULL;
764
765   // Determine the length of the property value.
766   while (s[l] != 0
767          && ! isspace (s[l])
768          && s[l] != ':'
769          && s[l] != '=')
770     {
771       if (s[l] == '\\'
772           && s[l+1] != 0)
773         l += 2;
774       else
775         l++;
776     }
777
778   *length = l;
779
780   return s;
781 }
782
783 static void
784 process_gcj_properties ()
785 {
786   char *props = getenv("GCJ_PROPERTIES");
787   char *p = props;
788   size_t length;
789   size_t property_count = 0;
790
791   if (NULL == props)
792     return;
793
794   // Whip through props quickly in order to count the number of
795   // property values.
796   while (p && (p = next_property_key (p, &length)))
797     {
798       // Skip to the end of the key
799       p += length;
800
801       p = next_property_value (p, &length);
802       if (p)
803         p += length;
804       
805       property_count++;
806     }
807
808   // Allocate an array of property value/key pairs.
809   _Jv_Environment_Properties = 
810     (property_pair *) malloc (sizeof(property_pair) 
811                               * (property_count + 1));
812
813   // Go through the properties again, initializing _Jv_Properties
814   // along the way.
815   p = props;
816   property_count = 0;
817   while (p && (p = next_property_key (p, &length)))
818     {
819       _Jv_Environment_Properties[property_count].key = p;
820       _Jv_Environment_Properties[property_count].key_length = length;
821
822       // Skip to the end of the key
823       p += length;
824
825       p = next_property_value (p, &length);
826       
827       _Jv_Environment_Properties[property_count].value = p;
828       _Jv_Environment_Properties[property_count].value_length = length;
829
830       if (p)
831         p += length;
832
833       property_count++;
834     }
835   memset ((void *) &_Jv_Environment_Properties[property_count], 
836           0, sizeof (property_pair));
837   {
838     size_t i = 0;
839
840     // Null terminate the strings.
841     while (_Jv_Environment_Properties[i].key)
842       {
843         _Jv_Environment_Properties[i].key[_Jv_Environment_Properties[i].key_length] = 0;
844         _Jv_Environment_Properties[i++].value[_Jv_Environment_Properties[i].value_length] = 0;
845       }
846   }
847 }
848 #endif // DISABLE_GETENV_PROPERTIES
849
850 namespace gcj
851 {
852   _Jv_Utf8Const *void_signature;
853   _Jv_Utf8Const *clinit_name;
854   _Jv_Utf8Const *init_name;
855   _Jv_Utf8Const *finit_name;
856   
857   bool runtimeInitialized = false;
858 }
859
860 jint
861 _Jv_CreateJavaVM (void* /*vm_args*/)
862 {
863   using namespace gcj;
864   
865   if (runtimeInitialized)
866     return -1;
867
868   runtimeInitialized = true;
869
870   PROCESS_GCJ_PROPERTIES;
871
872   _Jv_InitThreads ();
873   _Jv_InitGC ();
874   _Jv_InitializeSyncMutex ();
875
876   /* Initialize Utf8 constants declared in jvm.h. */
877   void_signature = _Jv_makeUtf8Const ("()V", 3);
878   clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
879   init_name = _Jv_makeUtf8Const ("<init>", 6);
880   finit_name = _Jv_makeUtf8Const ("finit$", 6);
881
882   /* Initialize built-in classes to represent primitive TYPEs. */
883   _Jv_InitPrimClass (&_Jv_byteClass,    "byte",    'B', 1, &_Jv_byteVTable);
884   _Jv_InitPrimClass (&_Jv_shortClass,   "short",   'S', 2, &_Jv_shortVTable);
885   _Jv_InitPrimClass (&_Jv_intClass,     "int",     'I', 4, &_Jv_intVTable);
886   _Jv_InitPrimClass (&_Jv_longClass,    "long",    'J', 8, &_Jv_longVTable);
887   _Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1, &_Jv_booleanVTable);
888   _Jv_InitPrimClass (&_Jv_charClass,    "char",    'C', 2, &_Jv_charVTable);
889   _Jv_InitPrimClass (&_Jv_floatClass,   "float",   'F', 4, &_Jv_floatVTable);
890   _Jv_InitPrimClass (&_Jv_doubleClass,  "double",  'D', 8, &_Jv_doubleVTable);
891   _Jv_InitPrimClass (&_Jv_voidClass,    "void",    'V', 0, &_Jv_voidVTable);
892
893   // Turn stack trace generation off while creating exception objects.
894   _Jv_InitClass (&java::lang::VMThrowable::class$);
895   java::lang::VMThrowable::trace_enabled = 0;
896   
897   INIT_SEGV;
898 #ifdef HANDLE_FPE
899   INIT_FPE;
900 #else
901   arithexception = new java::lang::ArithmeticException
902     (JvNewStringLatin1 ("/ by zero"));
903 #endif
904   
905   no_memory = new java::lang::OutOfMemoryError;
906   
907   java::lang::VMThrowable::trace_enabled = 1;
908   
909 #ifdef USE_LTDL
910   LTDL_SET_PRELOADED_SYMBOLS ();
911 #endif
912
913   _Jv_platform_initialize ();
914
915   _Jv_JNI_Init ();
916
917   _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
918
919   // Start the GC finalizer thread.  A VirtualMachineError can be
920   // thrown by the runtime if, say, threads aren't available.  In this
921   // case finalizers simply won't run.
922   try
923     {
924       using namespace gnu::gcj::runtime;
925       FinalizerThread *ft = new FinalizerThread ();
926       ft->start ();
927     }
928   catch (java::lang::VirtualMachineError *ignore)
929     {
930     }
931
932   return 0;
933 }
934
935 void
936 _Jv_RunMain (jclass klass, const char *name, int argc, const char **argv, 
937              bool is_jar)
938 {
939   _Jv_argv = argv;
940   _Jv_argc = argc;
941
942   java::lang::Runtime *runtime = NULL;
943
944   try
945     {
946       // Set this very early so that it is seen when java.lang.System
947       // is initialized.
948       if (is_jar)
949         _Jv_Jar_Class_Path = strdup (name);
950       _Jv_CreateJavaVM (NULL);
951
952       // Get the Runtime here.  We want to initialize it before searching
953       // for `main'; that way it will be set up if `main' is a JNI method.
954       runtime = java::lang::Runtime::getRuntime ();
955
956 #ifdef DISABLE_MAIN_ARGS
957       arg_vec = JvConvertArgv (0, 0);
958 #else      
959       arg_vec = JvConvertArgv (argc - 1, argv + 1);
960 #endif
961
962       using namespace gnu::gcj::runtime;
963       if (klass)
964         main_thread = new FirstThread (klass, arg_vec);
965       else
966         main_thread = new FirstThread (JvNewStringLatin1 (name),
967                                        arg_vec, is_jar);
968     }
969   catch (java::lang::Throwable *t)
970     {
971       java::lang::System::err->println (JvNewStringLatin1 
972         ("Exception during runtime initialization"));
973       t->printStackTrace();
974       runtime->exit (1);
975     }
976
977   _Jv_AttachCurrentThread (main_thread);
978   _Jv_ThreadRun (main_thread);
979   _Jv_ThreadWait ();
980
981   int status = (int) java::lang::ThreadGroup::had_uncaught_exception;
982   runtime->exit (status);
983 }
984
985 void
986 JvRunMain (jclass klass, int argc, const char **argv)
987 {
988   _Jv_RunMain (klass, NULL, argc, argv, false);
989 }
990
991 \f
992
993 // Parse a string and return a heap size.
994 static size_t
995 parse_heap_size (const char *spec)
996 {
997   char *end;
998   unsigned long val = strtoul (spec, &end, 10);
999   if (*end == 'k' || *end == 'K')
1000     val *= 1024;
1001   else if (*end == 'm' || *end == 'M')
1002     val *= 1048576;
1003   return (size_t) val;
1004 }
1005
1006 // Set the initial heap size.  This might be ignored by the GC layer.
1007 // This must be called before _Jv_RunMain.
1008 void
1009 _Jv_SetInitialHeapSize (const char *arg)
1010 {
1011   size_t size = parse_heap_size (arg);
1012   _Jv_GCSetInitialHeapSize (size);
1013 }
1014
1015 // Set the maximum heap size.  This might be ignored by the GC layer.
1016 // This must be called before _Jv_RunMain.
1017 void
1018 _Jv_SetMaximumHeapSize (const char *arg)
1019 {
1020   size_t size = parse_heap_size (arg);
1021   _Jv_GCSetMaximumHeapSize (size);
1022 }
1023
1024 \f
1025
1026 void *
1027 _Jv_Malloc (jsize size)
1028 {
1029   if (__builtin_expect (size == 0, false))
1030     size = 1;
1031   void *ptr = malloc ((size_t) size);
1032   if (__builtin_expect (ptr == NULL, false))
1033     throw no_memory;
1034   return ptr;
1035 }
1036
1037 void *
1038 _Jv_Realloc (void *ptr, jsize size)
1039 {
1040   if (__builtin_expect (size == 0, false))
1041     size = 1;
1042   ptr = realloc (ptr, (size_t) size);
1043   if (__builtin_expect (ptr == NULL, false))
1044     throw no_memory;
1045   return ptr;
1046 }
1047
1048 void *
1049 _Jv_MallocUnchecked (jsize size)
1050 {
1051   if (__builtin_expect (size == 0, false))
1052     size = 1;
1053   return malloc ((size_t) size);
1054 }
1055
1056 void
1057 _Jv_Free (void* ptr)
1058 {
1059   return free (ptr);
1060 }
1061
1062 \f
1063
1064 // In theory, these routines can be #ifdef'd away on machines which
1065 // support divide overflow signals.  However, we never know if some
1066 // code might have been compiled with "-fuse-divide-subroutine", so we
1067 // always include them in libgcj.
1068
1069 jint
1070 _Jv_divI (jint dividend, jint divisor)
1071 {
1072   if (__builtin_expect (divisor == 0, false))
1073     _Jv_ThrowSignal (arithexception);
1074   
1075   if (dividend == (jint) 0x80000000L && divisor == -1)
1076     return dividend;
1077
1078   return dividend / divisor;
1079 }
1080
1081 jint
1082 _Jv_remI (jint dividend, jint divisor)
1083 {
1084   if (__builtin_expect (divisor == 0, false))
1085     _Jv_ThrowSignal (arithexception);
1086   
1087   if (dividend == (jint) 0x80000000L && divisor == -1)
1088     return 0;
1089
1090   return dividend % divisor;
1091 }
1092
1093 jlong
1094 _Jv_divJ (jlong dividend, jlong divisor)
1095 {
1096   if (__builtin_expect (divisor == 0, false))
1097     _Jv_ThrowSignal (arithexception);
1098   
1099   if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
1100     return dividend;
1101
1102   return dividend / divisor;
1103 }
1104
1105 jlong
1106 _Jv_remJ (jlong dividend, jlong divisor)
1107 {
1108   if (__builtin_expect (divisor == 0, false))
1109     _Jv_ThrowSignal (arithexception);
1110   
1111   if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
1112     return 0;
1113
1114   return dividend % divisor;
1115 }