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