LCOV - code coverage report
Current view: top level - vm/jit - stacktrace.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 195 336 58.0 %
Date: 2017-07-14 10:03:36 Functions: 14 23 60.9 %

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

Generated by: LCOV version 1.11