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