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