Motivation: Exception manager will need to translate native instruction pointers to bytecode offsets to select appropriate exception handler from exception_table.
This solution uses a per-thread variable to store the current bytecode offset, which is set before converting a bytecode and before selecting instructions for a tree node. HIR (struct expression, struct statement) and LIR (struct insn) entities upon allocation assign that variable's value to 'bytecode_offset' field. Signed-off-by: Tomek Grabiec <[email protected]> --- Makefile | 3 +- arch/x86/include/arch/instruction.h | 3 + arch/x86/insn-selector_32.brg | 3 + arch/x86/instruction.c | 2 + include/jit/bc-offset-mapping.h | 19 ++++++ include/jit/expression.h | 5 ++ include/jit/statement.h | 4 + jit/bc-offset-mapping.c | 114 +++++++++++++++++++++++++++++++++++ jit/bytecode-to-ir.c | 6 ++ jit/expression.c | 2 + jit/spill-reload.c | 4 + jit/statement.c | 2 + test/arch-x86/Makefile | 1 + test/include/arch/instruction.h | 5 ++ test/jit/Makefile | 1 + vm/jato.c | 2 + 16 files changed, 175 insertions(+), 1 deletions(-) create mode 100644 include/jit/bc-offset-mapping.h create mode 100644 jit/bc-offset-mapping.c diff --git a/Makefile b/Makefile index 9dd15c9..ee2587f 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,8 @@ JIT_OBJS = \ jit/typeconv-bc.o \ jit/vtable.o \ jit/fixup-site.o \ - jit/exception.o + jit/exception.o \ + jit/bc-offset-mapping.o VM_OBJS = \ vm/bitset.o \ diff --git a/arch/x86/include/arch/instruction.h b/arch/x86/include/arch/instruction.h index ec5f4cb..a27b24b 100644 --- a/arch/x86/include/arch/instruction.h +++ b/arch/x86/include/arch/instruction.h @@ -120,6 +120,9 @@ struct insn { /* Position of this instruction in LIR. */ unsigned long lir_pos; bool escaped; + + /* Offset of bytecode instruction from which this one comes from */ + unsigned long bytecode_offset; }; static inline unsigned long lir_position(struct use_position *reg) diff --git a/arch/x86/insn-selector_32.brg b/arch/x86/insn-selector_32.brg index 9dcc26c..46fe6a0 100644 --- a/arch/x86/insn-selector_32.brg +++ b/arch/x86/insn-selector_32.brg @@ -13,6 +13,7 @@ #include <jit/emulate.h> #include <jit/expression.h> #include <jit/statement.h> +#include <jit/bc-offset-mapping.h> #include <arch/instruction.h> #include <arch/stack-frame.h> @@ -1313,7 +1314,9 @@ static void emit_code(struct basic_block *bb, MBState *state, int goal) for (i = 0; nts[i]; i++) emit_code(bb, kids[i], nts[i]); + set_current_bytecode_offset(tree_bytecode_offset(state->tree)); mono_burg_emit(ern, state, state->tree, bb); + set_current_bytecode_offset(BC_OFFSET_UNKNOWN); } static void free_state(MBState *state) diff --git a/arch/x86/instruction.c b/arch/x86/instruction.c index 624651a..4d9418f 100644 --- a/arch/x86/instruction.c +++ b/arch/x86/instruction.c @@ -25,6 +25,7 @@ */ #include <arch/instruction.h> +#include <jit/bc-offset-mapping.h> #include <stdlib.h> #include <string.h> @@ -37,6 +38,7 @@ struct insn *alloc_insn(enum insn_type type) INIT_LIST_HEAD(&insn->insn_list_node); INIT_LIST_HEAD(&insn->branch_list_node); insn->type = type; + insn->bytecode_offset = get_current_bytecode_offset(); } return insn; } diff --git a/include/jit/bc-offset-mapping.h b/include/jit/bc-offset-mapping.h new file mode 100644 index 0000000..2485a39 --- /dev/null +++ b/include/jit/bc-offset-mapping.h @@ -0,0 +1,19 @@ +#ifndef _BC_OFFSET_MAPPING_ +#define _BC_OFFSET_MAPPING_ + +#include <jit/compilation-unit.h> +#include <jit/tree-node.h> +#include <vm/string.h> +#include <limits.h> + +#define BC_OFFSET_UNKNOWN ULONG_MAX + +void init_bytecode_offset_mapping(void); +unsigned long get_current_bytecode_offset(void); +void set_current_bytecode_offset(unsigned long bc_offset); +unsigned long native_ptr_to_bytecode_offset(struct compilation_unit *cu, + unsigned char *native_ptr); +void print_bytecode_offset(unsigned long bc_offset, struct string *str); +unsigned long tree_bytecode_offset(struct tree_node *node); + +#endif diff --git a/include/jit/expression.h b/include/jit/expression.h index cba8209..81e8989 100644 --- a/include/jit/expression.h +++ b/include/jit/expression.h @@ -76,6 +76,11 @@ enum unary_operator { struct expression { unsigned long refcount; enum vm_type vm_type; + + /* Offset of bytecode instruction from which this expression + comes from */ + unsigned long bytecode_offset; + union { struct tree_node node; diff --git a/include/jit/statement.h b/include/jit/statement.h index f87abc0..cdbc2f6 100644 --- a/include/jit/statement.h +++ b/include/jit/statement.h @@ -23,6 +23,10 @@ enum statement_type { }; struct statement { + /* Offset of bytecode instruction from which this statement + comes from */ + unsigned long bytecode_offset; + union { struct tree_node node; diff --git a/jit/bc-offset-mapping.c b/jit/bc-offset-mapping.c new file mode 100644 index 0000000..e6a9906 --- /dev/null +++ b/jit/bc-offset-mapping.c @@ -0,0 +1,115 @@ +/* + * 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 <jit/bc-offset-mapping.h> +#include <jit/statement.h> +#include <jit/expression.h> + +#include <vm/string.h> +#include <vm/buffer.h> + +#include <arch/instruction.h> + +#include <pthread.h> +#include <malloc.h> + +static pthread_key_t bytecode_offset_key; + +static void key_descructor(void *value) +{ + free(value); + pthread_setspecific(bytecode_offset_key, NULL); +} + +void init_bytecode_offset_mapping(void) +{ + pthread_key_create(&bytecode_offset_key, key_descructor); +} + +static unsigned long *get_current(void) +{ + unsigned long *current; + + current = pthread_getspecific(bytecode_offset_key); + if (current == NULL) { + current = malloc(sizeof(unsigned long)); + pthread_setspecific(bytecode_offset_key, current); + + *current = BC_OFFSET_UNKNOWN; + } + + return current; +} + +unsigned long get_current_bytecode_offset(void) +{ + unsigned long *current = get_current(); + + return *current; +} + +void set_current_bytecode_offset(unsigned long bytecode_offset) +{ + unsigned long *current = get_current(); + + *current = bytecode_offset; +} + +unsigned long native_ptr_to_bytecode_offset(struct compilation_unit *cu, + unsigned char *native_ptr) +{ + unsigned char *method_ptr = buffer_ptr(cu->objcode); + struct basic_block *bb; + struct insn *insn; + + for_each_basic_block(bb, &cu->bb_list) { + for_each_insn(insn, &bb->insn_list) { + if (method_ptr + insn->mach_offset == native_ptr) + return insn->bytecode_offset; + } + } + + return BC_OFFSET_UNKNOWN; +} + +void print_bytecode_offset(unsigned long bytecode_offset, struct string *str) +{ + if (bytecode_offset == BC_OFFSET_UNKNOWN) + str_append(str, "?"); + else { + static char buf[32]; + sprintf(buf, "%ld", bytecode_offset); + str_append(str, buf); + } +} + +unsigned long tree_bytecode_offset(struct tree_node *node) +{ + if (node_is_stmt(node)) + return to_stmt(node)->bytecode_offset; + + return to_expr(node)->bytecode_offset; +} diff --git a/jit/bytecode-to-ir.c b/jit/bytecode-to-ir.c index 8680efa..854d28b 100644 --- a/jit/bytecode-to-ir.c +++ b/jit/bytecode-to-ir.c @@ -11,6 +11,7 @@ #include <jit/compiler.h> #include <jit/statement.h> #include <jit/expression.h> +#include <jit/bc-offset-mapping.h> #include <vm/bytecode.h> #include <vm/bytecodes.h> @@ -297,9 +298,14 @@ int convert_to_ir(struct compilation_unit *cu) int err = 0; while (ctx.offset < ctx.code_size) { + set_current_bytecode_offset(ctx.offset); + err = parse_bytecode_insn(&ctx); if (err) break; } + + set_current_bytecode_offset(BC_OFFSET_UNKNOWN); + return err; } diff --git a/jit/expression.c b/jit/expression.c index 8a37502..42dce3f 100644 --- a/jit/expression.c +++ b/jit/expression.c @@ -6,6 +6,7 @@ */ #include <jit/expression.h> +#include <jit/bc-offset-mapping.h> #include <vm/vm.h> #include <vm/method.h> #include <stdlib.h> @@ -21,6 +22,7 @@ struct expression *alloc_expression(enum expression_type type, expr->node.op = type << EXPR_TYPE_SHIFT; expr->vm_type = vm_type; expr->refcount = 1; + expr->bytecode_offset = get_current_bytecode_offset(); } return expr; } diff --git a/jit/spill-reload.c b/jit/spill-reload.c index 14e1758..f8d3230 100644 --- a/jit/spill-reload.c +++ b/jit/spill-reload.c @@ -63,6 +63,8 @@ static int insert_spill_insn(struct live_interval *interval, struct compilation_ interval->spill_slot = slot; + spill->bytecode_offset = last->bytecode_offset; + list_add(&spill->insn_list_node, &last->insn_list_node); return 0; @@ -89,6 +91,8 @@ static int insert_reload_insn(struct live_interval *interval, struct compilation if (!reload) return -ENOMEM; + reload->bytecode_offset = first->bytecode_offset; + list_add_tail(&reload->insn_list_node, &first->insn_list_node); return 0; diff --git a/jit/statement.c b/jit/statement.c index 0c8ecf4..1e590d2 100644 --- a/jit/statement.c +++ b/jit/statement.c @@ -9,6 +9,7 @@ #include <assert.h> #include <jit/expression.h> #include <jit/statement.h> +#include <jit/bc-offset-mapping.h> #include <stdlib.h> #include <string.h> @@ -19,6 +20,7 @@ struct statement *alloc_statement(enum statement_type type) memset(stmt, 0, sizeof *stmt); INIT_LIST_HEAD(&stmt->stmt_list_node); stmt->node.op = type << STMT_TYPE_SHIFT; + stmt->bytecode_offset = get_current_bytecode_offset(); } return stmt; diff --git a/test/arch-x86/Makefile b/test/arch-x86/Makefile index 5014de5..8ab76d4 100644 --- a/test/arch-x86/Makefile +++ b/test/arch-x86/Makefile @@ -43,6 +43,7 @@ OBJS = \ ../../jit/statement.o \ ../../jit/tree-printer.o \ ../../jit/fixup-site.o \ + ../../jit/bc-offset-mapping.o \ ../../arch/x86/emit-code$(ARCH_POSTFIX).o \ ../../arch/x86/instruction.o \ ../../arch/x86/insn-selector$(ARCH_POSTFIX).o \ diff --git a/test/include/arch/instruction.h b/test/include/arch/instruction.h index d9776ca..bf61c74 100644 --- a/test/include/arch/instruction.h +++ b/test/include/arch/instruction.h @@ -52,8 +52,13 @@ struct insn { struct operand operand; }; struct list_head insn_list_node; + /* Offset in machine code. */ + unsigned long mach_offset; /* Position of this instruction in LIR. */ unsigned long lir_pos; + + /* Offset of bytecode instruction from which this one comes from */ + unsigned long bytecode_offset; }; static inline unsigned long lir_position(struct use_position *reg) diff --git a/test/jit/Makefile b/test/jit/Makefile index 1fb21d9..89d1489 100644 --- a/test/jit/Makefile +++ b/test/jit/Makefile @@ -34,6 +34,7 @@ OBJS = \ ../../jit/tree-printer.o \ ../../jit/args.o \ ../../jit/exception.o \ + ../../jit/bc-offset-mapping.o \ ../libharness/libharness.o \ ../jamvm/alloc-stub.o \ ../jamvm/resolve-stub.o \ diff --git a/vm/jato.c b/vm/jato.c index 8598648..f52bb40 100644 --- a/vm/jato.c +++ b/vm/jato.c @@ -29,6 +29,7 @@ #include <vm/signal.h> #include <vm/vm.h> #include <jit/compiler.h> +#include <jit/bc-offset-mapping.h> #ifdef USE_ZIP #define BCP_MESSAGE "<jar/zip files and directories separated by :>" @@ -293,6 +294,7 @@ int main(int argc, char *argv[]) { exe_name = argv[0]; setup_signal_handlers(); + init_bytecode_offset_mapping(); setDefaultInitArgs(&args); int class_arg = parseCommandLine(argc, argv, &args); -- 1.6.0.6 ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Jatovm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/jatovm-devel
