This options enable detailed information dump on method incokation
This includes:
 * method's return address and calling method's signature
 * target method entry address
 * 'this' pointer value and actual class name
 * actual invkoation arguments

Example:

trace invoke: 
java/lang/StringBuffer.append(Ljava/lang/String;)Ljava/lang/StringBuffer;
        entry   : 0xa7c76dc0
        ret     : 0xa7c7640d (java/lang/Throwable.toString()Ljava/lang/String;)
        this    : 0x81f9a78 (java/lang/StringBuffer)
        args    :
           J_REFERENCE : 0x81f9d68 = ": hello" (java/lang/String)

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/jit/args.h     |    1 +
 include/jit/compiler.h |    2 +
 include/vm/types.h     |    1 +
 jit/args.c             |   32 +++++++++++++
 jit/method.c           |    8 +++
 jit/trace-jit.c        |  118 +++++++++++++++++++++++++++++++++++++++++++++++-
 vm/jato.c              |    3 +
 vm/types.c             |   22 +++++++++
 8 files changed, 186 insertions(+), 1 deletions(-)

diff --git a/include/jit/args.h b/include/jit/args.h
index 9e15a20..265c43f 100644
--- a/include/jit/args.h
+++ b/include/jit/args.h
@@ -7,5 +7,6 @@
 
 struct expression *insert_arg(struct expression *root, struct expression 
*expr);
 struct expression *convert_args(struct stack *mimic_stack, unsigned long 
nr_args);
+const char *parse_method_args(const char *type_str, enum vm_type *vmtype);
 
 #endif
diff --git a/include/jit/compiler.h b/include/jit/compiler.h
index 439a020..7743a89 100644
--- a/include/jit/compiler.h
+++ b/include/jit/compiler.h
@@ -82,6 +82,7 @@ static inline unsigned long cu_native_size(struct 
compilation_unit *cu)
 }
 
 bool is_native(unsigned long eip);
+bool is_on_heap(unsigned long addr);
 
 void fixup_direct_calls(struct jit_trampoline *trampoline, unsigned long 
target);
 
@@ -95,6 +96,7 @@ extern bool opt_trace_machine_code;
 extern bool opt_trace_magic_trampoline;
 extern bool opt_trace_bytecode_offset;
 extern bool opt_trace_invoke;
+extern bool opt_trace_invoke_dtls;
 
 void trace_magic_trampoline(struct compilation_unit *);
 void trace_method(struct compilation_unit *);
diff --git a/include/vm/types.h b/include/vm/types.h
index f5bf6e7..204a6ee 100644
--- a/include/vm/types.h
+++ b/include/vm/types.h
@@ -22,5 +22,6 @@ extern enum vm_type get_method_return_type(char *);
 int count_arguments(const char *);
 enum vm_type bytecode_type_to_vmtype(int);
 int get_vmtype_size(enum vm_type);
+const char *get_vm_type_name(enum vm_type);
 
 #endif
diff --git a/jit/args.c b/jit/args.c
index 9ccac87..131a0d0 100644
--- a/jit/args.c
+++ b/jit/args.c
@@ -61,3 +61,35 @@ convert_args(struct stack *mimic_stack, unsigned long 
nr_args)
   out:
        return args_list;
 }
+
+const char *parse_method_args(const char *type_str, enum vm_type *vmtype)
+{
+       char type_name[] = { "X" };
+
+       if (*type_str == '(')
+               type_str++;
+
+       if (*type_str == ')')
+               return NULL;
+
+       if (*type_str == '[') {
+               *vmtype = J_REFERENCE;
+               type_str++;
+
+               if (*type_str != 'L') {
+                       return type_str + 1;
+               }
+       }
+
+       if (*type_str == 'L') {
+               ++type_str;
+               while (*(type_str++) != ';')
+                       ;
+               *vmtype = J_REFERENCE;
+       } else {
+               type_name[0] = *(type_str++);
+               *vmtype = str_to_type(type_name);
+       }
+
+       return type_str;
+}
diff --git a/jit/method.c b/jit/method.c
index e63b9e5..db1a4a1 100644
--- a/jit/method.c
+++ b/jit/method.c
@@ -49,6 +49,14 @@ bool is_native(unsigned long eip)
        return !is_jit_text((void *)eip);
 }
 
+/*
+ * Checks whether given address is on heap
+ */
+bool is_on_heap(unsigned long addr)
+{
+       return addr >= (unsigned long)&end && addr < (unsigned long)sbrk(0);
+}
+
 const char *method_symbol(struct vm_method *method, char *symbol, size_t size)
 {
        snprintf(symbol, size, "%s.%s%s", method->class->name, method->name, 
method->type);
diff --git a/jit/trace-jit.c b/jit/trace-jit.c
index 19118f1..fa3a75b 100644
--- a/jit/trace-jit.c
+++ b/jit/trace-jit.c
@@ -12,8 +12,12 @@
 #include <jit/basic-block.h>
 #include <jit/disassemble.h>
 #include <jit/lir-printer.h>
+#include <jit/cu-mapping.h>
 #include <jit/statement.h>
 #include <jit/vars.h>
+#include <jit/args.h>
+#include <vm/java_lang.h>
+#include <vm/object.h>
 
 #include <vm/buffer.h>
 #include <vm/class.h>
@@ -21,7 +25,8 @@
 #include <vm/string.h>
 #include <vm/vm.h>
 
-#include <stdbool.h>
+#include <malloc.h>
+#include <stdlib.h>
 #include <stdio.h>
 
 bool opt_trace_method;
@@ -34,6 +39,7 @@ bool opt_trace_machine_code;
 bool opt_trace_magic_trampoline;
 bool opt_trace_bytecode_offset;
 bool opt_trace_invoke;
+bool opt_trace_invoke_dtls;
 
 void trace_method(struct compilation_unit *cu)
 {
@@ -261,10 +267,120 @@ void trace_magic_trampoline(struct compilation_unit *cu)
               cu->method->method_index);
 }
 
