summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/gc.h1
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c10
-rw-r--r--mrbgems/mruby-eval/src/eval.c11
-rw-r--r--mrbgems/mruby-proc-ext/src/proc.c5
-rw-r--r--mrbgems/mruby-string-ext/src/string.c2
-rw-r--r--mrbgems/mruby-time/src/time.c40
-rw-r--r--src/array.c2
-rw-r--r--src/backtrace.c11
-rw-r--r--src/error.c25
-rw-r--r--src/gc.c43
10 files changed, 92 insertions, 58 deletions
diff --git a/include/mruby/gc.h b/include/mruby/gc.h
index dd161efa1..ce214aa56 100644
--- a/include/mruby/gc.h
+++ b/include/mruby/gc.h
@@ -64,6 +64,7 @@ typedef struct mrb_gc {
size_t threshold;
int interval_ratio;
int step_ratio;
+ mrb_bool iterating :1;
mrb_bool disabled :1;
mrb_bool full :1;
mrb_bool generational :1;
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index e790e6dfc..f863ef337 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -1024,9 +1024,9 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
default:
#ifndef MRB_DISABLE_STDIO
- printf("unknown lhs %d\n", type);
+ fprintf(stderr, "unknown lhs %d\n", type);
#endif
- break;
+ return;
}
if (val) push();
}
@@ -2195,11 +2195,11 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NTH_REF:
if (val) {
mrb_state *mrb = s->mrb;
- char buf[32];
+ mrb_value str;
int sym;
- snprintf(buf, sizeof(buf), "$%" MRB_PRId, (mrb_int)(intptr_t)tree);
- sym = new_sym(s, mrb_intern_cstr(mrb, buf));
+ str = mrb_format(mrb, "$%S", mrb_fixnum_value((mrb_int)(intptr_t)tree));
+ sym = new_sym(s, mrb_intern_str(mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
}
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
index 00cb2f15c..54a6aab2e 100644
--- a/mrbgems/mruby-eval/src/eval.c
+++ b/mrbgems/mruby-eval/src/eval.c
@@ -4,6 +4,7 @@
#include <mruby/irep.h>
#include <mruby/proc.h>
#include <mruby/opcode.h>
+#include <mruby/error.h>
mrb_value mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p);
mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
@@ -175,12 +176,14 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
if (0 < p->nerr) {
/* parse error */
- char buf[256];
- int n;
- n = snprintf(buf, sizeof(buf), "line %d: %s\n", p->error_buffer[0].lineno, p->error_buffer[0].message);
+ mrb_value str;
+
+ str = mrb_format(mrb, "line %S: %S",
+ mrb_fixnum_value(p->error_buffer[0].lineno),
+ mrb_str_new_cstr(mrb, p->error_buffer[0].message));
mrb_parser_free(p);
mrbc_context_free(mrb, cxt);
- mrb_exc_raise(mrb, mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
+ mrb_exc_raise(mrb, mrb_exc_new_str(mrb, E_SYNTAX_ERROR, str));
}
proc = mrb_generate_code(mrb, p);
diff --git a/mrbgems/mruby-proc-ext/src/proc.c b/mrbgems/mruby-proc-ext/src/proc.c
index f7f031e7b..b13606f5f 100644
--- a/mrbgems/mruby-proc-ext/src/proc.c
+++ b/mrbgems/mruby-proc-ext/src/proc.c
@@ -52,10 +52,7 @@ mrb_proc_inspect(mrb_state *mrb, mrb_value self)
line = mrb_debug_get_line(irep, 0);
if (line != -1) {
- char buf[32];
-
- snprintf(buf, sizeof(buf), "%" PRId32, line);
- mrb_str_cat_cstr(mrb, str, buf);
+ str = mrb_format(mrb, "%S:%S", str, mrb_fixnum_value(line));
}
else {
mrb_str_cat_lit(mrb, str, "-");
diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c
index 402dbf987..4c22f40c7 100644
--- a/mrbgems/mruby-string-ext/src/string.c
+++ b/mrbgems/mruby-string-ext/src/string.c
@@ -367,7 +367,7 @@ mrb_str_succ_bang(mrb_state *mrb, mrb_value self)
unsigned char *p, *e, *b, *t;
const char *prepend;
struct RString *s = mrb_str_ptr(self);
- size_t l;
+ mrb_int l;
if (RSTRING_LEN(self) == 0)
return self;
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index ce99a5a65..33755f570 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -5,12 +5,17 @@
*/
#include <math.h>
-#include <stdio.h>
#include <time.h>
#include <mruby.h>
#include <mruby/class.h>
#include <mruby/data.h>
+#ifndef DISABLE_STDIO
+#include <stdio.h>
+#else
+#include <string.h>
+#endif
+
#define NDIV(x,y) (-(-((x)+1)/(y))-1)
#if _MSC_VER < 1800
@@ -55,6 +60,13 @@ double round(double x) {
#endif
#endif
+/* asctime(3) */
+/* mruby usually use its own implementation of struct tm to string conversion */
+/* except when DISABLE_STDIO is set. In that case, it uses asctime() or asctime_r(). */
+/* By default mruby tries to use asctime_r() which is reentrant. */
+/* Undef following macro on platforms that does not have asctime_r(). */
+/* #define NO_ASCTIME_R */
+
/* timegm(3) */
/* mktime() creates tm structure for localtime; timegm() is for UTC time */
/* define following macro to use probably faster timegm() on the platform */
@@ -166,6 +178,7 @@ static const mrb_timezone_name timezone_names[] = {
{ "LOCAL", sizeof("LOCAL") - 1 },
};
+#ifndef DISABLE_STDIO
static const char mon_names[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
@@ -173,6 +186,7 @@ static const char mon_names[12][4] = {
static const char wday_names[7][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
};
+#endif
struct mrb_time {
time_t sec;
@@ -241,12 +255,12 @@ time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
tm->sec = tsec;
tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec);
if (tm->usec < 0) {
- long sec2 = NDIV(usec,1000000); /* negative div */
+ long sec2 = (long)NDIV(usec,1000000); /* negative div */
tm->usec -= sec2 * 1000000;
tm->sec += sec2;
}
else if (tm->usec >= 1000000) {
- long sec2 = usec / 1000000;
+ long sec2 = (long)(usec / 1000000);
tm->usec -= sec2 * 1000000;
tm->sec += sec2;
}
@@ -528,18 +542,28 @@ mrb_time_zone(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_time_asctime(mrb_state *mrb, mrb_value self)
{
- struct mrb_time *tm;
- struct tm *d;
- char buf[256];
+ struct mrb_time *tm = time_get_ptr(mrb, self);
+ struct tm *d = &tm->datetime;
int len;
- tm = time_get_ptr(mrb, self);
- d = &tm->datetime;
+#if defined(DISABLE_STDIO)
+ char *s;
+# ifdef NO_ASCTIME_R
+ s = asctime(d);
+# else
+ char buf[32];
+ s = asctime_r(d, buf);
+# endif
+ len = strlen(s)-1; /* truncate the last newline */
+#else
+ char buf[256];
+
len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
d->tm_hour, d->tm_min, d->tm_sec,
tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
d->tm_year + 1900);
+#endif
return mrb_str_new(mrb, buf, len);
}
diff --git a/src/array.c b/src/array.c
index 67cae92eb..3ab74f95d 100644
--- a/src/array.c
+++ b/src/array.c
@@ -192,7 +192,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, size_t len)
if (capa > (size_t)a->aux.capa) {
mrb_value *expanded_ptr = (mrb_value *)mrb_realloc(mrb, a->ptr, sizeof(mrb_value)*capa);
- a->aux.capa = capa;
+ a->aux.capa = (mrb_int)capa;
a->ptr = expanded_ptr;
}
}
diff --git a/src/backtrace.c b/src/backtrace.c
index d634123b4..b60c375f3 100644
--- a/src/backtrace.c
+++ b/src/backtrace.c
@@ -74,14 +74,12 @@ static void
get_backtrace_i(mrb_state *mrb, struct backtrace_location *loc, void *data)
{
mrb_value ary, str;
- char buf[32];
int ai = mrb_gc_arena_save(mrb);
ary = mrb_obj_value((struct RArray*)data);
str = mrb_str_new_cstr(mrb, loc->filename);
- snprintf(buf, sizeof(buf), ":%d", loc->lineno);
- mrb_str_cat_cstr(mrb, str, buf);
+ str = mrb_format(mrb, "%S:%S", str, mrb_fixnum_value(loc->lineno));
if (loc->method) {
mrb_str_cat_lit(mrb, str, ":in ");
@@ -400,14 +398,13 @@ mrb_restore_backtrace(mrb_state *mrb)
int ai;
mrb_backtrace_entry *entry;
mrb_value mrb_entry;
- char buf[32];
ai = mrb_gc_arena_save(mrb);
entry = &(mrb->backtrace.entries[i]);
- mrb_entry = mrb_str_new_cstr(mrb, entry->filename);
- snprintf(buf, sizeof(buf), ":%d", entry->lineno);
- mrb_str_cat_cstr(mrb, mrb_entry, buf);
+ mrb_entry = mrb_format(mrb, "%S:%S",
+ mrb_str_new_cstr(mrb, entry->filename),
+ mrb_fixnum_value(entry->lineno));
if (entry->method_id != 0) {
mrb_str_cat_lit(mrb, mrb_entry, ":in ");
diff --git a/src/error.c b/src/error.c
index ac11e4d8d..258a8f7df 100644
--- a/src/error.c
+++ b/src/error.c
@@ -137,6 +137,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
{
mrb_value str, mesg, file, line;
mrb_bool append_mesg;
+ const char *cname;
mesg = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "mesg"));
file = mrb_attr_get(mrb, exc, mrb_intern_lit(mrb, "file"));
@@ -148,28 +149,18 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
append_mesg = RSTRING_LEN(mesg) > 0;
}
+ cname = mrb_obj_classname(mrb, exc);
+ str = mrb_str_new_cstr(mrb, cname);
if (mrb_string_p(file) && mrb_fixnum_p(line)) {
- char buf[32];
-
- str = mrb_str_dup(mrb, file);
- snprintf(buf, sizeof(buf), ":%" MRB_PRId ": ", mrb_fixnum(line));
- mrb_str_cat_cstr(mrb, str, buf);
if (append_mesg) {
- mrb_str_cat_str(mrb, str, mesg);
- mrb_str_cat_lit(mrb, str, " (");
+ str = mrb_format(mrb, "%S:%S:%S (%S)", file, line, mesg, str);
}
- mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
- if (append_mesg) {
- mrb_str_cat_lit(mrb, str, ")");
+ else {
+ str = mrb_format(mrb, "%S:%S:%S", file, line, str);
}
}
- else {
- const char *cname = mrb_obj_classname(mrb, exc);
- str = mrb_str_new_cstr(mrb, cname);
- if (append_mesg) {
- mrb_str_cat_lit(mrb, str, ": ");
- mrb_str_cat_str(mrb, str, mesg);
- }
+ else if (append_mesg) {
+ str = mrb_format(mrb, "%S:%S", str, mesg);
}
return str;
}
diff --git a/src/gc.c b/src/gc.c
index c703428b5..469e5df6c 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -17,6 +17,7 @@
#include <mruby/variable.h>
#include <mruby/gc.h>
#include <mruby/error.h>
+#include <mruby/throw.h>
/*
= Tri-color Incremental Garbage Collection
@@ -594,8 +595,8 @@ mark_context(mrb_state *mrb, struct mrb_context *c)
}
/* mark fibers */
mrb_gc_mark(mrb, (struct RBasic*)c->fib);
- if (c->prev) {
- mark_context(mrb, c->prev);
+ if (c->prev && c->prev->fib) {
+ mrb_gc_mark(mrb, (struct RBasic*)c->prev->fib);
}
}
@@ -882,10 +883,10 @@ root_scan_phase(mrb_state *mrb, mrb_gc *gc)
mrb_gc_mark(mrb, (struct RBasic*)mrb->arena_err);
#endif
+ mark_context(mrb, mrb->root_c);
if (mrb->root_c != mrb->c) {
mark_context(mrb, mrb->c);
}
- mark_context(mrb, mrb->root_c);
}
static size_t
@@ -1162,7 +1163,7 @@ mrb_incremental_gc(mrb_state *mrb)
{
mrb_gc *gc = &mrb->gc;
- if (gc->disabled) return;
+ if (gc->disabled || gc->iterating) return;
GC_INVOKE_TIME_REPORT("mrb_incremental_gc()");
GC_TIME_START;
@@ -1202,7 +1203,7 @@ mrb_full_gc(mrb_state *mrb)
{
mrb_gc *gc = &mrb->gc;
- if (gc->disabled) return;
+ if (gc->disabled || gc->iterating) return;
GC_INVOKE_TIME_REPORT("mrb_full_gc()");
GC_TIME_START;
@@ -1491,9 +1492,7 @@ static void
gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback, void *data)
{
mrb_heap_page* page = gc->heaps;
- mrb_bool old_disable = gc->disabled;
- gc->disabled = TRUE;
while (page != NULL) {
RVALUE *p, *pend;
@@ -1501,18 +1500,40 @@ gc_each_objects(mrb_state *mrb, mrb_gc *gc, mrb_each_object_callback *callback,
pend = p + MRB_HEAP_PAGE_SIZE;
for (;p < pend; p++) {
if ((*callback)(mrb, &p->as.basic, data) == MRB_EACH_OBJ_BREAK)
- break;
+ return;
}
-
page = page->next;
}
- gc->disabled = old_disable;
}
void
mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data)
{
- gc_each_objects(mrb, &mrb->gc, callback, data);
+ mrb_bool iterating = mrb->gc.iterating;
+
+ mrb->gc.iterating = TRUE;
+ if (iterating) {
+ gc_each_objects(mrb, &mrb->gc, callback, data);
+ }
+ else {
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ gc_each_objects(mrb, &mrb->gc, callback, data);
+ mrb->jmp = prev_jmp;
+ mrb->gc.iterating = iterating;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+ mrb->gc.iterating = iterating;
+ if (mrb->exc) {
+ mrb_value exc = mrb_obj_value(mrb->exc);
+ mrb->exc = NULL;
+ mrb_exc_raise(mrb, exc);
+ }
+ } MRB_END_EXC(&c_jmp);
+ }
}
#ifdef GC_TEST