Removed warning: cast s4 to s8 on 64-bit machines.
[cacao.git] / src / vm / exceptions.c
1 /* exceptions.c - exception related functions
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    $Id: exceptions.c 1491 2004-11-12 13:25:02Z twisti $
30
31 */
32
33
34 #include <string.h>
35 #include <stdarg.h>
36 #include <stdlib.h>
37 #include "asmpart.h"
38 #include "global.h"
39 #include "loader.h"
40 #include "native.h"
41 #include "tables.h"
42 #include "jit/jit.h"
43 #include "toolbox/logging.h"
44 #include "toolbox/memory.h"
45 #include "nat/java_lang_String.h"
46 #include "nat/java_lang_Throwable.h"
47
48
49 /* system exception classes required in cacao */
50
51 classinfo *class_java_lang_Throwable;
52 classinfo *class_java_lang_Exception;
53 classinfo *class_java_lang_Error;
54 classinfo *class_java_lang_OutOfMemoryError;
55
56
57 /* exception/error super class */
58
59 char *string_java_lang_Throwable =
60     "java/lang/Throwable";
61
62 char *string_java_lang_VMThrowable =
63     "java/lang/VMThrowable";
64
65
66 /* specify some exception strings for code generation */
67
68 char *string_java_lang_ArithmeticException =
69     "java/lang/ArithmeticException";
70
71 char *string_java_lang_ArithmeticException_message =
72     "/ by zero";
73
74 char *string_java_lang_ArrayIndexOutOfBoundsException =
75     "java/lang/ArrayIndexOutOfBoundsException";
76
77 char *string_java_lang_ArrayStoreException =
78     "java/lang/ArrayStoreException";
79
80 char *string_java_lang_ClassCastException =
81     "java/lang/ClassCastException";
82
83 char *string_java_lang_ClassNotFoundException =
84         "java/lang/ClassNotFoundException";
85
86 char *string_java_lang_CloneNotSupportedException =
87     "java/lang/CloneNotSupportedException";
88
89 char *string_java_lang_Exception =
90     "java/lang/Exception";
91
92 char *string_java_lang_IllegalArgumentException =
93     "java/lang/IllegalArgumentException";
94
95 char *string_java_lang_IllegalMonitorStateException =
96     "java/lang/IllegalMonitorStateException";
97
98 char *string_java_lang_IndexOutOfBoundsException =
99     "java/lang/IndexOutOfBoundsException";
100
101 char *string_java_lang_InterruptedException =
102     "java/lang/InterruptedException";
103
104 char *string_java_lang_NegativeArraySizeException =
105     "java/lang/NegativeArraySizeException";
106
107 char *string_java_lang_NoSuchFieldException =
108         "java/lang/NoSuchFieldException";
109
110 char *string_java_lang_NoSuchMethodException =
111         "java/lang/NoSuchMethodException";
112
113 char *string_java_lang_NullPointerException =
114     "java/lang/NullPointerException";
115
116
117 /* specify some error strings for code generation */
118
119 char *string_java_lang_AbstractMethodError =
120     "java/lang/AbstractMethodError";
121
122 char *string_java_lang_ClassCircularityError =
123     "java/lang/ClassCircularityError";
124
125 char *string_java_lang_ClassFormatError =
126     "java/lang/ClassFormatError";
127
128 char *string_java_lang_Error =
129     "java/lang/Error";
130
131 char *string_java_lang_ExceptionInInitializerError =
132     "java/lang/ExceptionInInitializerError";
133
134 char *string_java_lang_IncompatibleClassChangeError =
135     "java/lang/IncompatibleClassChangeError";
136
137 char *string_java_lang_InternalError =
138     "java/lang/InternalError";
139
140 char *string_java_lang_LinkageError =
141     "java/lang/LinkageError";
142
143 char *string_java_lang_NoClassDefFoundError =
144     "java/lang/NoClassDefFoundError";
145
146 char *string_java_lang_NoSuchFieldError =
147         "java/lang/NoSuchFieldError";
148
149 char *string_java_lang_NoSuchMethodError =
150         "java/lang/NoSuchMethodError";
151
152 char *string_java_lang_OutOfMemoryError =
153     "java/lang/OutOfMemoryError";
154
155 char *string_java_lang_UnsupportedClassVersionError =
156     "java/lang/UnsupportedClassVersionError";
157
158 char *string_java_lang_VerifyError =
159     "java/lang/VerifyError";
160
161 char *string_java_lang_VirtualMachineError =
162     "java/lang/VirtualMachineError";
163
164
165 /* init_system_exceptions *****************************************************
166
167    load, link and compile exceptions used in the system
168
169 *******************************************************************************/
170
171 bool init_system_exceptions(void)
172 {
173         /* java/lang/Throwable */
174
175         class_java_lang_Throwable =
176                 class_new(utf_new_char(string_java_lang_Throwable));
177
178         if (!class_load(class_java_lang_Throwable))
179                 return false;
180
181         if (!class_link(class_java_lang_Throwable))
182                 return false;
183
184
185         /* java/lang/Exception */
186
187         class_java_lang_Exception =
188                 class_new(utf_new_char(string_java_lang_Exception));
189
190         if (!class_load(class_java_lang_Exception))
191                 return false;
192
193         if (!class_link(class_java_lang_Exception))
194                 return false;
195
196
197         /* java/lang/Error */
198
199         class_java_lang_Error =
200                 class_new(utf_new_char(string_java_lang_Error));
201
202         if (!class_load(class_java_lang_Error))
203                 return false;
204
205         if (!class_link(class_java_lang_Error))
206                 return false;
207
208
209         /* java/lang/OutOfMemoryError */
210
211         class_java_lang_OutOfMemoryError =
212                 class_new(utf_new_char(string_java_lang_OutOfMemoryError));
213
214         if (!class_load(class_java_lang_OutOfMemoryError))
215                 return false;
216
217         if (!class_link(class_java_lang_OutOfMemoryError))
218                 return false;
219
220         return true;
221 }
222
223
224 static void throw_exception_exit_intern(bool doexit)
225 {
226         java_objectheader *xptr;
227         classinfo *c;
228         methodinfo *pss;
229
230         xptr = *exceptionptr;
231
232         if (xptr) {
233                 /* clear exception, because we are calling jit code again */
234                 *exceptionptr = NULL;
235
236                 c = xptr->vftbl->class;
237
238                 pss = class_resolveclassmethod(c,
239                                                                            utf_new_char("printStackTrace"),
240                                                                            utf_new_char("()V"),
241                                                                            class_java_lang_Object,
242                                                                            false);
243
244                 /* print the stacktrace */
245                 if (pss) {
246                         asm_calljavafunction(pss, xptr, NULL, NULL, NULL);
247
248                         /* this normally means, we are EXTREMLY out of memory, but may be
249                            any other exception */
250                         if (*exceptionptr) {
251                                 utf_fprint_classname(stderr, c->name);
252                                 fprintf(stderr, "\n");
253                         }
254
255                 } else {
256                         utf_fprint_classname(stderr, c->name);
257                         fprintf(stderr, ": printStackTrace()V not found!\n");
258                 }
259
260                 fflush(stderr);
261
262                 /* good bye! */
263                 if (doexit) {
264                         exit(1);
265                 }
266         }
267 }
268
269
270 void throw_exception()
271 {
272         throw_exception_exit_intern(false);
273 }
274
275
276 void throw_exception_exit()
277 {
278         throw_exception_exit_intern(true);
279 }
280
281
282 void throw_main_exception()
283 {
284         fprintf(stderr, "Exception in thread \"main\" ");
285         fflush(stderr);
286
287         throw_exception_exit_intern(false);
288 }
289
290
291 void throw_main_exception_exit()
292 {
293         fprintf(stderr, "Exception in thread \"main\" ");
294         fflush(stderr);
295
296         throw_exception_exit_intern(true);
297 }
298
299
300 void throw_cacao_exception_exit(char *exception, char *message, ...)
301 {
302         s4 i;
303         char *tmp;
304         s4 len;
305         va_list ap;
306
307         len = strlen(exception);
308         tmp = MNEW(char, len+1);
309         strncpy(tmp, exception, len);
310         tmp[len]='\0';
311
312         /* convert to classname */
313
314         for (i = len - 1; i >= 0; i--) {
315                 if (tmp[i] == '/') tmp[i] = '.';
316         }
317
318         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
319
320         MFREE(tmp, char, len);
321
322         if (strlen(message) > 0) {
323                 fprintf(stderr, ": ");
324
325                 va_start(ap, message);
326                 fprintf(stderr, message, ap);
327                 va_end(ap);
328         }
329
330         fprintf(stderr, "\n");
331         fflush(stderr);
332
333         /* good bye! */
334         exit(1);
335 }
336
337
338 #if 1
339 #define CREATENEW_EXCEPTION(ex) \
340     return ex;
341 #else
342 #define CREATENEW_EXCEPTION(ex) \
343         java_objectheader *newEx; \
344         java_objectheader *oldexception=*exceptionptr;\
345         *exceptionptr=0;\
346         newEx=ex;\
347         *exceptionptr=oldexception;\
348         return newEx;
349 #endif
350
351 java_objectheader *new_exception(char *classname)
352 {
353         classinfo *c = class_new(utf_new_char(classname));
354
355         CREATENEW_EXCEPTION(native_new_and_init(c));
356 }
357
358 java_objectheader *new_exception_message(char *classname, char *message)
359 {
360         classinfo *c = class_new(utf_new_char(classname));
361
362         CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new_char(message)));
363 }
364
365
366 java_objectheader *new_exception_throwable(char *classname, java_lang_Throwable *throwable)
367 {
368         classinfo *c = class_new(utf_new_char(classname));
369
370         CREATENEW_EXCEPTION(native_new_and_init_throwable(c, throwable));
371 }
372
373
374 java_objectheader *new_exception_utfmessage(char *classname, utf *message)
375 {
376         classinfo *c = class_new(utf_new_char(classname));
377
378         CREATENEW_EXCEPTION(native_new_and_init_string(c, javastring_new(message)));
379 }
380
381
382 java_objectheader *new_exception_javastring(char *classname, java_lang_String *message)
383 {
384         classinfo *c = class_new(utf_new_char(classname));
385
386         CREATENEW_EXCEPTION(native_new_and_init_string(c, message));
387 }
388
389
390 java_objectheader *new_exception_int(char *classname, s4 i)
391 {
392         classinfo *c;
393
394         c = class_new(utf_new_char(classname));
395
396         CREATENEW_EXCEPTION(native_new_and_init_int(c, i));
397 }
398
399
400 /* new_classformaterror ********************************************************
401
402    generates a java.lang.ClassFormatError for the classloader
403
404 *******************************************************************************/
405
406 java_objectheader *new_classformaterror(classinfo *c, char *message, ...)
407 {
408         char msg[MAXLOGTEXT];
409         va_list ap;
410
411         utf_sprint_classname(msg, c->name);
412         sprintf(msg + strlen(msg), " (");
413
414         va_start(ap, message);
415         vsprintf(msg + strlen(msg), message, ap);
416         va_end(ap);
417
418         sprintf(msg + strlen(msg), ")");
419
420         return new_exception_message(string_java_lang_ClassFormatError, msg);
421 }
422
423
424 /* new_unsupportedclassversionerror ********************************************
425
426    generates a java.lang.UnsupportedClassVersionError for the classloader
427
428 *******************************************************************************/
429
430 java_objectheader *new_unsupportedclassversionerror(classinfo *c, char *message, ...)
431 {
432         char msg[MAXLOGTEXT];
433         va_list ap;
434
435         utf_sprint_classname(msg, c->name);
436         sprintf(msg + strlen(msg), " (");
437
438         va_start(ap, message);
439         vsprintf(msg + strlen(msg), message, ap);
440         va_end(ap);
441
442         sprintf(msg + strlen(msg), ")");
443
444         return new_exception_message(string_java_lang_UnsupportedClassVersionError,
445                                                                  msg);
446 }
447
448
449 /* new_verifyerror *************************************************************
450
451    generates a java.lang.VerifyError for the jit compiler
452
453 *******************************************************************************/
454
455 java_objectheader *new_verifyerror(methodinfo *m, char *message)
456 {
457         java_objectheader *o;
458         char *msg;
459         s4 len;
460
461         len = 8 + utf_strlen(m->class->name) +
462                 10 + utf_strlen(m->name) +
463                 13 + utf_strlen(m->descriptor) +
464                 2 + strlen(message) + 1;
465                 
466         msg = MNEW(char, len);
467
468         sprintf(msg, "(class: ");
469         utf_sprint(msg + strlen(msg), m->class->name);
470         sprintf(msg + strlen(msg), ", method: ");
471         utf_sprint(msg + strlen(msg), m->name);
472         sprintf(msg + strlen(msg), ", signature: ");
473         utf_sprint(msg + strlen(msg), m->descriptor);
474         sprintf(msg + strlen(msg), ") %s", message);
475
476         o = new_exception_message(string_java_lang_VerifyError, msg);
477
478         MFREE(msg, u1, len);
479
480         return o;
481 }
482
483
484 /* new_arithmeticexception *****************************************************
485
486    generates a java.lang.ArithmeticException for the jit compiler
487
488 *******************************************************************************/
489
490 java_objectheader *new_arithmeticexception()
491 {
492         java_objectheader *e;
493
494         e = new_exception_message(string_java_lang_ArithmeticException,
495                                                           string_java_lang_ArithmeticException_message);
496
497         if (!e)
498                 return *exceptionptr;
499
500         return e;
501 }
502
503
504 /* new_arrayindexoutofboundsexception ******************************************
505
506    generates a java.lang.ArrayIndexOutOfBoundsException for the jit compiler
507
508 *******************************************************************************/
509
510 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
511 {
512         java_objectheader *e;
513         methodinfo *m;
514         java_lang_String *s;
515
516         /* convert the index into a String, like Sun does */
517
518         m = class_resolveclassmethod(class_java_lang_String,
519                                                                  utf_new_char("valueOf"),
520                                                                  utf_new_char("(I)Ljava/lang/String;"),
521                                                                  class_java_lang_Object,
522                                                                  true);
523
524         if (!m)
525                 return *exceptionptr;
526
527         s = (java_lang_String *) asm_calljavafunction(m,
528 #if POINTERSIZE == 8
529                                                                                                   (void *) (s8) index,
530 #else
531                                                                                                   (void *) index,
532 #endif
533                                                                                                   NULL,
534                                                                                                   NULL,
535                                                                                                   NULL);
536
537         if (!s)
538                 return *exceptionptr;
539
540         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
541                                                                  s);
542
543         if (!e)
544                 return *exceptionptr;
545
546         return e;
547 }
548
549
550 /* new_arraystoreexception *****************************************************
551
552    generates a java.lang.ArrayStoreException for the jit compiler
553
554 *******************************************************************************/
555
556 java_objectheader *new_arraystoreexception()
557 {
558         java_objectheader *e;
559
560         e = new_exception(string_java_lang_ArrayStoreException);
561
562         if (!e)
563                 return *exceptionptr;
564
565         return e;
566 }
567
568
569 /* new_classcastexception ******************************************************
570
571    generates a java.lang.ClassCastException for the jit compiler
572
573 *******************************************************************************/
574
575 java_objectheader *new_classcastexception()
576 {
577         java_objectheader *e;
578
579         e = new_exception(string_java_lang_ClassCastException);
580
581         if (!e)
582                 return *exceptionptr;
583
584         return e;
585 }
586
587
588 /* new_negativearraysizeexception **********************************************
589
590    generates a java.lang.NegativeArraySizeException for the jit compiler
591
592 *******************************************************************************/
593
594 java_objectheader *new_negativearraysizeexception()
595 {
596         java_objectheader *e;
597
598         e = new_exception(string_java_lang_NegativeArraySizeException);
599
600         if (!e)
601                 return *exceptionptr;
602
603         return e;
604 }
605
606
607 /* new_nullpointerexception ****************************************************
608
609    generates a java.lang.NullPointerException for the jit compiler
610
611 *******************************************************************************/
612
613 java_objectheader *new_nullpointerexception()
614 {
615         java_objectheader *e;
616
617         e = new_exception(string_java_lang_NullPointerException);
618
619         if (!e)
620                 return *exceptionptr;
621
622         return e;
623 }
624
625
626 /*
627  * These are local overrides for various environment variables in Emacs.
628  * Please do not remove this and leave it at the end of the file, where
629  * Emacs will automagically detect them.
630  * ---------------------------------------------------------------------
631  * Local variables:
632  * mode: c
633  * indent-tabs-mode: t
634  * c-basic-offset: 4
635  * tab-width: 4
636  * End:
637  */