Merged revisions 7501-7598 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 7596 2007-03-28 21:05:53Z 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 *e;
1582         methodinfo        *m;
1583
1584         /* get exception */
1585
1586         e = *exceptionptr;
1587         assert(e);
1588
1589         /* clear exception */
1590
1591         *exceptionptr = NULL;
1592
1593         /* resolve methodinfo pointer from exception object */
1594
1595         m = class_resolvemethod(e->vftbl->class,
1596                                                         utf_fillInStackTrace,
1597                                                         utf_void__java_lang_Throwable);
1598
1599         /* call function */
1600
1601         (void) vm_call_method(m, e);
1602
1603         /* return exception object */
1604
1605         return e;
1606 }
1607
1608
1609 /* exceptions_get_and_clear_exception ******************************************
1610
1611    Gets the exception pointer of the current thread and clears it.
1612    This function may return NULL.
1613
1614 *******************************************************************************/
1615
1616 java_objectheader *exceptions_get_and_clear_exception(void)
1617 {
1618         java_objectheader **p;
1619         java_objectheader  *e;
1620
1621         /* get the pointer of the exception pointer */
1622
1623         p = exceptionptr;
1624
1625         /* get the exception */
1626
1627         e = *p;
1628
1629         /* and clear the exception */
1630
1631         *p = NULL;
1632
1633         /* return the exception */
1634
1635         return e;
1636 }
1637
1638
1639 /* exceptions_new_hardware_exception *******************************************
1640
1641    Creates the correct exception for a hardware-exception thrown and
1642    caught by a signal handler.
1643
1644 *******************************************************************************/
1645
1646 java_objectheader *exceptions_new_hardware_exception(u1 *pv, u1 *sp, u1 *ra, u1 *xpc, s4 type, ptrint val)
1647 {
1648         stackframeinfo     sfi;
1649         java_objectheader *e;
1650         java_objectheader *o;
1651         s4                 index;
1652
1653         /* create stackframeinfo */
1654
1655         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp, ra, xpc);
1656
1657         switch (type) {
1658         case EXCEPTION_HARDWARE_NULLPOINTER:
1659                 e = exceptions_new_nullpointerexception();
1660                 break;
1661
1662         case EXCEPTION_HARDWARE_ARITHMETIC:
1663                 e = exceptions_new_arithmeticexception();
1664                 break;
1665
1666         case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
1667                 index = (s4) val;
1668                 e = exceptions_new_arrayindexoutofboundsexception(index);
1669                 break;
1670
1671         case EXCEPTION_HARDWARE_CLASSCAST:
1672                 o = (java_objectheader *) val;
1673                 e = exceptions_new_classcastexception(o);
1674                 break;
1675
1676         case EXCEPTION_HARDWARE_EXCEPTION:
1677                 e = exceptions_fillinstacktrace();
1678                 break;
1679
1680         default:
1681                 /* let's try to get a backtrace */
1682
1683                 codegen_get_pv_from_pc(xpc);
1684
1685                 /* if that does not work, print more debug info */
1686
1687                 log_println("exceptions_new_hardware_exception: unknown exception type %d", type);
1688
1689 #if SIZEOF_VOID_P == 8
1690                 log_println("PC=0x%016lx", xpc);
1691 #else
1692                 log_println("PC=0x%08x", xpc);
1693 #endif
1694
1695 #if defined(ENABLE_DISASSEMBLER)
1696                 log_println("machine instruction at PC:");
1697                 disassinstr(xpc);
1698 #endif
1699
1700                 vm_abort("Exiting...");
1701         }
1702
1703         /* remove stackframeinfo */
1704
1705         stacktrace_remove_stackframeinfo(&sfi);
1706
1707         /* return the exception object */
1708
1709         return e;
1710 }
1711
1712
1713 /* exceptions_handle_exception *************************************************
1714
1715    Try to find an exception handler for the given exception and return it.
1716    If no handler is found, exit the monitor of the method (if any)
1717    and return NULL.
1718
1719    IN:
1720       xptr.........the exception object
1721           xpc..........PC of where the exception was thrown
1722           pv...........Procedure Value of the current method
1723           sp...........current stack pointer
1724
1725    RETURN VALUE:
1726       the address of the first matching exception handler, or
1727           NULL if no handler was found
1728
1729 *******************************************************************************/
1730
1731 #if defined(ENABLE_JIT)
1732 u1 *exceptions_handle_exception(java_objectheader *xptr, u1 *xpc, u1 *pv, u1 *sp)
1733 {
1734         methodinfo            *m;
1735         codeinfo              *code;
1736         s4                     issync;
1737         dseg_exception_entry  *ex;
1738         s4                     exceptiontablelength;
1739         s4                     i;
1740         classref_or_classinfo  cr;
1741         classinfo             *c;
1742 #if defined(ENABLE_THREADS)
1743         java_objectheader     *o;
1744 #endif
1745
1746 #ifdef __S390__
1747         /* Addresses are 31 bit integers */
1748 #       define ADDR_MASK(x) (u1 *)((u4)(x) & 0x7FFFFFFF)
1749 #else
1750 #       define ADDR_MASK(x) (x)
1751 #endif
1752
1753         xpc = ADDR_MASK(xpc);
1754
1755         /* get info from the method header */
1756
1757         code                 = *((codeinfo **)            (pv + CodeinfoPointer));
1758         issync               = *((s4 *)                   (pv + IsSync));
1759         ex                   =   (dseg_exception_entry *) (pv + ExTableStart);
1760         exceptiontablelength = *((s4 *)                   (pv + ExTableSize));
1761
1762         /* Get the methodinfo pointer from the codeinfo pointer. For
1763            asm_vm_call_method the codeinfo pointer is NULL. */
1764
1765         m = (code == NULL) ? NULL : code->m;
1766
1767 #if !defined(NDEBUG)
1768         /* print exception trace */
1769
1770         if (opt_verbose || opt_verbosecall || opt_verboseexception)
1771                 builtin_trace_exception(xptr, m, xpc, 1);
1772 #endif
1773
1774         for (i = 0; i < exceptiontablelength; i++) {
1775                 /* ATTENTION: keep this here, as we need to decrement the
1776            pointer before the loop executes! */
1777
1778                 ex--;
1779
1780                 /* If the start and end PC is NULL, this means we have the
1781                    special case of asm_vm_call_method.  So, just return the
1782                    proper exception handler. */
1783
1784                 if ((ex->startpc == NULL) && (ex->endpc == NULL))
1785                         return (u1 *) (ptrint) &asm_vm_call_method_exception_handler;
1786
1787                 /* is the xpc is the current catch range */
1788
1789                 if ((ADDR_MASK(ex->startpc) <= xpc) && (xpc < ADDR_MASK(ex->endpc))) {
1790                         cr = ex->catchtype;
1791
1792                         /* NULL catches everything */
1793
1794                         if (cr.any == NULL) {
1795 #if !defined(NDEBUG)
1796                                 /* Print stacktrace of exception when caught. */
1797
1798                                 if (opt_verboseexception) {
1799                                         exceptions_print_exception(xptr);
1800                                         stacktrace_print_trace(xptr);
1801                                 }
1802 #endif
1803
1804                                 return ex->handlerpc;
1805                         }
1806
1807                         /* resolve or load/link the exception class */
1808
1809                         if (IS_CLASSREF(cr)) {
1810                                 /* The exception class reference is unresolved. */
1811                                 /* We have to do _eager_ resolving here. While the class of */
1812                                 /* the exception object is guaranteed to be loaded, it may  */
1813                                 /* well have been loaded by a different loader than the     */
1814                                 /* defining loader of m's class, which is the one we must   */
1815                                 /* use to resolve the catch class. Thus lazy resolving      */
1816                                 /* might fail, even if the result of the resolution would   */
1817                                 /* be an already loaded class.                              */
1818
1819                                 c = resolve_classref_eager(cr.ref);
1820
1821                                 if (c == NULL) {
1822                                         /* Exception resolving the exception class, argh! */
1823                                         return NULL;
1824                                 }
1825
1826                                 /* Ok, we resolved it. Enter it in the table, so we don't */
1827                                 /* have to do this again.                                 */
1828                                 /* XXX this write should be atomic. Is it?                */
1829
1830                                 ex->catchtype.cls = c;
1831                         } else {
1832                                 c = cr.cls;
1833
1834                                 /* XXX I don't think this case can ever happen. -Edwin */
1835                                 if (!(c->state & CLASS_LOADED))
1836                                         /* use the methods' classloader */
1837                                         if (!load_class_from_classloader(c->name,
1838                                                                                                          m->class->classloader))
1839                                                 return NULL;
1840
1841                                 /* XXX I think, if it is not linked, we can be sure that     */
1842                                 /* the exception object is no (indirect) instance of it, no? */
1843                                 /* -Edwin                                                    */
1844                                 if (!(c->state & CLASS_LINKED))
1845                                         if (!link_class(c))
1846                                                 return NULL;
1847                         }
1848
1849                         /* is the thrown exception an instance of the catch class? */
1850
1851                         if (builtin_instanceof(xptr, c)) {
1852 #if !defined(NDEBUG)
1853                                 /* Print stacktrace of exception when caught. */
1854
1855                                 if (opt_verboseexception) {
1856                                         exceptions_print_exception(xptr);
1857                                         stacktrace_print_trace(xptr);
1858                                 }
1859 #endif
1860
1861                                 return ex->handlerpc;
1862                         }
1863                 }
1864         }
1865
1866 #if defined(ENABLE_THREADS)
1867         /* is this method synchronized? */
1868
1869         if (issync) {
1870                 /* get synchronization object */
1871
1872 # if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
1873                 /* XXX change this if we ever want to use 4-byte stackslots */
1874                 o = *((java_objectheader **) (sp + issync - 8));
1875 # else
1876                 o = *((java_objectheader **) (sp + issync - SIZEOF_VOID_P));
1877 #endif
1878
1879                 assert(o != NULL);
1880
1881                 lock_monitor_exit(o);
1882         }
1883 #endif
1884
1885         /* none of the exceptions catch this one */
1886
1887         return NULL;
1888 }
1889 #endif /* defined(ENABLE_JIT) */
1890
1891
1892 /* exceptions_print_exception **************************************************
1893
1894    Prints an exception, the detail message and the cause, if
1895    available, with CACAO internal functions to stdout.
1896
1897 *******************************************************************************/
1898
1899 void exceptions_print_exception(java_objectheader *xptr)
1900 {
1901         java_lang_Throwable   *t;
1902 #if defined(ENABLE_JAVASE)
1903         java_lang_Throwable   *cause;
1904 #endif
1905         utf                   *u;
1906
1907         t = (java_lang_Throwable *) xptr;
1908
1909         if (t == NULL) {
1910                 puts("NULL\n");
1911                 return;
1912         }
1913
1914 #if defined(ENABLE_JAVASE)
1915         cause = t->cause;
1916 #endif
1917
1918         /* print the root exception */
1919
1920         utf_display_printable_ascii_classname(t->header.vftbl->class->name);
1921
1922         if (t->detailMessage != NULL) {
1923                 u = javastring_toutf(t->detailMessage, false);
1924
1925                 printf(": ");
1926                 utf_display_printable_ascii(u);
1927         }
1928
1929         putc('\n', stdout);
1930
1931 #if defined(ENABLE_JAVASE)
1932         /* print the cause if available */
1933
1934         if ((cause != NULL) && (cause != t)) {
1935                 printf("Caused by: ");
1936                 utf_display_printable_ascii_classname(cause->header.vftbl->class->name);
1937
1938                 if (cause->detailMessage) {
1939                         u = javastring_toutf(cause->detailMessage, false);
1940
1941                         printf(": ");
1942                         utf_display_printable_ascii(u);
1943                 }
1944
1945                 putc('\n', stdout);
1946         }
1947 #endif
1948 }
1949
1950
1951 /* exceptions_print_current_exception ******************************************
1952
1953    Prints the current pending exception, the detail message and the
1954    cause, if available, with CACAO internal functions to stdout.
1955
1956 *******************************************************************************/
1957
1958 void exceptions_print_current_exception(void)
1959 {
1960         java_objectheader *xptr;
1961
1962         xptr = *exceptionptr;
1963
1964         exceptions_print_exception(xptr);
1965 }
1966
1967
1968 /* exceptions_print_stacktrace *************************************************
1969
1970    Prints a pending exception with Throwable.printStackTrace().  If
1971    there happens an exception during printStackTrace(), we print the
1972    thrown exception and the original one.
1973
1974    NOTE: This function calls Java code.
1975
1976 *******************************************************************************/
1977
1978 void exceptions_print_stacktrace(void)
1979 {
1980         java_objectheader *oxptr;
1981         java_objectheader *xptr;
1982         classinfo         *c;
1983         methodinfo        *m;
1984
1985         /* get original exception */
1986
1987         oxptr = *exceptionptr;
1988
1989         if (oxptr == NULL)
1990                 vm_abort("exceptions_print_stacktrace: no exception thrown");
1991
1992         /* clear exception, because we are calling jit code again */
1993
1994         *exceptionptr = NULL;
1995
1996         c = oxptr->vftbl->class;
1997
1998         /* find the printStackTrace() method */
1999
2000         m = class_resolveclassmethod(c,
2001                                                                  utf_printStackTrace,
2002                                                                  utf_void__void,
2003                                                                  class_java_lang_Object,
2004                                                                  false);
2005
2006         if (m == NULL)
2007                 vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
2008
2009         /* print compatibility message */
2010
2011         fprintf(stderr, "Exception in thread \"main\" ");
2012
2013         /* print the stacktrace */
2014
2015         (void) vm_call_method(m, oxptr);
2016
2017         /* This normally means, we are EXTREMLY out of memory or
2018            have a serious problem while printStackTrace. But may
2019            be another exception, so print it. */
2020
2021         xptr = *exceptionptr;
2022
2023         if (xptr != NULL) {
2024                 fprintf(stderr, "Exception while printStackTrace(): ");
2025
2026                 /* now print original exception */
2027
2028                 exceptions_print_exception(xptr);
2029                 stacktrace_print_trace(xptr);
2030
2031                 /* now print original exception */
2032
2033                 fprintf(stderr, "Original exception was: ");
2034                 exceptions_print_exception(oxptr);
2035                 stacktrace_print_trace(oxptr);
2036         }
2037
2038         fflush(stderr);
2039 }
2040
2041
2042 /*
2043  * These are local overrides for various environment variables in Emacs.
2044  * Please do not remove this and leave it at the end of the file, where
2045  * Emacs will automagically detect them.
2046  * ---------------------------------------------------------------------
2047  * Local variables:
2048  * mode: c
2049  * indent-tabs-mode: t
2050  * c-basic-offset: 4
2051  * tab-width: 4
2052  * End:
2053  * vim:noexpandtab:sw=4:ts=4:
2054  */