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