[PATCH 1/2] jit: fix basic block splitting
On splitting a bb, the successors of the new bb were still pointing at the original bb. This caused the CFG to be inconsistent and subsequently also mimic stack spill/restore to do the wrong thing. This fixes the java.security.ProtectionDomain crash. Codebugged-by: Arthur Huillet Signed-off-by: Vegard Nossum --- jit/basic-block.c | 13 + 1 files changed, 13 insertions(+), 0 deletions(-) diff --git a/jit/basic-block.c b/jit/basic-block.c index c0ac458..6e8759b 100644 --- a/jit/basic-block.c +++ b/jit/basic-block.c @@ -117,6 +117,19 @@ struct basic_block *bb_split(struct basic_block *orig_bb, unsigned long offset) new_bb->predecessors = NULL; new_bb->nr_predecessors = 0; + /* The original successors' predecessors must be updated to point to +* the new basic block. */ + for (unsigned int i = 0, n = new_bb->nr_successors; i < n; ++i) { + struct basic_block *successor = new_bb->successors[i]; + + for (unsigned int j = 0, m = successor->nr_predecessors; + j < m; ++j) + { + if (successor->predecessors[j] == orig_bb) + successor->predecessors[j] = new_bb; + } + } + if (orig_bb->has_branch) { orig_bb->has_branch = false; new_bb->has_branch = true; -- 1.6.0.4 -- 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
[PATCH 2/2] regression: add CFGCrashTest
Signed-off-by: Vegard Nossum --- Makefile |1 + regression/jvm/CFGCrashTest.java | 16 regression/run-suite.sh |1 + 3 files changed, 18 insertions(+), 0 deletions(-) create mode 100644 regression/jvm/CFGCrashTest.java diff --git a/Makefile b/Makefile index 99d56ac..ede2d0c 100644 --- a/Makefile +++ b/Makefile @@ -226,6 +226,7 @@ REGRESSION_TEST_SUITE_CLASSES = \ regression/jvm/ArrayMemberTest.java \ regression/jvm/ArrayTest.java \ regression/jvm/BranchTest.java \ + regression/jvm/CFGCrashTest.java \ regression/jvm/ClassExceptionsTest.java \ regression/jvm/CloneTest.java \ regression/jvm/ControlTransferTest.java \ diff --git a/regression/jvm/CFGCrashTest.java b/regression/jvm/CFGCrashTest.java new file mode 100644 index 000..7215c75 --- /dev/null +++ b/regression/jvm/CFGCrashTest.java @@ -0,0 +1,16 @@ +package jvm; + +public class CFGCrashTest extends TestCase { +private CFGCrashTest[] x; + +public CFGCrashTest(boolean unused) { +if (x == null) +x = null; + +x = (x == null ? null : null); +} + +public static void main(String[] args) { +new CFGCrashTest(false); +} +} diff --git a/regression/run-suite.sh b/regression/run-suite.sh index 02e5126..c3f6f7e 100755 --- a/regression/run-suite.sh +++ b/regression/run-suite.sh @@ -48,6 +48,7 @@ if [ -z "$CLASS_LIST" ]; then run_java jvm.ArrayMemberTest 0 run_java jvm.ArrayTest 0 run_java jvm.BranchTest 0 +run_java jvm.CFGCrashTest 0 run_java jvm.ClassExceptionsTest 0 run_java jvm.CloneTest 0 run_java jvm.ControlTransferTest 0 -- 1.6.0.4 -- 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
[PATCH 2/3] vm: skip mutex unlock in classloader_load() when load_class() fails.
Mutex lock is not held when calling lead_class() so we should not try to unlock it when the call fails. Signed-off-by: Tomek Grabiec --- vm/classloader.c |8 +--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/vm/classloader.c b/vm/classloader.c index a0add9d..3f436af 100644 --- a/vm/classloader.c +++ b/vm/classloader.c @@ -467,7 +467,7 @@ struct vm_class *classloader_load(const char *class_name) &classloader_mutex); vmc = classes[class_index].class; - goto out; + goto out_unlock; } /* @@ -482,7 +482,7 @@ struct vm_class *classloader_load(const char *class_name) if (!new_array) { NOT_IMPLEMENTED; vmc = NULL; - goto out; + goto out_unlock; } max_classes = new_max_classes; @@ -517,8 +517,10 @@ struct vm_class *classloader_load(const char *class_name) * be worth to use a per-class condition variable for that? */ pthread_cond_broadcast(&classloader_cond); -out: + out_unlock: pthread_mutex_unlock(&classloader_mutex); + + out: trace_pop(); return vmc; } -- 1.6.0.6 -- 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
[PATCH 1/3] vm: fix vm_monitor_*wait() functions.
When falling asleep we must set the lock count to 0 and restore the count on wakeup. Signed-off-by: Tomek Grabiec --- vm/object.c | 18 -- 1 files changed, 12 insertions(+), 6 deletions(-) diff --git a/vm/object.c b/vm/object.c index 509e92d..e91c074 100644 --- a/vm/object.c +++ b/vm/object.c @@ -657,6 +657,7 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) { struct vm_thread *self; struct timespec timespec; + int old_lock_count; int err; if (vm_monitor_get_owner(mon) != vm_thread_self()) { @@ -679,8 +680,10 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) timespec.tv_nsec -= 10l; } - if (--mon->lock_count == 0) - vm_monitor_set_owner(mon, NULL); + old_lock_count = mon->lock_count; + + mon->lock_count = 0; + vm_monitor_set_owner(mon, NULL); self = vm_thread_self(); @@ -694,7 +697,7 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) if (!err) { /* reacquire the lock */ vm_monitor_set_owner(mon, self); - mon->lock_count++; + mon->lock_count = old_lock_count; } /* TODO: check if thread has been interrupted. */ @@ -704,6 +707,7 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) int vm_monitor_wait(struct vm_monitor *mon) { struct vm_thread *self; + int old_lock_count; int err; self = vm_thread_self(); @@ -714,8 +718,10 @@ int vm_monitor_wait(struct vm_monitor *mon) return -1; } - if (--mon->lock_count == 0) - vm_monitor_set_owner(mon, NULL); + old_lock_count = mon->lock_count; + + mon->lock_count = 0; + vm_monitor_set_owner(mon, NULL); vm_thread_set_state(self, VM_THREAD_STATE_WAITING); err = pthread_cond_wait(&mon->cond, &mon->mutex); @@ -724,7 +730,7 @@ int vm_monitor_wait(struct vm_monitor *mon) if (!err) { /* reacquire the lock */ vm_monitor_set_owner(mon, self); - mon->lock_count++; + mon->lock_count = old_lock_count; } /* TODO: check if thread has been interrupted. */ -- 1.6.0.6 -- 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
[PATCH 3/3] vm: fix error handling in monitor operations
Signed-off-by: Tomek Grabiec --- vm/object.c | 42 -- 1 files changed, 24 insertions(+), 18 deletions(-) diff --git a/vm/object.c b/vm/object.c index e91c074..b4cf99b 100644 --- a/vm/object.c +++ b/vm/object.c @@ -620,7 +620,11 @@ void vm_monitor_set_owner(struct vm_monitor *mon, struct vm_thread *owner) int vm_monitor_lock(struct vm_monitor *mon) { - struct vm_thread *self = vm_thread_self(); + struct vm_thread *self; + int err; + + self = vm_thread_self(); + err = 0; if (pthread_mutex_trylock(&mon->mutex)) { /* @@ -629,14 +633,17 @@ int vm_monitor_lock(struct vm_monitor *mon) * for monitoring. */ vm_thread_set_state(self, VM_THREAD_STATE_BLOCKED); - pthread_mutex_lock(&mon->mutex); + err = pthread_mutex_lock(&mon->mutex); vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE); } - vm_monitor_set_owner(mon, self); - mon->lock_count++; + /* If err is non zero the lock has not been acquired. */ + if (!err) { + vm_monitor_set_owner(mon, self); + mon->lock_count++; + } - return 0; + return err; } int vm_monitor_unlock(struct vm_monitor *mon) @@ -647,10 +654,15 @@ int vm_monitor_unlock(struct vm_monitor *mon) return -1; } - if (--mon->lock_count == 0) - vm_monitor_set_owner(mon, NULL); + int err = pthread_mutex_unlock(&mon->mutex); + + /* If err is non zero the lock has not been released. */ + if (!err) { + if (--mon->lock_count == 0) + vm_monitor_set_owner(mon, NULL); + } - return pthread_mutex_unlock(&mon->mutex); + return err; } int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) @@ -694,11 +706,8 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) if (err == ETIMEDOUT) err = 0; - if (!err) { - /* reacquire the lock */ - vm_monitor_set_owner(mon, self); - mon->lock_count = old_lock_count; - } + vm_monitor_set_owner(mon, self); + mon->lock_count = old_lock_count; /* TODO: check if thread has been interrupted. */ return err; @@ -727,11 +736,8 @@ int vm_monitor_wait(struct vm_monitor *mon) err = pthread_cond_wait(&mon->cond, &mon->mutex); vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE); - if (!err) { - /* reacquire the lock */ - vm_monitor_set_owner(mon, self); - mon->lock_count = old_lock_count; - } + vm_monitor_set_owner(mon, self); + mon->lock_count = old_lock_count; /* TODO: check if thread has been interrupted. */ return err; -- 1.6.0.6 -- 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
[PATCH 3/3][V2] vm: fix error handling in monitor operations
Signed-off-by: Tomek Grabiec --- vm/object.c | 41 + 1 files changed, 25 insertions(+), 16 deletions(-) diff --git a/vm/object.c b/vm/object.c index e91c074..cb69dca 100644 --- a/vm/object.c +++ b/vm/object.c @@ -620,7 +620,11 @@ void vm_monitor_set_owner(struct vm_monitor *mon, struct vm_thread *owner) int vm_monitor_lock(struct vm_monitor *mon) { - struct vm_thread *self = vm_thread_self(); + struct vm_thread *self; + int err; + + self = vm_thread_self(); + err = 0; if (pthread_mutex_trylock(&mon->mutex)) { /* @@ -629,14 +633,17 @@ int vm_monitor_lock(struct vm_monitor *mon) * for monitoring. */ vm_thread_set_state(self, VM_THREAD_STATE_BLOCKED); - pthread_mutex_lock(&mon->mutex); + err = pthread_mutex_lock(&mon->mutex); vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE); } - vm_monitor_set_owner(mon, self); - mon->lock_count++; + /* If err is non zero the lock has not been acquired. */ + if (!err) { + vm_monitor_set_owner(mon, self); + mon->lock_count++; + } - return 0; + return err; } int vm_monitor_unlock(struct vm_monitor *mon) @@ -650,7 +657,15 @@ int vm_monitor_unlock(struct vm_monitor *mon) if (--mon->lock_count == 0) vm_monitor_set_owner(mon, NULL); - return pthread_mutex_unlock(&mon->mutex); + int err = pthread_mutex_unlock(&mon->mutex); + + /* If err is non zero the lock has not been released. */ + if (err) { + ++mon->lock_count; + vm_monitor_set_owner(mon, vm_thread_self()); + } + + return err; } int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) @@ -694,11 +709,8 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) if (err == ETIMEDOUT) err = 0; - if (!err) { - /* reacquire the lock */ - vm_monitor_set_owner(mon, self); - mon->lock_count = old_lock_count; - } + vm_monitor_set_owner(mon, self); + mon->lock_count = old_lock_count; /* TODO: check if thread has been interrupted. */ return err; @@ -727,11 +739,8 @@ int vm_monitor_wait(struct vm_monitor *mon) err = pthread_cond_wait(&mon->cond, &mon->mutex); vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE); - if (!err) { - /* reacquire the lock */ - vm_monitor_set_owner(mon, self); - mon->lock_count = old_lock_count; - } + vm_monitor_set_owner(mon, self); + mon->lock_count = old_lock_count; /* TODO: check if thread has been interrupted. */ return err; -- 1.6.0.6 -- 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
Re: [PATCH 3/3] vm: fix error handling in monitor operations
2009/7/29 Tomek Grabiec : > > Signed-off-by: Tomek Grabiec > --- > vm/object.c | 42 -- > 1 files changed, 24 insertions(+), 18 deletions(-) > > diff --git a/vm/object.c b/vm/object.c > index e91c074..b4cf99b 100644 > --- a/vm/object.c > +++ b/vm/object.c > @@ -620,7 +620,11 @@ void vm_monitor_set_owner(struct vm_monitor *mon, struct > vm_thread *owner) > > int vm_monitor_lock(struct vm_monitor *mon) > { > - struct vm_thread *self = vm_thread_self(); > + struct vm_thread *self; > + int err; > + > + self = vm_thread_self(); > + err = 0; > > if (pthread_mutex_trylock(&mon->mutex)) { > /* > @@ -629,14 +633,17 @@ int vm_monitor_lock(struct vm_monitor *mon) > * for monitoring. > */ > vm_thread_set_state(self, VM_THREAD_STATE_BLOCKED); > - pthread_mutex_lock(&mon->mutex); > + err = pthread_mutex_lock(&mon->mutex); > vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE); > } > > - vm_monitor_set_owner(mon, self); > - mon->lock_count++; > + /* If err is non zero the lock has not been acquired. */ > + if (!err) { > + vm_monitor_set_owner(mon, self); > + mon->lock_count++; > + } > > - return 0; > + return err; > } > > int vm_monitor_unlock(struct vm_monitor *mon) > @@ -647,10 +654,15 @@ int vm_monitor_unlock(struct vm_monitor *mon) > return -1; > } > > - if (--mon->lock_count == 0) > - vm_monitor_set_owner(mon, NULL); > + int err = pthread_mutex_unlock(&mon->mutex); > + > + /* If err is non zero the lock has not been released. */ > + if (!err) { > + if (--mon->lock_count == 0) > + vm_monitor_set_owner(mon, NULL); > + } > > - return pthread_mutex_unlock(&mon->mutex); > + return err; > } > > int vm_monitor_timed_wait(struct vm_monitor *mon, long long ms, int ns) > @@ -694,11 +706,8 @@ int vm_monitor_timed_wait(struct vm_monitor *mon, long > long ms, int ns) > if (err == ETIMEDOUT) > err = 0; > > - if (!err) { > - /* reacquire the lock */ > - vm_monitor_set_owner(mon, self); > - mon->lock_count = old_lock_count; > - } > + vm_monitor_set_owner(mon, self); > + mon->lock_count = old_lock_count; > > /* TODO: check if thread has been interrupted. */ > return err; > @@ -727,11 +736,8 @@ int vm_monitor_wait(struct vm_monitor *mon) > err = pthread_cond_wait(&mon->cond, &mon->mutex); > vm_thread_set_state(self, VM_THREAD_STATE_RUNNABLE); > > - if (!err) { > - /* reacquire the lock */ > - vm_monitor_set_owner(mon, self); > - mon->lock_count = old_lock_count; > - } > + vm_monitor_set_owner(mon, self); > + mon->lock_count = old_lock_count; > > /* TODO: check if thread has been interrupted. */ > return err; > -- > 1.6.0.6 > > Please trash this patch, I sent "[PATCH 3/3][V2] ..." Sorry for that. -- Tomek Grabiec -- 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
Re: [PATCH 1/2] jit: fix basic block splitting
On Wed, 2009-07-29 at 12:15 +0200, Vegard Nossum wrote: > On splitting a bb, the successors of the new bb were still pointing at > the original bb. This caused the CFG to be inconsistent and subsequently > also mimic stack spill/restore to do the wrong thing. > > This fixes the java.security.ProtectionDomain crash. > > Codebugged-by: Arthur Huillet > Signed-off-by: Vegard Nossum Woohoo! Excellent work guys! -- 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
[RFC][PATCH] jit: fix handling of split intervals in register allocator
Liveness analysis can produce intervals with range not ending at a use position. When splitting such interval after last use position we get the new interval with non-zero range length and without use positions. We should not add such intervals to the "unhandled" list. This bug led to incorrect compilation of java/lang/Thread.(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V because of splitting an interval with no use position. The bug didn't produce noticeable runtime effects when jato was compiled with -Os. When compiled with -O0 or -O2 it was failing in assertion: jit/spill-reload.c:51: last_insn: Assertion `ret != ((void *)0)' failed. Signed-off-by: Tomek Grabiec --- include/jit/vars.h |5 + jit/linear-scan.c | 25 +++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/jit/vars.h b/include/jit/vars.h index a697b1c..1f73c48 100644 --- a/include/jit/vars.h +++ b/include/jit/vars.h @@ -88,6 +88,11 @@ struct live_interval { bool fixed_reg; }; +static inline bool has_use_positions(struct live_interval *it) +{ + return !list_is_empty(&it->use_positions); +} + static inline void mark_need_reload(struct live_interval *it, struct live_interval *parent) { diff --git a/jit/linear-scan.c b/jit/linear-scan.c index ca3053b..e67a733 100644 --- a/jit/linear-scan.c +++ b/jit/linear-scan.c @@ -149,8 +149,11 @@ static void __spill_interval_intersecting(struct live_interval *current, return; new = split_interval_at(new, next_pos); - mark_need_reload(new, it); + if (!has_use_positions(new)) + return; + + mark_need_reload(new, it); insert_to_list(new, unhandled); } @@ -238,8 +241,12 @@ static void allocate_blocked_reg(struct live_interval *current, */ pos = next_use_pos(current, current->range.start); new = split_interval_at(current, pos); - mark_need_reload(new, current); - insert_to_list(new, unhandled); + + if (has_use_positions(new)) { + mark_need_reload(new, current); + insert_to_list(new, unhandled); + } + current->need_spill = 1; } else if (block_pos[reg] > current->range.end) { /* Spilling made a register free for the whole current */ @@ -248,7 +255,9 @@ static void allocate_blocked_reg(struct live_interval *current, inactive, unhandled); } else { new = split_interval_at(current, block_pos[reg]); - insert_to_list(new, unhandled); + + if (has_use_positions(new)) + insert_to_list(new, unhandled); current->reg = reg; spill_all_intervals_intersecting(current, reg, active, @@ -300,8 +309,12 @@ static void try_to_allocate_free_reg(struct live_interval *current, * Register available for the first part of the interval. */ new = split_interval_at(current, free_until_pos[reg]); - mark_need_reload(new, current); - insert_to_list(new, unhandled); + + if (has_use_positions(new)) { + mark_need_reload(new, current); + insert_to_list(new, unhandled); + } + current->reg = reg; current->need_spill = 1; } -- 1.6.0.6 -- 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