source: branches/libc-0.6/src/gcc/libjava/prims.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

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