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