This fixes incorrect lock order reported by helgrind: ==7951== Thread #1: lock order "0x5277F84 before 0x55D7D64" violated ==7951== at 0x4026125: pthread_mutex_lock (in /usr/lib/valgrind/x86-linux/vgpreload_helgrind.so) ==7951== by 0x80563BE: fixup_direct_calls (emit-code.c:355) ==7951== by 0x8082A83: jit_magic_trampoline (trampoline.c:161) ==7951== by 0x88D741C: ??? ==7951== by 0x88D79F9: ??? ==7951== Required order was established by acquisition of lock at 0x5277F84 ==7951== at 0x4026125: pthread_mutex_lock (in /usr/lib/valgrind/x86-linux/vgpreload_helgrind.so) ==7951== by 0x80829E0: jit_magic_trampoline (trampoline.c:125) ==7951== by 0x88D00CC: ??? ==7951== by 0x88D73CC: ??? ==7951== followed by a later acquisition of lock at 0x55D7D64 ==7951== at 0x4026125: pthread_mutex_lock (in /usr/lib/valgrind/x86-linux/vgpreload_helgrind.so) ==7951== by 0x8076801: trampoline_add_fixup_site (fixup-site.c:53) ==7951== by 0x805DA8B: invoke (insn-selector.c:754) ==7951== by 0x8063A08: mono_burg_emit (insn-selector.c:3094) ==7951== by 0x805E139: emit_code (insn-selector.c:869) ==7951== by 0x805E37E: insn_select (insn-selector.c:920) ==7951== by 0x805E4D4: select_instructions (insn-selector.c:970) ==7951== by 0x8073303: compile (compiler.c:80) ==7951== by 0x80828A3: jit_java_trampoline (trampoline.c:97) ==7951== by 0x8082A25: jit_magic_trampoline (trampoline.c:135) ==7951== by 0x88D00CC: ??? ==7951== by 0x88D73CC: ???
Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- arch/x86/emit-code.c | 12 +++--------- arch/x86/insn-selector.brg | 6 +++--- include/jit/compilation-unit.h | 1 + include/jit/compiler.h | 11 +++++++++-- jit/compilation-unit.c | 18 ++++++++++++++++++ jit/emit.c | 12 ++++++++++++ jit/fixup-site.c | 27 +++++++++++++++++++++++---- test/jit/Makefile | 1 + 8 files changed, 70 insertions(+), 18 deletions(-) diff --git a/arch/x86/emit-code.c b/arch/x86/emit-code.c index ea96a03..f7b2e2a 100644 --- a/arch/x86/emit-code.c +++ b/arch/x86/emit-code.c @@ -338,11 +338,9 @@ void fixup_direct_calls(struct jit_trampoline *t, unsigned long target) pthread_mutex_lock(&t->mutex); - list_for_each_entry_safe(this, next, &t->fixup_site_list, - fixup_list_node) { + list_for_each_entry_safe(this, next, &t->fixup_site_list, trampoline_node) { unsigned char *site_addr; uint32_t new_target; - bool is_compiled; /* * It is possible that we're fixing calls to @@ -352,18 +350,14 @@ void fixup_direct_calls(struct jit_trampoline *t, unsigned long target) * be set yet. We should skip fixing callsites coming * from not yet compiled methods. . */ - pthread_mutex_lock(&this->cu->mutex); - is_compiled = this->cu->is_compiled; - pthread_mutex_unlock(&this->cu->mutex); - - if (!is_compiled) + if (!fixup_site_is_ready(this)) continue; site_addr = fixup_site_addr(this); new_target = target - ((unsigned long) site_addr + CALL_INSN_SIZE); cpu_write_u32(site_addr+1, new_target); - list_del(&this->fixup_list_node); + list_del(&this->trampoline_node); free_fixup_site(this); } diff --git a/arch/x86/insn-selector.brg b/arch/x86/insn-selector.brg index 8eead10..5383368 100644 --- a/arch/x86/insn-selector.brg +++ b/arch/x86/insn-selector.brg @@ -3207,9 +3207,9 @@ static void invoke(struct basic_block *s, struct tree_node *tree) if (!is_compiled) { struct fixup_site *fixup; - fixup = alloc_fixup_site(); - fixup->cu = s->b_parent; - fixup->relcall_insn = call_insn; + fixup = alloc_fixup_site(s->b_parent, call_insn); + if (!fixup) + error("out of memory"); trampoline_add_fixup_site(method->trampoline, fixup); } diff --git a/include/jit/compilation-unit.h b/include/jit/compilation-unit.h index c3f55b1..4bfd9d8 100644 --- a/include/jit/compilation-unit.h +++ b/include/jit/compilation-unit.h @@ -62,6 +62,7 @@ struct compilation_unit { unsigned char *unwind_bb_ptr; struct list_head static_fixup_site_list; + struct list_head call_fixup_site_list; struct list_head tableswitch_list; struct list_head lookupswitch_list; diff --git a/include/jit/compiler.h b/include/jit/compiler.h index 6e1196a..7e5796b 100644 --- a/include/jit/compiler.h +++ b/include/jit/compiler.h @@ -19,12 +19,17 @@ struct statement; struct buffer; struct fixup_site { + pthread_mutex_t mutex; + bool ready; + + struct jit_trampoline *target; /* Compilation unit to which relcall_insn belongs */ struct compilation_unit *cu; /* We need this, because we don't have native pointer at instruction selection */ struct insn *relcall_insn; - struct list_head fixup_list_node; + struct list_head trampoline_node; + struct list_head cu_node; }; struct jit_trampoline { @@ -65,10 +70,12 @@ void *jit_magic_trampoline(struct compilation_unit *); struct jit_trampoline *alloc_jit_trampoline(void); struct jit_trampoline *build_jit_trampoline(struct compilation_unit *); void free_jit_trampoline(struct jit_trampoline *); -struct fixup_site *alloc_fixup_site(void); +struct fixup_site *alloc_fixup_site(struct compilation_unit *, struct insn *); void free_fixup_site(struct fixup_site *); void trampoline_add_fixup_site(struct jit_trampoline *, struct fixup_site *); unsigned char *fixup_site_addr(struct fixup_site *); +bool fixup_site_is_ready(struct fixup_site *); +void prepare_call_fixup_sites(struct compilation_unit *); const char *method_symbol(struct vm_method *method, char *symbol, size_t len); diff --git a/jit/compilation-unit.c b/jit/compilation-unit.c index 24c5738..e0c4be3 100644 --- a/jit/compilation-unit.c +++ b/jit/compilation-unit.c @@ -95,6 +95,7 @@ struct compilation_unit *compilation_unit_alloc(struct vm_method *method) goto out_of_memory; INIT_LIST_HEAD(&cu->static_fixup_site_list); + INIT_LIST_HEAD(&cu->call_fixup_site_list); INIT_LIST_HEAD(&cu->tableswitch_list); INIT_LIST_HEAD(&cu->lookupswitch_list); @@ -162,6 +163,22 @@ static void free_lookupswitch_list(struct compilation_unit *cu) } } +static void free_call_fixup_sites(struct compilation_unit *cu) +{ + struct fixup_site *this, *next; + + list_for_each_entry_safe(this, next, &cu->call_fixup_site_list, cu_node) + { + list_del(&this->cu_node); + + pthread_mutex_lock(&this->target->mutex); + list_del(&this->trampoline_node); + pthread_mutex_unlock(&this->target->mutex); + + free_fixup_site(this); + } +} + static void free_lir_insn_map(struct compilation_unit *cu) { free_radix_tree(cu->lir_insn_map); @@ -178,6 +195,7 @@ void free_compilation_unit(struct compilation_unit *cu) { struct basic_block *bb, *tmp_bb; + free_call_fixup_sites(cu); shrink_compilation_unit(cu); list_for_each_entry_safe(bb, tmp_bb, &cu->bb_list, bb_list_node) diff --git a/jit/emit.c b/jit/emit.c index ee5c4d9..de0a1ec 100644 --- a/jit/emit.c +++ b/jit/emit.c @@ -152,6 +152,17 @@ static void emit_resolution_blocks(struct basic_block *bb, struct buffer *buf) } } +void prepare_call_fixup_sites(struct compilation_unit *cu) +{ + struct fixup_site *site; + + list_for_each_entry(site, &cu->call_fixup_site_list, cu_node) { + pthread_mutex_lock(&site->mutex); + site->ready = true; + pthread_mutex_unlock(&site->mutex); + } +} + int emit_machine_code(struct compilation_unit *cu) { unsigned long frame_size; @@ -196,6 +207,7 @@ int emit_machine_code(struct compilation_unit *cu) emit_resolution_blocks(bb, cu->objcode); } + prepare_call_fixup_sites(cu); backpatch_tableswitch_targets(cu); backpatch_lookupswitch_targets(cu); build_exception_handlers_table(cu); diff --git a/jit/fixup-site.c b/jit/fixup-site.c index 0d38d8a..ee48681 100644 --- a/jit/fixup-site.c +++ b/jit/fixup-site.c @@ -26,24 +26,32 @@ #include "jit/compiler.h" #include "arch/instruction.h" +#include "vm/stdlib.h" + #include <memory.h> #include <malloc.h> -struct fixup_site *alloc_fixup_site(void) +struct fixup_site * +alloc_fixup_site(struct compilation_unit *cu, struct insn *call_insn) { struct fixup_site *site; - site = malloc(sizeof(*site)); + site = zalloc(sizeof(*site)); if (!site) return NULL; - memset(site, 0, sizeof(*site)); + site->cu = cu; + site->relcall_insn = call_insn; + + list_add(&site->cu_node, &cu->call_fixup_site_list); + pthread_mutex_init(&site->mutex, NULL); return site; } void free_fixup_site(struct fixup_site *site) { + pthread_mutex_destroy(&site->mutex); free(site); } @@ -51,7 +59,7 @@ void trampoline_add_fixup_site(struct jit_trampoline *trampoline, struct fixup_site *site) { pthread_mutex_lock(&trampoline->mutex); - list_add_tail(&site->fixup_list_node, &trampoline->fixup_site_list); + list_add_tail(&site->trampoline_node, &trampoline->fixup_site_list); pthread_mutex_unlock(&trampoline->mutex); } @@ -59,3 +67,14 @@ unsigned char *fixup_site_addr(struct fixup_site *site) { return buffer_ptr(site->cu->objcode) + site->relcall_insn->mach_offset; } + +bool fixup_site_is_ready(struct fixup_site *site) +{ + bool result; + + pthread_mutex_lock(&site->mutex); + result = site->ready; + pthread_mutex_unlock(&site->mutex); + + return result; +} diff --git a/test/jit/Makefile b/test/jit/Makefile index 3bb8aa1..17c8a4c 100644 --- a/test/jit/Makefile +++ b/test/jit/Makefile @@ -24,6 +24,7 @@ TOPLEVEL_OBJS := \ jit/exception-bc.o \ jit/exception.o \ jit/expression.o \ + jit/fixup-site.o \ jit/interval.o \ jit/invoke-bc.o \ jit/linear-scan.o \ -- 1.6.3.3 ------------------------------------------------------------------------------ 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