+static void print_arg(enum vm_type arg_type, const unsigned long *args,
+                     int *arg_index)
+{
+       if (arg_type == J_LONG || arg_type == J_DOUBLE) {
+               unsigned long long value;
+
+               value = *(unsigned long long*)(args + *arg_index);
+               (*arg_index) += 2;
+
+               printf("0x%llx", value);
+               return;
+       }
+
+       printf("0x%lx ", args[*arg_index]);
+
+       if (arg_type == J_REFERENCE) {
+               struct vm_object *obj;
+
+               obj = (struct vm_object *)args[*arg_index];
+
+               if (!obj) {
+                       printf("null");
+                       goto out;
+               }
+
+               if (!is_on_heap((unsigned long)obj)) {
+                       printf("*** pointer not on heap ***");
+                       goto out;
+               }
+
+               if (obj->class == vm_java_lang_String) {
+                       char *str;
+
+                       str = vm_string_to_cstr(obj);
+                       printf("= \"%s\"", str);
+                       free(str);
+               }
+
+               printf(" (%s)", obj->class->name);
+       }
+
+ out:
+       (*arg_index)++;
+       printf("\n");
+}
+
+static void trace_invoke_args(struct vm_method *vmm,
+                             struct jit_stack_frame *frame)
+{
+       enum vm_type arg_type;
+       const char *type_str;
+       int arg_index;
+
+       arg_index = 0;
+
+       if (!vm_method_is_static(vmm)) {
+               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");
+               return;
+       }
+
+       printf("\targs\t:\n");
+
+       while ((type_str = parse_method_args(type_str, &arg_type))) {
+               printf("\t   %-12s: ", get_vm_type_name(arg_type));
+               print_arg(arg_type, frame->args, &arg_index);
+       }
+}
+
+static void trace_return_address(struct jit_stack_frame *frame)
+{
+       printf("\tret\t: %p", (void*)frame->return_address);
+
+       if (is_native(frame->return_address)) {
+               printf(" (native)\n");
+       } else {
+               struct compilation_unit *cu;
+               struct vm_method *vmm;
+               struct vm_class *vmc;
+
+               cu = get_cu_from_native_addr(frame->return_address);
+               if (!cu) {
+                       printf(" (no compilation unit mapping)\n");
+                       return;
+               }
+
+               vmm = cu->method;;
+               vmc = vmm->class;
+
+               printf(" (%s.%s%s)\n", vmc->name, vmm->name, vmm->type );
+       }
+}
+
+
 void trace_invoke(struct compilation_unit *cu)
 {
        struct vm_method *vmm = cu->method;
        struct vm_class *vmc = vmm->class;
 
        printf("trace invoke: %s.%s%s\n", vmc->name, vmm->name, vmm->type);
+
+       if (opt_trace_invoke_dtls) {
+               struct jit_stack_frame *frame;
+
+               frame =  __builtin_frame_address(1);
+
+               printf("\tentry\t: %p\n", buffer_ptr(cu->objcode));
+               trace_return_address(frame);
+               trace_invoke_args(vmm, frame);
+       }
 }
diff --git a/vm/jato.c b/vm/jato.c
index 52ddf5b..3c17cdd 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -415,6 +415,9 @@ main(int argc, char *argv[])
                        opt_trace_classloader = true;
                } else if (!strcmp(argv[i], "-Xtrace:invoke")) {
                        opt_trace_invoke = true;
+               } else if (!strcmp(argv[i], "-Xtrace:invoke-dtls")) {
+                       opt_trace_invoke = true;
+                       opt_trace_invoke_dtls = true;
                } else if (!strcmp(argv[i], "-Xtrace:jit")) {
                        opt_trace_method = true;
                        opt_trace_cfg = true;
diff --git a/vm/types.c b/vm/types.c
index 9cb72b4..8d5ab0b 100644
--- a/vm/types.c
+++ b/vm/types.c
@@ -1,3 +1,4 @@
+#include <vm/system.h>
 #include <vm/types.h>
 #include <vm/die.h>
 #include <vm/vm.h>
@@ -171,3 +172,24 @@ int get_vmtype_size(enum vm_type type)
                error("type has no size");
        }
 }
+
+static const char *vm_type_names[] = {
+       [J_VOID] = "J_VOID",
+       [J_REFERENCE] = "J_REFERENCE",
+       [J_BYTE] = "J_BYTE",
+       [J_SHORT] = "J_SHORT",
+       [J_INT] = "J_INT",
+       [J_LONG] = "J_LONG",
+       [J_CHAR] = "J_CHAR",
+       [J_FLOAT] = "J_FLOAT",
+       [J_DOUBLE] = "J_DOUBLE",
+       [J_BOOLEAN] = "J_BOOLEAN",
+       [J_RETURN_ADDRESS] = "J_RETURN_ADDRESS"
+};
+
+const char *get_vm_type_name(enum vm_type type) {
+       if (type < 0 || type >= ARRAY_SIZE(vm_type_names))
+               return NULL;
+
+       return vm_type_names[type];
+}
-- 
1.6.0.6


------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to