Simplify backtrace mechanism; fix #3633 #3634 #3644

Instead of preserving a backtrace in `mrb_state`, `mrb_exc_set`
keeps packed backtrace in an exception object. `#backtrace` unpacks
it to an array of strings.
parent d2458e66
...@@ -152,12 +152,6 @@ struct mrb_context { ...@@ -152,12 +152,6 @@ struct mrb_context {
struct mrb_jmpbuf; struct mrb_jmpbuf;
typedef struct {
const char *filename;
int lineno;
mrb_sym method_id;
} mrb_backtrace_entry;
typedef void (*mrb_atexit_func)(struct mrb_state*); typedef void (*mrb_atexit_func)(struct mrb_state*);
#define MRB_STATE_NO_REGEXP 1 #define MRB_STATE_NO_REGEXP 1
...@@ -172,15 +166,9 @@ typedef struct mrb_state { ...@@ -172,15 +166,9 @@ typedef struct mrb_state {
struct mrb_context *c; struct mrb_context *c;
struct mrb_context *root_c; struct mrb_context *root_c;
struct iv_tbl *globals; /* global variable table */
struct RObject *exc; /* exception */ struct RObject *exc; /* exception */
struct {
struct RObject *exc;
int n;
int n_allocated;
mrb_backtrace_entry *entries;
} backtrace;
struct iv_tbl *globals; /* global variable table */
struct RObject *top_self; struct RObject *top_self;
struct RClass *object_class; /* Object class */ struct RClass *object_class; /* Object class */
......
...@@ -25,7 +25,6 @@ MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg); ...@@ -25,7 +25,6 @@ MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str); MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit)) #define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv); MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb); MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...); MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
......
...@@ -14,83 +14,24 @@ ...@@ -14,83 +14,24 @@
#include <mruby/error.h> #include <mruby/error.h>
#include <mruby/numeric.h> #include <mruby/numeric.h>
struct backtrace_location_raw {
int i;
int lineno;
const char *filename;
mrb_sym method_id;
};
struct backtrace_location { struct backtrace_location {
int i;
int lineno; int lineno;
const char *filename; const char *filename;
const char *method; mrb_sym method_id;
};
typedef void (*each_backtrace_func)(mrb_state*, struct backtrace_location_raw*, void*);
typedef void (*output_stream_func)(mrb_state*, struct backtrace_location*, void*);
#ifndef MRB_DISABLE_STDIO
struct print_backtrace_args {
FILE *stream;
int tracehead;
}; };
static void typedef void (*each_backtrace_func)(mrb_state*, int i, struct backtrace_location*, void*);
print_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data)
{
struct print_backtrace_args *args;
args = (struct print_backtrace_args*)data;
if (args->tracehead) {
fprintf(args->stream, "trace:\n");
args->tracehead = FALSE;
}
fprintf(args->stream, "\t[%d] %s:%d", loc->i, loc->filename, loc->lineno);
if (loc->method) {
fprintf(args->stream, ":in %s", loc->method);
}
fprintf(args->stream, "\n");
}
#endif
static void
get_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data)
{
mrb_value ary, str;
int ai = mrb_gc_arena_save(mrb);
ary = mrb_obj_value((struct RArray*)data);
str = mrb_str_new_cstr(mrb, loc->filename);
str = mrb_format(mrb, "%S:%S", str, mrb_fixnum_to_str(mrb, mrb_fixnum_value(loc->lineno), 10));
if (loc->method) {
mrb_str_cat_lit(mrb, str, ":in ");
mrb_str_cat_cstr(mrb, str, loc->method);
}
mrb_ary_push(mrb, ary, str);
mrb_gc_arena_restore(mrb, ai);
}
static void static void
each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func func, void *data) each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func func, void *data)
{ {
int i; int i, j;
if (ciidx >= mrb->c->ciend - mrb->c->cibase) if (ciidx >= mrb->c->ciend - mrb->c->cibase)
ciidx = 10; /* ciidx is broken... */ ciidx = 10; /* ciidx is broken... */
for (i = ciidx; i >= 0; i--) { for (i=ciidx, j=0; i >= 0; i--,j++) {
struct backtrace_location_raw loc; struct backtrace_location loc;
mrb_callinfo *ci; mrb_callinfo *ci;
mrb_irep *irep; mrb_irep *irep;
mrb_code *pc; mrb_code *pc;
...@@ -122,58 +63,11 @@ each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func ...@@ -122,58 +63,11 @@ each_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, each_backtrace_func
} }
loc.method_id = ci->mid; loc.method_id = ci->mid;
loc.i = i; func(mrb, j, &loc, data);
func(mrb, &loc, data);
} }
} }
struct output_backtrace_args { /* mrb_print_backtrace
output_stream_func func;
void *data;
};
static void
output_backtrace_i(mrb_state *mrb, struct backtrace_location_raw *loc_raw, void *data)
{
struct backtrace_location loc;
struct output_backtrace_args *args = (struct output_backtrace_args *)data;
loc.i = loc_raw->i;
loc.lineno = loc_raw->lineno;
loc.filename = loc_raw->filename;
loc.method = mrb_sym2name(mrb, loc_raw->method_id);
args->func(mrb, &loc, args->data);
}
static void
output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *data)
{
struct output_backtrace_args args;
args.func = func;
args.data = data;
each_backtrace(mrb, ciidx, pc0, output_backtrace_i, &args);
}
static void
exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream)
{
mrb_value lastpc;
mrb_code *code;
lastpc = mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "lastpc"));
if (mrb_nil_p(lastpc)) {
code = NULL;
}
else {
code = (mrb_code*)mrb_cptr(lastpc);
}
output_backtrace(mrb, mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "ciidx"))),
code, func, stream);
}
/* mrb_print_backtrace/mrb_get_backtrace:
function to retrieve backtrace information from the exception. function to retrieve backtrace information from the exception.
note that if you call method after the exception, call stack will be note that if you call method after the exception, call stack will be
...@@ -202,19 +96,27 @@ print_backtrace(mrb_state *mrb, mrb_value backtrace) ...@@ -202,19 +96,27 @@ print_backtrace(mrb_state *mrb, mrb_value backtrace)
} }
static void static void
print_backtrace_saved(mrb_state *mrb) print_packed_backtrace(mrb_state *mrb, mrb_value packed)
{ {
int i, ai;
FILE *stream = stderr; FILE *stream = stderr;
struct backtrace_location *bt;
mrb_int n, i;
fprintf(stream, "trace:\n"); if (!mrb_string_p(packed)) {
ai = mrb_gc_arena_save(mrb); broken:
for (i = 0; i < mrb->backtrace.n; i++) { mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace");
mrb_backtrace_entry *entry; }
n = RSTRING_LEN(packed);
entry = &(mrb->backtrace.entries[i]); if (n%sizeof(struct backtrace_location) != 0) goto broken;
fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno); n /= sizeof(struct backtrace_location);
bt = (struct backtrace_location*)RSTRING_PTR(packed);
fprintf(stream, "trace:\n");
for (i = 0; i < n; i++) {
int ai = mrb_gc_arena_save(mrb);
struct backtrace_location *entry = &bt[i];
if (entry->filename == NULL) continue;
fprintf(stream, "\t[%d] %s:%d", (int)i, entry->filename, entry->lineno);
if (entry->method_id != 0) { if (entry->method_id != 0) {
const char *method_name; const char *method_name;
...@@ -222,7 +124,6 @@ print_backtrace_saved(mrb_state *mrb) ...@@ -222,7 +124,6 @@ print_backtrace_saved(mrb_state *mrb)
fprintf(stream, ":in %s", method_name); fprintf(stream, ":in %s", method_name);
mrb_gc_arena_restore(mrb, ai); mrb_gc_arena_restore(mrb, ai);
} }
fprintf(stream, "\n"); fprintf(stream, "\n");
} }
} }
...@@ -237,20 +138,13 @@ mrb_print_backtrace(mrb_state *mrb) ...@@ -237,20 +138,13 @@ mrb_print_backtrace(mrb_state *mrb)
} }
backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace")); backtrace = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "backtrace"));
if (!mrb_nil_p(backtrace)) { if (mrb_array_p(backtrace)) {
print_backtrace(mrb, backtrace); print_backtrace(mrb, backtrace);
} }
else if (mrb->backtrace.n > 0) {
print_backtrace_saved(mrb);
}
else { else {
struct print_backtrace_args args; print_packed_backtrace(mrb, backtrace);
args.stream = stderr;
args.tracehead = TRUE;
exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)&args);
} }
} }
#else #else
MRB_API void MRB_API void
...@@ -260,126 +154,83 @@ mrb_print_backtrace(mrb_state *mrb) ...@@ -260,126 +154,83 @@ mrb_print_backtrace(mrb_state *mrb)
#endif #endif
MRB_API mrb_value
mrb_exc_backtrace(mrb_state *mrb, mrb_value self)
{
mrb_value ary;
ary = mrb_ary_new(mrb);
exc_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary));
return ary;
}
MRB_API mrb_value
mrb_get_backtrace(mrb_state *mrb)
{
mrb_value ary;
mrb_callinfo *ci = mrb->c->ci;
mrb_code *pc = ci->pc;
mrb_int ciidx = (mrb_int)(ci - mrb->c->cibase - 1);
if (ciidx < 0) ciidx = 0;
ary = mrb_ary_new(mrb);
output_backtrace(mrb, ciidx, pc, get_backtrace_i, (void*)mrb_ary_ptr(ary));
return ary;
}
void
mrb_free_backtrace(mrb_state *mrb)
{
mrb->backtrace.exc = 0;
mrb->backtrace.n = 0;
mrb->backtrace.n_allocated = 0;
mrb_free(mrb, mrb->backtrace.entries);
}
static void static void
save_backtrace_i(mrb_state *mrb, pack_backtrace_i(mrb_state *mrb,
struct backtrace_location_raw *loc_raw, int i,
struct backtrace_location *loc,
void *data) void *data)
{ {
mrb_backtrace_entry *entry; struct backtrace_location *entry = (struct backtrace_location*)data;
if (mrb->backtrace.n >= mrb->backtrace.n_allocated) {
int new_n_allocated;
if (mrb->backtrace.n_allocated == 0) {
new_n_allocated = 8;
}
else {
new_n_allocated = mrb->backtrace.n_allocated * 2;
}
mrb->backtrace.entries = (mrb_backtrace_entry *)
mrb_realloc(mrb,
mrb->backtrace.entries,
sizeof(mrb_backtrace_entry) * new_n_allocated);
mrb->backtrace.n_allocated = new_n_allocated;
}
entry = &mrb->backtrace.entries[mrb->backtrace.n];
entry->filename = loc_raw->filename;
entry->lineno = loc_raw->lineno;
entry->method_id = loc_raw->method_id;
mrb->backtrace.n++; entry[i] = *loc;
} }
void static mrb_value
mrb_save_backtrace(mrb_state *mrb) packed_backtrace(mrb_state *mrb)
{ {
mrb_value lastpc; mrb_value backtrace;
mrb_code *code; mrb_int ciidx = mrb->c->ci - mrb->c->cibase;
mrb_int ciidx; mrb_int len = (ciidx+1)*sizeof(struct backtrace_location);
char *ptr;
mrb->backtrace.n = 0;
mrb->backtrace.exc = 0; backtrace = mrb_str_new(mrb, NULL, len);
ptr = RSTRING_PTR(backtrace);
if (!mrb->exc) memset(ptr, 0, len);
return; each_backtrace(mrb, ciidx, mrb->c->ci->pc, pack_backtrace_i, ptr);
return backtrace;
mrb->backtrace.exc = mrb->exc;
lastpc = mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"));
if (mrb_nil_p(lastpc)) {
code = NULL;
}
else {
code = (mrb_code*)mrb_cptr(lastpc);
}
ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx")));
each_backtrace(mrb, ciidx, code, save_backtrace_i, NULL);
} }
mrb_value void
mrb_restore_backtrace(mrb_state *mrb) mrb_keep_backtrace(mrb_state *mrb, mrb_value exc)
{ {
int i;
mrb_value backtrace; mrb_value backtrace;
int ai = mrb_gc_arena_save(mrb);
backtrace = mrb_ary_new(mrb); backtrace = packed_backtrace(mrb);
for (i = 0; i < mrb->backtrace.n; i++) { mrb_iv_set(mrb, exc, mrb_intern_lit(mrb, "backtrace"), backtrace);
int ai; mrb_gc_arena_restore(mrb, ai);
mrb_backtrace_entry *entry; }
mrb_value mrb_entry;
ai = mrb_gc_arena_save(mrb); mrb_value
entry = &(mrb->backtrace.entries[i]); mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace)
{
mrb_value str;
struct backtrace_location *bt;
mrb_int n, i;
if (mrb_array_p(backtrace)) return backtrace;
if (!mrb_string_p(backtrace)) {
broken:
mrb_raise(mrb, E_RUNTIME_ERROR, "broken backtrace");
}
str = backtrace;
n = RSTRING_LEN(str);
if (n%sizeof(struct backtrace_location) != 0) goto broken;
n /= sizeof(struct backtrace_location);
bt = (struct backtrace_location*)RSTRING_PTR(str);
backtrace = mrb_ary_new_capa(mrb, n);
for (i = 0; i < n; i++) {
int ai = mrb_gc_arena_save(mrb);
struct backtrace_location *entry = &bt[i];
mrb_value btline;
mrb_entry = mrb_format(mrb, "%S:%S", if (entry->filename == NULL) continue;
btline = mrb_format(mrb, "%S:%S",
mrb_str_new_cstr(mrb, entry->filename), mrb_str_new_cstr(mrb, entry->filename),
mrb_fixnum_value(entry->lineno)); mrb_fixnum_value(entry->lineno));
if (entry->method_id != 0) { if (entry->method_id != 0) {
mrb_str_cat_lit(mrb, mrb_entry, ":in "); mrb_str_cat_lit(mrb, btline, ":in ");
mrb_str_cat_cstr(mrb, mrb_entry, mrb_sym2name(mrb, entry->method_id)); mrb_str_cat_cstr(mrb, btline, mrb_sym2name(mrb, entry->method_id));
} }
mrb_ary_push(mrb, backtrace, btline);
mrb_ary_push(mrb, backtrace, mrb_entry);
mrb_gc_arena_restore(mrb, ai); mrb_gc_arena_restore(mrb, ai);
} }
return backtrace; return backtrace;
} }
mrb_value
mrb_get_backtrace(mrb_state *mrb)
{
return mrb_unpack_backtrace(mrb, packed_backtrace(mrb));
}
...@@ -163,8 +163,8 @@ exc_inspect(mrb_state *mrb, mrb_value exc) ...@@ -163,8 +163,8 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
return str; return str;
} }
void mrb_save_backtrace(mrb_state *mrb); void mrb_keep_backtrace(mrb_state *mrb, mrb_value exc);
mrb_value mrb_restore_backtrace(mrb_state *mrb); mrb_value mrb_unpack_backtrace(mrb_state *mrb, mrb_value backtrace);
static mrb_value static mrb_value
exc_get_backtrace(mrb_state *mrb, mrb_value exc) exc_get_backtrace(mrb_state *mrb, mrb_value exc)
...@@ -175,17 +175,9 @@ exc_get_backtrace(mrb_state *mrb, mrb_value exc) ...@@ -175,17 +175,9 @@ exc_get_backtrace(mrb_state *mrb, mrb_value exc)
attr_name = mrb_intern_lit(mrb, "backtrace"); attr_name = mrb_intern_lit(mrb, "backtrace");
backtrace = mrb_iv_get(mrb, exc, attr_name); backtrace = mrb_iv_get(mrb, exc, attr_name);
if (!mrb_array_p(backtrace)) { if (!mrb_array_p(backtrace)) {
if (mrb_obj_ptr(exc) == mrb->backtrace.exc && mrb->backtrace.n > 0) { backtrace = mrb_unpack_backtrace(mrb, backtrace);
backtrace = mrb_restore_backtrace(mrb);
mrb->backtrace.n = 0;
mrb->backtrace.exc = 0;
}
else {
backtrace = mrb_exc_backtrace(mrb, exc);
}
mrb_iv_set(mrb, exc, attr_name, backtrace); mrb_iv_set(mrb, exc, attr_name, backtrace);
} }
return backtrace; return backtrace;
} }
...@@ -224,7 +216,6 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) ...@@ -224,7 +216,6 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
mrb_callinfo *ci = mrb->c->ci; mrb_callinfo *ci = mrb->c->ci;
mrb_code *pc = ci->pc; mrb_code *pc = ci->pc;
mrb_obj_iv_set(mrb, exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value((mrb_int)(ci - mrb->c->cibase)));
while (ci >= mrb->c->cibase) { while (ci >= mrb->c->cibase) {
mrb_code *err = ci->err; mrb_code *err = ci->err;
...@@ -245,36 +236,9 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) ...@@ -245,36 +236,9 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc)
} }
} }
static mrb_bool
have_backtrace(mrb_state *mrb, struct RObject *exc)
{
return !mrb_nil_p(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "backtrace")));
}
void void
mrb_exc_set(mrb_state *mrb, mrb_value exc) mrb_exc_set(mrb_state *mrb, mrb_value exc)
{ {
if (!mrb->gc.out_of_memory && mrb->backtrace.n > 0) {
mrb_value target_exc = mrb_nil_value();
int ai;
ai = mrb_gc_arena_save(mrb);
if ((mrb->exc && !have_backtrace(mrb, mrb->exc))) {
target_exc = mrb_obj_value(mrb->exc);
}
else if (!mrb_nil_p(exc) && mrb->backtrace.exc) {
target_exc = mrb_obj_value(mrb->backtrace.exc);
mrb_gc_protect(mrb, target_exc);
}
if (!mrb_nil_p(target_exc)) {
mrb_value backtrace;
backtrace = mrb_restore_backtrace(mrb);
set_backtrace(mrb, target_exc, backtrace);
}
mrb_gc_arena_restore(mrb, ai);
}
mrb->backtrace.n = 0;
if (mrb_nil_p(exc)) { if (mrb_nil_p(exc)) {
mrb->exc = 0; mrb->exc = 0;
} }
...@@ -282,7 +246,7 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc) ...@@ -282,7 +246,7 @@ mrb_exc_set(mrb_state *mrb, mrb_value exc)
mrb->exc = mrb_obj_ptr(exc); mrb->exc = mrb_obj_ptr(exc);
if (!mrb->gc.out_of_memory) { if (!mrb->gc.out_of_memory) {
exc_debug_info(mrb, mrb->exc); exc_debug_info(mrb, mrb->exc);
mrb_save_backtrace(mrb); mrb_keep_backtrace(mrb, exc);
} }
} }
} }
......
...@@ -735,8 +735,6 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end) ...@@ -735,8 +735,6 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
case MRB_TT_EXCEPTION: case MRB_TT_EXCEPTION:
mrb_gc_free_iv(mrb, (struct RObject*)obj); mrb_gc_free_iv(mrb, (struct RObject*)obj);
if ((struct RObject*)obj == mrb->backtrace.exc)
mrb->backtrace.exc = 0;
break; break;
case MRB_TT_CLASS: case MRB_TT_CLASS:
...@@ -870,8 +868,6 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc) ...@@ -870,8 +868,6 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self); mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
/* mark exception */ /* mark exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->exc); mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
/* mark backtrace */
mrb_gc_mark(mrb, (struct RBasic*)mrb->backtrace.exc);
/* mark pre-allocated exception */ /* mark pre-allocated exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err); mrb_gc_mark(mrb, (struct RBasic*)mrb->nomem_err);
mrb_gc_mark(mrb, (struct RBasic*)mrb->stack_err); mrb_gc_mark(mrb, (struct RBasic*)mrb->stack_err);
......
...@@ -872,7 +872,6 @@ mrb_f_raise(mrb_state *mrb, mrb_value self) ...@@ -872,7 +872,6 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
/* fall through */ /* fall through */
default: default:
exc = mrb_make_exception(mrb, argc, a); exc = mrb_make_exception(mrb, argc, a);
mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, mrb->c->ci->pc));
mrb_exc_raise(mrb, exc); mrb_exc_raise(mrb, exc);
break; break;
} }
......
...@@ -246,7 +246,6 @@ mrb_close(mrb_state *mrb) ...@@ -246,7 +246,6 @@ mrb_close(mrb_state *mrb)
/* free */ /* free */
mrb_gc_free_gv(mrb); mrb_gc_free_gv(mrb);
mrb_free_backtrace(mrb);
mrb_free_context(mrb, mrb->root_c); mrb_free_context(mrb, mrb->root_c);
mrb_free_symtbl(mrb); mrb_free_symtbl(mrb);
mrb_alloca_free(mrb); mrb_alloca_free(mrb);
......
...@@ -1741,8 +1741,6 @@ RETRY_TRY_BLOCK: ...@@ -1741,8 +1741,6 @@ RETRY_TRY_BLOCK:
L_RAISE: L_RAISE:
ci0 = ci = mrb->c->ci; ci0 = ci = mrb->c->ci;
mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, pc));
mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern_lit(mrb, "ciidx"), mrb_fixnum_value(ci - mrb->c->cibase));
eidx = ci->eidx; eidx = ci->eidx;
if (ci == mrb->c->cibase) { if (ci == mrb->c->cibase) {
if (ci->ridx == 0) goto L_STOP; if (ci->ridx == 0) goto L_STOP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment