From 82f2b57775ec55b44efa88e627a6106fd1f23381 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 21 Sep 2010 12:34:28 -0700 Subject: [PATCH] Handle control flow edge case in JIT. Fixes #478. See the crash test committed. The bug as because if the instruction after a git/gif was a loop header, we wouldn't set the exception handler of the loop body block. --- vm/llvm/cfg.hpp | 13 +++++++++++-- vm/test/jit/crash_goto_loop_header.rb | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 vm/test/jit/crash_goto_loop_header.rb diff --git a/vm/llvm/cfg.hpp b/vm/llvm/cfg.hpp index ba1232ac9c..7a2854e993 100644 --- a/vm/llvm/cfg.hpp +++ b/vm/llvm/cfg.hpp @@ -121,7 +121,16 @@ namespace jit { CFGBlock* add_block(int ip, bool loop=false) { CFGBlock* blk = find_block(ip); - if(blk) return blk; + if(blk) { + // If we hit a block that is the start of a loop header, + // be sure to set it's exception handler. These blocks are created + // during the first pass. + if(blk->loop_p()) { + // Inherit the current exception handler + blk->set_exception_handler(current_->exception_handler()); + } + return blk; + } blk = new CFGBlock(ip, loop); @@ -185,7 +194,7 @@ namespace jit { VMMethod::Iterator iter(stream_, stream_size_); for(;;) { if(CFGBlock* next_block = find_block(iter.position())) { - if(next_block->loop_p()) { + if(next_block->loop_p() && current_ != next_block) { // The handler wasn't setup originally, so we have to set it now. next_block->set_exception_handler(current_->exception_handler()); diff --git a/vm/test/jit/crash_goto_loop_header.rb b/vm/test/jit/crash_goto_loop_header.rb new file mode 100644 index 0000000000..4f8adcceaf --- /dev/null +++ b/vm/test/jit/crash_goto_loop_header.rb @@ -0,0 +1,22 @@ +# Test for a JIT bug where the while inside the if generated a goto +# of a loop header and skipped setup up the exception handler +# properly. +# +# If this doesn't crash, the bug is fixed. +def bad + i = 0 + begin + if i < 10 + while i < 20 + i += 2 + end + end + rescue => ex + raise "failure is an option" + end + i +end + +1000000.times do + bad +end