summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-07-07 06:01:50 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-07-07 06:01:50 +0000
commit8cfa1773652264837eab45cd907b1a99e9e20980 (patch)
treed1b723ee31102d3d209d1fe290f438db49e8a503 /gc.c
parent7d110cc79c20df49f24936db409192a281046479 (diff)
merge revision(s) 17832:
* eval.c (rb_longjmp): duplicate the thrown exception to set backtrace if it was frozen. clear all raised flags. * eval.c (stack_check): leave clearing flag to rb_longjmp. * eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic flags. * eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions. * gc.c (rb_memerror): use thread raised flag instead of static flag, and raise nomem_error without backtrace if failed to make backtrace. [ruby-dev:34724] * gc.c (ruby_xmalloc): increase malloc_increase only if malloc succeeds. failed malloc size can be huge. it may increase malloc_limit too big which cause less GC and memory full. (ruby_xrealloc): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@17928 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/gc.c b/gc.c
index be88358..807d8eb 100644
--- a/gc.c
+++ b/gc.c
@@ -74,16 +74,22 @@ static void run_final();
static VALUE nomem_error;
static void garbage_collect();
+NORETURN(void rb_exc_jump _((VALUE)));
+
void
rb_memerror()
{
- static int recurse = 0;
+ rb_thread_t th = rb_curr_thread;
- if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) {
+ if (!nomem_error ||
+ (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) {
fprintf(stderr, "[FATAL] failed to allocate memory\n");
exit(1);
}
- recurse++;
+ if (rb_thread_raised_p(th, RAISED_NOMEMORY)) {
+ rb_exc_jump(nomem_error);
+ }
+ rb_thread_raised_set(th, RAISED_NOMEMORY);
rb_exc_raise(nomem_error);
}
@@ -97,9 +103,8 @@ ruby_xmalloc(size)
rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
}
if (size == 0) size = 1;
- malloc_increase += size;
- if (malloc_increase > malloc_limit) {
+ if ((malloc_increase+size) > malloc_limit) {
garbage_collect();
}
RUBY_CRITICAL(mem = malloc(size));
@@ -110,6 +115,7 @@ ruby_xmalloc(size)
rb_memerror();
}
}
+ malloc_increase += size;
return mem;
}
@@ -138,7 +144,6 @@ ruby_xrealloc(ptr, size)
}
if (!ptr) return xmalloc(size);
if (size == 0) size = 1;
- malloc_increase += size;
RUBY_CRITICAL(mem = realloc(ptr, size));
if (!mem) {
garbage_collect();
@@ -147,6 +152,7 @@ ruby_xrealloc(ptr, size)
rb_memerror();
}
}
+ malloc_increase += size;
return mem;
}
@@ -2064,6 +2070,8 @@ Init_GC()
rb_global_variable(&nomem_error);
nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory");
+ OBJ_TAINT(nomem_error);
+ OBJ_FREEZE(nomem_error);
rb_define_method(rb_mKernel, "hash", rb_obj_id, 0);
rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0);