OSDN Git Service

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