summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--gc.c66
2 files changed, 51 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 7ca6a707aa..3f1128e956 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sun May 22 18:26:43 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (vm_xcalloc): use calloc provided by platforms.
+ fixes #4754
+
Sun May 22 11:44:53 2011 Eric Hodel <drbrain@segment7.net>
* ext/pty/pty.c: Improve documentaton. Patch by David Copeland.
diff --git a/gc.c b/gc.c
index d63300231f..28fa233adc 100644
--- a/gc.c
+++ b/gc.c
@@ -702,11 +702,9 @@ garbage_collect_with_gvl(rb_objspace_t *objspace)
static void vm_xfree(rb_objspace_t *objspace, void *ptr);
-static void *
-vm_xmalloc(rb_objspace_t *objspace, size_t size)
+static inline void
+vm_malloc_prepare(rb_objspace_t *objspace, size_t size)
{
- void *mem;
-
if ((ssize_t)size < 0) {
negative_size_allocation_error("negative allocation size (or too big)");
}
@@ -720,15 +718,11 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size)
(malloc_increase+size) > malloc_limit) {
garbage_collect_with_gvl(objspace);
}
- mem = malloc(size);
- if (!mem) {
- if (garbage_collect_with_gvl(objspace)) {
- mem = malloc(size);
- }
- if (!mem) {
- ruby_memerror();
- }
- }
+}
+
+static inline void *
+vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
+{
malloc_increase += size;
#if CALC_EXACT_MALLOC_SIZE
@@ -741,6 +735,24 @@ vm_xmalloc(rb_objspace_t *objspace, size_t size)
return mem;
}
+#define TRY_WITH_GC(alloc) do { \
+ if (!(alloc) && \
+ (!garbage_collect_with_gvl(objspace) || \
+ !(alloc))) { \
+ ruby_memerror(); \
+ } \
+ } while (0)
+
+static void *
+vm_xmalloc(rb_objspace_t *objspace, size_t size)
+{
+ void *mem;
+
+ vm_malloc_prepare(objspace, size);
+ TRY_WITH_GC(mem = malloc(size));
+ return vm_malloc_fixup(objspace, mem, size);
+}
+
static void *
vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
{
@@ -803,23 +815,37 @@ ruby_xmalloc(size_t size)
return vm_xmalloc(&rb_objspace, size);
}
-void *
-ruby_xmalloc2(size_t n, size_t size)
+static inline size_t
+xmalloc2_size(size_t n, size_t size)
{
size_t len = size * n;
if (n != 0 && size != len / n) {
rb_raise(rb_eArgError, "malloc: possible integer overflow");
}
- return vm_xmalloc(&rb_objspace, len);
+ return len;
}
void *
-ruby_xcalloc(size_t n, size_t size)
+ruby_xmalloc2(size_t n, size_t size)
{
- void *mem = ruby_xmalloc2(n, size);
- memset(mem, 0, n * size);
+ return vm_xmalloc(&rb_objspace, xmalloc2_size(n, size));
+}
- return mem;
+static void *
+vm_xcalloc(rb_objspace_t *objspace, size_t count, size_t elsize)
+{
+ void *mem;
+ const size_t size = xmalloc2_size(count, elsize);
+
+ vm_malloc_prepare(objspace, size);
+ TRY_WITH_GC(mem = calloc(count, elsize));
+ return vm_malloc_fixup(objspace, mem, size);
+}
+
+void *
+ruby_xcalloc(size_t n, size_t size)
+{
+ return vm_xcalloc(&rb_objspace, n, size);
}
void *