Merged revisions 8034-8055 via svnmerge from
[cacao.git] / src / vm / exceptions.c
1 /* src/vm/exceptions.c - exception related functions
2
3    Copyright (C) 1996-2005, 2006, 2007 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    $Id: exceptions.c 8056 2007-06-10 14:49:57Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <string.h>
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/mman.h>
38
39 #include "vm/types.h"
40
41 #include "md-abi.h"
42
43 #include "mm/memory.h"
44
45 #include "native/jni.h"
46 #include "native/native.h"
47 #include "native/include/java_lang_String.h"
48 #include "native/include/java_lang_Throwable.h"
49
50 #include "threads/lock-common.h"
51 #include "threads/threads-common.h"
52
53 #include "toolbox/logging.h"
54 #include "toolbox/util.h"
55
56 #include "vm/builtin.h"
57 #include "vm/exceptions.h"
58 #include "vm/global.h"
59 #include "vm/stringlocal.h"
60 #include "vm/vm.h"
61
62 #include "vm/jit/asmpart.h"
63 #include "vm/jit/disass.h"
64 #include "vm/jit/jit.h"
65 #include "vm/jit/methodheader.h"
66 #include "vm/jit/stacktrace.h"
67
68 #include "vmcore/class.h"
69 #include "vmcore/loader.h"
70 #include "vmcore/options.h"
71
72 #if defined(ENABLE_VMLOG)
73 #include <vmlog_cacao.h>
74 #endif
75
76
77 /* for raising exceptions from native methods *********************************/
78
79 #if !defined(ENABLE_THREADS)
80 java_objectheader *_no_threads_exceptionptr = NULL;
81 #endif
82
83
84 /* init_system_exceptions ******************************************************
85
86    Load and link exceptions used in the system.
87
88 *******************************************************************************/
89
90 bool exceptions_init(void)
91 {
92         int pagesize;
93
94         /* mmap a memory page at address 0x0, so our hardware-exceptions
95            work. */
96
97         pagesize = getpagesize();
98
99         (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
100
101         /* check if we get into trouble with our hardware-exceptions */
102
103         if (OFFSET(java_bytearray, data) <= EXCEPTION_HARDWARE_PATCHER)
104                 vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray, data), EXCEPTION_HARDWARE_PATCHER);
105
106         /* java/lang/Throwable */
107
108         if (!(class_java_lang_Throwable =
109                   load_class_bootstrap(utf_java_lang_Throwable)) ||
110                 !link_class(class_java_lang_Throwable))
111                 return false;
112
113         /* java/lang/Error */
114
115         if (!(class_java_lang_Error = load_class_bootstrap(utf_java_lang_Error)) ||
116                 !link_class(class_java_lang_Error))
117                 return false;
118
119 #if defined(ENABLE_JAVASE)
120         /* java/lang/LinkageError */
121
122         if (!(class_java_lang_LinkageError =
123                   load_class_bootstrap(utf_java_lang_LinkageError)) ||
124                 !link_class(class_java_lang_LinkageError))
125                 return false;
126 #endif
127
128         /* java/lang/NoClassDefFoundError */
129
130         if (!(class_java_lang_NoClassDefFoundError =
131                   load_class_bootstrap(utf_java_lang_NoClassDefFoundError)) ||
132                 !link_class(class_java_lang_NoClassDefFoundError))
133                 return false;
134
135         /* java/lang/OutOfMemoryError */
136
137         if (!(class_java_lang_OutOfMemoryError =
138                   load_class_bootstrap(utf_java_lang_OutOfMemoryError)) ||
139                 !link_class(class_java_lang_OutOfMemoryError))
140                 return false;
141
142         /* java/lang/VirtualMachineError */
143
144         if (!(class_java_lang_VirtualMachineError =
145                   load_class_bootstrap(utf_java_lang_VirtualMachineError)) ||
146                 !link_class(class_java_lang_VirtualMachineError))
147                 return false;
148
149
150         /* java/lang/Exception */
151
152         if (!(class_java_lang_Exception =
153                   load_class_bootstrap(utf_java_lang_Exception)) ||
154                 !link_class(class_java_lang_Exception))
155                 return false;
156
157         /* java/lang/ClassCastException */
158
159         if (!(class_java_lang_ClassCastException =
160                   load_class_bootstrap(utf_java_lang_ClassCastException)) ||
161                 !link_class(class_java_lang_ClassCastException))
162                 return false;
163
164         /* java/lang/ClassNotFoundException */
165
166         if (!(class_java_lang_ClassNotFoundException =
167                   load_class_bootstrap(utf_java_lang_ClassNotFoundException)) ||
168                 !link_class(class_java_lang_ClassNotFoundException))
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 #if defined(WITH_CLASSPATH_GNU)
180         /* java/lang/VMThrowable */
181
182         if (!(class_java_lang_VMThrowable =
183                   load_class_bootstrap(utf_java_lang_VMThrowable)) ||
184                 !link_class(class_java_lang_VMThrowable))
185                 return false;
186 #endif
187
188         return true;
189 }
190
191
192 /* exceptions_new_class ********************************************************
193
194    Creates an exception object from the given class and initalizes it.
195
196    IN:
197       class....class pointer
198
199 *******************************************************************************/
200
201 static java_objectheader *exceptions_new_class(classinfo *c)
202 {
203         java_objectheader *o;
204
205         o = native_new_and_init(c);
206
207         if (o == NULL)
208                 return *exceptionptr;
209
210         return o;
211 }
212
213
214 /* exceptions_new_utf **********************************************************
215
216    Creates an exception object with the given name and initalizes it.
217
218    IN:
219       classname....class name in UTF-8
220
221 *******************************************************************************/
222
223 static java_objectheader *exceptions_new_utf(utf *classname)
224 {
225         classinfo         *c;
226         java_objectheader *o;
227
228         c = load_class_bootstrap(classname);
229
230         if (c == NULL)
231                 return *exceptionptr;
232
233         o = exceptions_new_class(c);
234
235         return o;
236 }
237
238
239 /* exceptions_throw_class ******************************************************
240
241    Creates an exception object from the given class, initalizes and
242    throws it.
243
244    IN:
245       class....class pointer
246
247 *******************************************************************************/
248
249 static void exceptions_throw_class(classinfo *c)
250 {
251         java_objectheader *o;
252
253         o = exceptions_new_class(c);
254
255         if (o == NULL)
256                 return;
257
258         *exceptionptr = o;
259 }
260
261
262 /* exceptions_throw_utf ********************************************************
263
264    Creates an exception object with the given name, initalizes and
265    throws it.
266
267    IN:
268       classname....class name in UTF-8
269
270 *******************************************************************************/
271
272 static void exceptions_throw_utf(utf *classname)
273 {
274         classinfo *c;
275
276         c = load_class_bootstrap(classname);
277
278         if (c == NULL)
279                 return;
280
281         exceptions_throw_class(c);
282 }
283
284
285 /* exceptions_throw_utf_throwable **********************************************
286
287    Creates an exception object with the given name and initalizes it
288    with the given java/lang/Throwable exception.
289
290    IN:
291       classname....class name in UTF-8
292           cause........the given Throwable
293
294 *******************************************************************************/
295
296 static void exceptions_throw_utf_throwable(utf *classname,
297                                                                                    java_objectheader *cause)
298 {
299         java_objectheader *o;
300         classinfo         *c;
301    
302         c = load_class_bootstrap(classname);
303
304         if (c == NULL)
305                 return;
306
307         o = native_new_and_init_throwable(c, cause);
308
309         if (o == NULL)
310                 return;
311
312         *exceptionptr = o;
313 }
314
315
316 /* exceptions_throw_utf_exception **********************************************
317
318    Creates an exception object with the given name and initalizes it
319    with the given java/lang/Exception exception.
320
321    IN:
322       classname....class name in UTF-8
323           exception....the given Exception
324
325 *******************************************************************************/
326
327 static void exceptions_throw_utf_exception(utf *classname,
328                                                                                    java_objectheader *exception)
329 {
330         java_objectheader *o;
331         classinfo         *c;
332    
333         c = load_class_bootstrap(classname);
334
335         if (c == NULL)
336                 return;
337
338         o = native_new_and_init_exception(c, exception);
339
340         if (o == NULL)
341                 return;
342
343         *exceptionptr = o;
344 }
345
346
347 /* exceptions_new_utf_javastring ***********************************************
348
349    Creates an exception object with the given name and initalizes it
350    with the given java/lang/String message.
351
352    IN:
353       classname....class name in UTF-8
354           message......the message as a java.lang.String
355
356    RETURN VALUE:
357       an exception pointer (in any case -- either it is the newly created
358           exception, or an exception thrown while trying to create it).
359
360 *******************************************************************************/
361
362 static java_objectheader *exceptions_new_utf_javastring(utf *classname,
363                                                                                                                 java_objectheader *message)
364 {
365         java_objectheader *o;
366         classinfo         *c;
367    
368         c = load_class_bootstrap(classname);
369
370         if (c == NULL)
371                 return *exceptionptr;
372
373         o = native_new_and_init_string(c, message);
374
375         if (o == NULL)
376                 return *exceptionptr;
377
378         return o;
379 }
380
381
382 /* exceptions_new_class_utf ****************************************************
383
384    Creates an exception object of the given class and initalizes it.
385
386    IN:
387       c..........class pointer
388       message....the message as UTF-8 string
389
390 *******************************************************************************/
391
392 static java_objectheader *exceptions_new_class_utf(classinfo *c, utf *message)
393 {
394         java_objectheader *o;
395         java_objectheader *s;
396
397         s = javastring_new(message);
398
399         if (s == NULL)
400                 return *exceptionptr;
401
402         o = native_new_and_init_string(c, s);
403
404         if (o == NULL)
405                 return *exceptionptr;
406
407         return o;
408 }
409
410
411 /* exceptions_new_utf_utf ******************************************************
412
413    Creates an exception object with the given name and initalizes it
414    with the given utf message.
415
416    IN:
417       classname....class name in UTF-8
418           message......the message as an utf *
419
420    RETURN VALUE:
421       an exception pointer (in any case -- either it is the newly created
422           exception, or an exception thrown while trying to create it).
423
424 *******************************************************************************/
425
426 static java_objectheader *exceptions_new_utf_utf(utf *classname, utf *message)
427 {
428         classinfo         *c;
429         java_objectheader *o;
430
431         c = load_class_bootstrap(classname);
432
433         if (c == NULL)
434                 return *exceptionptr;
435
436         o = exceptions_new_class_utf(c, message);
437
438         return o;
439 }
440
441
442 /* exceptions_throw_class_utf **************************************************
443
444    Creates an exception object of the given class, initalizes and
445    throws it with the given utf message.
446
447    IN:
448       c..........class pointer
449           message....the message as an UTF-8
450
451 *******************************************************************************/
452
453 static void exceptions_throw_class_utf(classinfo *c, utf *message)
454 {
455         *exceptionptr = exceptions_new_class_utf(c, message);
456 }
457
458
459 /* exceptions_throw_utf_utf ****************************************************
460
461    Creates an exception object with the given name, initalizes and
462    throws it with the given utf message.
463
464    IN:
465       classname....class name in UTF-8
466           message......the message as an utf *
467
468 *******************************************************************************/
469
470 static void exceptions_throw_utf_utf(utf *classname, utf *message)
471 {
472         *exceptionptr = exceptions_new_utf_utf(classname, message);
473 }
474
475
476 /* exceptions_new_abstractmethoderror ****************************************
477
478    Generates a java.lang.AbstractMethodError for the VM.
479
480 *******************************************************************************/
481
482 java_objectheader *exceptions_new_abstractmethoderror(void)
483 {
484         java_objectheader *o;
485
486         o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
487
488         return o;
489 }
490
491
492 /* exceptions_new_error ********************************************************
493
494    Generates a java.lang.Error for the VM.
495
496 *******************************************************************************/
497
498 #if defined(ENABLE_JAVAME_CLDC1_1)
499 static java_objectheader *exceptions_new_error(utf *message)
500 {
501         java_objectheader *o;
502
503         o = exceptions_new_class_utf(class_java_lang_Error, message);
504
505         return o;
506 }
507 #endif
508
509
510 /* exceptions_asm_new_abstractmethoderror **************************************
511
512    Generates a java.lang.AbstractMethodError for
513    asm_abstractmethoderror.
514
515 *******************************************************************************/
516
517 java_objectheader *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
518 {
519         stackframeinfo     sfi;
520         java_objectheader *e;
521
522         /* create the stackframeinfo (XPC is equal to RA) */
523
524         stacktrace_create_extern_stackframeinfo(&sfi, NULL, sp, ra, ra);
525
526         /* create the exception */
527
528 #if defined(ENABLE_JAVASE)
529         e = exceptions_new_abstractmethoderror();
530 #else
531         e = exceptions_new_error(utf_java_lang_AbstractMethodError);
532 #endif
533
534         /* remove the stackframeinfo */
535
536         stacktrace_remove_stackframeinfo(&sfi);
537
538         return e;
539 }
540
541
542 /* exceptions_new_arraystoreexception ******************************************
543
544    Generates a java.lang.ArrayStoreException for the VM.
545
546 *******************************************************************************/
547
548 java_objectheader *exceptions_new_arraystoreexception(void)
549 {
550         java_objectheader *o;
551
552         o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
553
554         return o;
555 }
556
557
558 /* exceptions_throw_abstractmethoderror ****************************************
559
560    Generates and throws a java.lang.AbstractMethodError for the VM.
561
562 *******************************************************************************/
563
564 void exceptions_throw_abstractmethoderror(void)
565 {
566         exceptions_throw_utf(utf_java_lang_AbstractMethodError);
567 }
568
569
570 /* exceptions_throw_classcircularityerror **************************************
571
572    Generates and throws a java.lang.ClassCircularityError for the
573    classloader.
574
575    IN:
576       c....the class in which the error was found
577
578 *******************************************************************************/
579
580 void exceptions_throw_classcircularityerror(classinfo *c)
581 {
582         exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
583 }
584
585
586 /* exceptions_throw_classformaterror *******************************************
587
588    Generates and throws a java.lang.ClassFormatError for the VM.
589
590    IN:
591       c............the class in which the error was found
592           message......UTF-8 format string
593
594 *******************************************************************************/
595
596 void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
597 {
598         char    *msg;
599         s4       msglen;
600         va_list  ap;
601         utf     *u;
602
603         /* calculate message length */
604
605         msglen = 0;
606
607         if (c != NULL)
608                 msglen += utf_bytes(c->name) + strlen(" (");
609
610         va_start(ap, message);
611         msglen += get_variable_message_length(message, ap);
612         va_end(ap);
613
614         if (c != NULL)
615                 msglen += strlen(")");
616
617         msglen += strlen("0");
618
619         /* allocate a buffer */
620
621         msg = MNEW(char, msglen);
622
623         /* print message into allocated buffer */
624
625         if (c != NULL) {
626                 utf_copy_classname(msg, c->name);
627                 strcat(msg, " (");
628         }
629
630         va_start(ap, message);
631         vsprintf(msg + strlen(msg), message, ap);
632         va_end(ap);
633
634         if (c != NULL)
635                 strcat(msg, ")");
636
637         u = utf_new_char(msg);
638
639         /* free memory */
640
641         MFREE(msg, char, msglen);
642
643         /* throw exception */
644
645         exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
646 }
647
648
649 /* exceptions_throw_classnotfoundexception *************************************
650
651    Generates and throws a java.lang.ClassNotFoundException for the
652    VM.
653
654    IN:
655       name.........name of the class not found as a utf *
656
657 *******************************************************************************/
658
659 void exceptions_throw_classnotfoundexception(utf *name)
660 {
661         /* we use class here, as this one is rather frequent */
662
663         exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
664 }
665
666
667 /* exceptions_throw_noclassdeffounderror ***************************************
668
669    Generates and throws a java.lang.NoClassDefFoundError.
670
671    IN:
672       name.........name of the class not found as a utf *
673
674 *******************************************************************************/
675
676 void exceptions_throw_noclassdeffounderror(utf *name)
677 {
678         if (vm_initializing)
679                 vm_abort("java.lang.NoClassDefFoundError: %s", name->text);
680
681         exceptions_throw_class_utf(class_java_lang_NoClassDefFoundError, name);
682 }
683
684
685 /* exceptions_throw_noclassdeffounderror_wrong_name ****************************
686
687    Generates and throws a java.lang.NoClassDefFoundError with a
688    specific message:
689
690
691
692    IN:
693       name.........name of the class not found as a utf *
694
695 *******************************************************************************/
696
697 void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
698 {
699         char *msg;
700         s4    msglen;
701         utf  *u;
702
703         msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
704                 utf_bytes(name) + strlen(")") + strlen("0");
705
706         msg = MNEW(char, msglen);
707
708         utf_copy_classname(msg, c->name);
709         strcat(msg, " (wrong name: ");
710         utf_cat_classname(msg, name);
711         strcat(msg, ")");
712
713         u = utf_new_char(msg);
714
715         MFREE(msg, char, msglen);
716
717         exceptions_throw_noclassdeffounderror(u);
718 }
719
720
721 /* classnotfoundexception_to_noclassdeffounderror ******************************
722
723    Check the *exceptionptr for a ClassNotFoundException. If it is one,
724    convert it to a NoClassDefFoundError.
725
726 *******************************************************************************/
727
728 void classnotfoundexception_to_noclassdeffounderror(void)
729 {
730         java_objectheader   *xptr;
731         java_objectheader   *cause;
732         java_lang_Throwable *t;
733         java_objectheader   *s;
734
735         /* get the cause */
736
737         cause = *exceptionptr;
738
739         /* convert ClassNotFoundException's to NoClassDefFoundError's */
740
741         if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
742                 /* clear exception, because we are calling jit code again */
743
744                 *exceptionptr = NULL;
745
746                 /* create new error */
747
748                 t = (java_lang_Throwable *) cause;
749                 s = (java_objectheader *) t->detailMessage;
750
751                 xptr = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
752                                                                                          s);
753
754                 /* we had an exception while creating the error */
755
756                 if (*exceptionptr)
757                         return;
758
759                 /* set new exception */
760
761                 *exceptionptr = xptr;
762         }
763 }
764
765
766 /* exceptions_throw_exceptionininitializererror ********************************
767
768    Generates and throws a java.lang.ExceptionInInitializerError for
769    the VM.
770
771    IN:
772       cause......cause exception object
773
774 *******************************************************************************/
775
776 void exceptions_throw_exceptionininitializererror(java_objectheader *cause)
777 {
778         exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
779                                                                    cause);
780 }
781
782
783 /* exceptions_throw_incompatibleclasschangeerror *******************************
784
785    Generates and throws a java.lang.IncompatibleClassChangeError for
786    the VM.
787
788    IN:
789       message......UTF-8 message format string
790
791 *******************************************************************************/
792
793 void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
794 {
795         char *msg;
796         s4    msglen;
797         utf  *u;
798
799         /* calculate exception message length */
800
801         msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
802
803         /* allocate memory */
804
805         msg = MNEW(char, msglen);
806
807         utf_copy_classname(msg, c->name);
808         strcat(msg, message);
809
810         u = utf_new_char(msg);
811
812         /* free memory */
813
814         MFREE(msg, char, msglen);
815
816         /* throw exception */
817
818         exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
819 }
820
821
822 /* exceptions_throw_instantiationerror *****************************************
823
824    Generates and throws a java.lang.InstantiationError for the VM.
825
826 *******************************************************************************/
827
828 void exceptions_throw_instantiationerror(classinfo *c)
829 {
830         exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
831 }
832
833
834 /* exceptions_throw_internalerror **********************************************
835
836    Generates and throws a java.lang.InternalError for the VM.
837
838    IN:
839       message......UTF-8 message format string
840
841 *******************************************************************************/
842
843 void exceptions_throw_internalerror(const char *message, ...)
844 {
845         va_list  ap;
846         char    *msg;
847         s4       msglen;
848         utf     *u;
849
850         /* calculate exception message length */
851
852         va_start(ap, message);
853         msglen = get_variable_message_length(message, ap);
854         va_end(ap);
855
856         /* allocate memory */
857
858         msg = MNEW(char, msglen);
859
860         /* generate message */
861
862         va_start(ap, message);
863         vsprintf(msg, message, ap);
864         va_end(ap);
865
866         u = utf_new_char(msg);
867
868         /* free memory */
869
870         MFREE(msg, char, msglen);
871
872         /* throw exception */
873
874         exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
875 }
876
877
878 /* exceptions_throw_linkageerror ***********************************************
879
880    Generates and throws java.lang.LinkageError with an error message.
881
882    IN:
883       message......UTF-8 message
884           c............class related to the error. If this is != NULL
885                        the name of c is appended to the error message.
886
887 *******************************************************************************/
888
889 void exceptions_throw_linkageerror(const char *message, classinfo *c)
890 {
891         java_objectheader *o;
892         char              *msg;
893         s4                 msglen;
894
895         /* calculate exception message length */
896
897         msglen = strlen(message) + 1;
898
899         if (c != NULL)
900                 msglen += utf_bytes(c->name);
901                 
902         /* allocate memory */
903
904         msg = MNEW(char, msglen);
905
906         /* generate message */
907
908         strcpy(msg,message);
909
910         if (c != NULL)
911                 utf_cat_classname(msg, c->name);
912
913         o = native_new_and_init_string(class_java_lang_LinkageError,
914                                                                    javastring_new_from_utf_string(msg));
915
916         /* free memory */
917
918         MFREE(msg, char, msglen);
919
920         if (o == NULL)
921                 return;
922
923         *exceptionptr = o;
924 }
925
926
927 /* exceptions_throw_nosuchfielderror *******************************************
928
929    Generates and throws a java.lang.NoSuchFieldError with an error
930    message.
931
932    IN:
933       c............class in which the field was not found
934           name.........name of the field
935
936 *******************************************************************************/
937
938 void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
939 {
940         char *msg;
941         s4    msglen;
942         utf  *u;
943
944         /* calculate exception message length */
945
946         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
947
948         /* allocate memory */
949
950         msg = MNEW(char, msglen);
951
952         /* generate message */
953
954         utf_copy_classname(msg, c->name);
955         strcat(msg, ".");
956         utf_cat(msg, name);
957
958         u = utf_new_char(msg);
959
960         /* free memory */
961
962         MFREE(msg, char, msglen);
963
964         exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
965 }
966
967
968 /* exceptions_throw_nosuchmethoderror ******************************************
969
970    Generates and throws a java.lang.NoSuchMethodError with an error
971    message.
972
973    IN:
974       c............class in which the method was not found
975           name.........name of the method
976           desc.........descriptor of the method
977
978 *******************************************************************************/
979
980 void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
981 {
982         char *msg;
983         s4    msglen;
984         utf  *u;
985
986         /* calculate exception message length */
987
988         msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
989                 utf_bytes(desc) + strlen("0");
990
991         /* allocate memory */
992
993         msg = MNEW(char, msglen);
994
995         /* generate message */
996
997         utf_copy_classname(msg, c->name);
998         strcat(msg, ".");
999         utf_cat(msg, name);
1000         utf_cat(msg, desc);
1001
1002         u = utf_new_char(msg);
1003
1004         /* free memory */
1005
1006         MFREE(msg, char, msglen);
1007
1008 #if defined(ENABLE_JAVASE)
1009         exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
1010 #else
1011         exceptions_throw_class_utf(class_java_lang_Error, u);
1012 #endif
1013 }
1014
1015
1016 /* exceptions_throw_outofmemoryerror *******************************************
1017
1018    Generates and throws an java.lang.OutOfMemoryError for the VM.
1019
1020 *******************************************************************************/
1021
1022 void exceptions_throw_outofmemoryerror(void)
1023 {
1024         exceptions_throw_class(class_java_lang_OutOfMemoryError);
1025 }
1026
1027
1028 /* exceptions_throw_unsatisfiedlinkerror ***************************************
1029
1030    Generates and throws a java.lang.UnsatisfiedLinkError for the
1031    classloader.
1032
1033    IN:
1034           name......UTF-8 name string
1035
1036 *******************************************************************************/
1037
1038 void exceptions_throw_unsatisfiedlinkerror(utf *name)
1039 {
1040 #if defined(ENABLE_JAVASE)
1041         exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
1042 #else
1043         exceptions_throw_class_utf(class_java_lang_Error, name);
1044 #endif
1045 }
1046
1047
1048 /* exceptions_throw_unsupportedclassversionerror *******************************
1049
1050    Generates and throws a java.lang.UnsupportedClassVersionError for
1051    the classloader.
1052
1053    IN:
1054       c............class in which the method was not found
1055           message......UTF-8 format string
1056
1057 *******************************************************************************/
1058
1059 void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
1060 {
1061         char *msg;
1062     s4    msglen;
1063         utf  *u;
1064
1065         /* calculate exception message length */
1066
1067         msglen =
1068                 utf_bytes(c->name) +
1069                 strlen(" (Unsupported major.minor version 00.0)") +
1070                 strlen("0");
1071
1072         /* allocate memory */
1073
1074         msg = MNEW(char, msglen);
1075
1076         /* generate message */
1077
1078         utf_copy_classname(msg, c->name);
1079         sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
1080                         ma, mi);
1081
1082         u = utf_new_char(msg);
1083
1084         /* free memory */
1085
1086         MFREE(msg, char, msglen);
1087
1088         /* throw exception */
1089
1090         exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
1091 }
1092
1093
1094 /* exceptions_throw_verifyerror ************************************************
1095
1096    Generates and throws a java.lang.VerifyError for the JIT compiler.
1097
1098    IN:
1099       m............method in which the error was found
1100           message......UTF-8 format string
1101
1102 *******************************************************************************/
1103
1104 void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
1105 {
1106         va_list  ap;
1107         char    *msg;
1108         s4       msglen;
1109         utf     *u;
1110
1111         /* calculate exception message length */
1112
1113         msglen = 0;
1114
1115         if (m != NULL)
1116                 msglen =
1117                         strlen("(class: ") + utf_bytes(m->class->name) +
1118                         strlen(", method: ") + utf_bytes(m->name) +
1119                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1120                         strlen(") ") + strlen("0");
1121
1122         va_start(ap, message);
1123         msglen += get_variable_message_length(message, ap);
1124         va_end(ap);
1125
1126         /* allocate memory */
1127
1128         msg = MNEW(char, msglen);
1129
1130         /* generate message */
1131
1132         if (m != NULL) {
1133                 strcpy(msg, "(class: ");
1134                 utf_cat_classname(msg, m->class->name);
1135                 strcat(msg, ", method: ");
1136                 utf_cat(msg, m->name);
1137                 strcat(msg, " signature: ");
1138                 utf_cat(msg, m->descriptor);
1139                 strcat(msg, ") ");
1140         }
1141
1142         va_start(ap, message);
1143         vsprintf(msg + strlen(msg), message, ap);
1144         va_end(ap);
1145
1146         u = utf_new_char(msg);
1147
1148         /* free memory */
1149
1150         MFREE(msg, char, msglen);
1151
1152         /* throw exception */
1153
1154         exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
1155 }
1156
1157
1158 /* exceptions_throw_verifyerror_for_stack **************************************
1159
1160    throws a java.lang.VerifyError for an invalid stack slot type
1161
1162    IN:
1163       m............method in which the error was found
1164           type.........the expected type
1165
1166    RETURN VALUE:
1167       an exception pointer (in any case -- either it is the newly created
1168           exception, or an exception thrown while trying to create it).
1169
1170 *******************************************************************************/
1171
1172 void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
1173 {
1174         char *msg;
1175         s4    msglen;
1176         char *typename;
1177         utf  *u;
1178
1179         /* calculate exception message length */
1180
1181         msglen = 0;
1182
1183         if (m != NULL)
1184                 msglen = strlen("(class: ") + utf_bytes(m->class->name) +
1185                         strlen(", method: ") + utf_bytes(m->name) +
1186                         strlen(" signature: ") + utf_bytes(m->descriptor) +
1187                         strlen(") Expecting to find longest-------typename on stack") 
1188                         + strlen("0");
1189
1190         /* allocate memory */
1191
1192         msg = MNEW(char, msglen);
1193
1194         /* generate message */
1195
1196         if (m != NULL) {
1197                 strcpy(msg, "(class: ");
1198                 utf_cat_classname(msg, m->class->name);
1199                 strcat(msg, ", method: ");
1200                 utf_cat(msg, m->name);
1201                 strcat(msg, " signature: ");
1202                 utf_cat(msg, m->descriptor);
1203                 strcat(msg, ") ");
1204         }
1205         else {
1206                 msg[0] = 0;
1207         }
1208
1209         strcat(msg, "Expecting to find ");
1210
1211         switch (type) {
1212                 case TYPE_INT: typename = "integer"; break;
1213                 case TYPE_LNG: typename = "long"; break;
1214                 case TYPE_FLT: typename = "float"; break;
1215                 case TYPE_DBL: typename = "double"; break;
1216                 case TYPE_ADR: typename = "object/array"; break;
1217                 case TYPE_RET: typename = "returnAddress"; break;
1218                 default:       typename = "<INVALID>"; assert(0); break;
1219         }
1220
1221         strcat(msg, typename);
1222         strcat(msg, " on stack");
1223
1224         u = utf_new_char(msg);
1225
1226         /* free memory */
1227
1228         MFREE(msg, char, msglen);
1229
1230         /* throw exception */
1231
1232         exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
1233 }
1234
1235
1236 /* exceptions_new_arithmeticexception ******************************************
1237
1238    Generates a java.lang.ArithmeticException for the JIT compiler.
1239
1240 *******************************************************************************/
1241
1242 java_objectheader *exceptions_new_arithmeticexception(void)
1243 {
1244         java_objectheader *o;
1245
1246         o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
1247                                                            utf_division_by_zero);
1248
1249         return o;
1250 }
1251
1252
1253 /* exceptions_new_arrayindexoutofboundsexception *******************************
1254
1255    Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
1256    system.
1257
1258 *******************************************************************************/
1259
1260 java_objectheader *exceptions_new_arrayindexoutofboundsexception(s4 index)
1261 {
1262         java_objectheader *o;
1263         methodinfo        *m;
1264         java_objectheader *s;
1265
1266         /* convert the index into a String, like Sun does */
1267
1268         m = class_resolveclassmethod(class_java_lang_String,
1269                                                                  utf_new_char("valueOf"),
1270                                                                  utf_new_char("(I)Ljava/lang/String;"),
1271                                                                  class_java_lang_Object,
1272                                                                  true);
1273
1274         if (m == NULL)
1275                 return *exceptionptr;
1276
1277         s = vm_call_method(m, NULL, index);
1278
1279         if (s == NULL)
1280                 return *exceptionptr;
1281
1282         o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
1283                                                                           s);
1284
1285         if (o == NULL)
1286                 return *exceptionptr;
1287
1288         return o;
1289 }
1290
1291
1292 /* exceptions_throw_arrayindexoutofboundsexception *****************************
1293
1294    Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
1295    the VM.
1296
1297 *******************************************************************************/
1298
1299 void exceptions_throw_arrayindexoutofboundsexception(void)
1300 {
1301         exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
1302 }
1303
1304
1305 /* exceptions_throw_arraystoreexception ****************************************
1306
1307    Generates and throws a java.lang.ArrayStoreException for the VM.
1308
1309 *******************************************************************************/
1310
1311 void exceptions_throw_arraystoreexception(void)
1312 {
1313         exceptions_throw_utf(utf_java_lang_ArrayStoreException);
1314 /*      e = native_new_and_init(class_java_lang_ArrayStoreException); */
1315 }
1316
1317
1318 /* exceptions_new_classcastexception *******************************************
1319
1320    Generates a java.lang.ClassCastException for the JIT compiler.
1321
1322 *******************************************************************************/
1323
1324 java_objectheader *exceptions_new_classcastexception(java_objectheader *o)
1325 {
1326         java_objectheader *e;
1327         utf               *classname;
1328
1329         classname = o->vftbl->class->name;
1330
1331         e = exceptions_new_class_utf(class_java_lang_ClassCastException, classname);
1332
1333         return e;
1334 }
1335
1336
1337 /* exceptions_throw_clonenotsupportedexception *********************************
1338
1339    Generates and throws a java.lang.CloneNotSupportedException for the
1340    VM.
1341
1342 *******************************************************************************/
1343
1344 void exceptions_throw_clonenotsupportedexception(void)
1345 {
1346         exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
1347 }
1348
1349
1350 /* exceptions_throw_illegalaccessexception *************************************
1351
1352    Generates and throws a java.lang.IllegalAccessException for the VM.
1353
1354 *******************************************************************************/
1355
1356 void exceptions_throw_illegalaccessexception(utf *message)
1357 {
1358         exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
1359 }
1360
1361
1362 /* exceptions_throw_illegalargumentexception ***********************************
1363
1364    Generates and throws a java.lang.IllegalArgumentException for the
1365    VM.
1366
1367 *******************************************************************************/
1368
1369 void exceptions_throw_illegalargumentexception(void)
1370 {
1371         exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
1372 }
1373
1374
1375 /* exceptions_throw_illegalmonitorstateexception *******************************
1376
1377    Generates and throws a java.lang.IllegalMonitorStateException for
1378    the VM.
1379
1380 *******************************************************************************/
1381
1382 void exceptions_throw_illegalmonitorstateexception(void)
1383 {
1384         exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
1385 }
1386
1387
1388 /* exceptions_throw_instantiationexception *************************************
1389
1390    Generates and throws a java.lang.InstantiationException for the VM.
1391
1392 *******************************************************************************/
1393
1394 void exceptions_throw_instantiationexception(classinfo *c)
1395 {
1396         exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
1397 }
1398
1399
1400 /* exceptions_throw_interruptedexception ***************************************
1401
1402    Generates and throws a java.lang.InterruptedException for the VM.
1403
1404 *******************************************************************************/
1405
1406 void exceptions_throw_interruptedexception(void)
1407 {
1408         exceptions_throw_utf(utf_java_lang_InterruptedException);
1409 }
1410
1411
1412 /* exceptions_throw_invocationtargetexception **********************************
1413
1414    Generates and throws a java.lang.reflect.InvocationTargetException
1415    for the VM.
1416
1417    IN:
1418       cause......cause exception object
1419
1420 *******************************************************************************/
1421
1422 void exceptions_throw_invocationtargetexception(java_objectheader *cause)
1423 {
1424         exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
1425                                                                    cause);
1426 }
1427
1428
1429 /* exceptions_throw_negativearraysizeexception *********************************
1430
1431    Generates and throws a java.lang.NegativeArraySizeException for the
1432    VM.
1433
1434 *******************************************************************************/
1435
1436 void exceptions_throw_negativearraysizeexception(void)
1437 {
1438         exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
1439 }
1440
1441
1442 /* exceptions_new_nullpointerexception *****************************************
1443
1444    Generates a java.lang.NullPointerException for the VM system.
1445
1446 *******************************************************************************/
1447
1448 java_objectheader *exceptions_new_nullpointerexception(void)
1449 {
1450         java_objectheader *o;
1451
1452         o = exceptions_new_class(class_java_lang_NullPointerException);
1453
1454         return o;
1455 }
1456
1457
1458 /* exceptions_throw_nullpointerexception ***************************************
1459
1460    Generates a java.lang.NullPointerException for the VM system and
1461    throw it in the VM system.
1462
1463 *******************************************************************************/
1464
1465 void exceptions_throw_nullpointerexception(void)
1466 {
1467         exceptions_throw_class(class_java_lang_NullPointerException);
1468 }
1469
1470
1471 /* exceptions_throw_privilegedactionexception **********************************
1472
1473    Generates and throws a java.security.PrivilegedActionException.
1474
1475 *******************************************************************************/
1476
1477 void exceptions_throw_privilegedactionexception(java_objectheader *exception)
1478 {
1479         exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
1480                                                                    exception);
1481 }
1482
1483
1484 /* exceptions_throw_stringindexoutofboundsexception ****************************
1485
1486    Generates and throws a java.lang.StringIndexOutOfBoundsException
1487    for the VM.
1488
1489 *******************************************************************************/
1490
1491 void exceptions_throw_stringindexoutofboundsexception(void)
1492 {
1493         exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
1494 }
1495
1496
1497 /* exceptions_get_exception ****************************************************
1498
1499    Returns the current exception pointer of the current thread.
1500
1501 *******************************************************************************/
1502
1503 java_objectheader *exceptions_get_exception(void)
1504 {
1505         /* return the exception */
1506
1507         return *exceptionptr;
1508 }
1509
1510
1511 /* exceptions_set_exception ****************************************************
1512
1513    Sets the exception pointer of the current thread.
1514
1515 *******************************************************************************/
1516
1517 void exceptions_set_exception(java_objectheader *o)
1518 {
1519         /* set the exception */
1520
1521         *exceptionptr = o;
1522 }
1523
1524
1525 /* exceptions_clear_exception **************************************************
1526
1527    Clears the current exception pointer of the current thread.
1528
1529 *******************************************************************************/
1530
1531 void exceptions_clear_exception(void)
1532 {
1533         /* and clear the exception */
1534
1535         *exceptionptr = NULL;
1536 }
1537
1538
1539 /* exceptions_fillinstacktrace *************************************************
1540
1541    Calls the fillInStackTrace-method of the currently thrown
1542    exception.
1543
1544 *******************************************************************************/
1545
1546 java_objectheader *exceptions_fillinstacktrace(void)
1547 {
1548         java_objectheader *o;
1549         methodinfo        *m;
1550
1551         /* get exception */
1552
1553         o = *exceptionptr;
1554         assert(o);
1555
1556         /* clear exception */
1557
1558         *exceptionptr = NULL;
1559
1560         /* resolve methodinfo pointer from exception object */
1561
1562 #if defined(ENABLE_JAVASE)
1563         m = class_resolvemethod(o->vftbl->class,
1564                                                         utf_fillInStackTrace,
1565                                                         utf_void__java_lang_Throwable);
1566 #elif defined(ENABLE_JAVAME_CLDC1_1)
1567         m = class_resolvemethod(o->vftbl->class,
1568                                                         utf_fillInStackTrace,
1569                                                         utf_void__void);
1570 #else
1571 #error IMPLEMENT ME!
1572 #endif
1573
1574         /* call function */
1575
1576         (void) vm_call_method(m, o);
1577
1578         /* return exception object */
1579
1580         return o;
1581 }
1582
1583
1584 /* exceptions_get_and_clear_exception ******************************************
1585
1586    Gets the exception pointer of the current thread and clears it.
1587    This function may return NULL.
1588
1589 *******************************************************************************/
1590
1591 java_objectheader *exceptions_get_and_clear_exception(void)
1592 {
1593         java_objectheader **p;
1594         java_objectheader  *e;
1595
1596         /* get the pointer of the exception pointer */
1597
1598         p = exceptionptr;
1599
1600         /* get the exception */
1601
1602         e = *p;
1603
1604         /* and clear the exception */
1605
1606         *p = NULL;
1607
1608         /* return the exception */
1609
1610         return e;
1611 }
1612
1613
1614 /* exceptions_new_hardware_exception *******************************************
1615
1616    Creates the correct exception for a hardware-exception thrown and
1617    caught by a signal handler.
1618
1619 *******************************************************************************/
1620
1621 java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val)
1622 {
1623         stackframeinfo     sfi;
1624         java_objectheader *e;
1625         java_objectheader *o;
1626         s4                 index;
1627
1628         /* create stackframeinfo */
1629
1630         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
1631
1632         switch (type) {
1633         case EXCEPTION_HARDWARE_NULLPOINTER:
1634                 e = exceptions_new_nullpointerexception();
1635                 break;
1636
1637         case EXCEPTION_HARDWARE_ARITHMETIC:
1638                 e = exceptions_new_arithmeticexception();
1639                 break;
1640
1641         case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
1642                 index = (s4) val;
1643                 e = exceptions_new_arrayindexoutofboundsexception(index);
1644                 break;
1645
1646         case EXCEPTION_HARDWARE_CLASSCAST:
1647                 o = (java_objectheader *) val;
1648                 e = exceptions_new_classcastexception(o);
1649                 break;
1650
1651         case EXCEPTION_HARDWARE_EXCEPTION:
1652                 e = exceptions_fillinstacktrace();
1653                 break;
1654
1655         default:
1656                 /* let's try to get a backtrace */
1657
1658                 codegen_get_pv_from_pc(xpc);
1659
1660                 /* if that does not work, print more debug info */
1661
1662                 log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
1663
1664 #if SIZEOF_VOID_P == 8
1665                 log_println("PC=0x%016lx", xpc);
1666 #else
1667                 log_println("PC=0x%08x", xpc);
1668 #endif
1669
1670 #if defined(ENABLE_DISASSEMBLER)
1671                 log_println("machine instruction at PC:");
1672                 disassinstr(xpc);
1673 #endif
1674
1675                 vm_abort("Exiting...");
1676
1677                 /* keep compiler happy */
1678
1679                 e = NULL;
1680         }
1681
1682         /* remove stackframeinfo */
1683
1684         stacktrace_remove_stackframeinfo(&sfi);
1685
1686         /* return the exception object */
1687
1688         return e;
1689 }
1690
1691
1692 /* exceptions_handle_exception *************************************************
1693
1694    Try to find an exception handler for the given exception and return it.
1695    If no handler is found, exit the monitor of the method (if any)
1696    and return NULL.
1697
1698    IN:
1699       xptr.........the exception object
1700           xpc..........PC of where the exception was thrown
1701           pv...........Procedure Value of the current method
1702           sp...........current stack pointer
1703
1704    RETURN VALUE:
1705       the address of the first matching exception handler, or
1706           NULL if no handler was found
1707
1708 *******************************************************************************/
1709
1710 #if defined(ENABLE_JIT)
1711 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1712 {
1713         methodinfo            *m;
1714         codeinfo              *code;
1715         s4                     issync;
1716         dseg_exception_entry  *ex;
1717         s4                     exceptiontablelength;
1718         s4                     i;
1719         classref_or_classinfo  cr;
1720         classinfo             *c;
1721 #if defined(ENABLE_THREADS)
1722         java_objectheader     *o;
1723 #endif
1724
1725 #ifdef __S390__
1726         /* Addresses are 31 bit integers */
1727 #       define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF)
1728 #else
1729 #       define ADDR_MASK(x) (x)
1730 #endif
1731
1732         xpc = ADDR_MASK(xpc);
1733
1734         /* get info from the method header */
1735
1736         code                 = *((codeinfo **)            (pv + CodeinfoPointer));
1737         issync               = *((s4 *)                   (pv + IsSync));
1738         ex                   =   (dseg_exception_entry *) (pv + ExTableStart);
1739         exceptiontablelength = *((s4 *)                   (pv + ExTableSize));
1740
1741         /* Get the methodinfo pointer from the codeinfo pointer. For
1742            asm_vm_call_method the codeinfo pointer is NULL. */
1743
1744         m = (code == NULL) ? NULL : code->m;
1745
1746 #if !defined(NDEBUG)
1747         /* print exception trace */
1748
1749         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1750                 builtin_trace_exception(xptr, m, xpc, 1);
1751 #endif
1752
1753 #if defined(ENABLE_VMLOG)
1754         vmlog_cacao_throw(xptr);
1755 #endif
1756
1757         for (i = 0; i < exceptiontablelength; i++) {
1758                 /* ATTENTION: keep this here, as we need to decrement the
1759            pointer before the loop executes! */
1760
1761                 ex--;
1762
1763                 /* If the start and end PC is NULL, this means we have the
1764                    special case of asm_vm_call_method.  So, just return the
1765                    proper exception handler. */
1766
1767                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1768                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1769
1770                 /* is the xpc is the current catch range */
1771
1772                 if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) {
1773                         cr = ex->catchtype;
1774
1775                         /* NULL catches everything */
1776
1777                         if (cr.any == NULL) {
1778 #if !defined(NDEBUG)
1779                                 /* Print stacktrace of exception when caught. */
1780
1781 #if defined(ENABLE_VMLOG)
1782                                 vmlog_cacao_catch(xptr);
1783 #endif
1784
1785                                 if (opt_verboseexception) {
1786                                         exceptions_print_exception(xptr);
1787                                         stacktrace_print_trace(xptr);
1788                                 }
1789 #endif
1790
1791                                 return ex->handlerpc;
1792                         }
1793
1794                         /* resolve or load/link the exception class */
1795
1796                         if (IS_CLASSREF(cr)) {
1797                                 /* The exception class reference is unresolved. */
1798                                 /* We have to do _eager_ resolving here. While the class of */
1799                                 /* the exception object is guaranteed to be loaded, it may  */
1800                                 /* well have been loaded by a different loader than the     */
1801                                 /* defining loader of m's class, which is the one we must   */
1802                                 /* use to resolve the catch class. Thus lazy resolving      */
1803                                 /* might fail, even if the result of the resolution would   */
1804                                 /* be an already loaded class.                              */
1805
1806                                 c = resolve_classref_eager(cr.ref);
1807
1808                                 if (c == NULL) {
1809                                         /* Exception resolving the exception class, argh! */
1810                                         return NULL;
1811                                 }
1812
1813                                 /* Ok, we resolved it. Enter it in the table, so we don't */
1814                                 /* have to do this again.                                 */
1815                                 /* XXX this write should be atomic. Is it?                */
1816
1817                                 ex->catchtype.cls = c;
1818                         } else {
1819                                 c = cr.cls;
1820
1821                                 /* XXX I don't think this case can ever happen. -Edwin */
1822                                 if (!(c->state & CLASS_LOADED))
1823                                         /* use the methods' classloader */
1824                                         if (!load_class_from_classloader(c->name,
1825                                                                                                          m->class->classloader))
1826                                                 return NULL;
1827
1828                                 /* XXX I think, if it is not linked, we can be sure that     */
1829                                 /* the exception object is no (indirect) instance of it, no? */
1830                                 /* -Edwin                                                    */
1831                                 if (!(c->state & CLASS_LINKED))
1832                                         if (!link_class(c))
1833                                                 return NULL;
1834                         }
1835
1836                         /* is the thrown exception an instance of the catch class? */
1837
1838                         if (builtin_instanceof(xptr, c)) {
1839 #if !defined(NDEBUG)
1840                                 /* Print stacktrace of exception when caught. */
1841
1842 #if defined(ENABLE_VMLOG)
1843                                 vmlog_cacao_catch(xptr);
1844 #endif
1845
1846                                 if (opt_verboseexception) {
1847                                         exceptions_print_exception(xptr);
1848                                         stacktrace_print_trace(xptr);
1849                                 }
1850 #endif
1851
1852                                 return ex->handlerpc;
1853                         }
1854                 }
1855         }
1856
1857 #if defined(ENABLE_THREADS)
1858         /* is this method synchronized? */
1859
1860         if (issync) {
1861                 /* get synchronization object */
1862
1863 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1864                 /* XXX change this if we ever want to use 4-byte stackslots */
1865                 o = *((java_objectheader **) (sp + issync - 8));
1866 # else
1867                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1868 #endif
1869
1870                 assert(o != NULL);
1871
1872                 lock_monitor_exit(o);
1873         }
1874 #endif
1875
1876         /* none of the exceptions catch this one */
1877
1878 #if defined(ENABLE_VMLOG)
1879         vmlog_cacao_unwnd_method(m);
1880 #endif
1881
1882         return NULL;
1883 }
1884 #endif /* defined(ENABLE_JIT) */
1885
1886
1887 /* exceptions_print_exception **************************************************
1888
1889    Prints an exception, the detail message and the cause, if
1890    available, with CACAO internal functions to stdout.
1891
1892 *******************************************************************************/
1893
1894 void exceptions_print_exception(java_objectheader *xptr)
1895 {
1896         java_lang_Throwable   *t;
1897 #if defined(ENABLE_JAVASE)
1898         java_lang_Throwable   *cause;
1899 #endif
1900         utf                   *u;
1901
1902         t = (java_lang_Throwable *) xptr;
1903
1904         if (t == NULL) {
1905                 puts("NULL\n");
1906                 return;
1907         }
1908
1909 #if defined(ENABLE_JAVASE)
1910         cause = t->cause;
1911 #endif
1912
1913         /* print the root exception */
1914
1915         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1916
1917         if (t->detailMessage != NULL) {
1918                 u = javastring_toutf((java_objectheader *) t->detailMessage, false);
1919
1920                 printf(": ");
1921                 utf_display_printable_ascii(u);
1922         }
1923
1924         putc('\n', stdout);
1925
1926 #if defined(ENABLE_JAVASE)
1927         /* print the cause if available */
1928
1929         if ((cause != NULL) && (cause != t)) {
1930                 printf("Caused by: ");
1931                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1932
1933                 if (cause->detailMessage != NULL) {
1934                         u = javastring_toutf((java_objectheader *) cause->detailMessage,
1935                                                                  false);
1936
1937                         printf(": ");
1938                         utf_display_printable_ascii(u);
1939                 }
1940
1941                 putc('\n', stdout);
1942         }
1943 #endif
1944 }
1945
1946
1947 /* exceptions_print_current_exception ******************************************
1948
1949    Prints the current pending exception, the detail message and the
1950    cause, if available, with CACAO internal functions to stdout.
1951
1952 *******************************************************************************/
1953
1954 void exceptions_print_current_exception(void)
1955 {
1956         java_objectheader *xptr;
1957
1958         xptr = *exceptionptr;
1959
1960         exceptions_print_exception(xptr);
1961 }
1962
1963
1964 /* exceptions_print_stacktrace *************************************************
1965
1966    Prints a pending exception with Throwable.printStackTrace().  If
1967    there happens an exception during printStackTrace(), we print the
1968    thrown exception and the original one.
1969
1970    NOTE: This function calls Java code.
1971
1972 *******************************************************************************/
1973
1974 void exceptions_print_stacktrace(void)
1975 {
1976         java_objectheader *oxptr;
1977         java_objectheader *xptr;
1978         classinfo         *c;
1979         methodinfo        *m;
1980
1981         /* get original exception */
1982
1983         oxptr = *exceptionptr;
1984
1985         if (oxptr == NULL)
1986                 vm_abort("exceptions_print_stacktrace: no exception thrown");
1987
1988         /* clear exception, because we are calling jit code again */
1989
1990         *exceptionptr = NULL;
1991
1992         c = oxptr->vftbl->class;
1993
1994         /* find the printStackTrace() method */
1995
1996         m = class_resolveclassmethod(c,
1997                                                                  utf_printStackTrace,
1998                                                                  utf_void__void,
1999                                                                  class_java_lang_Object,
2000                                                                  false);
2001
2002         if (m == NULL)
2003                 vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
2004
2005         /* print compatibility message */
2006
2007         fprintf(stderr, "Exception in thread \"main\" ");
2008
2009         /* print the stacktrace */
2010
2011         (void) vm_call_method(m, oxptr);
2012
2013         /* This normally means, we are EXTREMLY out of memory or
2014            have a serious problem while printStackTrace. But may
2015            be another exception, so print it. */
2016
2017         xptr = *exceptionptr;
2018
2019         if (xptr != NULL) {
2020                 fprintf(stderr, "Exception while printStackTrace(): ");
2021
2022                 /* now print original exception */
2023
2024                 exceptions_print_exception(xptr);
2025                 stacktrace_print_trace(xptr);
2026
2027                 /* now print original exception */
2028
2029                 fprintf(stderr, "Original exception was: ");
2030                 exceptions_print_exception(oxptr);
2031                 stacktrace_print_trace(oxptr);
2032         }
2033
2034         fflush(stderr);
2035 }
2036
2037
2038 /*
2039  * These are local overrides for various environment variables in Emacs.
2040  * Please do not remove this and leave it at the end of the file, where
2041  * Emacs will automagically detect them.
2042  * ---------------------------------------------------------------------
2043  * Local variables:
2044  * mode: c
2045  * indent-tabs-mode: t
2046  * c-basic-offset: 4
2047  * tab-width: 4
2048  * End:
2049  * vim:noexpandtab:sw=4:ts=4:
2050  */