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

Reply via email to