Each thread has its own trace buffer to which strings are printed with trace_pritnf(). When trace_flush() is called the buffer's content is printed to stderr. trace_flush() is synchronized with other threads.
if -Xtrace:threads is passed to jato, every line of trace will be printed with trailing current thread's name. Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- Makefile | 1 + arch/x86/backtrace.c | 3 + arch/x86/disassemble.c | 12 ++- include/jit/compiler.h | 4 +- include/vm/trace.h | 7 ++ jit/compiler.c | 4 + jit/exception.c | 11 +- jit/trace-jit.c | 239 ++++++++++++++++++++++-------------------------- test/arch-x86/Makefile | 1 + test/jit/Makefile | 2 + test/jit/trace-stub.c | 1 + test/vm/Makefile | 5 +- test/vm/thread-stub.c | 8 ++ vm/bytecodes.c | 17 ++-- vm/classloader.c | 8 +- vm/jato.c | 9 ++ vm/stack-trace.c | 25 +++-- vm/trace.c | 101 ++++++++++++++++++++ 18 files changed, 293 insertions(+), 165 deletions(-) create mode 100644 include/vm/trace.h create mode 100644 test/vm/thread-stub.c create mode 100644 vm/trace.c diff --git a/Makefile b/Makefile index c037fb8..1cdc587 100644 --- a/Makefile +++ b/Makefile @@ -114,6 +114,7 @@ VM_OBJS = \ vm/stack-trace.o \ vm/static.o \ vm/thread.o \ + vm/trace.o \ vm/types.o \ vm/utf8.o \ vm/zalloc.o \ diff --git a/arch/x86/backtrace.c b/arch/x86/backtrace.c index aaa0615..64e5ccd 100644 --- a/arch/x86/backtrace.c +++ b/arch/x86/backtrace.c @@ -38,6 +38,7 @@ #include "vm/class.h" #include "vm/method.h" #include "vm/stack-trace.h" +#include "vm/trace.h" /* get REG_EIP from ucontext.h */ #include <ucontext.h> @@ -241,5 +242,7 @@ void print_backtrace_and_die(int sig, siginfo_t *info, void *secret) print_trace_from(eip, (void *) ebp); + trace_flush(); + exit(1); } diff --git a/arch/x86/disassemble.c b/arch/x86/disassemble.c index 67ae90b..095ebac 100644 --- a/arch/x86/disassemble.c +++ b/arch/x86/disassemble.c @@ -36,6 +36,8 @@ #include "jit/compiler.h" #include "lib/string.h" +#include "vm/trace.h" + #include <assert.h> #include <dis-asm.h> #include <stdarg.h> @@ -84,25 +86,25 @@ unsigned char *disassinstr(struct compilation_unit *cu, unsigned char *code) bc_offset = native_ptr_to_bytecode_offset(cu, code); print_bytecode_offset(bc_offset, str); - printf("[ %5s ]", str->value); + trace_printf("[ %5s ]", str->value); free_str(str); } - printf(" 0x%08lx: ", (unsigned long) code); + trace_printf(" 0x%08lx: ", (unsigned long) code); disass_len = 0; seqlen = print_insn_i386((bfd_vma) (unsigned long) code, &info); for (i = 0; i < seqlen; i++, code++) { - printf("%02x ", *code); + trace_printf("%02x ", *code); } for (; i < 8; i++) { - printf(" "); + trace_printf(" "); } - printf(" %s\n", disass_buf); + trace_printf(" %s\n", disass_buf); return code; } diff --git a/include/jit/compiler.h b/include/jit/compiler.h index a781730..087a795 100644 --- a/include/jit/compiler.h +++ b/include/jit/compiler.h @@ -101,6 +101,8 @@ extern bool opt_trace_invoke; extern bool opt_trace_invoke_verbose; extern bool opt_trace_exceptions; extern bool opt_trace_bytecode; +extern bool opt_trace_compile; +extern bool opt_trace_threads; void trace_magic_trampoline(struct compilation_unit *); void trace_method(struct compilation_unit *); @@ -116,7 +118,5 @@ void trace_exception_handler(struct compilation_unit *, unsigned char *); void trace_exception_unwind(struct jit_stack_frame *); void trace_exception_unwind_to_native(struct jit_stack_frame *); void trace_bytecode(struct vm_method *); -void trace_begin(void); -void trace_end(void); #endif diff --git a/include/vm/trace.h b/include/vm/trace.h new file mode 100644 index 0000000..79959ea --- /dev/null +++ b/include/vm/trace.h @@ -0,0 +1,7 @@ +#ifndef _VM_TRACE_H +#define _VM_TRACE_H + +int trace_printf(const char *fmt, ...); +void trace_flush(void); + +#endif /* _VM_TRACE_H */ diff --git a/jit/compiler.c b/jit/compiler.c index fa3deaa..e88dd55 100644 --- a/jit/compiler.c +++ b/jit/compiler.c @@ -17,6 +17,7 @@ #include "vm/class.h" #include "vm/method.h" +#include "vm/trace.h" #include <errno.h> #include <stdlib.h> @@ -120,6 +121,9 @@ int compile(struct compilation_unit *cu) perf_append_cu(cu); out: + if (opt_trace_compile) + trace_flush(); + if (err) compile_error(cu, err); return err; diff --git a/jit/exception.c b/jit/exception.c index c5a7160..13f4800 100644 --- a/jit/exception.c +++ b/jit/exception.c @@ -43,6 +43,7 @@ #include "vm/object.h" #include "vm/preload.h" #include "vm/thread.h" +#include "vm/trace.h" #include "arch/stack-frame.h" #include "arch/instruction.h" @@ -317,21 +318,21 @@ print_exception_table(const struct vm_method *method, int exception_table_length) { if (exception_table_length == 0) { - printf("\t(empty)\n"); + trace_printf("\t(empty)\n"); return; } - printf("\tfrom\tto\ttarget\ttype\n"); + trace_printf("\tfrom\tto\ttarget\ttype\n"); for (int i = 0; i < exception_table_length; i++) { const struct cafebabe_code_attribute_exception *eh; eh = &exception_table[i]; - printf("\t%d\t%d\t%d\t", eh->start_pc, eh->end_pc, + trace_printf("\t%d\t%d\t%d\t", eh->start_pc, eh->end_pc, eh->handler_pc); if (!eh->catch_type) { - printf("all\n"); + trace_printf("all\n"); return; } @@ -339,6 +340,6 @@ print_exception_table(const struct vm_method *method, catch_class = vm_class_resolve_class(method->class, eh->catch_type); - printf("Class %s\n", catch_class->name); + trace_printf("Class %s\n", catch_class->name); } } diff --git a/jit/trace-jit.c b/jit/trace-jit.c index 37fe6d4..8a3eaa9 100644 --- a/jit/trace-jit.c +++ b/jit/trace-jit.c @@ -20,6 +20,7 @@ #include "vm/preload.h" #include "vm/object.h" #include "vm/bytecodes.h" +#include "vm/trace.h" #include "lib/buffer.h" #include "vm/class.h" @@ -47,39 +48,8 @@ bool opt_trace_invoke; bool opt_trace_invoke_verbose; bool opt_trace_exceptions; bool opt_trace_bytecode; - -static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER; - -static void print_current_thread(void) -{ - struct vm_object *thread; - struct vm_object *name; - struct vm_thread *self; - - self = vm_thread_self(); - if (!self) - return; - - thread = vm_thread_get_java_thread(self); - - name = field_get_object(thread, vm_java_lang_Thread_name); - - char * name_s; - - name_s = vm_string_to_cstr(name); - printf("[thread: %s] ", name_s); - free(name_s); -} - -void trace_begin(void) -{ - pthread_mutex_lock(&trace_mutex); - print_current_thread(); -} - -void trace_end(void) { - pthread_mutex_unlock(&trace_mutex); -} +bool opt_trace_compile; +bool opt_trace_threads; void trace_method(struct compilation_unit *cu) { @@ -87,11 +57,11 @@ void trace_method(struct compilation_unit *cu) unsigned char *p; unsigned int i, j; - printf("\nTRACE: %s.%s%s\n", + trace_printf("\nTRACE: %s.%s%s\n", method->class->name, method->name, method->type); - printf("Length: %d\n", method->code_attribute.code_length); - printf("Code:\n"); + trace_printf("Length: %d\n", method->code_attribute.code_length); + trace_printf("Code:\n"); p = method->code_attribute.code; unsigned int n = method->code_attribute.code_length; @@ -105,62 +75,62 @@ void trace_method(struct compilation_unit *cu) break; } - printf("[ %04u ] ", i * 16); + trace_printf("[ %04u ] ", i * 16); for (j = 0; j < cols; ++j) { - printf("%02x%s", + trace_printf("%02x%s", p[i * 16 + j], j == 7 ? " " : " "); } - printf("\n"); + trace_printf("\n"); } - printf("\n\n"); + trace_printf("\n\n"); } void trace_cfg(struct compilation_unit *cu) { struct basic_block *bb; - printf("Control Flow Graph:\n\n"); - printf(" #:\t\tRange\t\tSuccessors\t\tPredecessors\n"); + trace_printf("Control Flow Graph:\n\n"); + trace_printf(" #:\t\tRange\t\tSuccessors\t\tPredecessors\n"); for_each_basic_block(bb, &cu->bb_list) { unsigned long i; - printf(" %p\t%lu..%lu\t", bb, bb->start, bb->end); + trace_printf(" %p\t%lu..%lu\t", bb, bb->start, bb->end); if (bb->is_eh) - printf(" (eh)"); + trace_printf(" (eh)"); - printf("\t"); + trace_printf("\t"); for (i = 0; i < bb->nr_successors; i++) { if (i != 0) - printf(", "); + trace_printf(", "); - printf("%p", bb->successors[i]); + trace_printf("%p", bb->successors[i]); } if (i == 0) - printf("none "); + trace_printf("none "); - printf("\t"); + trace_printf("\t"); for (i = 0; i < bb->nr_predecessors; i++) { if (i != 0) - printf(", "); + trace_printf(", "); - printf("%p", bb->predecessors[i]); + trace_printf("%p", bb->predecessors[i]); } if (i == 0) - printf("none "); + trace_printf("none "); - printf("\n"); + trace_printf("\n"); } - printf("\n"); + trace_printf("\n"); } void trace_tree_ir(struct compilation_unit *cu) @@ -169,17 +139,17 @@ void trace_tree_ir(struct compilation_unit *cu) struct statement *stmt; struct string *str; - printf("High-Level Intermediate Representation (HIR):\n\n"); + trace_printf("High-Level Intermediate Representation (HIR):\n\n"); for_each_basic_block(bb, &cu->bb_list) { - printf("[bb %p]:\n\n", bb); + trace_printf("[bb %p]:\n\n", bb); for_each_stmt(stmt, &bb->stmt_list) { str = alloc_str(); tree_print(&stmt->node, str); - printf("%s", str->value); + trace_printf("%s", str->value); free_str(str); } - printf("\n"); + trace_printf("\n"); } } @@ -190,11 +160,11 @@ void trace_lir(struct compilation_unit *cu) struct string *str; struct insn *insn; - printf("Low-Level Intermediate Representation (LIR):\n\n"); + trace_printf("Low-Level Intermediate Representation (LIR):\n\n"); - printf("Bytecode LIR\n"); - printf("offset offset Instruction Operands\n"); - printf("--------- ------- ----------- --------\n"); + trace_printf("Bytecode LIR\n"); + trace_printf("offset offset Instruction Operands\n"); + trace_printf("--------- ------- ----------- --------\n"); for_each_basic_block(bb, &cu->bb_list) { for_each_insn(insn, &bb->insn_list) { @@ -209,16 +179,16 @@ void trace_lir(struct compilation_unit *cu) print_bytecode_offset(bc_offset, bc_str); - printf("[ %5s ] ", bc_str->value); + trace_printf("[ %5s ] ", bc_str->value); free_str(bc_str); } - printf(" %5lu: %s\n", offset++, str->value); + trace_printf(" %5lu: %s\n", offset++, str->value); free_str(str); } } - printf("\n"); + trace_printf("\n"); } static void @@ -229,7 +199,7 @@ print_var_liveness(struct compilation_unit *cu, struct var_info *var) unsigned long offset; struct insn *insn; - printf(" %2lu: ", var->vreg); + trace_printf(" %2lu: ", var->vreg); offset = 0; for_each_basic_block(bb, &cu->bb_list) { @@ -237,24 +207,24 @@ print_var_liveness(struct compilation_unit *cu, struct var_info *var) if (in_range(range, offset)) { if (next_use_pos(var->interval, offset) == offset) { /* In use */ - printf("UUU"); + trace_printf("UUU"); } else { if (var->interval->reg == REG_UNASSIGNED) - printf("***"); + trace_printf("***"); else - printf("---"); + trace_printf("---"); } } else - printf(" "); + trace_printf(" "); offset++; } } if (!range_is_empty(range)) - printf(" (start: %2lu, end: %2lu)\n", range->start, range->end); + trace_printf(" (start: %2lu, end: %2lu)\n", range->start, range->end); else - printf(" (empty)\n"); + trace_printf(" (empty)\n"); } void trace_liveness(struct compilation_unit *cu) @@ -264,83 +234,85 @@ void trace_liveness(struct compilation_unit *cu) unsigned long offset; struct insn *insn; - printf("Liveness:\n\n"); + trace_printf("Liveness:\n\n"); - printf("Legend: (U) In use, (-) Fixed register, (*) Non-fixed register\n\n"); + trace_printf("Legend: (U) In use, (-) Fixed register, (*) Non-fixed register\n\n"); - printf(" "); + trace_printf(" "); offset = 0; for_each_basic_block(bb, &cu->bb_list) { for_each_insn(insn, &bb->insn_list) { - printf("%-2lu ", offset++); + trace_printf("%-2lu ", offset++); } } - printf("\n"); + trace_printf("\n"); for_each_variable(var, cu->var_infos) print_var_liveness(cu, var); - printf("\n"); + trace_printf("\n"); } void trace_regalloc(struct compilation_unit *cu) { struct var_info *var; - printf("Register Allocation:\n\n"); + trace_printf("Register Allocation:\n\n"); for_each_variable(var, cu->var_infos) { struct live_interval *interval; for (interval = var->interval; interval != NULL; interval = interval->next_child) { - printf(" %2lu (pos: %2ld-%2lu):", var->vreg, (signed long)interval->range.start, interval->range.end); - printf("\t%s", reg_name(interval->reg)); - printf("\t%s", interval->fixed_reg ? "fixed\t" : "non-fixed"); + trace_printf(" %2lu (pos: %2ld-%2lu):", var->vreg, (signed long)interval->range.start, interval->range.end); + trace_printf("\t%s", reg_name(interval->reg)); + trace_printf("\t%s", interval->fixed_reg ? "fixed\t" : "non-fixed"); if (interval->need_spill) { unsigned long ndx = -1; if (interval->spill_slot) ndx = interval->spill_slot->index; - printf("\tspill (%ld)", ndx); + trace_printf("\tspill (%ld)", ndx); } else - printf("\tno spill "); + trace_printf("\tno spill "); if (interval->need_reload) { unsigned long ndx = -1; if (interval->spill_parent && interval->spill_parent->spill_slot) ndx = interval->spill_parent->spill_slot->index; - printf("\treload (%ld)", ndx); + trace_printf("\treload (%ld)", ndx); } else - printf("\tno reload "); - printf("\n"); + trace_printf("\tno reload "); + trace_printf("\n"); } } - printf("\n"); + trace_printf("\n"); } void trace_machine_code(struct compilation_unit *cu) { void *start, *end; - printf("Disassembler Listing:\n\n"); + trace_printf("Disassembler Listing:\n\n"); start = buffer_ptr(cu->objcode); end = buffer_current(cu->objcode); disassemble(cu, start, end); - printf("\n"); + trace_printf("\n"); } void trace_magic_trampoline(struct compilation_unit *cu) { - printf("jit_magic_trampoline: ret0=%p, ret1=%p: %s.%s #%d\n", + trace_printf("jit_magic_trampoline: ret0=%p, ret1=%p: %s.%s #%d\n", __builtin_return_address(1), __builtin_return_address(2), cu->method->class->name, cu->method->name, cu->method->method_index); + + trace_flush(); } static void print_arg(enum vm_type arg_type, const unsigned long *args, @@ -352,11 +324,11 @@ static void print_arg(enum vm_type arg_type, const unsigned long *args, value = *(unsigned long long*)(args + *arg_index); (*arg_index) += 2; - printf("0x%llx", value); + trace_printf("0x%llx", value); return; } - printf("0x%lx ", args[*arg_index]); + trace_printf("0x%lx ", args[*arg_index]); if (arg_type == J_REFERENCE) { struct vm_object *obj; @@ -364,12 +336,12 @@ static void print_arg(enum vm_type arg_type, const unsigned long *args, obj = (struct vm_object *)args[*arg_index]; if (!obj) { - printf("null"); + trace_printf("null"); goto out; } if (!is_on_heap((unsigned long)obj)) { - printf("*** pointer not on heap ***"); + trace_printf("*** pointer not on heap ***"); goto out; } @@ -377,16 +349,16 @@ static void print_arg(enum vm_type arg_type, const unsigned long *args, char *str; str = vm_string_to_cstr(obj); - printf("= \"%s\"", str); + trace_printf("= \"%s\"", str); free(str); } - printf(" (%s)", obj->class->name); + trace_printf(" (%s)", obj->class->name); } out: (*arg_index)++; - printf("\n"); + trace_printf("\n"); } static void trace_invoke_args(struct vm_method *vmm, @@ -402,21 +374,21 @@ static void trace_invoke_args(struct vm_method *vmm, arg_index = 0; if (!vm_method_is_static(vmm)) { - printf("\tthis\t: "); + trace_printf("\tthis\t: "); print_arg(J_REFERENCE, frame->args, &arg_index); } type_str = vmm->type; if (!strncmp(type_str, "()", 2)) { - printf("\targs\t: none\n"); + trace_printf("\targs\t: none\n"); return; } - printf("\targs\t:\n"); + trace_printf("\targs\t:\n"); while ((type_str = parse_method_args(type_str, &arg_type))) { - printf("\t %-12s: ", get_vm_type_name(arg_type)); + trace_printf("\t %-12s: ", get_vm_type_name(arg_type)); print_arg(arg_type, frame->args, &arg_index); } } @@ -429,23 +401,23 @@ static void print_source_and_line(struct compilation_unit *cu, source_file = cu->method->class->source_file_name; if (source_file) - printf("%s", source_file); + trace_printf("%s", source_file); else - printf("UNKNOWN"); + trace_printf("UNKNOWN"); pc = native_ptr_to_bytecode_offset(cu, ptr); if (pc == BC_OFFSET_UNKNOWN) return; - printf(":%d", bytecode_offset_to_line_no(cu->method, pc)); + trace_printf(":%d", bytecode_offset_to_line_no(cu->method, pc)); } static void trace_return_address(struct jit_stack_frame *frame) { - printf("\tret\t: %p:", (void*)frame->return_address); + trace_printf("\tret\t: %p:", (void*)frame->return_address); if (is_native(frame->return_address)) { - printf(" (native)\n"); + trace_printf(" (native)\n"); } else { struct compilation_unit *cu; struct vm_method *vmm; @@ -453,17 +425,17 @@ static void trace_return_address(struct jit_stack_frame *frame) cu = jit_lookup_cu(frame->return_address); if (!cu) { - printf(" (no compilation unit mapping)\n"); + trace_printf(" (no compilation unit mapping)\n"); return; } vmm = cu->method;; vmc = vmm->class; - printf(" %s.%s%s\n", vmc->name, vmm->name, vmm->type ); - printf("\t\t ("); + trace_printf(" %s.%s%s\n", vmc->name, vmm->name, vmm->type ); + trace_printf("\t\t ("); print_source_and_line(cu, (void *) frame->return_address); - printf(")\n"); + trace_printf(")\n"); } } @@ -472,21 +444,20 @@ void trace_invoke(struct compilation_unit *cu) struct vm_method *vmm = cu->method; struct vm_class *vmc = vmm->class; - trace_begin(); - - printf("trace invoke: %s.%s%s\n", vmc->name, vmm->name, vmm->type); + trace_printf("trace invoke: %s.%s%s\n", vmc->name, vmm->name, + vmm->type); if (opt_trace_invoke_verbose) { struct jit_stack_frame *frame; frame = __builtin_frame_address(1); - printf("\tentry\t: %p\n", buffer_ptr(cu->objcode)); + trace_printf("\tentry\t: %p\n", buffer_ptr(cu->objcode)); trace_return_address(frame); trace_invoke_args(vmm, frame); } - trace_end(); + trace_flush(); } void trace_exception(struct compilation_unit *cu, struct jit_stack_frame *frame, @@ -503,23 +474,27 @@ void trace_exception(struct compilation_unit *cu, struct jit_stack_frame *frame, exception = exception_occurred(); assert(exception); - printf("trace exception: exception object %p (%s) thrown\n", + trace_printf("trace exception: exception object %p (%s) thrown\n", exception, exception->class->name); - printf("\tfrom\t: %p: %s.%s%s\n", native_ptr, vmc->name, vmm->name, + trace_printf("\tfrom\t: %p: %s.%s%s\n", native_ptr, vmc->name, vmm->name, vmm->type); - printf("\t\t ("); + trace_printf("\t\t ("); print_source_and_line(cu, native_ptr); - printf(")\n"); + trace_printf(")\n"); + + /* XXX: trace is flushed in one of the action tracers. */ } void trace_exception_handler(struct compilation_unit *cu, unsigned char *ptr) { - printf("\taction\t: jump to handler at %p\n", ptr); - printf("\t\t ("); + trace_printf("\taction\t: jump to handler at %p\n", ptr); + trace_printf("\t\t ("); print_source_and_line(cu, ptr); - printf(")\n"); + trace_printf(")\n"); + + trace_flush(); } void trace_exception_unwind(struct jit_stack_frame *frame) @@ -533,27 +508,31 @@ void trace_exception_unwind(struct jit_stack_frame *frame) vmm = cu->method; vmc = vmm->class; - printf("\taction\t: unwind to %p: %s.%s%s\n", + trace_printf("\taction\t: unwind to %p: %s.%s%s\n", (void*)frame->return_address, vmc->name, vmm->name, vmm->type); - printf("\t\t ("); + trace_printf("\t\t ("); print_source_and_line(cu, (void *) frame->return_address); - printf(")\n"); + trace_printf(")\n"); + + trace_flush(); } void trace_exception_unwind_to_native(struct jit_stack_frame *frame) { - printf("\taction\t: unwind to native caller at %p\n", + trace_printf("\taction\t: unwind to native caller at %p\n", (void*)frame->return_address); + + trace_flush(); } void trace_bytecode(struct vm_method *method) { - printf("Code:\n"); + trace_printf("Code:\n"); bytecode_disassemble(method->code_attribute.code, method->code_attribute.code_length); - printf("\nException table:\n"); + trace_printf("\nException table:\n"); print_exception_table(method, method->code_attribute.exception_table, method->code_attribute.exception_table_length); - printf("\n"); + trace_printf("\n"); } diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile index 078685d..de408a5 100644 --- a/test/arch-x86/Makefile +++ b/test/arch-x86/Makefile @@ -67,6 +67,7 @@ TOPLEVEL_OBJS := \ vm/stack-trace.o \ vm/static.o \ vm/thread.o \ + vm/trace.o \ vm/types.o \ vm/utf8.o \ vm/zalloc.o \ diff --git a/test/jit/Makefile b/test/jit/Makefile index 75055d7..dcf8e20 100644 --- a/test/jit/Makefile +++ b/test/jit/Makefile @@ -54,6 +54,7 @@ TOPLEVEL_OBJS := \ vm/die.o \ vm/guard-page.o \ vm/stack.o \ + vm/trace.o \ vm/types.o \ vm/zalloc.o \ arch/mmix/instruction.o \ @@ -67,6 +68,7 @@ TOPLEVEL_OBJS := \ test/vm/preload-stub.o \ test/vm/jni-stub.o \ test/vm/stack-trace-stub.o \ + test/vm/thread-stub.o \ test/jit/trace-stub.o TEST_OBJS := \ diff --git a/test/jit/trace-stub.c b/test/jit/trace-stub.c index 5b0d8bf..3883339 100644 --- a/test/jit/trace-stub.c +++ b/test/jit/trace-stub.c @@ -8,6 +8,7 @@ struct compilation_unit; bool opt_trace_invoke = false; bool opt_trace_exceptions = false; bool opt_trace_bytecode = false; +bool opt_trace_threads = false; void trace_invoke(struct compilation_unit *cu) { diff --git a/test/vm/Makefile b/test/vm/Makefile index b29df2a..c6a6c39 100644 --- a/test/vm/Makefile +++ b/test/vm/Makefile @@ -13,10 +13,13 @@ TOPLEVEL_OBJS := \ vm/die.o \ vm/natives.o \ vm/stack.o \ + vm/trace.o \ vm/types.o \ vm/zalloc.o \ test/libharness/libharness.o \ - test/vm/stack-trace-stub.o + test/jit/trace-stub.o \ + test/vm/stack-trace-stub.o \ + test/vm/thread-stub.o TEST_OBJS := \ bitset-test.o \ diff --git a/test/vm/thread-stub.c b/test/vm/thread-stub.c new file mode 100644 index 0000000..a511fcb --- /dev/null +++ b/test/vm/thread-stub.c @@ -0,0 +1,8 @@ +#include "vm/thread.h" + +__thread struct vm_exec_env current_exec_env; + +char *vm_thread_get_name(struct vm_thread *thread) +{ + return NULL; +} diff --git a/vm/bytecodes.c b/vm/bytecodes.c index 4d78d38..163a423 100644 --- a/vm/bytecodes.c +++ b/vm/bytecodes.c @@ -12,6 +12,9 @@ #include "vm/bytecodes.h" #include "vm/die.h" #include "vm/opcodes.h" +#include "vm/trace.h" + +#include "jit/compiler.h" #include <assert.h> #include <stdint.h> @@ -211,11 +214,11 @@ void bytecode_disassemble(const unsigned char *code, unsigned long size) size = bc_insn_size(&code[pc]); - printf(" [ %-3ld ] 0x%02x ", pc, code[pc]); + trace_printf(" [ %-3ld ] 0x%02x ", pc, code[pc]); opc_name = bc_get_insn_name(&code[pc]); if (!opc_name) { - printf("(string alloc failed)\n"); + trace_printf("(string alloc failed)\n"); continue; } @@ -227,20 +230,20 @@ void bytecode_disassemble(const unsigned char *code, unsigned long size) } if (size > 1) - printf("%-14s", opc_name); + trace_printf("%-14s", opc_name); else - printf("%s", opc_name); + trace_printf("%s", opc_name); free(opc_name); if (bc_is_branch(code[_pc])) { - printf(" %ld\n", bc_target_off(&code[_pc]) + _pc); + trace_printf(" %ld\n", bc_target_off(&code[_pc]) + _pc); continue; } for (int i = 1; i < size; i++) - printf(" 0x%02x", (unsigned int)code[_pc + i]); + trace_printf(" 0x%02x", (unsigned int)code[_pc + i]); - printf("\n"); + trace_printf("\n"); } } diff --git a/vm/classloader.c b/vm/classloader.c index 3f436af..b612c86 100644 --- a/vm/classloader.c +++ b/vm/classloader.c @@ -13,6 +13,7 @@ #include "vm/class.h" #include "vm/die.h" #include "vm/backtrace.h" +#include "vm/trace.h" bool opt_trace_classloader; static __thread int trace_classloader_level = 0; @@ -25,10 +26,9 @@ static inline void trace_push(const char *class_name) assert(trace_classloader_level >= 0); if (opt_trace_classloader) { - trace_begin(); - fprintf(stderr, "classloader: %*s%s\n", - trace_classloader_level, "", class_name); - trace_end(); + trace_printf("classloader: %*s%s\n", + trace_classloader_level, "", class_name); + trace_flush(); } ++trace_classloader_level; diff --git a/vm/jato.c b/vm/jato.c index 1319ba6..96f80ae 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -685,6 +685,7 @@ static void handle_trace_asm(void) { opt_trace_method = true; opt_trace_machine_code = true; + opt_trace_compile = true; } static void handle_trace_bytecode_offset(void) @@ -729,12 +730,19 @@ static void handle_trace_jit(void) opt_trace_machine_code = true; opt_trace_magic_trampoline = true; opt_trace_bytecode_offset = true; + opt_trace_compile = true; } static void handle_trace_bytecode(void) { opt_trace_bytecode = true; opt_trace_method = true; + opt_trace_compile = true; +} + +static void handle_trace_threads(void) +{ + opt_trace_threads = true; } static void handle_trace_trampoline(void) @@ -812,6 +820,7 @@ const struct option options[] = { DEFINE_OPTION("Xtrace:invoke-verbose", handle_trace_invoke_verbose), DEFINE_OPTION("Xtrace:itable", handle_trace_itable), DEFINE_OPTION("Xtrace:jit", handle_trace_jit), + DEFINE_OPTION("Xtrace:threads", handle_trace_threads), DEFINE_OPTION("Xtrace:trampoline", handle_trace_trampoline), }; diff --git a/vm/stack-trace.c b/vm/stack-trace.c index 95a8bf6..935a524 100644 --- a/vm/stack-trace.c +++ b/vm/stack-trace.c @@ -38,6 +38,7 @@ #include "vm/stack-trace.h" #include "vm/system.h" #include "vm/thread.h" +#include "vm/trace.h" #include "jit/bc-offset-mapping.h" #include "jit/cu-mapping.h" @@ -431,19 +432,19 @@ void print_java_stack_trace_elem(struct stack_trace_elem *elem) cu = stack_trace_elem_get_cu(elem); struct vm_method *vmm = cu->method; - printf("%s.%s", vmm->class->name, vmm->name); + trace_printf("%s.%s", vmm->class->name, vmm->name); if (vm_method_is_native(vmm)) { - printf("(Native Method)"); + trace_printf("(Native Method)"); return; } if (!vmm->class->source_file_name) { - printf("(Unknown Source)"); + trace_printf("(Unknown Source)"); return; } - printf("(%s", vmm->class->source_file_name); + trace_printf("(%s", vmm->class->source_file_name); if (elem->type == STACK_TRACE_ELEM_TYPE_TRAMPOLINE) bc_offset = 0; @@ -458,10 +459,10 @@ void print_java_stack_trace_elem(struct stack_trace_elem *elem) if (line_no == -1) goto out; - printf(":%d", line_no); + trace_printf(":%d", line_no); out: - printf(")"); + trace_printf(")"); } /** @@ -719,18 +720,18 @@ const char *stack_trace_elem_type_name(enum stack_trace_elem_type type) static void show_mixed_stack_trace(struct stack_trace_elem *elem) { - printf("Native and JAVA stack trace:\n"); + trace_printf("Native and JAVA stack trace:\n"); do { - printf(" [<%08lx>] %-10s : ", elem->addr, + trace_printf(" [<%08lx>] %-10s : ", elem->addr, stack_trace_elem_type_name(elem->type)); if (elem->type != STACK_TRACE_ELEM_TYPE_OTHER) { print_java_stack_trace_elem(elem); - printf("\n"); + trace_printf("\n"); - printf("%-27s"," "); + trace_printf("%-27s"," "); if (!show_exe_function((void *) elem->addr)) - printf("\r"); + trace_printf("\r"); continue; } @@ -749,6 +750,8 @@ void print_trace(void) stack_trace_elem_next(&elem); show_mixed_stack_trace(&elem); + + trace_flush(); } void print_trace_from(unsigned long eip, void *frame) diff --git a/vm/trace.c b/vm/trace.c new file mode 100644 index 0000000..6e8fc02 --- /dev/null +++ b/vm/trace.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2009 Tomasz Grabiec + * + * This file is released under the GPL version 2 with the following + * clarification and special exception: + * + * Linking this library statically or dynamically with other modules is + * making a combined work based on this library. Thus, the terms and + * conditions of the GNU General Public License cover the whole + * combination. + * + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules to produce an + * executable, regardless of the license terms of these independent + * modules, and to copy and distribute the resulting executable under terms + * of your choice, provided that you also meet, for each linked independent + * module, the terms and conditions of the license of that module. An + * independent module is a module which is not derived from or based on + * this library. If you modify this library, you may extend this exception + * to your version of the library, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + * Please refer to the file LICENSE for details. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "jit/compiler.h" + +#include "lib/string.h" + +#include "vm/die.h" +#include "vm/thread.h" +#include "vm/trace.h" + +static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Holds the trace output. It it initialized in trace_begin() and + printed in trace_end(). */ +static __thread struct string *trace_buffer = NULL; + +static void ensure_trace_buffer(void) +{ + if (trace_buffer) + return; + + trace_buffer = alloc_str(); + if (!trace_buffer) + error("out of memory"); +} + +int trace_printf(const char *fmt, ...) +{ + int err; + va_list args; + + ensure_trace_buffer(); + + va_start(args, fmt); + err = str_vappend(trace_buffer, fmt, args); + va_end(args); + return err; +} + +void trace_flush(void) { + struct vm_thread *self; + char *thread_name; + char *strtok_ptr; + char *line; + + ensure_trace_buffer(); + + self = vm_thread_self(); + if (self) + thread_name = vm_thread_get_name(self); + else + thread_name = "unknown"; + + pthread_mutex_lock(&trace_mutex); + + if (opt_trace_threads) { + line = strtok_r(trace_buffer->value, "\n", &strtok_ptr); + while (line) { + fprintf(stderr, "[%s] %s\n", thread_name, line); + + line = strtok_r(NULL, "\n", &strtok_ptr); + } + } else { + fprintf(stderr, "%s", trace_buffer->value); + } + + pthread_mutex_unlock(&trace_mutex); + + if (self) + free(thread_name); + + trace_buffer->length = 0; +} -- 1.6.0.6 ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel