Store exception message to `mesg` field of `struct RException`.
authortake_cheeze <[email protected]>
Tue, 22 Jul 2014 14:08:15 +0000 (22 23:08 +0900)
committertake_cheeze <[email protected]>
Mon, 28 Jul 2014 07:34:01 +0000 (28 16:34 +0900)
include/mruby/error.h
src/error.c
src/gc.c

index 210ae34..8b5e9dd 100644 (file)
@@ -14,9 +14,11 @@ extern "C" {
 struct RException {
   MRB_OBJECT_HEADER;
   struct iv_tbl *iv;
+  mrb_value mesg;
 };
 
 #define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v))
+#define MRB_EXC_MESG_INIT_FLAG 0x100
 
 void mrb_sys_fail(mrb_state *mrb, const char *mesg);
 mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
index 223e213..9fc6fe4 100644 (file)
 #include "mruby/class.h"
 #include "mrb_throw.h"
 
+static void
+exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg)
+{
+  exc->flags |= MRB_EXC_MESG_INIT_FLAG;
+  exc->mesg = mesg;
+  mrb_field_write_barrier_value(mrb, (struct RBasic*)exc, mesg);
+}
+
+static mrb_value
+exc_mesg_get(mrb_state *mrb, struct RException *exc)
+{
+  return (exc->flags & MRB_EXC_MESG_INIT_FLAG) != 0 ? exc->mesg : mrb_nil_value();
+}
+
 mrb_value
 mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
 {
@@ -46,7 +60,7 @@ exc_initialize(mrb_state *mrb, mrb_value exc)
   mrb_value mesg;
 
   if (mrb_get_args(mrb, "|o", &mesg) == 1) {
-    mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), mesg);
+    exc_mesg_set(mrb, mrb_exc_ptr(exc), mesg);
   }
   return exc;
 }
@@ -75,7 +89,7 @@ exc_exception(mrb_state *mrb, mrb_value self)
   if (argc == 0) return self;
   if (mrb_obj_equal(mrb, self, a)) return self;
   exc = mrb_obj_clone(mrb, self);
-  mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "mesg"), a);
+  exc_mesg_set(mrb, mrb_exc_ptr(exc), a);
 
   return exc;
 }
@@ -91,7 +105,7 @@ exc_exception(mrb_state *mrb, mrb_value self)
 static mrb_value
 exc_to_s(mrb_state *mrb, mrb_value exc)
 {
-  mrb_value mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
+  mrb_value mesg = exc_mesg_get(mrb, mrb_exc_ptr(exc));
   struct RObject *p;
 
   if (!mrb_string_p(mesg)) {
@@ -136,7 +150,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
   mrb_value str, mesg, file, line;
   mrb_bool append_mesg;
 
-  mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
+  mesg = exc_mesg_get(mrb, mrb_exc_ptr(exc));
   file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file"));
   line = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "line"));
 
index bdcbc52..6fcac6c 100644 (file)
--- a/src/gc.c
+++ b/src/gc.c
@@ -515,7 +515,6 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
 
   case MRB_TT_OBJECT:
   case MRB_TT_DATA:
-  case MRB_TT_EXCEPTION:
     mrb_gc_mark_iv(mrb, (struct RObject*)obj);
     break;
 
@@ -581,6 +580,13 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
     }
     break;
 
+  case MRB_TT_EXCEPTION:
+    mrb_gc_mark_iv(mrb, (struct RObject*)obj);
+    if ((obj->flags & MRB_EXC_MESG_INIT_FLAG) != 0) {
+      mrb_gc_mark_value(mrb, ((struct RException*)obj)->mesg);
+    }
+    break;
+
   default:
     break;
   }
@@ -751,7 +757,6 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
 
   case MRB_TT_OBJECT:
   case MRB_TT_DATA:
-  case MRB_TT_EXCEPTION:
     children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
     break;
 
@@ -801,6 +806,13 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
     children+=2;
     break;
 
+  case MRB_TT_EXCEPTION:
+    children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
+    if ((obj->flags & MRB_EXC_MESG_INIT_FLAG) != 0) {
+      children++;
+    }
+    break;
+
   default:
     break;
   }