aboutsummaryrefslogtreecommitdiffstats
path: root/gc.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-21 21:28:34 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-07-21 21:28:34 +0000
commitdf27e0c3649979429650b8df573656846863c837 (patch)
treebe55d43d1f665299f05f5ebb6345babd9b798af8 /gc.c
parent4a3f636e73cc63d3a42016eec9580214cfc3f8cb (diff)
downloadruby-df27e0c3649979429650b8df573656846863c837.tar.gz
gc.c: reduce EXEC_TAG
* gc.c (run_finalizer): push and exec tag just once, instead of protecting for each finalizer. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55722 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/gc.c b/gc.c
index fe2c225f23..bc55f78a50 100644
--- a/gc.c
+++ b/gc.c
@@ -2691,36 +2691,41 @@ rb_gc_copy_finalizer(VALUE dest, VALUE obj)
}
static VALUE
-run_single_final(VALUE arg)
+run_single_final(VALUE final, VALUE objid)
{
- VALUE *args = (VALUE *)arg;
+ const VALUE cmd = RARRAY_AREF(final, 1);
+ const int level = OBJ_TAINTED(cmd) ?
+ RUBY_SAFE_LEVEL_MAX : FIX2INT(RARRAY_AREF(final, 0));
- return rb_check_funcall(args[0], idCall, 1, args+1);
+ rb_set_safe_level_force(level);
+ return rb_check_funcall(cmd, idCall, 1, &objid);
}
static void
run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
{
long i;
- VALUE args[2];
+ int status;
const int safe = rb_safe_level();
const VALUE errinfo = rb_errinfo();
-
- args[1] = nonspecial_obj_id(obj);
-
- for (i=0; i<RARRAY_LEN(table); i++) {
- const VALUE final = RARRAY_AREF(table, i);
- const VALUE cmd = RARRAY_AREF(final, 1);
- const int level = OBJ_TAINTED(cmd) ?
- RUBY_SAFE_LEVEL_MAX : FIX2INT(RARRAY_AREF(final, 0));
- int status = 0;
-
- args[0] = cmd;
- rb_set_safe_level_force(level);
- rb_protect(run_single_final, (VALUE)args, &status);
+ const VALUE objid = nonspecial_obj_id(obj);
+ rb_thread_t *const th = GET_THREAD();
+ volatile long finished = 0;
+
+ TH_PUSH_TAG(th);
+ status = TH_EXEC_TAG();
+ if (status) {
+ ++finished; /* skip failed finalizer */
+ rb_set_safe_level_force(safe);
+ rb_set_errinfo(errinfo);
+ }
+ for (i = finished; i<RARRAY_LEN(table); i++) {
+ finished = i;
+ run_single_final(RARRAY_AREF(table, i), objid);
rb_set_safe_level_force(safe);
rb_set_errinfo(errinfo);
}
+ TH_POP_TAG();
}
static void