Merged with tip.
authorStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 5 May 2008 13:02:09 +0000 (15:02 +0200)
committerStefan Ring <stefan@complang.tuwien.ac.at>
Mon, 5 May 2008 13:02:09 +0000 (15:02 +0200)
1  2 
src/vm/jit/i386/darwin/md-asm.h
src/vm/jit/stacktrace.c

index 588811a39a7844d92d52d7966dac589c755e9480,1228b0607eafec6b39b3a19c246b2e7fb0b255cb..d610cc3ce1dc3a24803ccab9cf12b4332aa7eb40
@@@ -1,7 -1,9 +1,7 @@@
  /* src/vm/jit/i386/darwin/md-asm.h - assembler defines for i386 Darwin ABI
  
 -   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
 -   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
 -   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
 -   J. Wenninger, Institut f. Computersprachen - TU Wien
 +   Copyright (C) 1996-2005, 2006, 2008
 +   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
  
     This file is part of CACAO.
  
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     02110-1301, USA.
  
 -   Contact: cacao@cacaojvm.org
 -
 -   Authors: Christian Thalinger
 -
 -   Changes:
 -
  */
  
  
  #define asm_builtin_d2i                       _asm_builtin_d2i
  #define asm_builtin_d2l                       _asm_builtin_d2l
  
 -#define asm_criticalsections                  _asm_criticalsections
 -#define asm_getclassvalues_atomic             _asm_getclassvalues_atomic
 -
  
  /* external defines ***********************************************************/
  
  #define exceptions_get_and_clear_exception    _exceptions_get_and_clear_exception
  
  #define builtin_throw_exception               _builtin_throw_exception
 -#define codegen_get_pv_from_pc                _codegen_get_pv_from_pc
 +#define methodtree_find                       _methodtree_find
  #define exceptions_handle_exception           _exceptions_handle_exception
  #define jit_asm_compile                       _jit_asm_compile
  
  #define builtin_d2i                           _builtin_d2i
  #define builtin_d2l                           _builtin_d2l
  
+ #define asm_get_cycle_count                   _asm_get_cycle_count
  #endif /* _MD_ASM_H */
  
  
diff --combined src/vm/jit/stacktrace.c
index 493e1c5f7290d49352266e7f8102f3fd46a2bfc4,e8d59d422a513669569c4c0aa59304362eb4cdbd..461c09d18f68d38ff92196ac1ad0f2daf64febab
@@@ -1,7 -1,9 +1,7 @@@
  /* src/vm/jit/stacktrace.c - machine independent stacktrace system
  
 -   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
 -   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
 -   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
 -   J. Wenninger, Institut f. Computersprachen - TU Wien
 +   Copyright (C) 1996-2005, 2006, 2007, 2008
 +   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
  
     This file is part of CACAO.
  
  #include "vm/global.h"                   /* required here for native includes */
  #include "native/jni.h"
  #include "native/llni.h"
 +
 +#include "native/include/java_lang_Object.h"
  #include "native/include/java_lang_Throwable.h"
  
  #if defined(WITH_CLASSPATH_GNU)
 +# include "native/include/gnu_classpath_Pointer.h"
  # include "native/include/java_lang_VMThrowable.h"
  #endif
  
 -#if defined(ENABLE_THREADS)
 -# include "threads/native/threads.h"
 -#else
 -# include "threads/none/threads.h"
 -#endif
 +#include "threads/thread.h"
  
  #include "toolbox/logging.h"
  
  #include "vm/jit/codegen-common.h"
  #include "vm/jit/linenumbertable.h"
  #include "vm/jit/methodheader.h"
 +#include "vm/jit/methodtree.h"
  
  #include "vmcore/class.h"
  #include "vmcore/loader.h"
 +#include "vmcore/method.h"
  #include "vmcore/options.h"
  
  
  /* global variables ***********************************************************/
 -#if !defined(ENABLE_THREADS)
 -stackframeinfo_t *_no_threads_stackframeinfo = NULL;
 -#endif
  
  CYCLES_STATS_DECLARE(stacktrace_overhead        , 100, 1)
+ CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40,  5000)
  CYCLES_STATS_DECLARE(stacktrace_get,              40,  5000)
  CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40,  5000)
  CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40,  5000)
