re GNATS gcj/51 (Writing on OutputStream of bad Socket kills app with "Broken pipe")
[gcc.git] / libjava / prims.cc
1 // prims.cc - Code for core of runtime environment.
2
3 /* Copyright (C) 1998, 1999 Cygnus Solutions
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
13 #include <stdlib.h>
14 #include <stdarg.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <signal.h>
18
19 #pragma implementation "gcj/array.h"
20
21 #include <gcj/cni.h>
22 #include <jvm.h>
23 #include <java-signal.h>
24 #include <java-threads.h>
25
26 #include <java/lang/Class.h>
27 #include <java/lang/Runtime.h>
28 #include <java/lang/String.h>
29 #include <java/lang/Thread.h>
30 #include <java/lang/ThreadGroup.h>
31 #include <java/lang/FirstThread.h>
32 #include <java/lang/ArrayIndexOutOfBoundsException.h>
33 #include <java/lang/ArithmeticException.h>
34 #include <java/lang/ClassFormatError.h>
35 #include <java/lang/ClassCastException.h>
36 #include <java/lang/NegativeArraySizeException.h>
37 #include <java/lang/NullPointerException.h>
38 #include <java/lang/OutOfMemoryError.h>
39 #include <java/lang/ArrayStoreException.h>
40 #include <java/lang/System.h>
41 #include <java/lang/reflect/Modifier.h>
42 #include <java/io/PrintStream.h>
43
44 #ifdef USE_LTDL
45 #include <ltdl.h>
46 #endif
47
48 #define ObjectClass _CL_Q34java4lang6Object
49 extern java::lang::Class ObjectClass;
50
51 // We allocate a single OutOfMemoryError exception which we keep
52 // around for use if we run out of memory.
53 static java::lang::OutOfMemoryError *no_memory;
54
55 // Largest representable size_t.
56 #define SIZE_T_MAX ((size_t) (~ (size_t) 0))
57
58 \f
59
60 #ifdef HANDLE_SEGV
61 static java::lang::NullPointerException *nullp;
62 SIGNAL_HANDLER (catch_segv)
63 {
64 MAKE_THROW_FRAME;
65 _Jv_Throw (nullp);
66 }
67 #endif
68
69 static java::lang::ArithmeticException *arithexception;
70
71 #ifdef HANDLE_FPE
72 SIGNAL_HANDLER (catch_fpe)
73 {
74 #ifdef HANDLE_DIVIDE_OVERFLOW
75 HANDLE_DIVIDE_OVERFLOW;
76 #else
77 MAKE_THROW_FRAME;
78 #endif
79 _Jv_Throw (arithexception);
80 }
81 #endif
82
83 \f
84
85 jboolean
86 _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
87 {
88 register int len;
89 register _Jv_ushort *aptr, *bptr;
90 if (a == b)
91 return true;
92 if (a->hash != b->hash)
93 return false;
94 len = a->length;
95 if (b->length != len)
96 return false;
97 aptr = (_Jv_ushort *)a->data;
98 bptr = (_Jv_ushort *)b->data;
99 len = (len + 1) >> 1;
100 while (--len >= 0)
101 if (*aptr++ != *bptr++)
102 return false;
103 return true;
104 }
105
106 /* True iff A is equal to STR.
107 HASH is STR->hashCode().
108 */
109
110 jboolean
111 _Jv_equal (Utf8Const* a, jstring str, jint hash)
112 {
113 if (a->hash != (_Jv_ushort) hash)
114 return false;
115 jint len = str->length();
116 jint i = 0;
117 jchar *sptr = _Jv_GetStringChars (str);
118 register unsigned char* ptr = (unsigned char*) a->data;
119 register unsigned char* limit = ptr + a->length;
120 for (;; i++, sptr++)
121 {
122 int ch = UTF8_GET (ptr, limit);
123 if (i == len)
124 return ch < 0;
125 if (ch != *sptr)
126 return false;
127 }
128 return true;
129 }
130
131 /* Count the number of Unicode chars encoded in a given Ut8 string. */
132 int
133 _Jv_strLengthUtf8(char* str, int len)
134 {
135 register unsigned char* ptr;
136 register unsigned char* limit;
137 int str_length;
138
139 ptr = (unsigned char*) str;
140 limit = ptr + len;
141 str_length = 0;
142 for (; ptr < limit; str_length++) {
143 if (UTF8_GET (ptr, limit) < 0) {
144 return (-1);
145 }
146 }
147 return (str_length);
148 }
149
150 /* Calculate a hash value for a string encoded in Utf8 format.
151 * This returns the same hash value as specified or java.lang.String.hashCode.
152 */
153 static jint
154 hashUtf8String (char* str, int len)
155 {
156 register unsigned char* ptr = (unsigned char*) str;
157 register unsigned char* limit = ptr + len;
158 jint hash = 0;
159
160 for (; ptr < limit;)
161 {
162 int ch = UTF8_GET (ptr, limit);
163 /* Updated specification from
164 http://www.javasoft.com/docs/books/jls/clarify.html. */
165 hash = (31 * hash) + ch;
166 }
167 return hash;
168 }
169
170 _Jv_Utf8Const *
171 _Jv_makeUtf8Const (char* s, int len)
172 {
173 if (len < 0)
174 len = strlen (s);
175 Utf8Const* m = (Utf8Const*) _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
176 if (! m)
177 JvThrow (no_memory);
178 memcpy (m->data, s, len);
179 m->data[len] = 0;
180 m->length = len;
181 m->hash = hashUtf8String (s, len) & 0xFFFF;
182 return (m);
183 }
184
185 _Jv_Utf8Const *
186 _Jv_makeUtf8Const (jstring string)
187 {
188 jint hash = string->hashCode ();
189 jint len = _Jv_GetStringUTFLength (string);
190
191 Utf8Const* m = (Utf8Const*)
192 _Jv_AllocBytesChecked (sizeof(Utf8Const) + len + 1);
193
194 m->hash = hash;
195 m->length = len;
196
197 _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
198 m->data[len] = 0;
199
200 return m;
201 }
202
203 \f
204
205 #ifdef DEBUG
206 void
207 _Jv_Abort (const char *function, const char *file, int line,
208 const char *message)
209 #else
210 void
211 _Jv_Abort (const char *, const char *, int, const char *message)
212 #endif
213 {
214 #ifdef DEBUG
215 fprintf (stderr,
216 "libgcj failure: %s\n in function %s, file %s, line %d\n",
217 message, function, file, line);
218 #else
219 java::io::PrintStream *err = java::lang::System::err;
220 err->print(JvNewStringLatin1 ("libgcj failure: "));
221 err->println(JvNewStringLatin1 (message));
222 err->flush();
223 #endif
224 abort ();
225 }
226
227 static void
228 fail_on_finalization (jobject)
229 {
230 JvFail ("object was finalized");
231 }
232
233 void
234 _Jv_GCWatch (jobject obj)
235 {
236 _Jv_RegisterFinalizer (obj, fail_on_finalization);
237 }
238
239 void
240 _Jv_ThrowBadArrayIndex(jint bad_index)
241 {
242 JvThrow (new java::lang::ArrayIndexOutOfBoundsException
243 (java::lang::String::valueOf(bad_index)));
244 }
245
246 void*
247 _Jv_CheckCast (jclass c, jobject obj)
248 {
249 if (obj != NULL && ! c->isAssignableFrom(obj->getClass()))
250 JvThrow (new java::lang::ClassCastException);
251 return obj;
252 }
253
254 void
255 _Jv_CheckArrayStore (jobject arr, jobject obj)
256 {
257 if (obj)
258 {
259 JvAssert (arr != NULL);
260 jclass arr_class = arr->getClass();
261 JvAssert (arr_class->isArray());
262 jclass elt_class = arr_class->getComponentType();
263 jclass obj_class = obj->getClass();
264 if (! elt_class->isAssignableFrom(obj_class))
265 JvThrow (new java::lang::ArrayStoreException);
266 }
267 }
268
269 \f
270
271 // Allocate some unscanned memory and throw an exception if no memory.
272 void *
273 _Jv_AllocBytesChecked (jsize size)
274 {
275 void *r = _Jv_AllocBytes (size);
276 if (! r)
277 _Jv_Throw (no_memory);
278 return r;
279 }
280
281 // Allocate a new object of class C. SIZE is the size of the object
282 // to allocate. You might think this is redundant, but it isn't; some
283 // classes, such as String, aren't of fixed size.
284 jobject
285 _Jv_AllocObject (jclass c, jint size)
286 {
287 _Jv_InitClass (c);
288
289 jobject obj = (jobject) _Jv_AllocObj (size);
290 if (! obj)
291 JvThrow (no_memory);
292 *((_Jv_VTable **) obj) = c->vtable;
293
294 // If this class has inherited finalize from Object, then don't
295 // bother registering a finalizer. We know that finalize() is the
296 // very first method after the dummy entry. If this turns out to be
297 // unreliable, a more robust implementation can be written. Such an
298 // implementation would look for Object.finalize in Object's method
299 // table at startup, and then use that information to find the
300 // appropriate index in the method vector.
301 if (c->vtable->method[1] != ObjectClass.vtable->method[1])
302 _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
303
304 return obj;
305 }
306
307 // Allocate a new array of Java objects. Each object is of type
308 // `elementClass'. `init' is used to initialize each slot in the
309 // array.
310 jobjectArray
311 _Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
312 {
313 if (count < 0)
314 JvThrow (new java::lang::NegativeArraySizeException);
315
316 // Check for overflow.
317 if ((size_t) count > (SIZE_T_MAX - sizeof (__JArray)) / sizeof (jobject))
318 JvThrow (no_memory);
319
320 size_t size = count * sizeof (jobject) + sizeof (__JArray);
321
322 // FIXME: second argument should be "current loader" //
323 jclass clas = _Jv_FindArrayClass (elementClass, 0);
324
325 jobjectArray obj = (jobjectArray) _Jv_AllocArray (size);
326 if (! obj)
327 JvThrow (no_memory);
328 obj->length = count;
329 jobject* ptr = elements(obj);
330 // We know the allocator returns zeroed memory. So don't bother
331 // zeroing it again.
332 if (init)
333 {
334 while (--count >= 0)
335 *ptr++ = init;
336 }
337 // Set the vtbl last to avoid problems if the GC happens during the
338 // window in this function between the allocation and this
339 // assignment.
340 *((_Jv_VTable **) obj) = clas->vtable;
341 return obj;
342 }
343
344 // Allocate a new array of primitives. ELTYPE is the type of the
345 // element, COUNT is the size of the array.
346 jobject
347 _Jv_NewPrimArray (jclass eltype, jint count)
348 {
349 int elsize = eltype->size();
350 if (count < 0)
351 JvThrow (new java::lang::NegativeArraySizeException ());
352
353 // Check for overflow.
354 if ((size_t) count > (SIZE_T_MAX - sizeof (__JArray)) / elsize)
355 JvThrow (no_memory);
356
357 __JArray *arr = (__JArray*) _Jv_AllocObj (sizeof (__JArray)
358 + elsize * count);
359 if (! arr)
360 JvThrow (no_memory);
361 arr->length = count;
362 // Note that we assume we are given zeroed memory by the allocator.
363
364 jclass klass = _Jv_FindArrayClass (eltype, 0);
365 // Set the vtbl last to avoid problems if the GC happens during the
366 // window in this function between the allocation and this
367 // assignment.
368 *((_Jv_VTable **) arr) = klass->vtable;
369 return arr;
370 }
371
372 jcharArray
373 JvNewCharArray (jint length)
374 {
375 return (jcharArray) _Jv_NewPrimArray (JvPrimClass (char), length);
376 }
377
378 jbooleanArray
379 JvNewBooleanArray (jint length)
380 {
381 return (jbooleanArray) _Jv_NewPrimArray (JvPrimClass (boolean), length);
382 }
383
384 jbyteArray
385 JvNewByteArray (jint length)
386 {
387 return (jbyteArray) _Jv_NewPrimArray (JvPrimClass (byte), length);
388 }
389
390 jshortArray
391 JvNewShortArray (jint length)
392 {
393 return (jshortArray) _Jv_NewPrimArray (JvPrimClass (short), length);
394 }
395
396 jintArray
397 JvNewIntArray (jint length)
398 {
399 return (jintArray) _Jv_NewPrimArray (JvPrimClass (int), length);
400 }
401
402 jlongArray
403 JvNewLongArray (jint length)
404 {
405 return (jlongArray) _Jv_NewPrimArray (JvPrimClass (long), length);
406 }
407
408 jfloatArray
409 JvNewFloatArray (jint length)
410 {
411 return (jfloatArray) _Jv_NewPrimArray (JvPrimClass (float), length);
412 }
413
414 jdoubleArray
415 JvNewDoubleArray (jint length)
416 {
417 return (jdoubleArray) _Jv_NewPrimArray (JvPrimClass (double), length);
418 }
419
420 jobject
421 _Jv_NewArray (jint type, jint size)
422 {
423 switch (type)
424 {
425 case 4: return JvNewBooleanArray (size);
426 case 5: return JvNewCharArray (size);
427 case 6: return JvNewFloatArray (size);
428 case 7: return JvNewDoubleArray (size);
429 case 8: return JvNewByteArray (size);
430 case 9: return JvNewShortArray (size);
431 case 10: return JvNewIntArray (size);
432 case 11: return JvNewLongArray (size);
433 }
434 JvFail ("newarray - bad type code");
435 return NULL; // Placate compiler.
436 }
437
438 jobject
439 _Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
440 {
441 JvAssert (type->isArray());
442 jclass element_type = type->getComponentType();
443 jobject result;
444 if (element_type->isPrimitive())
445 result = _Jv_NewPrimArray (element_type, sizes[0]);
446 else
447 result = _Jv_NewObjectArray (sizes[0], element_type, NULL);
448
449 if (dimensions > 1)
450 {
451 JvAssert (! element_type->isPrimitive());
452 JvAssert (element_type->isArray());
453 jobject *contents = elements ((jobjectArray) result);
454 for (int i = 0; i < sizes[0]; ++i)
455 contents[i] = _Jv_NewMultiArray (element_type, dimensions - 1,
456 sizes + 1);
457 }
458
459 return result;
460 }
461
462 jobject
463 _Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
464 {
465 va_list args;
466 jint sizes[dimensions];
467 va_start (args, dimensions);
468 for (int i = 0; i < dimensions; ++i)
469 {
470 jint size = va_arg (args, jint);
471 sizes[i] = size;
472 }
473 va_end (args);
474
475 return _Jv_NewMultiArray (array_type, dimensions, sizes);
476 }
477
478 \f
479
480 class _Jv_PrimClass : public java::lang::Class
481 {
482 public:
483 // FIXME: calling convention is weird. If we use the natural types
484 // then the compiler will complain because they aren't Java types.
485 _Jv_PrimClass (jobject cname, jbyte sig, jint len)
486 {
487 using namespace java::lang::reflect;
488
489 // We must initialize every field of the class. We do this in
490 // the same order they are declared in Class.h.
491 next = NULL;
492 name = _Jv_makeUtf8Const ((char *) cname, -1);
493 accflags = Modifier::PUBLIC | Modifier::FINAL;
494 superclass = NULL;
495 constants.size = 0;
496 constants.tags = NULL;
497 constants.data = NULL;
498 methods = NULL;
499 method_count = sig;
500 vtable_method_count = 0;
501 fields = NULL;
502 size_in_bytes = len;
503 field_count = 0;
504 static_field_count = 0;
505 vtable = JV_PRIMITIVE_VTABLE;
506 interfaces = NULL;
507 loader = NULL;
508 interface_count = 0;
509 state = 0; // FIXME.
510 thread = NULL;
511 }
512 };
513
514 #define DECLARE_PRIM_TYPE(NAME, SIG, LEN) \
515 _Jv_PrimClass _Jv_##NAME##Class((jobject) #NAME, (jbyte) SIG, (jint) LEN)
516
517 DECLARE_PRIM_TYPE(byte, 'B', 1);
518 DECLARE_PRIM_TYPE(short, 'S', 2);
519 DECLARE_PRIM_TYPE(int, 'I', 4);
520 DECLARE_PRIM_TYPE(long, 'J', 8);
521 DECLARE_PRIM_TYPE(boolean, 'Z', 1);
522 DECLARE_PRIM_TYPE(char, 'C', 2);
523 DECLARE_PRIM_TYPE(float, 'F', 4);
524 DECLARE_PRIM_TYPE(double, 'D', 8);
525 DECLARE_PRIM_TYPE(void, 'V', 0);
526
527 jclass
528 _Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader)
529 {
530 switch (*sig)
531 {
532 case 'B':
533 return JvPrimClass (byte);
534 case 'S':
535 return JvPrimClass (short);
536 case 'I':
537 return JvPrimClass (int);
538 case 'J':
539 return JvPrimClass (long);
540 case 'Z':
541 return JvPrimClass (boolean);
542 case 'C':
543 return JvPrimClass (char);
544 case 'F':
545 return JvPrimClass (float);
546 case 'D':
547 return JvPrimClass (double);
548 case 'V':
549 return JvPrimClass (void);
550 case 'L':
551 {
552 int i;
553 for (i = 1; sig[i] && sig[i] != ';'; ++i)
554 ;
555 _Jv_Utf8Const *name = _Jv_makeUtf8Const (&sig[1], i - 1);
556 return _Jv_FindClass (name, loader);
557
558 }
559 case '[':
560 return _Jv_FindArrayClass (_Jv_FindClassFromSignature (&sig[1], loader),
561 loader);
562 }
563 JvFail ("couldn't understand class signature");
564 return NULL; // Placate compiler.
565 }
566
567 \f
568
569 JArray<jstring> *
570 JvConvertArgv (int argc, const char **argv)
571 {
572 if (argc < 0)
573 argc = 0;
574 jobjectArray ar = JvNewObjectArray(argc, &StringClass, NULL);
575 jobject* ptr = elements(ar);
576 for (int i = 0; i < argc; i++)
577 {
578 const char *arg = argv[i];
579 // FIXME - should probably use JvNewStringUTF.
580 *ptr++ = JvNewStringLatin1(arg, strlen(arg));
581 }
582 return (JArray<jstring>*) ar;
583 }
584
585 // FIXME: These variables are static so that they will be
586 // automatically scanned by the Boehm collector. This is needed
587 // because with qthreads the collector won't scan the initial stack --
588 // it will only scan the qthreads stacks.
589
590 // Command line arguments.
591 static jobject arg_vec;
592
593 // The primary threadgroup.
594 static java::lang::ThreadGroup *main_group;
595
596 // The primary thread.
597 static java::lang::Thread *main_thread;
598
599 static void
600 main_init (void)
601 {
602 INIT_SEGV;
603 #ifdef HANDLE_FPE
604 INIT_FPE;
605 #else
606 arithexception = new java::lang::ArithmeticException
607 (JvNewStringLatin1 ("/ by zero"));
608 #endif
609
610 no_memory = new java::lang::OutOfMemoryError;
611
612 #ifdef USE_LTDL
613 LTDL_SET_PRELOADED_SYMBOLS ();
614 #endif
615
616 // FIXME: we only want this on POSIX systems.
617 struct sigaction act;
618 act.sa_handler = SIG_IGN;
619 sigemptyset (&act.sa_mask);
620 act.sa_flags = 0;
621 sigaction (SIGPIPE, &act, NULL);
622 }
623
624 void
625 JvRunMain (jclass klass, int argc, const char **argv)
626 {
627 main_init ();
628
629 arg_vec = JvConvertArgv (argc - 1, argv + 1);
630 main_group = new java::lang::ThreadGroup (23);
631 main_thread = new java::lang::FirstThread (main_group, klass, arg_vec);
632
633 main_thread->start();
634 _Jv_ThreadWait ();
635
636 java::lang::Runtime::getRuntime ()->exit (0);
637 }
638
639 void
640 _Jv_RunMain (const char *class_name, int argc, const char **argv)
641 {
642 main_init ();
643
644 arg_vec = JvConvertArgv (argc - 1, argv + 1);
645 main_group = new java::lang::ThreadGroup (23);
646 main_thread = new java::lang::FirstThread (main_group,
647 JvNewStringLatin1 (class_name),
648 arg_vec);
649 main_thread->start();
650 _Jv_ThreadWait ();
651
652 java::lang::Runtime::getRuntime ()->exit (0);
653 }
654
655
656 \f
657
658 void *
659 _Jv_Malloc (jsize size)
660 {
661 if (size == 0)
662 size = 1;
663 void *ptr = malloc ((size_t) size);
664 if (ptr == NULL)
665 JvThrow (no_memory);
666 return ptr;
667 }
668
669 void
670 _Jv_Free (void* ptr)
671 {
672 return free (ptr);
673 }
674
675 \f
676
677 // In theory, these routines can be #ifdef'd away on machines which
678 // support divide overflow signals. However, we never know if some
679 // code might have been compiled with "-fuse-divide-subroutine", so we
680 // always include them in libgcj.
681
682 jint
683 _Jv_divI (jint dividend, jint divisor)
684 {
685 if (divisor == 0)
686 _Jv_Throw (arithexception);
687
688 if (dividend == (jint) 0x80000000L && divisor == -1)
689 return dividend;
690
691 return dividend / divisor;
692 }
693
694 jint
695 _Jv_remI (jint dividend, jint divisor)
696 {
697 if (divisor == 0)
698 _Jv_Throw (arithexception);
699
700 if (dividend == (jint) 0x80000000L && divisor == -1)
701 return 0;
702
703 return dividend % divisor;
704 }
705
706 jlong
707 _Jv_divJ (jlong dividend, jlong divisor)
708 {
709 if (divisor == 0)
710 _Jv_Throw (arithexception);
711
712 if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
713 return dividend;
714
715 return dividend / divisor;
716 }
717
718 jlong
719 _Jv_remJ (jlong dividend, jlong divisor)
720 {
721 if (divisor == 0)
722 _Jv_Throw (arithexception);
723
724 if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
725 return 0;
726
727 return dividend % divisor;
728 }
729
730
731
732
733
734
735