summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-01-11 15:24:53 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-01-11 15:24:53 +0000
commitf3a4870b42fcbaefd051b3754738a869b87098e2 (patch)
treeaf684c1853659d3b2ec71efcc47640ae0a4eae65
parent3c299b5fe5d653e2ec231f6afb97445f8860c898 (diff)
merge revision(s) 18392:
* gc.c (gc_sweep, obj_free, run_final): defer finalizers of IO and Data. [ruby-dev:35578] * gc.c (rb_gc_call_finalizer_at_exit): self-referencing finalizers cannot be invoked. [ruby-dev:35681] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@21435 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog8
-rw-r--r--gc.c108
-rw-r--r--version.h8
3 files changed, 82 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index 030250c7ed..682cbbd7d4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Mon Jan 12 00:23:37 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (gc_sweep, obj_free, run_final): defer finalizers of IO and
+ Data. [ruby-dev:35578]
+
+ * gc.c (rb_gc_call_finalizer_at_exit): self-referencing finalizers
+ cannot be invoked. [ruby-dev:35681]
+
Sun Jan 11 11:33:27 2009 Shugo Maeda <shugo@ruby-lang.org>
* lib/net/ftp.rb (chdir): handle 5xx errors correctly.
diff --git a/gc.c b/gc.c
index b41df745a5..445041aa92 100644
--- a/gc.c
+++ b/gc.c
@@ -1052,7 +1052,16 @@ gc_mark_children(ptr, lev)
}
}
-static void obj_free _((VALUE));
+static int obj_free _((VALUE));
+
+static inline void
+add_freelist(p)
+ RVALUE *p;
+{
+ p->as.free.flags = 0;
+ p->as.free.next = freelist;
+ freelist = p;
+}
static void
finalize_list(p)
@@ -1062,9 +1071,7 @@ finalize_list(p)
RVALUE *tmp = p->as.free.next;
run_final((VALUE)p);
if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
+ add_freelist(p);
}
p = tmp;
}
@@ -1089,6 +1096,8 @@ free_unused_heaps()
}
}
+#define T_DEFERRED 0x3a
+
void rb_gc_abort_threads(void);
static void
@@ -1132,26 +1141,28 @@ gc_sweep()
int n = 0;
RVALUE *free = freelist;
RVALUE *final = final_list;
+ int deferred;
p = heaps[i].slot; pend = p + heaps[i].limit;
while (p < pend) {
if (!(p->as.basic.flags & FL_MARK)) {
- if (p->as.basic.flags) {
- obj_free((VALUE)p);
- }
- if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
- p->as.free.flags = FL_MARK; /* remain marked */
+ if (p->as.basic.flags &&
+ ((deferred = obj_free((VALUE)p)) ||
+ ((FL_TEST(p, FL_FINALIZE)) && need_call_final))) {
+ if (!deferred) {
+ p->as.free.flags = T_DEFERRED;
+ RDATA(p)->dfree = 0;
+ }
+ p->as.free.flags |= FL_MARK;
p->as.free.next = final_list;
final_list = p;
}
else {
- p->as.free.flags = 0;
- p->as.free.next = freelist;
- freelist = p;
+ add_freelist(p);
}
n++;
}
- else if (RBASIC(p)->flags == FL_MARK) {
+ else if (BUILTIN_TYPE(p) == T_DEFERRED) {
/* objects to be finalized */
/* do nothing remain marked */
}
@@ -1197,16 +1208,21 @@ void
rb_gc_force_recycle(p)
VALUE p;
{
- RANY(p)->as.free.flags = 0;
- RANY(p)->as.free.next = freelist;
- freelist = RANY(p);
+ add_freelist(p);
}
-static void
+static inline void
+make_deferred(p)
+ RVALUE *p;
+{
+ p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_DEFERRED;
+}
+
+static int
obj_free(obj)
VALUE obj;
{
- switch (RANY(obj)->as.basic.flags & T_MASK) {
+ switch (BUILTIN_TYPE(obj)) {
case T_NIL:
case T_FIXNUM:
case T_TRUE:
@@ -1219,7 +1235,7 @@ obj_free(obj)
rb_free_generic_ivar((VALUE)obj);
}
- switch (RANY(obj)->as.basic.flags & T_MASK) {
+ switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
if (RANY(obj)->as.object.iv_tbl) {
st_free_table(RANY(obj)->as.object.iv_tbl);
@@ -1262,7 +1278,8 @@ obj_free(obj)
RUBY_CRITICAL(free(DATA_PTR(obj)));
}
else if (RANY(obj)->as.data.dfree) {
- (*RANY(obj)->as.data.dfree)(DATA_PTR(obj));
+ make_deferred(RANY(obj));
+ return 1;
}
}
break;
@@ -1274,8 +1291,11 @@ obj_free(obj)
break;
case T_FILE:
if (RANY(obj)->as.file.fptr) {
- rb_io_fptr_finalize(RANY(obj)->as.file.fptr);
- RUBY_CRITICAL(free(RANY(obj)->as.file.fptr));
+ struct rb_io_t *fptr = RANY(obj)->as.file.fptr;
+ make_deferred(RANY(obj));
+ RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
+ RDATA(obj)->data = fptr;
+ return 1;
}
break;
case T_ICLASS:
@@ -1303,7 +1323,7 @@ obj_free(obj)
RUBY_CRITICAL(free(RANY(obj)->as.node.u1.node));
break;
}
- return; /* no need to free iv_tbl */
+ break; /* no need to free iv_tbl */
case T_SCOPE:
if (RANY(obj)->as.scope.local_vars &&
@@ -1326,6 +1346,8 @@ obj_free(obj)
rb_bug("gc_sweep(): unknown data type 0x%lx(0x%lx)",
RANY(obj)->as.basic.flags & T_MASK, obj);
}
+
+ return 0;
}
void
@@ -1671,6 +1693,7 @@ os_obj_of(of)
case T_VARMAP:
case T_SCOPE:
case T_NODE:
+ case T_DEFERRED:
continue;
case T_CLASS:
if (FL_TEST(p, FL_SINGLETON)) continue;
@@ -1918,6 +1941,21 @@ rb_gc_finalize_deferred()
}
}
+static int
+chain_finalized_object(st_data_t key, st_data_t val, st_data_t arg)
+{
+ RVALUE *p = (RVALUE *)key, **final_list = (RVALUE **)arg;
+ if ((p->as.basic.flags & (FL_FINALIZE|FL_MARK)) == FL_FINALIZE) {
+ if (BUILTIN_TYPE(p) != T_DEFERRED) {
+ p->as.free.flags = FL_MARK | T_DEFERRED; /* remain marked */
+ RDATA(p)->dfree = 0;
+ }
+ p->as.free.next = *final_list;
+ *final_list = p;
+ }
+ return ST_CONTINUE;
+}
+
void
rb_gc_call_finalizer_at_exit()
{
@@ -1926,20 +1964,14 @@ rb_gc_call_finalizer_at_exit()
/* run finalizers */
if (need_call_final) {
- p = deferred_final_list;
- deferred_final_list = 0;
- finalize_list(p);
- for (i = 0; i < heaps_used; i++) {
- p = heaps[i].slot; pend = p + heaps[i].limit;
- while (p < pend) {
- if (FL_TEST(p, FL_FINALIZE)) {
- FL_UNSET(p, FL_FINALIZE);
- p->as.basic.klass = 0;
- run_final((VALUE)p);
- }
- p++;
- }
- }
+ do {
+ p = deferred_final_list;
+ deferred_final_list = 0;
+ finalize_list(p);
+ mark_tbl(finalizer_table, 0);
+ st_foreach(finalizer_table, chain_finalized_object,
+ (st_data_t)&deferred_final_list);
+ } while (deferred_final_list);
}
/* run data object's finalizers */
for (i = 0; i < heaps_used; i++) {
@@ -2000,7 +2032,7 @@ id2ref(obj, objid)
}
if (!is_pointer_to_heap((void *)ptr)||
- (type = BUILTIN_TYPE(ptr)) >= T_BLKTAG || type == T_ICLASS) {
+ (type = BUILTIN_TYPE(ptr)) > T_SYMBOL || type == T_ICLASS) {
rb_raise(rb_eRangeError, "0x%lx is not id value", p0);
}
if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
diff --git a/version.h b/version.h
index d631c49351..99a76b88d4 100644
--- a/version.h
+++ b/version.h
@@ -1,15 +1,15 @@
#define RUBY_VERSION "1.8.7"
-#define RUBY_RELEASE_DATE "2009-01-11"
+#define RUBY_RELEASE_DATE "2009-01-12"
#define RUBY_VERSION_CODE 187
-#define RUBY_RELEASE_CODE 20090111
-#define RUBY_PATCHLEVEL 82
+#define RUBY_RELEASE_CODE 20090112
+#define RUBY_PATCHLEVEL 83
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
#define RUBY_VERSION_TEENY 7
#define RUBY_RELEASE_YEAR 2009
#define RUBY_RELEASE_MONTH 1
-#define RUBY_RELEASE_DAY 11
+#define RUBY_RELEASE_DAY 12
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];