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