[macruby-changes] [1566] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Mon May 11 17:47:07 PDT 2009


Revision: 1566
          http://trac.macosforge.org/projects/ruby/changeset/1566
Author:   lsansonetti at apple.com
Date:     2009-05-11 17:47:06 -0700 (Mon, 11 May 2009)
Log Message:
-----------
now keeping the current exceptions in a stack, which fixes several bugs

Modified Paths:
--------------
    MacRuby/branches/experimental/roxor.cpp
    MacRuby/branches/experimental/test_vm/exception.rb

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-05-11 22:50:13 UTC (rev 1565)
+++ MacRuby/branches/experimental/roxor.cpp	2009-05-12 00:47:06 UTC (rev 1566)
@@ -369,6 +369,7 @@
 	void compile_landing_pad_header(void);
 	void compile_landing_pad_footer(void);
 	void compile_rethrow_exception(void);
+	void compile_pop_exception(void);
 	Value *compile_lvar_slot(ID name);
 	bool compile_lvars(ID *tbl);
 	Value *compile_new_struct(Value *klass, std::vector<Value *> &fields);
@@ -503,13 +504,13 @@
 	    to_rval_convertors, to_ocval_convertors;
 
 	std::vector<rb_vm_block_t *> current_blocks;
+	std::vector<VALUE> current_exceptions;
 
     public:
 	static RoxorVM *current;
 
 	Class current_class;
 	VALUE current_top_object;
-	VALUE current_exception;
 	VALUE loaded_features;
 	VALUE load_path;
 	VALUE backref;
@@ -561,6 +562,25 @@
 	    return b;
 	}
 
+	VALUE current_exception(void) {
+	    return current_exceptions.empty()
+		? Qnil : current_exceptions.back();
+	}
+
+	void push_current_exception(VALUE exc) {
+	    assert(!NIL_P(exc));
+	    rb_objc_retain((void *)exc);
+	    current_exceptions.push_back(exc);
+	}
+
+	VALUE pop_current_exception(void) {
+	    assert(!current_exceptions.empty());
+	    VALUE exc = current_exceptions.back();
+	    rb_objc_release((void *)exc);
+	    current_exceptions.pop_back();
+	    return exc;
+	}
+
 	std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
 	std::vector<jmp_buf *> return_from_block_jmp_bufs;
 
@@ -1817,7 +1837,9 @@
 
     switch (nd_type(node)) {
 	case NODE_RETRY:
-	    // Simply jump to the nearest begin label.
+	    // Simply jump to the nearest begin label, after poping the
+	    // current exception.
+	    compile_pop_exception();
 	    if (begin_bb == NULL) {
 		rb_raise(rb_eSyntaxError, "unexpected retry");
 	    }
@@ -1967,7 +1989,7 @@
 }
 
 void
-RoxorCompiler::compile_landing_pad_footer(void)
+RoxorCompiler::compile_pop_exception(void)
 {
     if (popExceptionFunc == NULL) {
 	// void rb_vm_pop_exception(void);
@@ -1976,7 +1998,13 @@
 		    Type::VoidTy, NULL));
     }
     CallInst::Create(popExceptionFunc, "", bb);
+}
 
