* src/vm/jit/alpha/patcher.c (patcher_wrapper): Added return address
[cacao.git] / src / vm / exceptions.c
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes: Edwin Steiner
30
31    $Id: exceptions.c 5088 2006-07-08 20:16:05Z twisti $
32
33 */
34
35
36 #include "config.h"
37
38 #include <assert.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <stdlib.h>
42
43 #include "vm/types.h"
44
45 #include "mm/memory.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_String.h"
48 #include "native/include/java_lang_Throwable.h"
49 #include "toolbox/logging.h"
50 #include "toolbox/util.h"
51 #include "vm/class.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vm/loader.h"
55 #include "vm/options.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61
62
63 /* for raising exceptions from native methods *********************************/
64
65 #if !defined(ENABLE_THREADS)
66 java_objectheader *_no_threads_exceptionptr = NULL;
67 #endif
68
69
70 /* init_system_exceptions ******************************************************
71
72    Load and link exceptions used in the system.
73
74 *******************************************************************************/
75
76 bool exceptions_init(void)
77 {
78         /* java/lang/Throwable */
79
80         if (!(class_java_lang_Throwable =
81                   load_class_bootstrap(utf_java_lang_Throwable)) ||
82                 !link_class(class_java_lang_Throwable))
83                 return false;
84
85
86         /* java/lang/VMThrowable */
87
88         if (!(class_java_lang_VMThrowable =
89                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
90                 !link_class(class_java_lang_VMThrowable))
91                 return false;
92
93
94         /* java/lang/Error */
95
96         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
97                 !link_class(class_java_lang_Error))
98                 return false;
99
100         /* java/lang/AbstractMethodError */
101
102         if (!(class_java_lang_AbstractMethodError =
103                   load_class_bootstrap(utf_java_lang_AbstractMethodError)) ||
104                 !link_class(class_java_lang_AbstractMethodError))
105                 return false;
106
107         /* java/lang/LinkageError */
108
109         if (!(class_java_lang_LinkageError =
110                   load_class_bootstrap(utf_java_lang_LinkageError)) ||
111                 !link_class(class_java_lang_LinkageError))
112                 return false;
113
114         /* java/lang/NoClassDefFoundError */
115
116         if (!(class_java_lang_NoClassDefFoundError =
117                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
118                 !link_class(class_java_lang_NoClassDefFoundError))
119                 return false;
120
121         /* java/lang/NoSuchMethodError */
122
123         if (!(class_java_lang_NoSuchMethodError =
124                   load_class_bootstrap(utf_java_lang_NoSuchMethodError)) ||
125                 !link_class(class_java_lang_NoSuchMethodError))
126                 return false;
127
128         /* java/lang/OutOfMemoryError */
129
130         if (!(class_java_lang_OutOfMemoryError =
131                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
132                 !link_class(class_java_lang_OutOfMemoryError))
133                 return false;
134
135
136         /* java/lang/Exception */
137
138         if (!(class_java_lang_Exception =
139                   load_class_bootstrap(utf_java_lang_Exception)) ||
140                 !link_class(class_java_lang_Exception))
141                 return false;
142
143         /* java/lang/ClassCastException */
144
145         if (!(class_java_lang_ClassCastException =
146                   load_class_bootstrap(utf_java_lang_ClassCastException)) ||
147                 !link_class(class_java_lang_ClassCastException))
148                 return false;
149
150         /* java/lang/ClassNotFoundException */
151
152         if (!(class_java_lang_ClassNotFoundException =
153                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
154                 !link_class(class_java_lang_ClassNotFoundException))
155                 return false;
156
157         /* java/lang/IllegalArgumentException */
158
159         if (!(class_java_lang_IllegalArgumentException =
160                   load_class_bootstrap(utf_java_lang_IllegalArgumentException)) ||
161                 !link_class(class_java_lang_IllegalArgumentException))
162                 return false;
163
164         /* java/lang/IllegalMonitorStateException */
165
166         if (!(class_java_lang_IllegalMonitorStateException =
167                   load_class_bootstrap(utf_java_lang_IllegalMonitorStateException)) ||
168                 !link_class(class_java_lang_IllegalMonitorStateException))
169                 return false;
170
171         /* java/lang/NullPointerException */
172
173         if (!(class_java_lang_NullPointerException =
174                   load_class_bootstrap(utf_java_lang_NullPointerException)) ||
175                 !link_class(class_java_lang_NullPointerException))
176                 return false;
177
178
179         return true;
180 }
181
182
183 static void throw_exception_exit_intern(bool doexit)
184 {
185         java_objectheader *xptr;
186         classinfo *c;
187         methodinfo *pss;
188
189         xptr = *exceptionptr;
190
191         if (xptr) {
192                 /* clear exception, because we are calling jit code again */
193                 *exceptionptr = NULL;
194
195                 c = xptr->vftbl->class;
196
197                 pss = class_resolveclassmethod(c,
198                                                                            utf_printStackTrace,
199                                                                            utf_void__void,
200                                                                            class_java_lang_Object,
201                                                                            false);
202
203                 /* print the stacktrace */
204
205                 if (pss) {
206                         (void) vm_call_method(pss, xptr);
207
208                         /* This normally means, we are EXTREMLY out of memory or have a   */
209                         /* serious problem while printStackTrace. But may be another      */
210                         /* exception, so print it.                                        */
211
212                         if (*exceptionptr) {
213                                 java_lang_Throwable *t;
214
215                                 t = (java_lang_Throwable *) *exceptionptr;
216
217                                 fprintf(stderr, "Exception while printStackTrace(): ");
218                                 utf_fprint_printable_ascii_classname(stderr, t->header.vftbl->class->name);
219
220                                 if (t->detailMessage) {
221                                         char *buf;
222
223                                         buf = javastring_tochar((java_objectheader *) t->detailMessage);
224                                         fprintf(stderr, ": %s", buf);
225                                         MFREE(buf, char, strlen(buf));
226                                 }
227                                         
228                                 fprintf(stderr, "\n");
229                         }
230
231                 } else {
232                         utf_fprint_printable_ascii_classname(stderr, c->name);
233                         fprintf(stderr, ": printStackTrace()V not found!\n");
234                 }
235
236                 fflush(stderr);
237
238                 /* good bye! */
239
240                 if (doexit)
241                         exit(1);
242         }
243 }
244
245
246 void throw_exception(void)
247 {
248         throw_exception_exit_intern(false);
249 }
250
251
252 void throw_exception_exit(void)
253 {
254         throw_exception_exit_intern(true);
255 }
256
257
258 void throw_main_exception(void)
259 {
260         fprintf(stderr, "Exception in thread \"main\" ");
261         fflush(stderr);
262
263         throw_exception_exit_intern(false);
264 }
265
266
267 void throw_main_exception_exit(void)
268 {
269         fprintf(stderr, "Exception in thread \"main\" ");
270         fflush(stderr);
271
272         throw_exception_exit_intern(true);
273 }
274
275
276 void throw_cacao_exception_exit(const char *exception, const char *message, ...)
277 {
278         s4 i;
279         char *tmp;
280         s4 len;
281         va_list ap;
282
283         len = strlen(exception);
284         tmp = MNEW(char, len + 1);
285         strncpy(tmp, exception, len);
286         tmp[len] = '\0';
287
288         /* convert to classname */
289
290         for (i = len - 1; i >= 0; i--)
291                 if (tmp[i] == '/') tmp[i] = '.';
292
293         fprintf(stderr, "Exception in thread \"main\" %s", tmp);
294
295         MFREE(tmp, char, len);
296
297         if (strlen(message) > 0) {
298                 fprintf(stderr, ": ");
299
300                 va_start(ap, message);
301                 vfprintf(stderr, message, ap);
302                 va_end(ap);
303         }
304
305         fprintf(stderr, "\n");
306         fflush(stderr);
307
308         /* good bye! */
309
310         exit(1);
311 }
312
313
314 /* exceptions_throw_outofmemory_exit *******************************************
315
316    Just print an: java.lang.InternalError: Out of memory
317
318 *******************************************************************************/
319
320 void exceptions_throw_outofmemory_exit(void)
321 {
322         throw_cacao_exception_exit(string_java_lang_InternalError,
323                                                            "Out of memory");
324 }
325
326
327 /* new_exception ***************************************************************
328
329    Creates an exception object with the given name and initalizes it.
330
331    IN:
332       classname....class name in UTF-8
333
334    RETURN VALUE:
335       an exception pointer (in any case -- either it is the newly created
336           exception, or an exception thrown while trying to create it).
337
338 *******************************************************************************/
339
340 java_objectheader *new_exception(const char *classname)
341 {
342         java_objectheader *o;
343         classinfo         *c;
344
345         if (!(c = load_class_bootstrap(utf_new_char(classname))))
346                 return *exceptionptr;
347
348         o = native_new_and_init(c);
349
350         if (!o)
351                 return *exceptionptr;
352
353         return o;
354 }
355
356
357 /* new_exception_message *******************************************************
358
359    Creates an exception object with the given name and initalizes it
360    with the given char message.
361
362    IN:
363       classname....class name in UTF-8
364           message......message in UTF-8
365
366    RETURN VALUE:
367       an exception pointer (in any case -- either it is the newly created
368           exception, or an exception thrown while trying to create it).
369
370 *******************************************************************************/
371
372 java_objectheader *new_exception_message(const char *classname,
373                                                                                  const char *message)
374 {
375         java_lang_String *s;
376
377         s = javastring_new_from_utf_string(message);
378         if (!s)
379                 return *exceptionptr;
380
381         return new_exception_javastring(classname, s);
382 }
383
384
385 /* new_exception_throwable *****************************************************
386
387    Creates an exception object with the given name and initalizes it
388    with the given java/lang/Throwable exception.
389
390    IN:
391       classname....class name in UTF-8
392           throwable....the given Throwable
393
394    RETURN VALUE:
395       an exception pointer (in any case -- either it is the newly created
396           exception, or an exception thrown while trying to create it).
397
398 *******************************************************************************/
399
400 java_objectheader *new_exception_throwable(const char *classname,
401                                                                                    java_lang_Throwable *throwable)
402 {
403         java_objectheader *o;
404         classinfo         *c;
405    
406         if (!(c = load_class_bootstrap(utf_new_char(classname))))
407                 return *exceptionptr;
408
409         o = native_new_and_init_throwable(c, throwable);
410
411         if (!o)
412                 return *exceptionptr;
413
414         return o;
415 }
416
417
418 /* new_exception_utfmessage ****************************************************
419
420    Creates an exception object with the given name and initalizes it
421    with the given utf message.
422
423    IN:
424       classname....class name in UTF-8
425           message......the message as an utf *
426
427    RETURN VALUE:
428       an exception pointer (in any case -- either it is the newly created
429           exception, or an exception thrown while trying to create it).
430
431 *******************************************************************************/
432
433 java_objectheader *new_exception_utfmessage(const char *classname, utf *message)
434 {
435         java_lang_String *s;
436
437         s = javastring_new(message);
438         if (!s)
439                 return *exceptionptr;
440
441         return new_exception_javastring(classname, s);
442 }
443
444
445 /* new_exception_javastring ****************************************************
446
447    Creates an exception object with the given name and initalizes it
448    with the given java/lang/String message.
449
450    IN:
451       classname....class name in UTF-8
452           message......the message as a java.lang.String
453
454    RETURN VALUE:
455       an exception pointer (in any case -- either it is the newly created
456           exception, or an exception thrown while trying to create it).
457
458 *******************************************************************************/
459
460 java_objectheader *new_exception_javastring(const char *classname,
461                                                                                         java_lang_String *message)
462 {
463         java_objectheader *o;
464         classinfo         *c;
465    
466         if (!(c = load_class_bootstrap(utf_new_char(classname))))
467                 return *exceptionptr;
468
469         o = native_new_and_init_string(c, message);
470
471         if (!o)
472                 return *exceptionptr;
473
474         return o;
475 }
476
477
478 /* new_exception_int ***********************************************************
479
480    Creates an exception object with the given name and initalizes it
481    with the given int value.
482
483    IN:
484       classname....class name in UTF-8
485           i............the integer
486
487    RETURN VALUE:
488       an exception pointer (in any case -- either it is the newly created
489           exception, or an exception thrown while trying to create it).
490
491 *******************************************************************************/
492
493 java_objectheader *new_exception_int(const char *classname, s4 i)
494 {
495         java_objectheader *o;
496         classinfo         *c;
497    
498         if (!(c = load_class_bootstrap(utf_new_char(classname))))
499                 return *exceptionptr;
500
501         o = native_new_and_init_int(c, i);
502
503         if (!o)
504                 return *exceptionptr;
505
506         return o;
507 }
508
509
510 /* exceptions_new_abstractmethoderror ******************************************
511
512    Generates a java.lang.AbstractMethodError for the VM.
513
514 *******************************************************************************/
515
516 java_objectheader *exceptions_new_abstractmethoderror(void)
517 {
518         java_objectheader *e;
519
520         e = native_new_and_init(class_java_lang_AbstractMethodError);
521
522         if (e == NULL)
523                 return *exceptionptr;
524
525         return e;
526 }
527
528
529 /* exceptions_asm_new_abstractmethoderror **************************************
530
531    Generates a java.lang.AbstractMethodError for
532    asm_abstractmethoderror.
533
534 *******************************************************************************/
535
536 java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
537 {
538         stackframeinfo     sfi;
539         java_objectheader *e;
540
541         /* create the stackframeinfo (XPC is equal to RA) */
542
543         stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
544
545         /* create the exception */
546
547         e = exceptions_new_abstractmethoderror();
548
549         /* remove the stackframeinfo */
550
551         stacktrace_remove_stackframeinfo(&sfi);
552
553         return e;
554 }
555
556
557 /* exceptions_throw_abstractmethoderror ****************************************
558
559    Generates a java.lang.AbstractMethodError for the VM and throws it.
560
561 *******************************************************************************/
562
563 void exceptions_throw_abstractmethoderror(void)
564 {
565         *exceptionptr = exceptions_new_abstractmethoderror();
566 }
567
568
569 /* new_classformaterror ********************************************************
570
571    generates a java.lang.ClassFormatError for the classloader
572
573    IN:
574       c............the class in which the error was found
575           message......UTF-8 format string
576
577    RETURN VALUE:
578       an exception pointer (in any case -- either it is the newly created
579           exception, or an exception thrown while trying to create it).
580
581 *******************************************************************************/
582
583 java_objectheader *new_classformaterror(classinfo *c, const char *message, ...)
584 {
585         java_objectheader *o;
586         char              *msg;
587         s4                 msglen;
588         va_list            ap;
589
590         /* calculate message length */
591
592         msglen = 0;
593
594         if (c)
595                 msglen += utf_bytes(c->name) + strlen(" (");
596
597         va_start(ap, message);
598         msglen += get_variable_message_length(message, ap);
599         va_end(ap);
600
601         if (c)
602                 msglen += strlen(")");
603
604         msglen += strlen("0");
605
606         /* allocate a buffer */
607
608         msg = MNEW(char, msglen);
609
610         /* print message into allocated buffer */
611
612         if (c) {
613                 utf_copy_classname(msg, c->name);
614                 strcat(msg, " (");
615         }
616
617         va_start(ap, message);
618         vsprintf(msg + strlen(msg), message, ap);
619         va_end(ap);
620
621         if (c)
622                 strcat(msg, ")");
623
624         o = new_exception_message(string_java_lang_ClassFormatError, msg);
625
626         MFREE(msg, char, msglen);
627
628         return o;
629 }
630
631
632 /* exceptions_throw_classformaterror *******************************************
633
634    Generate a java.lang.ClassFormatError for the VM system and throw it.
635
636    IN:
637       c............the class in which the error was found
638           message......UTF-8 format string
639
640    RETURN VALUE:
641       an exception pointer (in any case -- either it is the newly created
642           exception, or an exception thrown while trying to create it).
643
644 *******************************************************************************/
645
646 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
647 {
648         va_list ap;
649
650         va_start(ap, message);
651         *exceptionptr = new_classformaterror(c, message, ap);
652         va_end(ap);
653 }
654
655
656 /* new_classnotfoundexception **************************************************
657
658    Generates a java.lang.ClassNotFoundException for the classloader.
659
660    IN:
661       name.........name of the class not found as a utf *
662
663    RETURN VALUE:
664       an exception pointer (in any case -- either it is the newly created
665           exception, or an exception thrown while trying to create it).
666
667 *******************************************************************************/
668
669 java_objectheader *new_classnotfoundexception(utf *name)
670 {
671         java_objectheader *o;
672         java_lang_String  *s;
673
674         s = javastring_new(name);
675         if (!s)
676                 return *exceptionptr;
677
678         o = native_new_and_init_string(class_java_lang_ClassNotFoundException, s);
679
680         if (!o)
681                 return *exceptionptr;
682
683         return o;
684 }
685
686
687 /* new_noclassdeffounderror ****************************************************
688
689    Generates a java.lang.NoClassDefFoundError
690
691    IN:
692       name.........name of the class not found as a utf *
693
694    RETURN VALUE:
695       an exception pointer (in any case -- either it is the newly created
696           exception, or an exception thrown while trying to create it).
697
698 *******************************************************************************/
699
700 java_objectheader *new_noclassdeffounderror(utf *name)
701 {
702         java_objectheader *o;
703         java_lang_String  *s;
704
705         s = javastring_new(name);
706         if (!s)
707                 return *exceptionptr;
708
709         o = native_new_and_init_string(class_java_lang_NoClassDefFoundError, s);
710
711         if (!o)
712                 return *exceptionptr;
713
714         return o;
715 }
716
717
718 /* classnotfoundexception_to_noclassdeffounderror ******************************
719
720    Check the *exceptionptr for a ClassNotFoundException. If it is one,
721    convert it to a NoClassDefFoundError.
722
723 *******************************************************************************/
724
725 void classnotfoundexception_to_noclassdeffounderror(void)
726 {
727         java_objectheader *xptr;
728         java_objectheader *cause;
729
730         /* get the cause */
731
732         cause = *exceptionptr;
733
734         /* convert ClassNotFoundException's to NoClassDefFoundError's */
735
736         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
737                 /* clear exception, because we are calling jit code again */
738
739                 *exceptionptr = NULL;
740
741                 /* create new error */
742
743                 xptr =
744                         new_exception_javastring(string_java_lang_NoClassDefFoundError,
745                                         ((java_lang_Throwable *) cause)->detailMessage);
746
747                 /* we had an exception while creating the error */
748
749                 if (*exceptionptr)
750                         return;
751
752                 /* set new exception */
753
754                 *exceptionptr = xptr;
755         }
756 }
757
758
759 /* new_internalerror ***********************************************************
760
761    Generates a java.lang.InternalError for the VM.
762
763    IN:
764       message......UTF-8 message format string
765
766    RETURN VALUE:
767       an exception pointer (in any case -- either it is the newly created
768           exception, or an exception thrown while trying to create it).
769
770 *******************************************************************************/
771
772 java_objectheader *new_internalerror(const char *message, ...)
773 {
774         java_objectheader *o;
775         va_list            ap;
776         char              *msg;
777         s4                 msglen;
778
779         /* calculate exception message length */
780
781         va_start(ap, message);
782         msglen = get_variable_message_length(message, ap);
783         va_end(ap);
784
785         /* allocate memory */
786
787         msg = MNEW(char, msglen);
788
789         /* generate message */
790
791         va_start(ap, message);
792         vsprintf(msg, message, ap);
793         va_end(ap);
794
795         /* create exception object */
796
797         o = new_exception_message(string_java_lang_InternalError, msg);
798
799         /* free memory */
800
801         MFREE(msg, char, msglen);
802
803         return o;
804 }
805
806
807 /* exceptions_new_linkageerror *************************************************
808
809    Generates a java.lang.LinkageError with an error message.
810
811    IN:
812       message......UTF-8 message
813           c............class related to the error. If this is != NULL
814                        the name of c is appended to the error message.
815
816    RETURN VALUE:
817       an exception pointer (in any case -- either it is the newly created
818           exception, or an exception thrown while trying to create it).
819
820 *******************************************************************************/
821
822 java_objectheader *exceptions_new_linkageerror(const char *message,
823                                                                                            classinfo *c)
824 {
825         java_objectheader *o;
826         char              *msg;
827         s4                 msglen;
828
829         /* calculate exception message length */
830
831         msglen = strlen(message) + 1;
832         if (c) {
833                 msglen += utf_bytes(c->name);
834         }
835                 
836         /* allocate memory */
837
838         msg = MNEW(char, msglen);
839
840         /* generate message */
841
842         strcpy(msg,message);
843         if (c) {
844                 utf_cat_classname(msg, c->name);
845         }
846
847         o = native_new_and_init_string(class_java_lang_LinkageError,
848                                                                    javastring_new_from_utf_string(msg));
849
850         /* free memory */
851
852         MFREE(msg, char, msglen);
853
854         if (!o)
855                 return *exceptionptr;
856
857         return o;
858 }
859
860
861 /* exceptions_new_nosuchmethoderror ********************************************
862
863    Generates a java.lang.NoSuchMethodError with an error message.
864
865    IN:
866       c............class in which the method was not found
867           name.........name of the method
868           desc.........descriptor of the method
869
870    RETURN VALUE:
871       an exception pointer (in any case -- either it is the newly created
872           exception, or an exception thrown while trying to create it).
873
874 *******************************************************************************/
875
876 java_objectheader *exceptions_new_nosuchmethoderror(classinfo *c,
877                                                                                                         utf *name, utf *desc)
878 {
879         java_objectheader *o;
880         char              *msg;
881         s4                 msglen;
882
883         /* calculate exception message length */
884
885         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
886                 utf_bytes(desc) + strlen("0");
887
888         /* allocate memory */
889
890         msg = MNEW(char, msglen);
891
892         /* generate message */
893
894         utf_copy_classname(msg, c->name);
895         strcat(msg, ".");
896         utf_cat(msg, name);
897         utf_cat(msg, desc);
898
899         o = native_new_and_init_string(class_java_lang_NoSuchMethodError,
900                                                                    javastring_new_from_utf_string(msg));
901
902         /* free memory */
903
904         MFREE(msg, char, msglen);
905
906         if (!o)
907                 return *exceptionptr;
908
909         return o;
910 }
911
912
913 /* exceptions_throw_nosuchmethoderror ******************************************
914
915    Generates a java.lang.NoSuchMethodError with an error message.
916
917    IN:
918       c............class in which the method was not found
919           name.........name of the method
920           desc.........descriptor of the method
921
922 *******************************************************************************/
923
924 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
925 {
926         *exceptionptr = exceptions_new_nosuchmethoderror(c, name, desc);
927 }
928
929
930 /* new_unsupportedclassversionerror ********************************************
931
932    Generate a java.lang.UnsupportedClassVersionError for the classloader
933
934    IN:
935       c............class in which the method was not found
936           message......UTF-8 format string
937
938    RETURN VALUE:
939       an exception pointer (in any case -- either it is the newly created
940           exception, or an exception thrown while trying to create it).
941
942 *******************************************************************************/
943
944 java_objectheader *new_unsupportedclassversionerror(classinfo *c, const char *message, ...)
945 {
946         java_objectheader *o;
947         va_list            ap;
948         char              *msg;
949     s4                 msglen;
950
951         /* calculate exception message length */
952
953         msglen = utf_bytes(c->name) + strlen(" (") + strlen(")") + strlen("0");
954
955         va_start(ap, message);
956         msglen += get_variable_message_length(message, ap);
957         va_end(ap);
958
959         /* allocate memory */
960
961         msg = MNEW(char, msglen);
962
963         /* generate message */
964
965         utf_copy_classname(msg, c->name);
966         strcat(msg, " (");
967
968         va_start(ap, message);
969         vsprintf(msg + strlen(msg), message, ap);
970         va_end(ap);
971
972         strcat(msg, ")");
973
974         /* create exception object */
975
976         o = new_exception_message(string_java_lang_UnsupportedClassVersionError,
977                                                           msg);
978
979         /* free memory */
980
981         MFREE(msg, char, msglen);
982
983         return o;
984 }
985
986
987 /* new_verifyerror *************************************************************
988
989    Generates a java.lang.VerifyError for the JIT compiler.
990
991    IN:
992       m............method in which the error was found
993           message......UTF-8 format string
994
995    RETURN VALUE:
996       an exception pointer (in any case -- either it is the newly created
997           exception, or an exception thrown while trying to create it).
998
999 *******************************************************************************/
1000
1001 java_objectheader *new_verifyerror(methodinfo *m, const char *message, ...)
1002 {
1003         java_objectheader *o;
1004         va_list            ap;
1005         char              *msg;
1006         s4                 msglen;
1007
1008         useinlining = false; /* at least until sure inlining works with exceptions*/
1009
1010         /* calculate exception message length */
1011
1012         msglen = 0;
1013
1014         if (m)
1015                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1016                         strlen(", method: ") + utf_bytes(m->name) +
1017                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1018                         strlen(") ") + strlen("0");
1019
1020         va_start(ap, message);
1021         msglen += get_variable_message_length(message, ap);
1022         va_end(ap);
1023
1024         /* allocate memory */
1025
1026         msg = MNEW(char, msglen);
1027
1028         /* generate message */
1029
1030         if (m) {
1031                 strcpy(msg, "(class: ");
1032                 utf_cat_classname(msg, m->class->name);
1033                 strcat(msg, ", method: ");
1034                 utf_cat(msg, m->name);
1035                 strcat(msg, " signature: ");
1036                 utf_cat(msg, m->descriptor);
1037                 strcat(msg, ") ");
1038         }
1039
1040         va_start(ap, message);
1041         vsprintf(msg + strlen(msg), message, ap);
1042         va_end(ap);
1043
1044         /* create exception object */
1045
1046         o = new_exception_message(string_java_lang_VerifyError, msg);
1047
1048         /* free memory */
1049
1050         MFREE(msg, char, msglen);
1051
1052         return o;
1053 }
1054
1055
1056 /* exceptions_throw_verifyerror_for_stack **************************************
1057
1058    throws a java.lang.VerifyError for an invalid stack slot type
1059
1060    IN:
1061       m............method in which the error was found
1062           type.........the expected type
1063
1064    RETURN VALUE:
1065       an exception pointer (in any case -- either it is the newly created
1066           exception, or an exception thrown while trying to create it).
1067
1068 *******************************************************************************/
1069
1070 void exceptions_throw_verifyerror_for_stack(methodinfo *m,int type)
1071 {
1072         java_objectheader *o;
1073         char              *msg;
1074         s4                 msglen;
1075         char              *typename;
1076
1077         /* calculate exception message length */
1078
1079         msglen = 0;
1080
1081         if (m)
1082                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1083                         strlen(", method: ") + utf_bytes(m->name) +
1084                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1085                         strlen(") Expecting to find longest-------typename on stack") 
1086                         + strlen("0");
1087
1088         /* allocate memory */
1089
1090         msg = MNEW(char, msglen);
1091
1092         /* generate message */
1093
1094         if (m) {
1095                 strcpy(msg, "(class: ");
1096                 utf_cat_classname(msg, m->class->name);
1097                 strcat(msg, ", method: ");
1098                 utf_cat(msg, m->name);
1099                 strcat(msg, " signature: ");
1100                 utf_cat(msg, m->descriptor);
1101                 strcat(msg, ") ");
1102         }
1103         else {
1104                 msg[0] = 0;
1105         }
1106
1107         strcat(msg,"Expecting to find ");
1108         switch (type) {
1109                 case TYPE_INT: typename = "integer"; break;
1110                 case TYPE_LNG: typename = "long"; break;
1111                 case TYPE_FLT: typename = "float"; break;
1112                 case TYPE_DBL: typename = "double"; break;
1113                 case TYPE_ADR: typename = "object/array"; break;
1114                 default:       typename = "<INVALID>"; assert(0); break;
1115         }
1116         strcat(msg, typename);
1117         strcat(msg, " on stack");
1118
1119         /* create exception object */
1120
1121         o = new_exception_message(string_java_lang_VerifyError, msg);
1122
1123         /* free memory */
1124
1125         MFREE(msg, char, msglen);
1126
1127         *exceptionptr = o;
1128 }
1129
1130
1131 /* new_arithmeticexception *****************************************************
1132
1133    Generates a java.lang.ArithmeticException for the jit compiler.
1134
1135 *******************************************************************************/
1136
1137 java_objectheader *new_arithmeticexception(void)
1138 {
1139         java_objectheader *e;
1140
1141         e = new_exception_message(string_java_lang_ArithmeticException,
1142                                                           string_java_lang_ArithmeticException_message);
1143
1144         if (!e)
1145                 return *exceptionptr;
1146
1147         return e;
1148 }
1149
1150
1151 /* exceptions_new_arrayindexoutofboundsexception *******************************
1152
1153    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1154    system.
1155
1156 *******************************************************************************/
1157
1158 java_objectheader *new_arrayindexoutofboundsexception(s4 index)
1159 {
1160         java_objectheader *e;
1161         methodinfo        *m;
1162         java_objectheader *o;
1163         java_lang_String  *s;
1164
1165         /* convert the index into a String, like Sun does */
1166
1167         m = class_resolveclassmethod(class_java_lang_String,
1168                                                                  utf_new_char("valueOf"),
1169                                                                  utf_new_char("(I)Ljava/lang/String;"),
1170                                                                  class_java_lang_Object,
1171                                                                  true);
1172
1173         if (m == NULL)
1174                 return *exceptionptr;
1175
1176         o = vm_call_method(m, NULL, index);
1177
1178         s = (java_lang_String *) o;
1179
1180         if (s == NULL)
1181                 return *exceptionptr;
1182
1183         e = new_exception_javastring(string_java_lang_ArrayIndexOutOfBoundsException,
1184                                                                  s);
1185
1186         if (e == NULL)
1187                 return *exceptionptr;
1188
1189         return e;
1190 }
1191
1192
1193 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1194
1195    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1196    system.
1197
1198 *******************************************************************************/
1199
1200 void exceptions_throw_arrayindexoutofboundsexception(void)
1201 {
1202         java_objectheader *e;
1203
1204         e = new_exception(string_java_lang_ArrayIndexOutOfBoundsException);
1205
1206         if (!e)
1207                 return;
1208
1209         *exceptionptr = e;
1210 }
1211
1212
1213 /* new_arraystoreexception *****************************************************
1214
1215    generates a java.lang.ArrayStoreException for the jit compiler
1216
1217 *******************************************************************************/
1218
1219 java_objectheader *new_arraystoreexception(void)
1220 {
1221         java_objectheader *e;
1222
1223         e = new_exception(string_java_lang_ArrayStoreException);
1224 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1225
1226         if (!e)
1227                 return *exceptionptr;
1228
1229         return e;
1230 }
1231
1232
1233 /* exceptions_new_classcastexception *******************************************
1234
1235    Generates a java.lang.ClassCastException for the JIT compiler.
1236
1237 *******************************************************************************/
1238
1239 java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
1240 {
1241         java_objectheader *e;
1242         utf               *classname;
1243         java_lang_String  *s;
1244
1245         classname = o->vftbl->class->name;
1246
1247         s = javastring_new(classname);
1248
1249         e = native_new_and_init_string(class_java_lang_ClassCastException, s);
1250
1251         if (e == NULL)
1252                 return *exceptionptr;
1253
1254         return e;
1255 }
1256
1257
1258 /* exceptions_new_illegalargumentexception *************************************
1259
1260    Generates a java.lang.IllegalArgumentException for the VM system.
1261
1262 *******************************************************************************/
1263
1264 java_objectheader *new_illegalargumentexception(void)
1265 {
1266         java_objectheader *e;
1267
1268         e = native_new_and_init(class_java_lang_IllegalArgumentException);
1269
1270         if (!e)
1271                 return *exceptionptr;
1272
1273         return e;
1274 }
1275
1276
1277 /* exceptions_throw_illegalargumentexception ***********************************
1278
1279    Generates a java.lang.IllegalArgumentException for the VM system
1280    and throw it in the VM system.
1281
1282 *******************************************************************************/
1283
1284 void exceptions_throw_illegalargumentexception(void)
1285 {
1286         *exceptionptr = new_illegalargumentexception();
1287 }
1288
1289
1290 /* new_illegalmonitorstateexception ********************************************
1291
1292    Generates a java.lang.IllegalMonitorStateException for the VM
1293    thread system.
1294
1295 *******************************************************************************/
1296
1297 java_objectheader *new_illegalmonitorstateexception(void)
1298 {
1299         java_objectheader *e;
1300
1301         e = native_new_and_init(class_java_lang_IllegalMonitorStateException);
1302
1303         if (!e)
1304                 return *exceptionptr;
1305
1306         return e;
1307 }
1308
1309
1310 /* exceptions_new_negativearraysizeexception ***********************************
1311
1312    Generates a java.lang.NegativeArraySizeException for the VM system.
1313
1314 *******************************************************************************/
1315
1316 java_objectheader *new_negativearraysizeexception(void)
1317 {
1318         java_objectheader *e;
1319
1320         e = new_exception(string_java_lang_NegativeArraySizeException);
1321
1322         if (!e)
1323                 return *exceptionptr;
1324
1325         return e;
1326 }
1327
1328
1329 /* exceptions_throw_negativearraysizeexception *********************************
1330
1331    Generates a java.lang.NegativeArraySizeException for the VM system.
1332
1333 *******************************************************************************/
1334
1335 void exceptions_throw_negativearraysizeexception(void)
1336 {
1337         *exceptionptr = new_negativearraysizeexception();
1338 }
1339
1340
1341 /* new_nullpointerexception ****************************************************
1342
1343    generates a java.lang.NullPointerException for the jit compiler
1344
1345 *******************************************************************************/
1346
1347 java_objectheader *new_nullpointerexception(void)
1348 {
1349         java_objectheader *e;
1350
1351         e = native_new_and_init(class_java_lang_NullPointerException);
1352
1353         if (!e)
1354                 return *exceptionptr;
1355
1356         return e;
1357 }
1358
1359
1360 /* exceptions_throw_nullpointerexception ***************************************
1361
1362    Generates a java.lang.NullPointerException for the VM system and
1363    throw it in the VM system.
1364
1365 *******************************************************************************/
1366
1367 void exceptions_throw_nullpointerexception(void)
1368 {
1369         *exceptionptr = new_nullpointerexception();
1370 }
1371
1372
1373 /* exceptions_new_stringindexoutofboundsexception ******************************
1374
1375    Generates a java.lang.StringIndexOutOfBoundsException for the VM
1376    system.
1377
1378 *******************************************************************************/
1379
1380 java_objectheader *exceptions_new_stringindexoutofboundsexception(void)
1381 {
1382         java_objectheader *e;
1383
1384         e = new_exception(string_java_lang_StringIndexOutOfBoundsException);
1385
1386         if (e == NULL)
1387                 return *exceptionptr;
1388
1389         return e;
1390 }
1391
1392
1393 /* exceptions_throw_stringindexoutofboundsexception ****************************
1394
1395    Throws a java.lang.StringIndexOutOfBoundsException for the VM
1396    system.
1397
1398 *******************************************************************************/
1399
1400 void exceptions_throw_stringindexoutofboundsexception(void)
1401 {
1402         *exceptionptr = exceptions_new_stringindexoutofboundsexception();
1403 }
1404
1405
1406 /* exceptions_get_and_clear_exception ******************************************
1407
1408    Gets the exception pointer of the current thread and clears it.
1409    This function may return NULL.
1410
1411 *******************************************************************************/
1412
1413 java_objectheader *exceptions_get_and_clear_exception(void)
1414 {
1415         java_objectheader **p;
1416         java_objectheader  *e;
1417
1418         /* get the pointer of the exception pointer */
1419
1420         p = exceptionptr;
1421
1422         /* get the exception */
1423
1424         e = *p;
1425
1426         /* and clear the exception */
1427
1428         *p = NULL;
1429
1430         /* return the exception */
1431
1432         return e;
1433 }
1434
1435
1436 /* exceptions_handle_exception *************************************************
1437
1438    Try to find an exception handler for the given exception and return it.
1439    If no handler is found, exit the monitor of the method (if any)
1440    and return NULL.
1441
1442    IN:
1443       xptr.........the exception object
1444           xpc..........PC of where the exception was thrown
1445           pv...........Procedure Value of the current method
1446           sp...........current stack pointer
1447
1448    RETURN VALUE:
1449       the address of the first matching exception handler, or
1450           NULL if no handler was found
1451
1452 *******************************************************************************/
1453
1454 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1455 {
1456         methodinfo            *m;
1457         codeinfo              *code;
1458         s4                     framesize;
1459         s4                     issync;
1460         exceptionentry        *ex;
1461         s4                     exceptiontablelength;
1462         s4                     i;
1463         classref_or_classinfo  cr;
1464         classinfo             *c;
1465 #if defined(ENABLE_THREADS)
1466         java_objectheader     *o;
1467 #endif
1468
1469         /* get info from the method header */
1470
1471         code                 = *((codeinfo **)      (pv + CodeinfoPointer));
1472         framesize            = *((s4 *)             (pv + FrameSize));
1473         issync               = *((s4 *)             (pv + IsSync));
1474         ex                   =   (exceptionentry *) (pv + ExTableStart);
1475         exceptiontablelength = *((s4 *)             (pv + ExTableSize));
1476
1477         /* Get the methodinfo pointer from the codeinfo pointer. For
1478            asm_vm_call_method the codeinfo pointer is NULL. */
1479
1480         m = (code == NULL) ? NULL : code->m;
1481
1482 #if !defined(NDEBUG)
1483         /* print exception trace */
1484
1485         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1486                 builtin_trace_exception(xptr, m, xpc, 1);
1487 #endif
1488
1489         for (i = 0; i < exceptiontablelength; i++) {
1490                 /* ATTENTION: keep this here, as we need to decrement the
1491            pointer before the loop executes! */
1492
1493                 ex--;
1494
1495                 /* If the start and end PC is NULL, this means we have the
1496                    special case of asm_vm_call_method.  So, just return the
1497                    proper exception handler. */
1498
1499                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1500                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1501
1502                 /* is the xpc is the current catch range */
1503
1504                 if ((ex->startpc <= xpc) && (xpc < ex->endpc)) {
1505                         cr = ex->catchtype;
1506
1507                         /* NULL catches everything */
1508
1509                         if (cr.any == NULL) {
1510 #if !defined(NDEBUG)
1511                                 /* Print stacktrace of exception when caught. */
1512
1513                                 if (opt_verboseexception) {
1514                                         exceptions_print_exception(xptr);
1515                                         stacktrace_print_trace(xptr);
1516                                 }
1517 #endif
1518
1519                                 return ex->handlerpc;
1520                         }
1521
1522                         /* resolve or load/link the exception class */
1523
1524                         if (IS_CLASSREF(cr)) {
1525                                 c = resolve_classref_eager(cr.ref);
1526
1527                         } else {
1528                                 c = cr.cls;
1529
1530                                 if (!(c->state & CLASS_LOADED))
1531                                         /* use the methods' classloader */
1532                                         if (!load_class_from_classloader(c->name,
1533                                                                                                          m->class->classloader))
1534                                                 return NULL;
1535
1536                                 if (!(c->state & CLASS_LINKED))
1537                                         if (!link_class(c))
1538                                                 return NULL;
1539                         }
1540
1541                         /* is the thrown exception an instance of the catch class? */
1542
1543                         if (builtin_instanceof(xptr, c)) {
1544 #if !defined(NDEBUG)
1545                                 /* Print stacktrace of exception when caught. */
1546
1547                                 if (opt_verboseexception) {
1548                                         exceptions_print_exception(xptr);
1549                                         stacktrace_print_trace(xptr);
1550                                 }
1551 #endif
1552
1553                                 return ex->handlerpc;
1554                         }
1555                 }
1556         }
1557
1558 #if defined(ENABLE_THREADS)
1559         /* is this method synchronized? */
1560
1561         if (issync) {
1562                 /* get synchronization object */
1563
1564 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1565                 /* XXX change this if we ever want to use 4-byte stackslots */
1566                 o = *((java_objectheader **) (sp + issync - 8));
1567 # else
1568                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1569 #endif
1570
1571                 assert(o != NULL);
1572
1573                 builtin_monitorexit(o);
1574         }
1575 #endif
1576
1577         /* none of the exceptions catch this one */
1578
1579         return NULL;
1580 }
1581
1582
1583 /* exceptions_print_exception **************************************************
1584
1585    Prints an exception, the detail message and the cause, if
1586    available, with CACAO internal functions to stdout.
1587
1588 *******************************************************************************/
1589
1590 #if !defined(NDEBUG)
1591 void exceptions_print_exception(java_objectheader *xptr)
1592 {
1593         java_lang_Throwable   *t;
1594         java_lang_Throwable   *cause;
1595         utf                   *u;
1596
1597         t = (java_lang_Throwable *) xptr;
1598
1599         if (t == NULL) {
1600                 puts("NULL\n");
1601                 return;
1602         }
1603
1604         cause = t->cause;
1605
1606         /* print the root exception */
1607
1608         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1609
1610         if (t->detailMessage) {
1611                 u = javastring_toutf(t->detailMessage, false);
1612
1613                 printf(": ");
1614                 utf_display_printable_ascii(u);
1615         }
1616
1617         putc('\n', stdout);
1618
1619         /* print the cause if available */
1620
1621         if (cause && (cause != t)) {
1622                 printf("Caused by: ");
1623                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1624
1625                 if (cause->detailMessage) {
1626                         u = javastring_toutf(cause->detailMessage, false);
1627
1628                         printf(": ");
1629                         utf_display_printable_ascii(u);
1630                 }
1631
1632                 putc('\n', stdout);
1633         }
1634 }
1635 #endif /* !defined(NDEBUG) */
1636
1637
1638 /*
1639  * These are local overrides for various environment variables in Emacs.
1640  * Please do not remove this and leave it at the end of the file, where
1641  * Emacs will automagically detect them.
1642  * ---------------------------------------------------------------------
1643  * Local variables:
1644  * mode: c
1645  * indent-tabs-mode: t
1646  * c-basic-offset: 4
1647  * tab-width: 4
1648  * End:
1649  * vim:noexpandtab:sw=4:ts=4:
1650  */