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