The -Xtrace:bytecode option enables dump of disassembled bytecode along with the exception table. This dumps are especially usefull in debugging code which has been modified by inlining procedures.
Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- include/jit/compiler.h | 3 ++ include/jit/exception.h | 4 +++ include/vm/bytecodes.h | 9 ++++++- jit/compiler.c | 3 ++ jit/exception.c | 32 +++++++++++++++++++++++++++++++ jit/trace-jit.c | 14 +++++++++++++ vm/bytecodes.c | 48 ++++++++++++++++++++++++++++++++++++++++++++-- vm/jato.c | 7 ++++++ 8 files changed, 115 insertions(+), 5 deletions(-) diff --git a/include/jit/compiler.h b/include/jit/compiler.h index 11df1be..f56371f 100644 --- a/include/jit/compiler.h +++ b/include/jit/compiler.h @@ -10,6 +10,7 @@ #include <pthread.h> #include <stdbool.h> +struct vm_method; struct compilation_unit; struct expression; struct statement; @@ -97,6 +98,7 @@ extern bool opt_trace_bytecode_offset; extern bool opt_trace_invoke; extern bool opt_trace_invoke_verbose; extern bool opt_trace_exceptions; +extern bool opt_trace_bytecode; void trace_magic_trampoline(struct compilation_unit *); void trace_method(struct compilation_unit *); @@ -111,5 +113,6 @@ void trace_exception(struct compilation_unit *, struct jit_stack_frame *, unsign void trace_exception_handler(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 *); #endif diff --git a/include/jit/exception.h b/include/jit/exception.h index 813866b..ea5f7e6 100644 --- a/include/jit/exception.h +++ b/include/jit/exception.h @@ -14,9 +14,11 @@ #include "vm/method.h" #include "vm/vm.h" +struct cafebabe_code_attribute_exception; struct compilation_unit; struct jit_stack_frame; struct vm_object; +struct vm_method; /* * This is a per-thread pointer to a memory location which should be @@ -62,6 +64,8 @@ int signal_new_exception_with_cause(struct vm_class *vmc, void clear_exception(void); void init_exceptions(void); void thread_init_exceptions(void); +void print_exception_table(const struct vm_method *, + const struct cafebabe_code_attribute_exception *, int); static inline bool exception_covers(struct cafebabe_code_attribute_exception *eh, unsigned long offset) diff --git a/include/vm/bytecodes.h b/include/vm/bytecodes.h index 6671ac2..d71b1b3 100644 --- a/include/vm/bytecodes.h +++ b/include/vm/bytecodes.h @@ -3,17 +3,22 @@ #include <stdbool.h> -unsigned long bc_insn_size(unsigned char *); +unsigned long bc_insn_size(const unsigned char *); bool bc_is_branch(unsigned char); bool bc_is_goto(unsigned char); bool bc_is_wide(unsigned char); -long bc_target_off(unsigned char *); +long bc_target_off(const unsigned char *); bool bc_is_athrow(unsigned char); bool bc_is_return(unsigned char); +void bytecode_disassemble(const unsigned char *, unsigned long); + static inline bool bc_branches_to_follower(unsigned char code) { return bc_is_branch(code) && !bc_is_goto(code); } +#define bytecode_for_each_insn(code, code_length, pc) \ + for (pc = 0; pc < (code_length); pc += bc_insn_size(&(code)[(pc)])) + #endif diff --git a/jit/compiler.c b/jit/compiler.c index 525652e..2f40f7e 100644 --- a/jit/compiler.c +++ b/jit/compiler.c @@ -53,6 +53,9 @@ int compile(struct compilation_unit *cu) if (opt_trace_method) trace_method(cu); + if (opt_trace_bytecode) + trace_bytecode(cu->method); + err = analyze_control_flow(cu); if (err) goto out; diff --git a/jit/exception.c b/jit/exception.c index 649bedf..641a7f8 100644 --- a/jit/exception.c +++ b/jit/exception.c @@ -288,3 +288,35 @@ throw_exception_from(struct compilation_unit *cu, struct jit_stack_frame *frame, return bb_native_ptr(cu->unwind_bb); } + +void +print_exception_table(const struct vm_method *method, + const struct cafebabe_code_attribute_exception *exception_table, + int exception_table_length) +{ + if (exception_table_length == 0) { + printf("\t(empty)\n"); + return; + } + + 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, + eh->handler_pc); + + if (!eh->catch_type) { + printf("all\n"); + return; + } + + const struct vm_class *catch_class; + catch_class = vm_class_resolve_class(method->class, + eh->catch_type); + + printf("Class %s\n", catch_class->name); + } +} diff --git a/jit/trace-jit.c b/jit/trace-jit.c index a7b4d3a..8a64912 100644 --- a/jit/trace-jit.c +++ b/jit/trace-jit.c @@ -19,6 +19,7 @@ #include "jit/args.h" #include "vm/preload.h" #include "vm/object.h" +#include "vm/bytecodes.h" #include "lib/buffer.h" #include "vm/class.h" @@ -44,6 +45,7 @@ bool opt_trace_bytecode_offset; bool opt_trace_invoke; bool opt_trace_invoke_verbose; bool opt_trace_exceptions; +bool opt_trace_bytecode; void trace_method(struct compilation_unit *cu) { @@ -438,3 +440,15 @@ void trace_exception_unwind_to_native(struct jit_stack_frame *frame) printf("\taction\t: unwind to native caller at %p\n", (void*)frame->return_address); } + +void trace_bytecode(struct vm_method *method) +{ + printf("Code:\n"); + bytecode_disassemble(method->code_attribute.code, + method->code_attribute.code_length); + printf("Exception table:\n"); + print_exception_table(method, + method->code_attribute.exception_table, + method->code_attribute.exception_table_length); + printf("\n"); +} diff --git a/vm/bytecodes.c b/vm/bytecodes.c index 0378b20..20b7098 100644 --- a/vm/bytecodes.c +++ b/vm/bytecodes.c @@ -10,10 +10,14 @@ #include "vm/vm.h" #include "vm/bytecode.h" #include "vm/bytecodes.h" +#include "vm/die.h" +#include "vm/opcodes.h" #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <ctype.h> enum bytecode_type { BYTECODE_NORMAL = 0x01, @@ -26,10 +30,11 @@ enum bytecode_type { struct bytecode_info { unsigned char size; enum bytecode_type type; + const char *name; }; #define BYTECODE(__opc, __name, __size, __type) \ - [__opc] = { .size = __size, .type = __type }, + [__opc] = { .size = __size, .name = #__opc, .type = __type }, static struct bytecode_info bytecode_infos[] = { # include <vm/bytecode-def.h> @@ -37,7 +42,7 @@ static struct bytecode_info bytecode_infos[] = { #undef BYTECODE -unsigned long bc_insn_size(unsigned char *bc_start) +unsigned long bc_insn_size(const unsigned char *bc_start) { unsigned long size; @@ -81,7 +86,7 @@ bool bc_is_return(unsigned char opc) * bc_target_off - Return branch opcode target offset. * @code: start of branch bytecode. */ -long bc_target_off(unsigned char *code) +long bc_target_off(const unsigned char *code) { unsigned char opc = *code; @@ -90,3 +95,40 @@ long bc_target_off(unsigned char *code) return read_s16(code + 1); } + +void bytecode_disassemble(const unsigned char *code, unsigned long size) +{ + unsigned long pc; + + bytecode_for_each_insn(code, size, pc) { + const char *opc_name; + char tmp_name[16]; + int size; + int i; + + opc_name = bytecode_infos[code[pc]].name + 4; + size = bc_insn_size(&code[pc]); + + for (i = 0; *opc_name; opc_name++, i++) + tmp_name[i] = tolower(*opc_name); + + tmp_name[i] = 0; + + printf(" [ %-3ld ] ", pc); + + if (size > 1) + printf("%-14s", tmp_name); + else + printf("%s", tmp_name); + + if (bc_is_branch(code[pc])) { + 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]); + + printf("\n"); + } +} diff --git a/vm/jato.c b/vm/jato.c index 1cd81a5..5420dfc 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -449,6 +449,12 @@ static void handle_trace_jit(void) opt_trace_bytecode_offset = true; } +static void handle_trace_bytecode(void) +{ + opt_trace_bytecode = true; + opt_trace_method = true; +} + static void handle_trace_trampoline(void) { opt_trace_magic_trampoline = true; @@ -488,6 +494,7 @@ const struct option options[] = { DEFINE_OPTION("Xtrace:itable", handle_trace_itable), DEFINE_OPTION("Xtrace:jit", handle_trace_jit), DEFINE_OPTION("Xtrace:trampoline", handle_trace_trampoline), + DEFINE_OPTION("Xtrace:bytecode", handle_trace_bytecode), }; static const struct option *get_option(const char *name) -- 1.6.0.6 ------------------------------------------------------------------------------ Enter the BlackBerry Developer Challenge This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel