* eval.c (PUSH_FRAME): generate unique number to be TAG_JUMP()

destination.

* eval.c (localjump_destination): use unique number in ruby_frame
  for localjump destination.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4811 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2003-10-20 08:33:49 +00:00
parent 8405551e6d
commit 6eb98c5ebe
4 changed files with 24 additions and 13 deletions

View File

@ -1,3 +1,11 @@
Mon Oct 20 17:31:46 2003 Yukihiro Matsumoto <matz@ruby-lang.org>
* eval.c (PUSH_FRAME): generate unique number to be TAG_JUMP()
destination.
* eval.c (localjump_destination): use unique number in ruby_frame
for localjump destination.
Mon Oct 20 11:31:44 2003 Nobuyoshi Nakada <nobu@ruby-lang.org> Mon Oct 20 11:31:44 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* test/ruby/test_signal.rb (test_signal): restore old trap. * test/ruby/test_signal.rb (test_signal): restore old trap.

1
env.h
View File

@ -25,6 +25,7 @@ extern struct FRAME {
struct RNode *node; struct RNode *node;
int iter; int iter;
int flags; int flags;
unsigned long uniq;
} *ruby_frame; } *ruby_frame;
void rb_gc_mark_frame _((struct FRAME *)); void rb_gc_mark_frame _((struct FRAME *));

26
eval.c
View File

@ -604,6 +604,8 @@ struct SCOPE *ruby_scope;
static struct FRAME *top_frame; static struct FRAME *top_frame;
static struct SCOPE *top_scope; static struct SCOPE *top_scope;
static unsigned long frame_unique = 0;
#define PUSH_FRAME() do { \ #define PUSH_FRAME() do { \
struct FRAME _frame; \ struct FRAME _frame; \
_frame.prev = ruby_frame; \ _frame.prev = ruby_frame; \
@ -613,6 +615,7 @@ static struct SCOPE *top_scope;
_frame.argc = 0; \ _frame.argc = 0; \
_frame.argv = 0; \ _frame.argv = 0; \
_frame.flags = FRAME_ALLOCA; \ _frame.flags = FRAME_ALLOCA; \
_frame.uniq = frame_unique++; \
ruby_frame = &_frame ruby_frame = &_frame
#define POP_FRAME() \ #define POP_FRAME() \
@ -875,7 +878,7 @@ static struct tag *prot_tag;
prot_tag = _tag.prev; \ prot_tag = _tag.prev; \
} while (0) } while (0)
#define TAG_DST() (_tag.dst == (VALUE)_tag.scope) #define TAG_DST() (_tag.dst == (VALUE)ruby_frame->uniq)
#define TAG_RETURN 0x1 #define TAG_RETURN 0x1
#define TAG_BREAK 0x2 #define TAG_BREAK 0x2
@ -2448,7 +2451,7 @@ class_prefix(self, cpath)
}\ }\
} while (0) } while (0)
NORETURN(static void localjump_destination _((int, struct SCOPE*, VALUE))); NORETURN(static void localjump_destination _((int, VALUE)));
static VALUE static VALUE
rb_eval(self, n) rb_eval(self, n)
@ -2771,7 +2774,7 @@ rb_eval(self, n)
break; break;
case NODE_BREAK: case NODE_BREAK:
localjump_destination(TAG_BREAK, ruby_scope, rb_eval(self, node->nd_stts)); localjump_destination(TAG_BREAK, rb_eval(self, node->nd_stts));
break; break;
case NODE_NEXT: case NODE_NEXT:
@ -2952,7 +2955,7 @@ rb_eval(self, n)
break; break;
case NODE_RETURN: case NODE_RETURN:
localjump_destination(TAG_RETURN, ruby_scope, rb_eval(self, node->nd_stts)); localjump_destination(TAG_RETURN, rb_eval(self, node->nd_stts));
break; break;
case NODE_ARGSCAT: case NODE_ARGSCAT:
@ -3106,7 +3109,7 @@ rb_eval(self, n)
break; break;
case TAG_RETURN: case TAG_RETURN:
case TAG_BREAK: case TAG_BREAK:
localjump_destination(state, ruby_scope, result); localjump_destination(state, result);
default: default:
JUMP_TAG(state); JUMP_TAG(state);
} }
@ -3882,7 +3885,7 @@ rb_f_abort(argc, argv)
void void
rb_iter_break() rb_iter_break()
{ {
localjump_destination(TAG_BREAK, ruby_scope, Qnil); localjump_destination(TAG_BREAK, Qnil);
} }
NORETURN(static void rb_longjmp _((int, VALUE))); NORETURN(static void rb_longjmp _((int, VALUE)));
@ -4056,9 +4059,8 @@ rb_f_block_given_p()
static VALUE rb_eThreadError; static VALUE rb_eThreadError;
static void static void
localjump_destination(state, scope, retval) localjump_destination(state, retval)
int state; int state;
struct SCOPE *scope;
VALUE retval; VALUE retval;
{ {
struct tag *tt = prot_tag; struct tag *tt = prot_tag;
@ -4067,12 +4069,12 @@ localjump_destination(state, scope, retval)
if (retval == Qundef) retval = Qnil; if (retval == Qundef) retval = Qnil;
while (tt) { while (tt) {
if (tt->tag == PROT_PCALL || (tt->tag == PROT_THREAD && state == TAG_BREAK) || if (tt->tag == PROT_PCALL || (tt->tag == PROT_THREAD && state == TAG_BREAK) ||
(tt->tag == PROT_CALL || tt->tag == tag) && tt->scope == scope) { (tt->tag == PROT_CALL || tt->tag == tag) && tt->frame->uniq == ruby_frame->uniq) {
tt->dst = (VALUE)scope; tt->dst = (VALUE)ruby_frame->uniq;
tt->retval = retval; tt->retval = retval;
JUMP_TAG(state); JUMP_TAG(state);
} }
if (tt->tag == PROT_FUNC && tt->scope == scope) break; if (tt->tag == PROT_FUNC && tt->frame->uniq == ruby_frame->uniq) break;
if (tt->tag == PROT_THREAD) { if (tt->tag == PROT_THREAD) {
rb_raise(rb_eThreadError, "return jump can't across threads"); rb_raise(rb_eThreadError, "return jump can't across threads");
} }
@ -7087,7 +7089,7 @@ proc_invoke(proc, args, self, klass)
localjump_error(mesg, result, state); localjump_error(mesg, result, state);
} }
if (result != Qundef) { if (result != Qundef) {
localjump_destination(state, ruby_scope, result); localjump_destination(state, result);
} }
default: default:
JUMP_TAG(state); JUMP_TAG(state);

View File

@ -419,7 +419,7 @@ class TestIterator < Test::Unit::TestCase
def test_return_trace_func def test_return_trace_func
ok = "returned gracefully" ok = "returned gracefully"
result = "skipped" result = "skipped"
result = _test_return_from_builtin(ok) result = _test_return_trace_func(ok)
ensure ensure
assert_equal(ok, result) assert_equal(ok, result)
return return