@@@ -92,15 -97,18 +93,15 @@@ CYCLES_STATS_DECLARE(stacktrace_get_sta
  
  void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
  {
 -      stackframeinfo_t **psfi;
 -      codeinfo          *code;
 -#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
 -      bool               isleafmethod;
 -#endif
 +      stackframeinfo_t *currentsfi;
 +      codeinfo         *code;
  #if defined(ENABLE_JIT)
        s4                 framesize;
  #endif
  
 -      /* get current stackframe info pointer */
 +      /* Get current stackframe info. */
  
 -      psfi = &STACKFRAMEINFO;
 +      currentsfi = threads_get_current_stackframeinfo();
  
        /* sometimes we don't have pv handy (e.g. in asmpart.S:
         L_asm_call_jit_compiler_exception or in the interpreter). */
        if (pv == NULL) {
  #if defined(ENABLE_INTRP)
                if (opt_intrp)
 -                      pv = codegen_get_pv_from_pc(ra);
 +                      pv = methodtree_find(ra);
                else
  #endif
                        {
        code = code_get_codeinfo_for_pv(pv);
  
        /* XXX */
 -/*    assert(m != NULL); */
 +      /*      assert(m != NULL); */
  
  #if defined(ENABLE_JIT)
  # if defined(ENABLE_INTRP)
  
                ra = md_stacktrace_get_returnaddress(sp, framesize);
  # else
 -              /* If the method is a non-leaf function, we need to get the return
 -                 address from the stack. For leaf functions the return address
 -                 is set correctly. This makes the assembler and the signal
 -                 handler code simpler. */
 -
 -              isleafmethod = *((s4 *) (pv + IsLeaf));
 +              /* If the method is a non-leaf function, we need to get the
 +                 return address from the stack.  For leaf functions the
 +                 return address is set correctly.  This makes the assembler
 +                 and the signal handler code simpler.  The code is NULL is
 +                 the asm_vm_call_method special case. */
  
 -              if (!isleafmethod) {
 +              if ((code == NULL) || !code_is_leafmethod(code)) {
                        framesize = *((u4 *) (pv + FrameSize));
  
                        ra = md_stacktrace_get_returnaddress(sp, framesize);
  
        /* Fill new stackframeinfo structure. */
  
 -      sfi->prev = *psfi;
 +      sfi->prev = currentsfi;
        sfi->code = code;
        sfi->pv   = pv;
        sfi->sp   = sp;
  
        /* Store new stackframeinfo pointer. */
  
 -      *psfi = sfi;
 +      threads_set_current_stackframeinfo(sfi);
  
        /* set the native world flag for the current thread */
        /* ATTENTION: This flag tells the GC how to treat this thread in case of
  
  void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
  {
 -      stackframeinfo_t **psfi;
 -
 -      /* clear the native world flag for the current thread */
 -      /* ATTENTION: Clear this flag _before_ removing the stackframe info */
 +      /* Clear the native world flag for the current thread. */
 +      /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
  
        THREAD_NATIVEWORLD_EXIT;
  
 -      /* get current stackframe info pointer */
 -
 -      psfi = &STACKFRAMEINFO;
 -
  #if !defined(NDEBUG)
        if (opt_DebugStackFrameInfo) {
                log_start();
        }
  #endif
  
 -      /* restore the old pointer */
 +      /* Set previous stackframe info. */
  
 -      *psfi = sfi->prev;
 +      threads_set_current_stackframeinfo(sfi->prev);
  }
  
  
@@@ -267,8 -282,18 +268,8 @@@ static inline void stacktrace_stackfram
        tmpsfi->prev = sfi->prev;
  
  #if !defined(NDEBUG)
 -      /* Print current method information. */
 -
 -      if (opt_DebugStackTrace) {
 -              log_println("[stacktrace start]");
 -              log_start();
 -              log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
 -                                tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
 -                                tmpsfi->xpc);
 -              method_print(tmpsfi->code->m);
 -              log_print("]");
 -              log_finish();
 -      }
 +      if (opt_DebugStackTrace)
 +              log_println("[stacktrace fill]");
  #endif
  }
  
@@@ -335,7 -360,7 +336,7 @@@ static inline void stacktrace_stackfram
  
  #if defined(ENABLE_INTRP)
        if (opt_intrp)
 -              pv = codegen_get_pv_from_pc(ra);
 +              pv = methodtree_find(ra);
        else
  #endif
                {
@@@ -507,20 -532,18 +508,20 @@@ static int stacktrace_depth(stackframei
  
  /* stacktrace_get **************************************************************
  
 -   Builds and returns a stacktrace from the current thread for and
 -   returns the stacktrace structure wrapped in a Java byte-array to
 -   not confuse the GC.
 +   Builds and returns a stacktrace starting from the given stackframe
 +   info and returns the stacktrace structure wrapped in a Java
 +   byte-array to not confuse the GC.
 +
 +   IN:
 +       sfi ... stackframe info to start stacktrace from
  
     RETURN:
         stacktrace as Java byte-array
  
  *******************************************************************************/
  
 -java_handle_bytearray_t *stacktrace_get(void)
 +java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
  {
 -      stackframeinfo_t        *sfi;
        stackframeinfo_t         tmpsfi;
        int                      depth;
        java_handle_bytearray_t *ba;
        skip_fillInStackTrace = true;
        skip_init             = true;
  
 -      /* Get the stacktrace depth of the current thread. */
 -
 -      sfi = STACKFRAMEINFO;
 -
        depth = stacktrace_depth(sfi);
  
        if (depth == 0)
                        /* For GNU Classpath we also need to skip
                           VMThrowable.fillInStackTrace(). */
  
 -                      if ((m->class == class_java_lang_VMThrowable) &&
 +                      if ((m->clazz == class_java_lang_VMThrowable) &&
                                (m->name  == utf_fillInStackTrace))
                                continue;
  #endif
                   exception we are going to skipping them in stack trace. */
  
                if (skip_init == true) {
 -                      if (m->name == utf_init) {
 -/*                            throwable->is_a(method->method_holder())) { */
 +                      if ((m->name == utf_init) &&
 +                              (class_issubclass(m->clazz, class_java_lang_Throwable))) {
                                continue;
                        }
                        else {
@@@ -656,105 -683,6 +657,105 @@@ return_NULL
  }
  
  
 +/* stacktrace_get_current ******************************************************
 +
 +   Builds and returns a stacktrace from the current thread and returns
 +   the stacktrace structure wrapped in a Java byte-array to not
 +   confuse the GC.
 +
 +   RETURN:
 +       stacktrace as Java byte-array
 +
 +*******************************************************************************/
 +
 +java_handle_bytearray_t *stacktrace_get_current(void)
 +{
 +      stackframeinfo_t        *sfi;
 +      java_handle_bytearray_t *ba;
 +
 +      sfi = threads_get_current_stackframeinfo();
 +      ba  = stacktrace_get(sfi);
 +
 +      return ba;
 +}
 +
 +
 +/* stacktrace_get_caller_class *************************************************
 +
 +   Get the class on the stack at the given depth.  This function skips
 +   various special classes or methods.
 +
 +   ARGUMENTS:
 +       depth ... depth to get caller class of
 +
 +   RETURN:
 +       caller class
 +
 +*******************************************************************************/
 +
 +#if defined(ENABLE_JAVASE)
 +classinfo *stacktrace_get_caller_class(int depth)
 +{
 +      stackframeinfo_t *sfi;
 +      stackframeinfo_t  tmpsfi;
 +      methodinfo       *m;
 +      classinfo        *c;
 +      int               i;
 +
 +#if !defined(NDEBUG)
 +      if (opt_DebugStackTrace)
 +              log_println("[stacktrace_get_caller_class]");
 +#endif
 +
 +      /* Get the stackframeinfo of the current thread. */
 +
 +      sfi = threads_get_current_stackframeinfo();
 +
 +      /* Iterate over the whole stack until we reached the requested
 +         depth. */
 +
 +      i = 0;
 +
 +      for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
 +               stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
 +               stacktrace_stackframeinfo_next(&tmpsfi)) {
 +
 +              m = tmpsfi.code->m;
 +              c = m->clazz;
 +
 +              /* Skip builtin methods. */
 +
 +              if (m->flags & ACC_METHOD_BUILTIN)
 +                      continue;
 +
 +#if defined(WITH_CLASSPATH_SUN)
 +              /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
 +                 (vframeStreamCommon::security_get_caller_frame). */
 +
 +              /* This is java.lang.reflect.Method.invoke(), skip it. */
 +
 +              if (m == method_java_lang_reflect_Method_invoke)
 +                      continue;
 +
 +              /* This is an auxiliary frame, skip it. */
 +
 +              if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
 +                      continue;
 +#endif
 +
 +              /* We reached the requested depth. */
 +
 +              if (i >= depth)
 +                      return c;
 +
 +              i++;
 +      }
 +
 +      return NULL;
 +}
 +#endif
 +
 +
  /* stacktrace_first_nonnull_classloader ****************************************
  
     Returns the first non-null (user-defined) classloader on the stack.
  
  *******************************************************************************/
  
 -classloader *stacktrace_first_nonnull_classloader(void)
 +classloader_t *stacktrace_first_nonnull_classloader(void)
  {
        stackframeinfo_t *sfi;
        stackframeinfo_t  tmpsfi;
        methodinfo       *m;
 -      classloader      *cl;
 +      classloader_t    *cl;
  
  #if !defined(NDEBUG)
        if (opt_DebugStackTrace)
  
        /* Get the stackframeinfo of the current thread. */
  
 -      sfi = STACKFRAMEINFO;
 +      sfi = threads_get_current_stackframeinfo();
  
        /* Iterate over the whole stack. */
  
                 stacktrace_stackframeinfo_next(&tmpsfi)) {
  
                m  = tmpsfi.code->m;
 -              cl = class_get_classloader(m->class);
 +              cl = class_get_classloader(m->clazz);
  
                if (cl != NULL)
                        return cl;
@@@ -825,7 -753,7 +826,7 @@@ java_handle_objectarray_t *stacktrace_g
                log_println("[stacktrace_getClassContext]");
  #endif
  
 -      sfi = STACKFRAMEINFO;
 +      sfi = threads_get_current_stackframeinfo();
  
        /* Get the depth of the current stack. */
  
  
                /* Store the class in the array. */
  
 -              data[i] = (java_object_t *) m->class;
 +              data[i] = (java_object_t *) m->clazz;
  
                i++;
        }
@@@ -919,7 -847,7 +920,7 @@@ classinfo *stacktrace_get_current_class
  
        /* Get the stackframeinfo of the current thread. */
  
 -      sfi = STACKFRAMEINFO;
 +      sfi = threads_get_current_stackframeinfo();
  
        /* If the stackframeinfo is NULL then FindClass is called through
           the Invocation Interface and we return NULL */
  
                m = tmpsfi.code->m;
  
 -              if (m->class == class_java_security_PrivilegedAction) {
 +              if (m->clazz == class_java_security_PrivilegedAction) {
                        CYCLES_STATS_END(stacktrace_getCurrentClass);
  
                        return NULL;
                }
  
 -              if (m->class != NULL) {
 +              if (m->clazz != NULL) {
                        CYCLES_STATS_END(stacktrace_getCurrentClass);
  
 -                      return m->class;
 +                      return m->clazz;
                }
        }
  
@@@ -993,7 -921,7 +994,7 @@@ java_handle_objectarray_t *stacktrace_g
  
        /* Get the stackframeinfo of the current thread. */
  
 -      sfi = STACKFRAMEINFO;
 +      sfi = threads_get_current_stackframeinfo();
  
        /* Get the depth of the current stack. */
  
                /* NOTE: We use a LLNI-macro here, because a classinfo is not
                   a handle. */
  
 -              LLNI_array_direct(classes, i) = (java_object_t *) m->class;
 +              LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
  
                /* Store the name in the array. */
  
@@@ -1072,51 -1000,6 +1073,51 @@@ return_NULL
  #endif
  
  
 +/* stacktrace_print_entry ****************************************************
 +
 +   Print line for a stacktrace entry.
 +
 +   ARGUMENTS:
 +       m ............ methodinfo of the entry
 +       linenumber ... linenumber of the entry
 +
 +*******************************************************************************/
 +
 +static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
 +{
 +      /* Sanity check. */
 +
 +      assert(m != NULL);
 +
 +      printf("\tat ");
 +
 +      if (m->flags & ACC_METHOD_BUILTIN)
 +              printf("NULL");
 +      else
 +              utf_display_printable_ascii_classname(m->clazz->name);
 +
 +      printf(".");
 +      utf_display_printable_ascii(m->name);
 +      utf_display_printable_ascii(m->descriptor);
 +
 +      if (m->flags & ACC_NATIVE) {
 +              puts("(Native Method)");
 +      }
 +      else {
 +              if (m->flags & ACC_METHOD_BUILTIN) {
 +                      puts("(builtin)");
 +              }
 +              else {
 +                      printf("(");
 +                      utf_display_printable_ascii(m->clazz->sourcefile);
 +                      printf(":%d)\n", linenumber);
 +              }
 +      }
 +
 +      fflush(stdout);
 +}
 +
 +
  /* stacktrace_print ************************************************************
  
     Print the given stacktrace with CACAO intern methods only (no Java
@@@ -1146,99 -1029,28 +1147,99 @@@ void stacktrace_print(stacktrace_t *st
  
                linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
  
 -              printf("\tat ");
 -              utf_display_printable_ascii_classname(m->class->name);
 -              printf(".");
 -              utf_display_printable_ascii(m->name);
 -              utf_display_printable_ascii(m->descriptor);
 +              stacktrace_print_entry(m, linenumber);
 +      }
 +}
 +
  
 -              if (m->flags & ACC_NATIVE) {
 -                      puts("(Native Method)");
 -              }
 -              else {
 -                      printf("(");
 -                      utf_display_printable_ascii(m->class->sourcefile);
 -                      printf(":%d)\n", linenumber);
 -              }
 +/* stacktrace_print_current ****************************************************
 +
 +   Print the current stacktrace of the current thread.
 +
 +   NOTE: This function prints all frames of the stacktrace and does
 +   not skip frames like stacktrace_get.
 +
 +*******************************************************************************/
 +
 +void stacktrace_print_current(void)
 +{
 +      stackframeinfo_t *sfi;
 +      stackframeinfo_t  tmpsfi;
 +      codeinfo         *code;
 +      methodinfo       *m;
 +      int32_t           linenumber;
 +
 +      sfi = threads_get_current_stackframeinfo();
 +
 +      if (sfi == NULL) {
 +              puts("\t<<No stacktrace available>>");
 +              fflush(stdout);
 +              return;
        }
  
 -      /* just to be sure */
 +      for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
 +               stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
 +               stacktrace_stackframeinfo_next(&tmpsfi)) {
 +              /* Get the methodinfo. */
 +
 +              code = tmpsfi.code;
 +              m    = code->m;
  
 -      fflush(stdout);
 +              /* Get the line number. */
 +
 +              linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
 +
 +              stacktrace_print_entry(m, linenumber);
 +      }
  }
  
  
 +/* stacktrace_print_of_thread **************************************************
 +
 +   Print the current stacktrace of the given thread.
 +
 +   ARGUMENTS:
 +       t ... thread
 +
 +*******************************************************************************/
 +
 +#if defined(ENABLE_THREADS)
 +void stacktrace_print_of_thread(threadobject *t)
 +{
 +      stackframeinfo_t *sfi;
 +      stackframeinfo_t  tmpsfi;
 +      codeinfo         *code;
 +      methodinfo       *m;
 +      int32_t           linenumber;
 +
 +      /* Build a stacktrace for the passed thread. */
 +
 +      sfi = t->_stackframeinfo;
 +      
 +      if (sfi == NULL) {
 +              puts("\t<<No stacktrace available>>");
 +              fflush(stdout);
 +              return;
 +      }
 +
 +      for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
 +               stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
 +               stacktrace_stackframeinfo_next(&tmpsfi)) {
 +              /* Get the methodinfo. */
 +
 +              code = tmpsfi.code;
 +              m    = code->m;
 +
 +              /* Get the line number. */
 +
 +              linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
 +
 +              stacktrace_print_entry(m, linenumber);
 +      }
 +}
 +#endif
 +
 +
  /* stacktrace_print_exception **************************************************
  
     Print the stacktrace of a given exception (more or less a wrapper
  void stacktrace_print_exception(java_handle_t *h)
  {
        java_lang_Throwable     *o;
 +
  #if defined(WITH_CLASSPATH_GNU)
        java_lang_VMThrowable   *vmt;
  #endif
 +
 +      java_lang_Object        *backtrace;
        java_handle_bytearray_t *ba;
        stacktrace_t            *st;
  
  #if defined(WITH_CLASSPATH_GNU)
  
        LLNI_field_get_ref(o,   vmState, vmt);
 -      LLNI_field_get_ref(vmt, vmData,  ba);
 +      LLNI_field_get_ref(vmt, vmdata,  backtrace);
  
  #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
  
 -      LLNI_field_get_ref(o, backtrace, ba);
 +      LLNI_field_get_ref(o, backtrace, backtrace);
  
  #else
  # error unknown classpath configuration
  #endif
  
 +      ba = (java_handle_bytearray_t *) backtrace;
 +
        /* Sanity check. */
  
        assert(ba != NULL);