type.
* include/jit/jit-except.h, include/jit/jit-common.h: move
- JIT_NO_OFFSET from jit-except.h to jit-common.h
+ JIT_NO_OFFSET from jit-except.h to jit-common.h.
+
+ * include/jit/jit-unwind.h, jit/jit-unwind.c: new files.
+ * include/jit/jit.h, include/jit/Makefile.am: add jit-unwind.h.
+ * jit/Makefile.am: add jit-unwind.c.
+
+ * jit/jit-except.c (jit_exception_get_stack_trace): re-implement
+ using unwind routines.
2008-05-28 Juan Jesus Garcia de Soria <juanj.g_soria@grupobbva.com>
BUILT_SOURCES = jit-arch.h
libjitincludedir = $(includedir)/jit
-libjitinclude_HEADERS = jit.h \
- jit-arch.h \
- jit-apply.h \
- jit-block.h \
- jit-common.h \
- jit-context.h \
- jit-debugger.h \
- jit-defs.h \
- jit-dump.h \
- jit-dynamic.h \
- jit-elf.h \
- jit-except.h \
- jit-function.h \
- jit-init.h \
- jit-insn.h \
- jit-intrinsic.h \
- jit-meta.h \
- jit-objmodel.h \
- jit-objmodel-private.h \
- jit-opcode.h \
- jit-plus.h \
- jit-type.h \
- jit-util.h \
- jit-value.h \
- jit-walk.h
+libjitinclude_HEADERS = \
+ jit.h \
+ jit-arch.h \
+ jit-apply.h \
+ jit-block.h \
+ jit-common.h \
+ jit-context.h \
+ jit-debugger.h \
+ jit-defs.h \
+ jit-dump.h \
+ jit-dynamic.h \
+ jit-elf.h \
+ jit-except.h \
+ jit-function.h \
+ jit-init.h \
+ jit-insn.h \
+ jit-intrinsic.h \
+ jit-meta.h \
+ jit-objmodel.h \
+ jit-objmodel-private.h \
+ jit-opcode.h \
+ jit-plus.h \
+ jit-type.h \
+ jit-unwind.h \
+ jit-util.h \
+ jit-value.h \
+ jit-walk.h
noinst_HEADERS = jit-arch-generic.h jit-arch-x86.h jit-arch-x86-64.h
--- /dev/null
+/*
+ * jit-unwind.h - Routines for performing stack unwinding.
+ *
+ * Copyright (C) 2008 Southern Storm Software, Pty Ltd.
+ *
+ * This file is part of the libjit library.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _JIT_UNWIND_H
+#define _JIT_UNWIND_H
+
+#include <jit/jit-common.h>
+#include <jit/jit-arch.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+ void *frame;
+ void *cache;
+ jit_context_t context;
+#ifdef _JIT_ARCH_UNWIND_DATA
+ _JIT_ARCH_UNWIND_DATA
+#endif
+} jit_unwind_context_t;
+
+int jit_unwind_init(jit_unwind_context_t *unwind, jit_context_t context);
+void jit_unwind_free(jit_unwind_context_t *unwind);
+
+int jit_unwind_next(jit_unwind_context_t *unwind);
+int jit_unwind_next_pc(jit_unwind_context_t *unwind);
+void *jit_unwind_get_pc(jit_unwind_context_t *unwind);
+
+int jit_unwind_jump(jit_unwind_context_t *unwind, void *pc);
+
+jit_function_t jit_unwind_get_function(jit_unwind_context_t *unwind);
+unsigned int jit_unwind_get_offset(jit_unwind_context_t *unwind);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _JIT_UNWIND_H */
#include <jit/jit-function.h>
#include <jit/jit-init.h>
#include <jit/jit-insn.h>
+#include <jit/jit-intrinsic.h>
#include <jit/jit-meta.h>
#include <jit/jit-objmodel.h>
#include <jit/jit-opcode.h>
#include <jit/jit-type.h>
-#include <jit/jit-intrinsic.h>
+#include <jit/jit-unwind.h>
#include <jit/jit-util.h>
#include <jit/jit-value.h>
#include <jit/jit-walk.h>
lib_LTLIBRARIES = libjit.la
libjit_la_SOURCES = \
- jit-alloc.c \
- jit-apply.c \
- jit-apply-func.h \
- jit-apply-alpha.h \
- jit-apply-alpha.c \
- jit-apply-arm.h \
- jit-apply-arm.c \
- jit-apply-x86.h \
- jit-apply-x86.c \
- jit-apply-x86-64.h \
- jit-apply-x86-64.c \
- jit-bitset.h \
- jit-bitset.c \
- jit-block.c \
- jit-cache.h \
- jit-cache.c \
- jit-cfg.h \
- jit-cfg.c \
- jit-context.c \
- jit-cpuid-x86.h \
- jit-cpuid-x86.c \
- jit-debugger.c \
- jit-dump.c \
- jit-elf-defs.h \
- jit-elf-read.c \
- jit-elf-write.c \
- jit-except.c \
- jit-function.c \
- jit-gen-alpha.h \
- jit-gen-arm.h \
- jit-gen-arm.c \
- jit-gen-x86.h \
- jit-gen-x86-64.h \
- jit-insn.c \
- jit-init.c \
- jit-internal.h \
- jit-interp.h \
- jit-interp.c \
- jit-intrinsic.c \
- jit-live.c \
- jit-memory.c \
- jit-memory.h \
- jit-meta.c \
- jit-objmodel.c \
- jit-opcode.c \
- jit-pool.c \
- jit-reg-alloc.h \
- jit-reg-alloc.c \
- jit-reg-class.h \
- jit-reg-class.c \
- jit-rules.h \
- jit-rules.c \
- jit-rules-interp.c \
- jit-rules-interp.h \
- jit-rules-alpha.h \
- jit-rules-alpha.c \
- jit-rules-arm.h \
- jit-rules-arm.c \
- jit-rules-x86.h \
- jit-rules-x86.c \
- jit-rules-x86-64.h \
- jit-rules-x86-64.c \
- jit-setjmp.h \
- jit-signal.c \
- jit-string.c \
- jit-symbol.c \
- jit-thread.c \
- jit-thread.h \
- jit-type.c \
- jit-value.c \
- jit-walk.c
+ jit-alloc.c \
+ jit-apply.c \
+ jit-apply-func.h \
+ jit-apply-alpha.h \
+ jit-apply-alpha.c \
+ jit-apply-arm.h \
+ jit-apply-arm.c \
+ jit-apply-x86.h \
+ jit-apply-x86.c \
+ jit-apply-x86-64.h \
+ jit-apply-x86-64.c \
+ jit-bitset.h \
+ jit-bitset.c \
+ jit-block.c \
+ jit-cache.h \
+ jit-cache.c \
+ jit-cfg.h \
+ jit-cfg.c \
+ jit-context.c \
+ jit-cpuid-x86.h \
+ jit-cpuid-x86.c \
+ jit-debugger.c \
+ jit-dump.c \
+ jit-elf-defs.h \
+ jit-elf-read.c \
+ jit-elf-write.c \
+ jit-except.c \
+ jit-function.c \
+ jit-gen-alpha.h \
+ jit-gen-arm.h \
+ jit-gen-arm.c \
+ jit-gen-x86.h \
+ jit-gen-x86-64.h \
+ jit-insn.c \
+ jit-init.c \
+ jit-internal.h \
+ jit-interp.h \
+ jit-interp.c \
+ jit-intrinsic.c \
+ jit-live.c \
+ jit-memory.c \
+ jit-memory.h \
+ jit-meta.c \
+ jit-objmodel.c \
+ jit-opcode.c \
+ jit-pool.c \
+ jit-reg-alloc.h \
+ jit-reg-alloc.c \
+ jit-reg-class.h \
+ jit-reg-class.c \
+ jit-rules.h \
+ jit-rules.c \
+ jit-rules-interp.c \
+ jit-rules-interp.h \
+ jit-rules-alpha.h \
+ jit-rules-alpha.c \
+ jit-rules-arm.h \
+ jit-rules-arm.c \
+ jit-rules-x86.h \
+ jit-rules-x86.c \
+ jit-rules-x86-64.h \
+ jit-rules-x86-64.c \
+ jit-setjmp.h \
+ jit-signal.c \
+ jit-string.c \
+ jit-symbol.c \
+ jit-thread.c \
+ jit-thread.h \
+ jit-type.c \
+ jit-unwind.c \
+ jit-value.c \
+ jit-walk.c
EXTRA_DIST = \
- mklabel.sh \
- jit-rules-alpha.ins \
- jit-rules-arm.sel \
- jit-rules-x86.ins \
- jit-rules-x86-64.ins
+ mklabel.sh \
+ jit-rules-alpha.ins \
+ jit-rules-arm.sel \
+ jit-rules-x86.ins \
+ jit-rules-x86-64.ins
AM_CFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I. -I$(srcdir)
@*/
jit_stack_trace_t jit_exception_get_stack_trace(void)
{
- jit_stack_trace_t trace = 0;
- unsigned int size = 0;
-#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
- jit_thread_control_t control;
- jit_backtrace_t top;
- jit_backtrace_t item;
-
+ jit_stack_trace_t trace;
+ unsigned int size;
+ jit_unwind_context_t unwind;
+
/* Count the number of items in the current thread's call stack */
- control = _jit_thread_get_control();
- if(!control)
+ size = 0;
+ if(jit_unwind_init(&unwind, NULL))
{
- return 0;
+ do
+ {
+ size++;
+ }
+ while(jit_unwind_next_pc(&unwind));
+ jit_unwind_free(&unwind);
}
- size = 0;
- top = control->backtrace_head;
- item = top;
- while(item != 0)
+
+ /* Bail out if the stack is not available */
+ if(size == 0)
{
- ++size;
- item = item->parent;
+ return 0;
}
/* Allocate memory for the stack trace */
- trace = (jit_stack_trace_t)jit_malloc
- (sizeof(struct jit_stack_trace) +
- size * sizeof(void *) - sizeof(void *));
+ trace = (jit_stack_trace_t) jit_malloc(sizeof(struct jit_stack_trace)
+ + size * sizeof(void *)
+ - sizeof(void *));
if(!trace)
{
return 0;
/* Populate the stack trace with the items we counted earlier */
size = 0;
- item = top;
- while(item != 0)
- {
- trace->items[size] = item->pc;
- ++size;
- item = item->parent;
- }
-#else
- void *frame = jit_get_current_frame();
-
- /* Count the number of items in the current thread's call stack */
- while(frame != 0)
+ if(jit_unwind_init(&unwind, NULL))
{
- frame = jit_get_next_frame_address(frame);
- ++size;
+ do
+ {
+ trace->items[size] = jit_unwind_get_pc(&unwind);
+ size++;
+ }
+ while(jit_unwind_next_pc(&unwind));
+ jit_unwind_free(&unwind);
}
-
- /* Allocate memory for the stack trace */
- trace = (jit_stack_trace_t)jit_malloc
- (sizeof(struct jit_stack_trace) +
- size * sizeof(void *) - sizeof(void *));
- if(!trace)
+ else
{
+ jit_free(trace);
return 0;
}
- trace->size = size;
- /* Populate the stack trace with the items we counted earlier */
- size = 0;
- frame = jit_get_current_frame();
- while(frame != 0)
- {
- trace->items[size] = jit_get_return_address(frame);
- frame = jit_get_next_frame_address(frame);
- ++size;
- }
-#endif
return trace;
}
}
}
}
- return JIT_CACHE_NO_OFFSET;
+ return JIT_NO_OFFSET;
}
/*@
--- /dev/null
+/*
+ * jit-unwind.c - Routines for performing stack unwinding.
+ *
+ * Copyright (C) 2008 Southern Storm Software, Pty Ltd.
+ *
+ * This file is part of the libjit library.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "jit-internal.h"
+#include "jit-cache.h"
+#include "jit-rules.h"
+#include "jit-apply-rules.h"
+#include <jit/jit-unwind.h>
+#include <jit/jit-walk.h>
+
+int
+jit_unwind_init(jit_unwind_context_t *unwind, jit_context_t context)
+{
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+ jit_thread_control_t control;
+
+ control = _jit_thread_get_control();
+ if(!control)
+ {
+ return 0;
+ }
+
+ unwind->frame = control->backtrace_head;
+#elif JIT_FAST_GET_CURRENT_FRAME != 0
+ unwind->frame = jit_get_next_frame_address(jit_get_current_frame());
+#else
+ unwind->frame = jit_get_frame_address(1);
+#endif
+
+ unwind->context = context;
+ unwind->cache = 0;
+
+#ifdef _JIT_ARCH_UNWIND_INIT
+ _JIT_ARCH_UNWIND_INIT(unwind);
+#endif
+
+ return (unwind->frame != 0);
+}
+
+void
+jit_unwind_free(jit_unwind_context_t *unwind)
+{
+#ifdef _JIT_ARCH_UNWIND_FREE
+ _JIT_ARCH_UNWIND_FREE(unwind);
+#endif
+}
+
+int
+jit_unwind_next(jit_unwind_context_t *unwind)
+{
+#if defined(_JIT_ARCH_UNWIND_NEXT) || defined(_JIT_ARCH_UNWIND_NEXT_PRE)
+ jit_function_t func;
+#endif
+
+ if(!unwind || !unwind->frame)
+ {
+ return 0;
+ }
+
+ unwind->cache = 0;
+
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+ unwind->frame = ((jit_backtrace_t) unwind->frame)->parent;
+ return (unwind->frame != 0);
+#else
+
+#ifdef _JIT_ARCH_UNWIND_NEXT_PRE
+ func = jit_unwind_get_function(unwind);
+ if(func)
+ {
+ _JIT_ARCH_UNWIND_NEXT_PRE(unwind, func);
+ }
+#endif
+
+ unwind->frame = jit_get_next_frame_address(unwind->frame);
+ if(!unwind->frame)
+ {
+ return 0;
+ }
+
+#ifdef _JIT_ARCH_UNWIND_NEXT
+ func = jit_unwind_get_function(unwind);
+ if(func)
+ {
+ _JIT_ARCH_UNWIND_NEXT(unwind, func);
+ }
+#endif
+
+ return 1;
+#endif
+}
+
+int
+jit_unwind_next_pc(jit_unwind_context_t *unwind)
+{
+ if(!unwind || !unwind->frame)
+ {
+ return 0;
+ }
+
+ unwind->cache = 0;
+
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+ unwind->frame = ((jit_backtrace_t) unwind->frame)->parent;
+#else
+ unwind->frame = jit_get_next_frame_address(unwind->frame);
+#endif
+ return (unwind->frame != 0);
+}
+
+void *
+jit_unwind_get_pc(jit_unwind_context_t *unwind)
+{
+ if(!unwind || !unwind->frame)
+ {
+ return 0;
+ }
+
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+ return ((jit_backtrace_t) unwind->frame)->pc;
+#else
+ return jit_get_return_address(unwind->frame);
+#endif
+}
+
+int
+jit_unwind_jump(jit_unwind_context_t *unwind, void *pc)
+{
+#ifdef _JIT_ARCH_UNWIND_JUMP
+ if(!unwind || !unwind->frame || !pc)
+ {
+ return 0;
+ }
+
+ return _JIT_ARCH_UNWIND_JUMP(unwind, pc);
+#else
+ return 0;
+#endif
+}
+
+jit_function_t
+jit_unwind_get_function(jit_unwind_context_t *unwind)
+{
+ if(!unwind || !unwind->frame || !unwind->context)
+ {
+ return 0;
+ }
+
+ if(!unwind->cache)
+ {
+ jit_cache_t cache = _jit_context_get_cache(unwind->context);
+ void *pc = jit_unwind_get_pc(unwind);
+ unwind->cache = (jit_function_t)
+ _jit_cache_get_method(cache, pc, NULL);
+ }
+
+ return (jit_function_t) unwind->cache;
+}
+
+unsigned int
+jit_unwind_get_offset(jit_unwind_context_t *unwind)
+{
+ jit_function_t func;
+ jit_cache_t cache;
+ void *pc, *start;
+
+ if(!unwind || !unwind->frame || !unwind->context)
+ {
+ return JIT_NO_OFFSET;
+ }
+
+ pc = jit_unwind_get_pc(unwind);
+ if(!pc)
+ {
+ return JIT_NO_OFFSET;
+ }
+
+ func = jit_unwind_get_function(unwind);
+ if(!func)
+ {
+ return JIT_NO_OFFSET;
+ }
+
+ cache = _jit_context_get_cache(unwind->context);
+
+#ifdef JIT_PROLOG_SIZE
+ start = _jit_cache_get_start_method(cache, func->entry_point);
+#else
+ start = func->entry_point;
+#endif
+
+ return _jit_cache_get_bytecode(cache, start, pc - start, 0);
+}