Skip to content

Commit 06c4c76

Browse files
committed
Merge branch 'exception' of https://github.com/dearblue/mruby into dearblue-exception
2 parents a243cf4 + 92ef9f1 commit 06c4c76

4 files changed

Lines changed: 57 additions & 51 deletions

File tree

include/mruby/error.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ MRB_BEGIN_DECL
1717
struct RException {
1818
MRB_OBJECT_HEADER;
1919
struct iv_tbl *iv;
20-
struct RString *mesg;
20+
struct RObject *mesg; // NULL or probably RString
21+
struct RObject *backtrace; // NULL, RArray or RData
2122
};
2223

2324
#define mrb_exc_ptr(v) ((struct RException*)mrb_ptr(v))
24-
#define MRB_EXC_MESG_STRING_FLAG 0x100
2525

2626
MRB_API mrb_noreturn void mrb_sys_fail(mrb_state *mrb, const char *mesg);
2727
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);

src/backtrace.c

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ typedef void (*each_backtrace_func)(mrb_state*, const struct backtrace_location*
2727

2828
static const mrb_data_type bt_type = { "Backtrace", mrb_free };
2929

30-
static mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
30+
struct RObject *mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace);
3131

3232
static void
3333
each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *data)
@@ -97,17 +97,17 @@ each_backtrace(mrb_state *mrb, ptrdiff_t ciidx, each_backtrace_func func, void *
9797
#ifndef MRB_NO_STDIO
9898

9999
static void
100-
print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
100+
print_backtrace(mrb_state *mrb, struct RObject *exc, struct RArray *backtrace)
101101
{
102102
mrb_int i;
103-
mrb_int n = RARRAY_LEN(backtrace);
103+
mrb_int n = ARY_LEN(backtrace);
104104
mrb_value *loc, mesg;
105105

106106
if (n != 0) {
107107
if (n > 1) {
108108
fprintf(stderr, "trace (most recent call last):\n");
109109
}
110-
for (i=n-1,loc=&RARRAY_PTR(backtrace)[i]; i>0; i--,loc--) {
110+
for (i=n-1,loc=&ARY_PTR(backtrace)[i]; i>0; i--,loc--) {
111111
if (mrb_string_p(*loc)) {
112112
fprintf(stderr, "\t[%d] %.*s\n",
113113
(int)i, (int)RSTRING_LEN(*loc), RSTRING_PTR(*loc));
@@ -130,16 +130,14 @@ print_backtrace(mrb_state *mrb, struct RObject *exc, mrb_value backtrace)
130130
MRB_API void
131131
mrb_print_backtrace(mrb_state *mrb)
132132
{
133-
mrb_value backtrace;
134-
135133
if (!mrb->exc) {
136134
return;
137135
}
138136

139-
backtrace = mrb_obj_iv_get(mrb, mrb->exc, MRB_SYM(backtrace));
140-
if (mrb_nil_p(backtrace)) return;
141-
if (!mrb_array_p(backtrace)) backtrace = mrb_unpack_backtrace(mrb, backtrace);
142-
print_backtrace(mrb, mrb->exc, backtrace);
137+
struct RObject *backtrace = ((struct RException*)mrb->exc)->backtrace;
138+
if (!backtrace) return;
139+
if (backtrace->tt != MRB_TT_ARRAY) backtrace = mrb_unpack_backtrace(mrb, backtrace);
140+
print_backtrace(mrb, mrb->exc, (struct RArray*)backtrace);
143141
}
144142
#else
145143

@@ -172,7 +170,7 @@ pack_backtrace_i(mrb_state *mrb,
172170
*pptr = ptr+1;
173171
}
174172

175-
static mrb_value
173+
static struct RObject*
176174
packed_backtrace(mrb_state *mrb)
177175
{
178176
struct RData *backtrace;
@@ -183,44 +181,51 @@ packed_backtrace(mrb_state *mrb)
183181

184182
each_backtrace(mrb, ciidx, count_backtrace_i, &len);
185183
size = len * sizeof(struct backtrace_location);
184+
backtrace = mrb_data_object_alloc(mrb, NULL, NULL, &bt_type);
186185
ptr = mrb_malloc(mrb, size);
187-
backtrace = mrb_data_object_alloc(mrb, NULL, ptr, &bt_type);
186+
backtrace->data = ptr;
188187
backtrace->flags = (uint32_t)len;
189188
each_backtrace(mrb, ciidx, pack_backtrace_i, &ptr);
190-
return mrb_obj_value(backtrace);
189+
return (struct RObject*)backtrace;
190+
}
191+
192+
static void
193+
store_backtrace(mrb_state *mrb, mrb_value exc, struct RObject *backtrace)
194+
{
195+
struct RException *e = mrb_exc_ptr(exc);
196+
e->backtrace = backtrace;
197+
mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)backtrace);
191198
}
192199

193200
void
194201
mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
195202
{
196-
mrb_sym sym = MRB_SYM(backtrace);
197-
mrb_value backtrace;
198203
int ai;
199204

200-
if (mrb_iv_defined(mrb, exc, sym)) return;
205+
if (mrb_exc_ptr(exc)->backtrace) return;
201206
ai = mrb_gc_arena_save(mrb);
202-
backtrace = packed_backtrace(mrb);
203-
mrb_iv_set(mrb, exc, sym, backtrace);
207+
struct RObject *backtrace = packed_backtrace(mrb);
208+
store_backtrace(mrb, exc, backtrace);
204209
mrb_gc_arena_restore(mrb, ai);
205210
}
206211

207-
static mrb_value
208-
mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
212+
struct RObject*
213+
mrb_unpack_backtrace(mrb_state *mrb, struct RObject *backtrace)
209214
{
210215
const struct backtrace_location *bt;
211216
mrb_int n, i;
212217
int ai;
213218

214-
if (mrb_nil_p(backtrace)) {
219+
if (backtrace == NULL) {
215220
empty_backtrace:
216-
return mrb_ary_new_capa(mrb, 0);
221+
return mrb_obj_ptr(mrb_ary_new_capa(mrb, 0));
217222
}
218-
if (mrb_array_p(backtrace)) return backtrace;
219-
bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, backtrace, &bt_type);
223+
if (backtrace->tt == MRB_TT_ARRAY) return backtrace;
224+
bt = (struct backtrace_location*)mrb_data_check_get_ptr(mrb, mrb_obj_value(backtrace), &bt_type);
220225
if (bt == NULL) goto empty_backtrace;
221-
n = (mrb_int)RDATA(backtrace)->flags;
226+
n = (mrb_int)backtrace->flags;
222227
if (n == 0) goto empty_backtrace;
223-
backtrace = mrb_ary_new_capa(mrb, n);
228+
backtrace = mrb_obj_ptr(mrb_ary_new_capa(mrb, n));
224229
ai = mrb_gc_arena_save(mrb);
225230
for (i = 0; i < n; i++) {
226231
const struct backtrace_location *entry = &bt[i];
@@ -236,7 +241,7 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
236241
mrb_str_cat_lit(mrb, btline, ":in ");
237242
mrb_str_cat_cstr(mrb, btline, mrb_sym_name(mrb, entry->method_id));
238243
}
239-
mrb_ary_push(mrb, backtrace, btline);
244+
mrb_ary_push(mrb, mrb_obj_value(backtrace), btline);
240245
mrb_gc_arena_restore(mrb, ai);
241246
}
242247

@@ -246,20 +251,21 @@ mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
246251
mrb_value
247252
mrb_exc_backtrace(mrb_state *mrb, mrb_value exc)
248253
{
249-
mrb_value backtrace;
250-
251-
backtrace = mrb_iv_get(mrb, exc, MRB_SYM(backtrace));
252-
if (mrb_nil_p(backtrace) || mrb_array_p(backtrace)) {
253-
return backtrace;
254+
struct RObject *backtrace = mrb_exc_ptr(exc)->backtrace;
255+
if (backtrace == NULL) {
256+
return mrb_nil_value();
257+
}
258+
if (backtrace->tt == MRB_TT_ARRAY) {
259+
return mrb_obj_value(backtrace);
254260
}
255261
/* unpack packed-backtrace */
256262
backtrace = mrb_unpack_backtrace(mrb, backtrace);
257-
mrb_iv_set(mrb, exc, MRB_SYM(backtrace), backtrace);
258-
return backtrace;
263+
store_backtrace(mrb, exc, backtrace);
264+
return mrb_obj_value(backtrace);
259265
}
260266

261267
mrb_value
262268
mrb_get_backtrace(mrb_state *mrb)
263269
{
264-
return mrb_unpack_backtrace(mrb, packed_backtrace(mrb));
270+
return mrb_obj_value(mrb_unpack_backtrace(mrb, packed_backtrace(mrb)));
265271
}

src/error.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,21 @@
2121
void
2222
mrb_exc_mesg_set(mrb_state *mrb, struct RException *exc, mrb_value mesg)
2323
{
24-
if (mrb_string_p(mesg)) {
25-
exc->flags |= MRB_EXC_MESG_STRING_FLAG;
26-
exc->mesg = RSTRING(mesg);
24+
if (!mrb_immediate_p(mesg)) {
25+
exc->mesg = mrb_obj_ptr(mesg);
2726
mrb_field_write_barrier_value(mrb, (struct RBasic*)exc, mesg);
27+
mrb_iv_remove(mrb, mrb_obj_value(exc), MRB_SYM(mesg));
2828
}
2929
else {
30-
exc->flags &= ~MRB_EXC_MESG_STRING_FLAG;
31-
if (mrb_nil_p(mesg)) {
32-
exc->mesg = 0;
33-
}
34-
else {
35-
mrb_obj_iv_set(mrb, (struct RObject*)exc, MRB_SYM(mesg), mesg);
36-
}
30+
exc->mesg = NULL;
31+
mrb_obj_iv_set(mrb, (struct RObject*)exc, MRB_SYM(mesg), mesg);
3732
}
3833
}
3934

4035
mrb_value
4136
mrb_exc_mesg_get(mrb_state *mrb, struct RException *exc)
4237
{
43-
if ((exc->flags & MRB_EXC_MESG_STRING_FLAG) != 0) {
38+
if (exc->mesg) {
4439
return mrb_obj_value(exc->mesg);
4540
}
4641
else {
@@ -174,7 +169,8 @@ set_backtrace(mrb_state *mrb, mrb_value exc, mrb_value backtrace)
174169
p++;
175170
}
176171
}
177-
mrb_iv_set(mrb, exc, MRB_SYM(backtrace), backtrace);
172+
mrb_exc_ptr(exc)->backtrace = mrb_obj_ptr(backtrace);
173+
mrb_field_write_barrier_value(mrb, mrb_basic_ptr(exc), backtrace);
178174
}
179175

180176
static mrb_value

src/gc.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,9 +763,10 @@ gc_mark_children(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
763763

764764
case MRB_TT_EXCEPTION:
765765
mrb_gc_mark_iv(mrb, (struct RObject*)obj);
766-
if ((obj->flags & MRB_EXC_MESG_STRING_FLAG) != 0) {
766+
if (((struct RException*)obj)->mesg) {
767767
mrb_gc_mark(mrb, (struct RBasic*)((struct RException*)obj)->mesg);
768768
}
769+
mrb_gc_mark(mrb, (struct RBasic*)((struct RException*)obj)->backtrace);
769770
break;
770771

771772
default:
@@ -1058,7 +1059,10 @@ gc_gray_counts(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
10581059

10591060
case MRB_TT_EXCEPTION:
10601061
children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
1061-
if ((obj->flags & MRB_EXC_MESG_STRING_FLAG) != 0) {
1062+
if (((struct RException*)obj)->mesg) {
1063+
children++;
1064+
}
1065+
if (((struct RException*)obj)->backtrace) {
10621066
children++;
10631067
}
10641068
break;

0 commit comments

Comments
 (0)