+void
+RoxorCompiler::compile_landing_pad_footer(void)
+{
+    compile_pop_exception();
+
     Function *endCatchFunc = NULL;
     if (endCatchFunc == NULL) {
 	// void __cxa_end_catch(void);
@@ -2636,7 +2664,6 @@
 {
     running = false;
     current_top_object = Qnil;
-    current_exception = Qnil;
     safe_level = 0;
 
     backref = Qnil;
@@ -8697,9 +8724,11 @@
 void
 rb_vm_raise(VALUE exception)
 {
-    rb_objc_retain((void *)exception);
     rb_iv_set(exception, "bt", rb_vm_backtrace(100));
-    GET_VM()->current_exception = exception;
+    if (exception != GET_VM()->current_exception()) {
+	rb_objc_retain((void *)exception);
+	GET_VM()->push_current_exception(exception);
+    }
     void *exc = __cxa_allocate_exception(0);
     __cxa_throw(exc, NULL, NULL);
 }
@@ -8769,8 +8798,10 @@
 rb_vm_is_eh_active(int argc, ...)
 {
     assert(argc > 0);
-    assert(GET_VM()->current_exception != Qnil);
 
+    VALUE current_exception = GET_VM()->current_exception();
+    assert(current_exception != Qnil);
+
     va_list ar;
     unsigned char active = 0;
 
@@ -8780,13 +8811,13 @@
 	if (TYPE(obj) == T_ARRAY) {
 	    for (int j = 0, count = RARRAY_LEN(obj); j < count; ++j) {
 		VALUE obj2 = RARRAY_AT(obj, j);
-		if (rb_obj_is_kind_of(GET_VM()->current_exception, obj2)) {
+		if (rb_obj_is_kind_of(current_exception, obj2)) {
 		    active = 1;
 		}
 	    }
 	}
 	else {
-	    if (rb_obj_is_kind_of(GET_VM()->current_exception, obj)) {
+	    if (rb_obj_is_kind_of(current_exception, obj)) {
 		active = 1;
 	    }
 	}
@@ -8800,30 +8831,28 @@
 void
 rb_vm_pop_exception(void)
 {
-    VALUE exc = GET_VM()->current_exception;
-    assert(exc != Qnil);
-    rb_objc_release((void *)exc);
-    GET_VM()->current_exception = Qnil;
+    GET_VM()->pop_current_exception();
 }
 
 extern "C"
 VALUE
 rb_vm_current_exception(void)
 {
-    return GET_VM()->current_exception;
+    return GET_VM()->current_exception();
 }
 
 extern "C"
 void
 rb_vm_set_current_exception(VALUE exception)
 {
-    if (GET_VM()->current_exception != exception) {
-	if (GET_VM()->current_exception != Qnil) {
-	    rb_objc_release((void *)GET_VM()->current_exception);
-	}
-	rb_objc_retain((void *)exception);
-	GET_VM()->current_exception = exception;
+    assert(!NIL_P(exception));
+
+    VALUE current = GET_VM()->current_exception();
+    assert(exception != current);
+    if (!NIL_P(current)) {
+	GET_VM()->pop_current_exception();
     }
+    GET_VM()->push_current_exception(exception);
 }
 
 extern "C"
@@ -8837,7 +8866,7 @@
 void
 rb_vm_print_current_exception(void)
 {
-    VALUE exc = GET_VM()->current_exception;
+    VALUE exc = GET_VM()->current_exception();
     if (exc == Qnil) {
 	printf("uncatched Objective-C/C++ exception...");
 	return;

Modified: MacRuby/branches/experimental/test_vm/exception.rb
===================================================================
--- MacRuby/branches/experimental/test_vm/exception.rb	2009-05-11 22:50:13 UTC (rev 1565)
+++ MacRuby/branches/experimental/test_vm/exception.rb	2009-05-12 00:47:06 UTC (rev 1566)
@@ -178,3 +178,45 @@
     p :ok if $! == e
   end
 }
+
+assert ":ok\n:ok\n:ok", %{
+  e1 = RuntimeError.new('e1')
+  e2 = RuntimeError.new('e2')
+  e3 = RuntimeError.new('e3')
+  begin
+    raise e1
+  rescue
+    begin
+      raise e2
+    rescue
+      begin
+        raise e3
+      rescue
+        p :ok if $! == e3
+      end
+      p :ok if $! == e2
+    end
+    p :ok if $! == e1
+  end
+}
+
+assert ":ok\n:ok\n:ok\n:ok", %{
+  x = 0
+  e = RuntimeError.new('foo')
+  begin
+    p :ok if $!.nil?
+    x += 1
+    raise e
+  rescue
+    p :ok if $! == e
+    retry if x < 2
+  end
+}
+
+assert ":ok", %{
+  begin
+    eval("1==2==3")
+  rescue Exception
+  end
+  p :ok if $!.nil?
+}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090511/b058b320/attachment.html>


More information about the macruby-changes mailing list