mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
at_exit list
* vm_core.h (rb_vm_struct): make at_exit a single linked list but not RArray, not to mark the registered functions by the write barrier. based on the patches by Evan Phoenix. [ruby-core:73908] [Bug #12095] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54484 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
dc58fbeade
commit
990d709eeb
6 changed files with 91 additions and 13 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Mon Apr 4 23:37:05 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* vm_core.h (rb_vm_struct): make at_exit a single linked list but
|
||||||
|
not RArray, not to mark the registered functions by the write
|
||||||
|
barrier. based on the patches by Evan Phoenix.
|
||||||
|
[ruby-core:73908] [Bug #12095]
|
||||||
|
|
||||||
Mon Apr 4 17:43:45 2016 Koichi Sasada <ko1@atdot.net>
|
Mon Apr 4 17:43:45 2016 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* gc.c: change deafult value of
|
* gc.c: change deafult value of
|
||||||
|
|
44
ext/-test-/vm/at_exit.c
Normal file
44
ext/-test-/vm/at_exit.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include <ruby/ruby.h>
|
||||||
|
#include <ruby/vm.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_nothing(ruby_vm_t *vm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_begin(ruby_vm_t *vm)
|
||||||
|
{
|
||||||
|
printf("begin\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_end(ruby_vm_t *vm)
|
||||||
|
{
|
||||||
|
printf("end\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
register_at_exit(VALUE self, VALUE t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case Qtrue:
|
||||||
|
ruby_vm_at_exit(print_begin);
|
||||||
|
break;
|
||||||
|
case Qfalse:
|
||||||
|
ruby_vm_at_exit(print_end);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ruby_vm_at_exit(do_nothing);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_at_exit(void)
|
||||||
|
{
|
||||||
|
VALUE m = rb_define_module("Bug");
|
||||||
|
VALUE c = rb_define_class_under(m, "VM", rb_cObject);
|
||||||
|
rb_define_singleton_method(c, "register_at_exit", register_at_exit, 1);
|
||||||
|
}
|
1
ext/-test-/vm/extconf.rb
Normal file
1
ext/-test-/vm/extconf.rb
Normal file
|
@ -0,0 +1 @@
|
||||||
|
create_makefile('-test-/vm/at_exit')
|
19
test/-ext-/vm/test_at_exit.rb
Normal file
19
test/-ext-/vm/test_at_exit.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# frozen_string_literal: false
|
||||||
|
class TestVM < Test::Unit::TestCase
|
||||||
|
|
||||||
|
# [Bug #12095]
|
||||||
|
def test_at_exit
|
||||||
|
|
||||||
|
assert_in_out_err([], <<-"end;", %w[begin end]) # do
|
||||||
|
require '-test-/vm/at_exit'
|
||||||
|
Bug::VM.register_at_exit(false)
|
||||||
|
1000.times do
|
||||||
|
Bug::VM.register_at_exit(nil)
|
||||||
|
["x"]*1000
|
||||||
|
end
|
||||||
|
GC.start
|
||||||
|
Bug::VM.register_at_exit(true)
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
19
vm.c
19
vm.c
|
@ -468,20 +468,25 @@ rb_frame_pop(void)
|
||||||
void
|
void
|
||||||
ruby_vm_at_exit(void (*func)(rb_vm_t *))
|
ruby_vm_at_exit(void (*func)(rb_vm_t *))
|
||||||
{
|
{
|
||||||
rb_ary_push((VALUE)&GET_VM()->at_exit, (VALUE)func);
|
rb_vm_t *vm = GET_VM();
|
||||||
|
rb_at_exit_list *nl = ALLOC(rb_at_exit_list);
|
||||||
|
nl->func = func;
|
||||||
|
nl->next = vm->at_exit;
|
||||||
|
vm->at_exit = nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
|
ruby_vm_run_at_exit_hooks(rb_vm_t *vm)
|
||||||
{
|
{
|
||||||
VALUE hook = (VALUE)&vm->at_exit;
|
rb_at_exit_list *l = vm->at_exit;
|
||||||
|
|
||||||
while (RARRAY_LEN(hook) > 0) {
|
while (l) {
|
||||||
typedef void rb_vm_at_exit_func(rb_vm_t*);
|
rb_at_exit_list* t = l->next;
|
||||||
rb_vm_at_exit_func *func = (rb_vm_at_exit_func*)rb_ary_pop(hook);
|
rb_vm_at_exit_func *func = l->func;
|
||||||
|
free(l);
|
||||||
|
l = t;
|
||||||
(*func)(vm);
|
(*func)(vm);
|
||||||
}
|
}
|
||||||
rb_ary_free(hook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Env */
|
/* Env */
|
||||||
|
@ -2172,8 +2177,6 @@ vm_init2(rb_vm_t *vm)
|
||||||
MEMZERO(vm, rb_vm_t, 1);
|
MEMZERO(vm, rb_vm_t, 1);
|
||||||
rb_vm_living_threads_init(vm);
|
rb_vm_living_threads_init(vm);
|
||||||
vm->src_encoding_index = -1;
|
vm->src_encoding_index = -1;
|
||||||
vm->at_exit.basic.flags = (T_ARRAY | RARRAY_EMBED_FLAG) & ~RARRAY_EMBED_LEN_MASK; /* len set 0 */
|
|
||||||
rb_obj_hide((VALUE)&vm->at_exit);
|
|
||||||
|
|
||||||
vm_default_params_setup(vm);
|
vm_default_params_setup(vm);
|
||||||
}
|
}
|
||||||
|
|
14
vm_core.h
14
vm_core.h
|
@ -462,6 +462,14 @@ enum ruby_basic_operators {
|
||||||
#define GetVMPtr(obj, ptr) \
|
#define GetVMPtr(obj, ptr) \
|
||||||
GetCoreDataFromValue((obj), rb_vm_t, (ptr))
|
GetCoreDataFromValue((obj), rb_vm_t, (ptr))
|
||||||
|
|
||||||
|
struct rb_vm_struct;
|
||||||
|
typedef void rb_vm_at_exit_func(struct rb_vm_struct*);
|
||||||
|
|
||||||
|
typedef struct rb_at_exit_list {
|
||||||
|
rb_vm_at_exit_func *func;
|
||||||
|
struct rb_at_exit_list *next;
|
||||||
|
} rb_at_exit_list;
|
||||||
|
|
||||||
struct rb_objspace;
|
struct rb_objspace;
|
||||||
struct rb_objspace *rb_objspace_alloc(void);
|
struct rb_objspace *rb_objspace_alloc(void);
|
||||||
void rb_objspace_free(struct rb_objspace *);
|
void rb_objspace_free(struct rb_objspace *);
|
||||||
|
@ -530,11 +538,7 @@ typedef struct rb_vm_struct {
|
||||||
|
|
||||||
struct rb_objspace *objspace;
|
struct rb_objspace *objspace;
|
||||||
|
|
||||||
/*
|
rb_at_exit_list *at_exit;
|
||||||
* @shyouhei notes that this is not for storing normal Ruby
|
|
||||||
* objects so do *NOT* mark this when you GC.
|
|
||||||
*/
|
|
||||||
struct RArray at_exit;
|
|
||||||
|
|
||||||
VALUE *defined_strings;
|
VALUE *defined_strings;
|
||||||
st_table *frozen_strings;
|
st_table *frozen_strings;
|
||||||
|
|
Loading…
Reference in a new issue