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