summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-10-12 22:14:11 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-10-12 22:14:11 +0900
commit291234c7aa17727d4a2e581330e0eb3c0f388c6b (patch)
treeed236208eb00ca16f5be0eedcb599b5b18e1841a /src
parent5004d9a282145488dd8f32668805145b02977be1 (diff)
parentf77fb11f4e47164c7c6063a20ed0791bf151308f (diff)
downloadmruby-291234c7aa17727d4a2e581330e0eb3c0f388c6b.tar.gz
mruby-291234c7aa17727d4a2e581330e0eb3c0f388c6b.zip
Merge branch 'exc_mesg' of https://github.com/take-cheeze/mruby into take-cheeze-exc_mesg
Diffstat (limited to 'src')
-rw-r--r--src/error.c29
-rw-r--r--src/gc.c16
2 files changed, 39 insertions, 6 deletions
diff --git a/src/error.c b/src/error.c
index 5ceff2436..b2ae38295 100644
--- a/src/error.c
+++ b/src/error.c
@@ -17,6 +17,27 @@
#include <mruby/throw.h>
#include <mruby/presym.h>
+static void
+exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg)
+{
+ if (mrb_string_p(mesg)) {
+ exc->flags |= MRB_EXC_MESG_STRING_FLAG;
+ exc->mesg = RSTRING(mesg);
+ mrb_field_write_barrier_value(mrb, (struct RBasic*)exc, mesg);
+ }
+ else if (!mrb_nil_p(mesg)) {
+ exc->flags &= ~MRB_EXC_MESG_STRING_FLAG;
+ mrb_obj_iv_set(mrb, (struct RObject*)exc, mrb_intern_lit(mrb, "mesg"), mesg);
+ }
+}
+
+static mrb_value
+exc_mesg_get(mrb_state *mrb, struct RException *exc)
+{
+ return (exc->flags & MRB_EXC_MESG_STRING_FLAG) != 0
+ ? mrb_obj_value(exc->mesg) : mrb_obj_iv_get(mrb, (struct RObject*)exc, mrb_intern_lit(mrb, "mesg"));
+}
+
MRB_API mrb_value
mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str)
{
@@ -48,7 +69,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_SYM(mesg), mesg);
+ exc_mesg_set(mrb, mrb_exc_ptr(exc), mesg);
}
return exc;
}
@@ -77,7 +98,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_SYM(mesg), a);
+ exc_mesg_set(mrb, mrb_exc_ptr(exc), a);
return exc;
}
@@ -93,7 +114,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_SYM(mesg));
+ mrb_value mesg = exc_mesg_get(mrb, mrb_exc_ptr(exc));
struct RObject *p;
if (!mrb_string_p(mesg)) {
@@ -133,7 +154,7 @@ exc_message(mrb_state *mrb, mrb_value exc)
mrb_value
mrb_exc_inspect(mrb_state *mrb, mrb_value exc)
{
- mrb_value mesg = mrb_attr_get(mrb, exc, MRB_SYM(mesg));
+ mrb_value mesg = exc_mesg_get(mrb, mrb_exc_ptr(exc));
mrb_value cname = mrb_mod_to_s(mrb, mrb_obj_value(mrb_obj_class(mrb, exc)));
mesg = mrb_obj_as_string(mrb, mesg);
return RSTRING_LEN(mesg) == 0 ? cname : mrb_format(mrb, "%v (%v)", mesg, cname);
diff --git a/src/gc.c b/src/gc.c
index 8e8941cd7..fce2c3150 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -686,7 +686,6 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
case MRB_TT_OBJECT:
case MRB_TT_DATA:
- case MRB_TT_EXCEPTION:
mrb_gc_mark_iv(mrb, (struct RObject*)obj);
break;
@@ -759,6 +758,13 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
}
break;
+ case MRB_TT_EXCEPTION:
+ mrb_gc_mark_iv(mrb, (struct RObject*)obj);
+ if ((obj->flags & MRB_EXC_MESG_STRING_FLAG) != 0) {
+ mrb_gc_mark(mrb, (struct RBasic*)((struct RException*)obj)->mesg);
+ }
+ break;
+
default:
break;
}
@@ -989,7 +995,6 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, 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;
@@ -1042,6 +1047,13 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, 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_STRING_FLAG) != 0) {
+ children++;
+ }
+ break;
+
default:
break;
}