f1ac6c92e816d27ec7b0bf8cf9a127226ae9286d
[cacao.git] / src / vm / jit / stacktrace.cpp
1 /* src/vm/jit/stacktrace.cpp - machine independent stacktrace system
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "vm/types.h"
34
35 #include "md.h"
36
37 #include "mm/gc.hpp"
38 #include "mm/memory.h"
39
40 #include "vm/jit/stacktrace.hpp"
41
42 #include "vm/global.h"                   /* required here for native includes */
43 #include "native/jni.h"
44 #include "native/llni.h"
45
46 #include "native/include/java_lang_Object.h"
47 #include "native/include/java_lang_Throwable.h"
48
49 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
50 # include "native/include/gnu_classpath_Pointer.h"
51 # include "native/include/java_lang_VMThrowable.h"
52 #endif
53
54 #include "threads/thread.hpp"
55
56 #include "toolbox/logging.h"
57
58 #include "vm/array.h"
59 #include "vm/builtin.h"
60 #include "vm/cycles-stats.h"
61 #include "vm/exceptions.hpp"
62 #include "vm/string.hpp"
63 #include "vm/vm.hpp"
64
65 #include "vm/jit/asmpart.h"
66 #include "vm/jit/codegen-common.h"
67 #include "vm/jit/linenumbertable.h"
68 #include "vm/jit/methodheader.h"
69 #include "vm/jit/methodtree.h"
70
71 #include "vmcore/class.h"
72 #include "vmcore/globals.hpp"
73 #include "vmcore/loader.h"
74 #include "vmcore/method.h"
75 #include "vmcore/options.h"
76
77
78 // FIXME Use C-linkage for now.
79 extern "C" {
80
81 /* global variables ***********************************************************/
82
83 CYCLES_STATS_DECLARE(stacktrace_overhead        , 100, 1)
84 CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40,  5000)
85 CYCLES_STATS_DECLARE(stacktrace_get,              40,  5000)
86 CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40,  5000)
87 CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40,  5000)
88 CYCLES_STATS_DECLARE(stacktrace_get_stack       , 40,  10000)
89
90
91 /* stacktrace_stackframeinfo_add ***********************************************
92
93    Fills a stackframe info structure with the given or calculated
94    values and adds it to the chain.
95
96 *******************************************************************************/
97
98 void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
99 {
100         stackframeinfo_t *currentsfi;
101         codeinfo         *code;
102 #if defined(ENABLE_JIT)
103         s4                 framesize;
104 #endif
105
106         /* Get current stackframe info. */
107
108         currentsfi = threads_get_current_stackframeinfo();
109
110         /* sometimes we don't have pv handy (e.g. in asmpart.S:
111        L_asm_call_jit_compiler_exception or in the interpreter). */
112
113         if (pv == NULL) {
114 #if defined(ENABLE_INTRP)
115                 if (opt_intrp)
116                         pv = methodtree_find(ra);
117                 else
118 #endif
119                         {
120 #if defined(ENABLE_JIT)
121 # if defined(__SPARC_64__)
122                                 pv = md_get_pv_from_stackframe(sp);
123 # else
124                                 pv = md_codegen_get_pv_from_pc(ra);
125 # endif
126 #endif
127                         }
128         }
129
130         /* Get codeinfo pointer for the parent Java method. */
131
132         code = code_get_codeinfo_for_pv(pv);
133
134         /* XXX */
135         /*      assert(m != NULL); */
136
137 #if defined(ENABLE_JIT)
138 # if defined(ENABLE_INTRP)
139         /* When using the interpreter, we pass RA to the function. */
140
141         if (!opt_intrp) {
142 # endif
143 # if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
144                 /* On i386 and x86_64 we always have to get the return address
145                    from the stack. */
146                 /* m68k has return address on stack always */
147                 /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
148                    the RA from stack. */
149
150                 framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
151
152                 ra = md_stacktrace_get_returnaddress(sp, framesize);
153 # else
154                 /* If the method is a non-leaf function, we need to get the
155                    return address from the stack.  For leaf functions the
156                    return address is set correctly.  This makes the assembler
157                    and the signal handler code simpler.  The code is NULL is
158                    the asm_vm_call_method special case. */
159
160                 if ((code == NULL) || !code_is_leafmethod(code)) {
161                         framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
162
163                         ra = md_stacktrace_get_returnaddress(sp, framesize);
164                 }
165 # endif
166 # if defined(ENABLE_INTRP)
167         }
168 # endif
169 #endif
170
171         /* Calculate XPC when not given.  The XPC is then the return
172            address of the current method minus 1 because the RA points to
173            the instruction after the call instruction.  This is required
174            e.g. for method stubs. */
175
176         if (xpc == NULL) {
177                 xpc = (void *) (((intptr_t) ra) - 1);
178         }
179
180         /* Fill new stackframeinfo structure. */
181
182         sfi->prev = currentsfi;
183         sfi->code = code;
184         sfi->pv   = pv;
185         sfi->sp   = sp;
186         sfi->ra   = ra;
187         sfi->xpc  = xpc;
188
189 #if !defined(NDEBUG)
190         if (opt_DebugStackFrameInfo) {
191                 log_start();
192                 log_print("[stackframeinfo add   : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
193                                   sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
194                 method_print(sfi->code->m);
195                 log_print("]");
196                 log_finish();
197         }
198 #endif
199
200         /* Store new stackframeinfo pointer. */
201
202         threads_set_current_stackframeinfo(sfi);
203
204         /* set the native world flag for the current thread */
205         /* ATTENTION: This flag tells the GC how to treat this thread in case of
206            a collection. Set this flag _after_ a valid stackframe info was set. */
207
208         THREAD_NATIVEWORLD_ENTER;
209 }
210
211
212 /* stacktrace_stackframeinfo_remove ********************************************
213
214    Remove the given stackframeinfo from the chain in the current
215    thread.
216
217 *******************************************************************************/
218
219 void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
220 {
221         /* Clear the native world flag for the current thread. */
222         /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
223
224         THREAD_NATIVEWORLD_EXIT;
225
226 #if !defined(NDEBUG)
227         if (opt_DebugStackFrameInfo) {
228                 log_start();
229                 log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
230                                   sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
231                 method_print(sfi->code->m);
232                 log_print("]");
233                 log_finish();
234         }
235 #endif
236
237         /* Set previous stackframe info. */
238
239         threads_set_current_stackframeinfo(sfi->prev);
240 }
241
242
243 /* stacktrace_stackframeinfo_fill **********************************************
244
245    Fill the temporary stackframeinfo structure with the values given
246    in sfi.
247
248    IN:
249        tmpsfi ... temporary stackframeinfo
250        sfi ...... stackframeinfo to be used in the next iteration
251
252 *******************************************************************************/
253
254 static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
255 {
256         /* Sanity checks. */
257
258         assert(tmpsfi != NULL);
259         assert(sfi != NULL);
260
261         /* Fill the temporary stackframeinfo. */
262
263         tmpsfi->code = sfi->code;
264         tmpsfi->pv   = sfi->pv;
265         tmpsfi->sp   = sfi->sp;
266         tmpsfi->ra   = sfi->ra;
267         tmpsfi->xpc  = sfi->xpc;
268
269         /* Set the previous stackframe info of the temporary one to the
270            next in the chain. */
271
272         tmpsfi->prev = sfi->prev;
273
274 #if !defined(NDEBUG)
275         if (opt_DebugStackTrace)
276                 log_println("[stacktrace fill]");
277 #endif
278 }
279
280
281 /* stacktrace_stackframeinfo_next **********************************************
282
283    Walk the stack (or the stackframeinfo-chain) to the next method and
284    return the new stackframe values in the temporary stackframeinfo
285    passed.
286
287    ATTENTION: This function does NOT skip builtin methods!
288
289    IN:
290        tmpsfi ... temporary stackframeinfo of current method
291
292 *******************************************************************************/
293
294 static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
295 {
296         codeinfo         *code;
297         void             *pv;
298         void             *sp;
299         void             *ra;
300         void             *xpc;
301         uint32_t          framesize;
302         stackframeinfo_t *prevsfi;
303
304         /* Sanity check. */
305
306         assert(tmpsfi != NULL);
307
308         /* Get values from the stackframeinfo. */
309
310         code = tmpsfi->code;
311         pv   = tmpsfi->pv;
312         sp   = tmpsfi->sp;
313         ra   = tmpsfi->ra;
314         xpc  = tmpsfi->xpc;
315  
316         /* Get the current stack frame size. */
317
318         framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
319
320         /* Get the RA of the current stack frame (RA to the parent Java
321            method) if the current method is a non-leaf method.  Otherwise
322            the value in the stackframeinfo is correct (from the signal
323            handler). */
324
325 #if defined(ENABLE_JIT)
326 # if defined(ENABLE_INTRP)
327         if (opt_intrp)
328                 ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
329         else
330 # endif
331                 {
332                         if (!code_is_leafmethod(code))
333                                 ra = md_stacktrace_get_returnaddress(sp, framesize);
334                 }
335 #else
336         ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
337 #endif
338
339         /* Get the PV for the parent Java method. */
340
341 #if defined(ENABLE_INTRP)
342         if (opt_intrp)
343                 pv = methodtree_find(ra);
344         else
345 #endif
346                 {
347 #if defined(ENABLE_JIT)
348 # if defined(__SPARC_64__)
349                         sp = md_get_framepointer(sp);
350                         pv = md_get_pv_from_stackframe(sp);
351 # else
352                         pv = md_codegen_get_pv_from_pc(ra);
353 # endif
354 #endif
355                 }
356
357         /* Get the codeinfo pointer for the parent Java method. */
358
359         code = code_get_codeinfo_for_pv(pv);
360
361         /* Calculate the SP for the parent Java method. */
362
363 #if defined(ENABLE_INTRP)
364         if (opt_intrp)
365                 sp = *(u1 **) (sp - framesize);
366         else
367 #endif
368                 {
369 #if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
370                         sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
371 #elif defined(__SPARC_64__)
372                         /* already has the new sp */
373 #else
374                         sp = (void *) (((intptr_t) sp) + framesize);
375 #endif
376                 }
377
378         /* If the new codeinfo pointer is NULL we reached a
379            asm_vm_call_method function.  In this case we get the next
380            values from the previous stackframeinfo in the chain.
381            Otherwise the new values have been calculated before. */
382
383         if (code == NULL) {
384                 prevsfi = tmpsfi->prev;
385
386                 /* If the previous stackframeinfo in the chain is NULL we
387                    reached the top of the stacktrace.  We set code and prev to
388                    NULL to mark the end, which is checked in
389                    stacktrace_stackframeinfo_end_check. */
390
391                 if (prevsfi == NULL) {
392                         tmpsfi->code = NULL;
393                         tmpsfi->prev = NULL;
394                         return;
395                 }
396
397                 /* Fill the temporary stackframeinfo with the new values. */
398
399                 stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
400         }
401         else {
402                 /* Store the new values in the stackframeinfo.  NOTE: We
403                    subtract 1 from the RA to get the XPC, because the RA
404                    points to the instruction after the call instruction. */
405
406                 tmpsfi->code = code;
407                 tmpsfi->pv   = pv;
408                 tmpsfi->sp   = sp;
409                 tmpsfi->ra   = ra;
410                 tmpsfi->xpc  = (void *) (((intptr_t) ra) - 1);
411         }
412
413 #if !defined(NDEBUG)
414         /* Print current method information. */
415
416         if (opt_DebugStackTrace) {
417                 log_start();
418                 log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
419                                   tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
420                                   tmpsfi->xpc);
421                 method_print(tmpsfi->code->m);
422                 log_print("]");
423                 log_finish();
424         }
425 #endif
426 }
427
428
429 /* stacktrace_stackframeinfo_end_check *****************************************
430
431    Check if we reached the end of the stacktrace.
432
433    IN:
434        tmpsfi ... temporary stackframeinfo of current method
435
436    RETURN:
437        true .... the end is reached
438            false ... the end is not reached
439
440 *******************************************************************************/
441
442 static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
443 {
444         /* Sanity check. */
445
446         assert(tmpsfi != NULL);
447
448         if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
449 #if !defined(NDEBUG)
450                 if (opt_DebugStackTrace)
451                         log_println("[stacktrace stop]");
452 #endif
453
454                 return true;
455         }
456
457         return false;
458 }
459
460
461 /* stacktrace_depth ************************************************************
462
463    Calculates and returns the depth of the current stacktrace.
464
465    IN:
466        sfi ... stackframeinfo where to start the stacktrace
467
468    RETURN:
469        depth of the stacktrace
470
471 *******************************************************************************/
472
473 static int stacktrace_depth(stackframeinfo_t *sfi)
474 {
475         stackframeinfo_t  tmpsfi;
476         int               depth;
477         methodinfo       *m;
478
479 #if !defined(NDEBUG)
480         if (opt_DebugStackTrace)
481                 log_println("[stacktrace_depth]");
482 #endif
483
484         /* XXX This is not correct, but a workaround for threads-dump for
485            now. */
486 /*      assert(sfi != NULL); */
487         if (sfi == NULL)
488                 return 0;
489
490         /* Iterate over all stackframes. */
491
492         depth = 0;
493
494         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
495                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
496                  stacktrace_stackframeinfo_next(&tmpsfi)) {
497                 /* Get methodinfo. */
498
499                 m = tmpsfi.code->m;
500
501                 /* Skip builtin methods. */
502
503                 if (m->flags & ACC_METHOD_BUILTIN)
504                         continue;
505
506                 depth++;
507         }
508
509         return depth;
510 }
511
512
513 /* stacktrace_get **************************************************************
514
515    Builds and returns a stacktrace starting from the given stackframe
516    info and returns the stacktrace structure wrapped in a Java
517    byte-array to not confuse the GC.
518
519    IN:
520        sfi ... stackframe info to start stacktrace from
521
522    RETURN:
523        stacktrace as Java byte-array
524
525 *******************************************************************************/
526
527 java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
528 {
529         stackframeinfo_t         tmpsfi;
530         int                      depth;
531         java_handle_bytearray_t *ba;
532         int32_t                  ba_size;
533         stacktrace_t            *st;
534         stacktrace_entry_t      *ste;
535         methodinfo              *m;
536         bool                     skip_fillInStackTrace;
537         bool                     skip_init;
538
539         CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
540
541 #if !defined(NDEBUG)
542         if (opt_DebugStackTrace)
543                 log_println("[stacktrace_get]");
544 #endif
545
546         skip_fillInStackTrace = true;
547         skip_init             = true;
548
549         depth = stacktrace_depth(sfi);
550
551         if (depth == 0)
552                 return NULL;
553
554         /* Allocate memory from the GC heap and copy the stacktrace
555            buffer. */
556         /* ATTENTION: Use a Java byte-array for this to not confuse the
557            GC. */
558         /* FIXME: We waste some memory here as we skip some entries
559            later. */
560
561         ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
562
563         ba = builtin_newarray_byte(ba_size);
564
565         if (ba == NULL)
566                 goto return_NULL;
567
568         /* Get a stacktrace entry pointer. */
569         /* ATTENTION: We need a critical section here because we use the
570            byte-array data pointer directly. */
571
572         LLNI_CRITICAL_START;
573
574         st = (stacktrace_t *) LLNI_array_data(ba);
575
576         ste = st->entries;
577
578         /* Iterate over the whole stack. */
579
580         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
581                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
582                  stacktrace_stackframeinfo_next(&tmpsfi)) {
583                 /* Get the methodinfo. */
584
585                 m = tmpsfi.code->m;
586
587                 /* Skip builtin methods. */
588
589                 if (m->flags & ACC_METHOD_BUILTIN)
590                         continue;
591
592                 /* This logic is taken from
593                    hotspot/src/share/vm/classfile/javaClasses.cpp
594                    (java_lang_Throwable::fill_in_stack_trace). */
595
596                 if (skip_fillInStackTrace == true) {
597                         /* Check "fillInStackTrace" only once, so we negate the
598                            flag after the first time check. */
599
600 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
601                         /* For GNU Classpath we also need to skip
602                            VMThrowable.fillInStackTrace(). */
603
604                         if ((m->clazz == class_java_lang_VMThrowable) &&
605                                 (m->name  == utf_fillInStackTrace))
606                                 continue;
607 #endif
608
609                         skip_fillInStackTrace = false;
610
611                         if (m->name == utf_fillInStackTrace)
612                                 continue;
613                 }
614
615                 /* Skip <init> methods of the exceptions klass.  If there is
616                    <init> methods that belongs to a superclass of the
617                    exception we are going to skipping them in stack trace. */
618
619                 if (skip_init == true) {
620                         if ((m->name == utf_init) &&
621                                 (class_issubclass(m->clazz, class_java_lang_Throwable))) {
622                                 continue;
623                         }
624                         else {
625                                 /* If no "Throwable.init()" method found, we stop
626                                    checking it next time. */
627
628                                 skip_init = false;
629                         }
630                 }
631
632                 /* Store the stacktrace entry and increment the pointer. */
633
634                 ste->code = tmpsfi.code;
635                 ste->pc   = tmpsfi.xpc;
636
637                 ste++;
638         }
639
640         /* Store the number of entries in the stacktrace structure. */
641
642         st->length = ste - st->entries;
643
644         LLNI_CRITICAL_END;
645
646         /* release dump memory */
647
648 /*      dump_release(dumpsize); */
649
650         CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
651                                                                    stacktrace_overhead)
652         return ba;
653
654 return_NULL:
655 /*      dump_release(dumpsize); */
656
657         CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
658                                                                    stacktrace_overhead)
659
660         return NULL;
661 }
662
663
664 /* stacktrace_get_current ******************************************************
665
666    Builds and returns a stacktrace from the current thread and returns
667    the stacktrace structure wrapped in a Java byte-array to not
668    confuse the GC.
669
670    RETURN:
671        stacktrace as Java byte-array
672
673 *******************************************************************************/
674
675 java_handle_bytearray_t *stacktrace_get_current(void)
676 {
677         stackframeinfo_t        *sfi;
678         java_handle_bytearray_t *ba;
679
680         sfi = threads_get_current_stackframeinfo();
681         ba  = stacktrace_get(sfi);
682
683         return ba;
684 }
685
686
687 /* stacktrace_get_caller_class *************************************************
688
689    Get the class on the stack at the given depth.  This function skips
690    various special classes or methods.
691
692    ARGUMENTS:
693        depth ... depth to get caller class of
694
695    RETURN:
696        caller class
697
698 *******************************************************************************/
699
700 #if defined(ENABLE_JAVASE)
701 classinfo *stacktrace_get_caller_class(int depth)
702 {
703         stackframeinfo_t *sfi;
704         stackframeinfo_t  tmpsfi;
705         methodinfo       *m;
706         classinfo        *c;
707         int               i;
708
709 #if !defined(NDEBUG)
710         if (opt_DebugStackTrace)
711                 log_println("[stacktrace_get_caller_class]");
712 #endif
713
714         /* Get the stackframeinfo of the current thread. */
715
716         sfi = threads_get_current_stackframeinfo();
717
718         /* Iterate over the whole stack until we reached the requested
719            depth. */
720
721         i = 0;
722
723         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
724                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
725                  stacktrace_stackframeinfo_next(&tmpsfi)) {
726
727                 m = tmpsfi.code->m;
728                 c = m->clazz;
729
730                 /* Skip builtin methods. */
731
732                 if (m->flags & ACC_METHOD_BUILTIN)
733                         continue;
734
735 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
736                 /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
737                    (vframeStreamCommon::security_get_caller_frame). */
738
739                 /* This is java.lang.reflect.Method.invoke(), skip it. */
740
741                 if (m == method_java_lang_reflect_Method_invoke)
742                         continue;
743
744                 /* This is an auxiliary frame, skip it. */
745
746                 if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
747                         continue;
748 #endif
749
750                 /* We reached the requested depth. */
751
752                 if (i >= depth)
753                         return c;
754
755                 i++;
756         }
757
758         return NULL;
759 }
760 #endif
761
762
763 /* stacktrace_first_nonnull_classloader ****************************************
764
765    Returns the first non-null (user-defined) classloader on the stack.
766    If none is found NULL is returned.
767
768    RETURN:
769        classloader
770
771 *******************************************************************************/
772
773 classloader_t *stacktrace_first_nonnull_classloader(void)
774 {
775         stackframeinfo_t *sfi;
776         stackframeinfo_t  tmpsfi;
777         methodinfo       *m;
778         classloader_t    *cl;
779
780 #if !defined(NDEBUG)
781         if (opt_DebugStackTrace)
782                 log_println("[stacktrace_first_nonnull_classloader]");
783 #endif
784
785         /* Get the stackframeinfo of the current thread. */
786
787         sfi = threads_get_current_stackframeinfo();
788
789         /* Iterate over the whole stack. */
790
791         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
792                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
793                  stacktrace_stackframeinfo_next(&tmpsfi)) {
794
795                 m  = tmpsfi.code->m;
796                 cl = class_get_classloader(m->clazz);
797
798                 if (cl != NULL)
799                         return cl;
800         }
801
802         return NULL;
803 }
804
805
806 /* stacktrace_getClassContext **************************************************
807
808    Creates a Class context array.
809
810    RETURN VALUE:
811       the array of java.lang.Class objects, or
812           NULL if an exception has been thrown
813
814 *******************************************************************************/
815
816 java_handle_objectarray_t *stacktrace_getClassContext(void)
817 {
818         stackframeinfo_t           *sfi;
819         stackframeinfo_t            tmpsfi;
820         int                         depth;
821         java_handle_objectarray_t  *oa;
822         java_object_t             **data;
823         int                         i;
824         methodinfo                 *m;
825
826         CYCLES_STATS_DECLARE_AND_START
827
828 #if !defined(NDEBUG)
829         if (opt_DebugStackTrace)
830                 log_println("[stacktrace_getClassContext]");
831 #endif
832
833         sfi = threads_get_current_stackframeinfo();
834
835         /* Get the depth of the current stack. */
836
837         depth = stacktrace_depth(sfi);
838
839         /* The first stackframe corresponds to the method whose
840            implementation calls this native function.  We remove that
841            entry. */
842
843         depth--;
844         stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
845         stacktrace_stackframeinfo_next(&tmpsfi);
846
847         /* Allocate the Class array. */
848
849         oa = builtin_anewarray(depth, class_java_lang_Class);
850
851         if (oa == NULL) {
852                 CYCLES_STATS_END(stacktrace_getClassContext);
853
854                 return NULL;
855         }
856
857         /* Fill the Class array from the stacktrace list. */
858
859         LLNI_CRITICAL_START;
860
861         data = LLNI_array_data(oa);
862
863         /* Iterate over the whole stack. */
864
865         i = 0;
866
867         for (;
868                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
869                  stacktrace_stackframeinfo_next(&tmpsfi)) {
870                 /* Get methodinfo. */
871
872                 m = tmpsfi.code->m;
873
874                 /* Skip builtin methods. */
875
876                 if (m->flags & ACC_METHOD_BUILTIN)
877                         continue;
878
879                 /* Store the class in the array. */
880
881                 data[i] = (java_object_t *) m->clazz;
882
883                 i++;
884         }
885
886         LLNI_CRITICAL_END;
887
888         CYCLES_STATS_END(stacktrace_getClassContext)
889
890         return oa;
891 }
892
893
894 /* stacktrace_getCurrentClass **************************************************
895
896    Find the current class by walking the stack trace.
897
898    Quote from the JNI documentation:
899          
900    In the Java 2 Platform, FindClass locates the class loader
901    associated with the current native method.  If the native code
902    belongs to a system class, no class loader will be
903    involved. Otherwise, the proper class loader will be invoked to
904    load and link the named class. When FindClass is called through the
905    Invocation Interface, there is no current native method or its
906    associated class loader. In that case, the result of
907    ClassLoader.getBaseClassLoader is used."
908
909 *******************************************************************************/
910
911 #if defined(ENABLE_JAVASE)
912 classinfo *stacktrace_get_current_class(void)
913 {
914         stackframeinfo_t *sfi;
915         stackframeinfo_t  tmpsfi;
916         methodinfo       *m;
917
918         CYCLES_STATS_DECLARE_AND_START;
919
920 #if !defined(NDEBUG)
921         if (opt_DebugStackTrace)
922                 log_println("[stacktrace_get_current_class]");
923 #endif
924
925         /* Get the stackframeinfo of the current thread. */
926
927         sfi = threads_get_current_stackframeinfo();
928
929         /* If the stackframeinfo is NULL then FindClass is called through
930            the Invocation Interface and we return NULL */
931
932         if (sfi == NULL) {
933                 CYCLES_STATS_END(stacktrace_getCurrentClass);
934
935                 return NULL;
936         }
937
938         /* Iterate over the whole stack. */
939
940         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
941                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
942                  stacktrace_stackframeinfo_next(&tmpsfi)) {
943                 /* Get the methodinfo. */
944
945                 m = tmpsfi.code->m;
946
947                 if (m->clazz == class_java_security_PrivilegedAction) {
948                         CYCLES_STATS_END(stacktrace_getCurrentClass);
949
950                         return NULL;
951                 }
952
953                 if (m->clazz != NULL) {
954                         CYCLES_STATS_END(stacktrace_getCurrentClass);
955
956                         return m->clazz;
957                 }
958         }
959
960         /* No Java method found on the stack. */
961
962         CYCLES_STATS_END(stacktrace_getCurrentClass);
963
964         return NULL;
965 }
966 #endif /* ENABLE_JAVASE */
967
968
969 /* stacktrace_get_stack ********************************************************
970
971    Create a 2-dimensional array for java.security.VMAccessControler.
972
973    RETURN VALUE:
974       the arrary, or
975          NULL if an exception has been thrown
976
977 *******************************************************************************/
978
979 #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
980 java_handle_objectarray_t *stacktrace_get_stack(void)
981 {
982         stackframeinfo_t          *sfi;
983         stackframeinfo_t           tmpsfi;
984         int                        depth;
985         java_handle_objectarray_t *oa;
986         java_handle_objectarray_t *classes;
987         java_handle_objectarray_t *methodnames;
988         methodinfo                *m;
989         java_handle_t             *string;
990         int                        i;
991
992         CYCLES_STATS_DECLARE_AND_START
993
994 #if !defined(NDEBUG)
995         if (opt_DebugStackTrace)
996                 log_println("[stacktrace_get_stack]");
997 #endif
998
999         /* Get the stackframeinfo of the current thread. */
1000
1001         sfi = threads_get_current_stackframeinfo();
1002
1003         /* Get the depth of the current stack. */
1004
1005         depth = stacktrace_depth(sfi);
1006
1007         if (depth == 0)
1008                 return NULL;
1009
1010         /* Allocate the required arrays. */
1011
1012         oa = builtin_anewarray(2, arrayclass_java_lang_Object);
1013
1014         if (oa == NULL)
1015                 goto return_NULL;
1016
1017         classes = builtin_anewarray(depth, class_java_lang_Class);
1018
1019         if (classes == NULL)
1020                 goto return_NULL;
1021
1022         methodnames = builtin_anewarray(depth, class_java_lang_String);
1023
1024         if (methodnames == NULL)
1025                 goto return_NULL;
1026
1027         /* Set up the 2-dimensional array. */
1028
1029         array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
1030         array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
1031
1032         /* Iterate over the whole stack. */
1033         /* TODO We should use a critical section here to speed things
1034            up. */
1035
1036         i = 0;
1037
1038         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1039                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1040                  stacktrace_stackframeinfo_next(&tmpsfi)) {
1041                 /* Get the methodinfo. */
1042
1043                 m = tmpsfi.code->m;
1044
1045                 /* Skip builtin methods. */
1046
1047                 if (m->flags & ACC_METHOD_BUILTIN)
1048                         continue;
1049
1050                 /* Store the class in the array. */
1051                 /* NOTE: We use a LLNI-macro here, because a classinfo is not
1052                    a handle. */
1053
1054                 LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
1055
1056                 /* Store the name in the array. */
1057
1058                 string = javastring_new(m->name);
1059
1060                 if (string == NULL)
1061                         goto return_NULL;
1062
1063                 array_objectarray_element_set(methodnames, i, string);
1064
1065                 i++;
1066         }
1067
1068         CYCLES_STATS_END(stacktrace_get_stack)
1069
1070         return oa;
1071
1072 return_NULL:
1073         CYCLES_STATS_END(stacktrace_get_stack)
1074
1075         return NULL;
1076 }
1077 #endif
1078
1079
1080 /* stacktrace_print_entry ****************************************************
1081
1082    Print line for a stacktrace entry.
1083
1084    ARGUMENTS:
1085        m ............ methodinfo of the entry
1086        linenumber ... linenumber of the entry
1087
1088 *******************************************************************************/
1089
1090 static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
1091 {
1092         /* Sanity check. */
1093
1094         assert(m != NULL);
1095
1096         printf("\tat ");
1097
1098         if (m->flags & ACC_METHOD_BUILTIN)
1099                 printf("NULL");
1100         else
1101                 utf_display_printable_ascii_classname(m->clazz->name);
1102
1103         printf(".");
1104         utf_display_printable_ascii(m->name);
1105         utf_display_printable_ascii(m->descriptor);
1106
1107         if (m->flags & ACC_NATIVE) {
1108                 puts("(Native Method)");
1109         }
1110         else {
1111                 if (m->flags & ACC_METHOD_BUILTIN) {
1112                         puts("(builtin)");
1113                 }
1114                 else {
1115                         printf("(");
1116                         utf_display_printable_ascii(m->clazz->sourcefile);
1117                         printf(":%d)\n", linenumber);
1118                 }
1119         }
1120
1121         fflush(stdout);
1122 }
1123
1124
1125 /* stacktrace_print ************************************************************
1126
1127    Print the given stacktrace with CACAO intern methods only (no Java
1128    code required).
1129
1130    This method is used by stacktrace_dump_trace and
1131    builtin_trace_exception.
1132
1133    IN:
1134        st ... stacktrace to print
1135
1136 *******************************************************************************/
1137
1138 void stacktrace_print(stacktrace_t *st)
1139 {
1140         stacktrace_entry_t *ste;
1141         methodinfo         *m;
1142         int32_t             linenumber;
1143         int                 i;
1144
1145         ste = &(st->entries[0]);
1146
1147         for (i = 0; i < st->length; i++, ste++) {
1148                 m = ste->code->m;
1149
1150                 /* Get the line number. */
1151
1152                 linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
1153
1154                 stacktrace_print_entry(m, linenumber);
1155         }
1156 }
1157
1158
1159 /* stacktrace_print_current ****************************************************
1160
1161    Print the current stacktrace of the current thread.
1162
1163    NOTE: This function prints all frames of the stacktrace and does
1164    not skip frames like stacktrace_get.
1165
1166 *******************************************************************************/
1167
1168 void stacktrace_print_current(void)
1169 {
1170         stackframeinfo_t *sfi;
1171         stackframeinfo_t  tmpsfi;
1172         codeinfo         *code;
1173         methodinfo       *m;
1174         int32_t           linenumber;
1175
1176         sfi = threads_get_current_stackframeinfo();
1177
1178         if (sfi == NULL) {
1179                 puts("\t<<No stacktrace available>>");
1180                 fflush(stdout);
1181                 return;
1182         }
1183
1184         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1185                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1186                  stacktrace_stackframeinfo_next(&tmpsfi)) {
1187                 /* Get the methodinfo. */
1188
1189                 code = tmpsfi.code;
1190                 m    = code->m;
1191
1192                 /* Get the line number. */
1193
1194                 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1195
1196                 stacktrace_print_entry(m, linenumber);
1197         }
1198 }
1199
1200
1201 /* stacktrace_print_of_thread **************************************************
1202
1203    Print the current stacktrace of the given thread.
1204
1205    ARGUMENTS:
1206        t ... thread
1207
1208 *******************************************************************************/
1209
1210 #if defined(ENABLE_THREADS)
1211 void stacktrace_print_of_thread(threadobject *t)
1212 {
1213         stackframeinfo_t *sfi;
1214         stackframeinfo_t  tmpsfi;
1215         codeinfo         *code;
1216         methodinfo       *m;
1217         int32_t           linenumber;
1218
1219         /* Build a stacktrace for the passed thread. */
1220
1221         sfi = t->_stackframeinfo;
1222         
1223         if (sfi == NULL) {
1224                 puts("\t<<No stacktrace available>>");
1225                 fflush(stdout);
1226                 return;
1227         }
1228
1229         for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
1230                  stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
1231                  stacktrace_stackframeinfo_next(&tmpsfi)) {
1232                 /* Get the methodinfo. */
1233
1234                 code = tmpsfi.code;
1235                 m    = code->m;
1236
1237                 /* Get the line number. */
1238
1239                 linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
1240
1241                 stacktrace_print_entry(m, linenumber);
1242         }
1243 }
1244 #endif
1245
1246
1247 /* stacktrace_print_exception **************************************************
1248
1249    Print the stacktrace of a given exception (more or less a wrapper
1250    to stacktrace_print).
1251
1252    IN:
1253        h ... handle of exception to print
1254
1255 *******************************************************************************/
1256
1257 void stacktrace_print_exception(java_handle_t *h)
1258 {
1259         java_lang_Throwable     *o;
1260
1261 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1262         java_lang_VMThrowable   *vmt;
1263 #endif
1264
1265         java_lang_Object        *backtrace;
1266         java_handle_bytearray_t *ba;
1267         stacktrace_t            *st;
1268
1269         o = (java_lang_Throwable *) h;
1270
1271         if (o == NULL)
1272                 return;
1273
1274         /* now print the stacktrace */
1275
1276 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
1277
1278         LLNI_field_get_ref(o,   vmState, vmt);
1279         LLNI_field_get_ref(vmt, vmdata,  backtrace);
1280
1281 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
1282
1283         LLNI_field_get_ref(o, backtrace, backtrace);
1284
1285 #else
1286 # error unknown classpath configuration
1287 #endif
1288
1289         ba = (java_handle_bytearray_t *) backtrace;
1290
1291         /* Sanity check. */
1292
1293         assert(ba != NULL);
1294
1295         /* We need a critical section here as we use the byte-array data
1296            pointer directly. */
1297
1298         LLNI_CRITICAL_START;
1299         
1300         st = (stacktrace_t *) LLNI_array_data(ba);
1301
1302         stacktrace_print(st);
1303
1304         LLNI_CRITICAL_END;
1305 }
1306
1307
1308 #if defined(ENABLE_CYCLES_STATS)
1309 void stacktrace_print_cycles_stats(FILE *file)
1310 {
1311         CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
1312         CYCLES_STATS_PRINT(stacktrace_get,               file);
1313         CYCLES_STATS_PRINT(stacktrace_getClassContext ,  file);
1314         CYCLES_STATS_PRINT(stacktrace_getCurrentClass ,  file);
1315         CYCLES_STATS_PRINT(stacktrace_get_stack,         file);
1316 }
1317 #endif
1318
1319 } // extern "C"
1320
1321
1322 /*
1323  * These are local overrides for various environment variables in Emacs.
1324  * Please do not remove this and leave it at the end of the file, where
1325  * Emacs will automagically detect them.
1326  * ---------------------------------------------------------------------
1327  * Local variables:
1328  * mode: c++
1329  * indent-tabs-mode: t
1330  * c-basic-offset: 4
1331  * tab-width: 4
1332  * End:
1333  * vim:noexpandtab:sw=4:ts=4:
1334  */