mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* vm_core.h, vm.c, proc.c: fix GC mark miss on bindings.
[ruby-dev:48616] [Bug #10368] * test/ruby/test_eval.rb: add a test code. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48000 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									108627d911
								
							
						
					
					
						commit
						231f45ad36
					
				
					 5 changed files with 69 additions and 29 deletions
				
			
		|  | @ -1,3 +1,10 @@ | |||
| Sat Oct 18 20:38:48 2014  Kazuki Tsujimoto  <kazuki@callcc.net> | ||||
| 
 | ||||
| 	* vm_core.h, vm.c, proc.c: fix GC mark miss on bindings. | ||||
| 	  [ruby-dev:48616] [Bug #10368] | ||||
| 
 | ||||
| 	* test/ruby/test_eval.rb: add a test code. | ||||
| 
 | ||||
| Fri Oct 17 22:47:11 2014  Tanaka Akira  <akr@fsij.org> | ||||
| 
 | ||||
| 	* pack.c (pack_unpack): Add casts for char references for 'u'. | ||||
|  |  | |||
							
								
								
									
										36
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -247,6 +247,7 @@ binding_mark(void *ptr) | |||
| 	bind = ptr; | ||||
| 	RUBY_MARK_UNLESS_NULL(bind->env); | ||||
| 	RUBY_MARK_UNLESS_NULL(bind->path); | ||||
| 	RUBY_MARK_UNLESS_NULL(bind->blockprocval); | ||||
|     } | ||||
|     RUBY_MARK_LEAVE("binding"); | ||||
| } | ||||
|  | @ -267,8 +268,8 @@ const rb_data_type_t ruby_binding_data_type = { | |||
|     NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY | ||||
| }; | ||||
| 
 | ||||
| static VALUE | ||||
| binding_alloc(VALUE klass) | ||||
| VALUE | ||||
| rb_binding_alloc(VALUE klass) | ||||
| { | ||||
|     VALUE obj; | ||||
|     rb_binding_t *bind; | ||||
|  | @ -280,12 +281,13 @@ binding_alloc(VALUE klass) | |||
| static VALUE | ||||
| binding_dup(VALUE self) | ||||
| { | ||||
|     VALUE bindval = binding_alloc(rb_cBinding); | ||||
|     VALUE bindval = rb_binding_alloc(rb_cBinding); | ||||
|     rb_binding_t *src, *dst; | ||||
|     GetBindingPtr(self, src); | ||||
|     GetBindingPtr(bindval, dst); | ||||
|     dst->env = src->env; | ||||
|     dst->path = src->path; | ||||
|     dst->blockprocval = src->blockprocval; | ||||
|     dst->first_lineno = src->first_lineno; | ||||
|     return bindval; | ||||
| } | ||||
|  | @ -302,30 +304,7 @@ binding_clone(VALUE self) | |||
| VALUE | ||||
| rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp) | ||||
| { | ||||
|     rb_control_frame_t *cfp = rb_vm_get_binding_creatable_next_cfp(th, src_cfp); | ||||
|     rb_control_frame_t *ruby_level_cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp); | ||||
|     VALUE bindval, envval; | ||||
|     rb_binding_t *bind; | ||||
| 
 | ||||
|     if (cfp == 0 || ruby_level_cfp == 0) { | ||||
| 	rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber."); | ||||
|     } | ||||
| 
 | ||||
|     while (1) { | ||||
| 	envval = rb_vm_make_env_object(th, cfp); | ||||
| 	if (cfp == ruby_level_cfp) { | ||||
| 	    break; | ||||
| 	} | ||||
| 	cfp = rb_vm_get_binding_creatable_next_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); | ||||
|     } | ||||
| 
 | ||||
|     bindval = binding_alloc(rb_cBinding); | ||||
|     GetBindingPtr(bindval, bind); | ||||
|     bind->env = envval; | ||||
|     bind->path = ruby_level_cfp->iseq->location.path; | ||||
|     bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp); | ||||
| 
 | ||||
|     return bindval; | ||||
|     return rb_vm_make_binding(th, src_cfp); | ||||
| } | ||||
| 
 | ||||
| VALUE | ||||
|  | @ -2485,9 +2464,10 @@ proc_binding(VALUE self) | |||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     bindval = binding_alloc(rb_cBinding); | ||||
|     bindval = rb_binding_alloc(rb_cBinding); | ||||
|     GetBindingPtr(bindval, bind); | ||||
|     bind->env = proc->envval; | ||||
|     bind->blockprocval = proc->blockprocval; | ||||
|     if (RUBY_VM_NORMAL_ISEQ_P(proc->block.iseq)) { | ||||
| 	bind->path = proc->block.iseq->location.path; | ||||
| 	bind->first_lineno = FIX2INT(rb_iseq_first_lineno(proc->block.iseq->self)); | ||||
|  |  | |||
|  | @ -484,4 +484,19 @@ class TestEval < Test::Unit::TestCase | |||
| 
 | ||||
|     assert_same a, b | ||||
|   end | ||||
| 
 | ||||
|   def test_gced_binding_block | ||||
|     assert_normal_exit %q{ | ||||
|       def m | ||||
|         binding | ||||
|       end | ||||
|       GC.stress = true | ||||
|       b = nil | ||||
|       tap do | ||||
|         b = m {} | ||||
|       end | ||||
|       0.times.to_a | ||||
|       b.eval('yield') | ||||
|     }, '[Bug #10368]' | ||||
|   end | ||||
| end | ||||
|  |  | |||
							
								
								
									
										37
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								vm.c
									
										
									
									
									
								
							|  | @ -688,6 +688,39 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass) | |||
|     return procval; | ||||
| } | ||||
| 
 | ||||
| /* Binding */ | ||||
| 
 | ||||
| VALUE | ||||
| rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp) | ||||
| { | ||||
|     rb_control_frame_t *cfp = rb_vm_get_binding_creatable_next_cfp(th, src_cfp); | ||||
|     rb_control_frame_t *ruby_level_cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp); | ||||
|     VALUE bindval, envval; | ||||
|     rb_binding_t *bind; | ||||
|     VALUE blockprocval = 0; | ||||
| 
 | ||||
|     if (cfp == 0 || ruby_level_cfp == 0) { | ||||
| 	rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber."); | ||||
|     } | ||||
| 
 | ||||
|     while (1) { | ||||
| 	envval = vm_make_env_object(th, cfp, &blockprocval); | ||||
| 	if (cfp == ruby_level_cfp) { | ||||
| 	    break; | ||||
| 	} | ||||
| 	cfp = rb_vm_get_binding_creatable_next_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); | ||||
|     } | ||||
| 
 | ||||
|     bindval = rb_binding_alloc(rb_cBinding); | ||||
|     GetBindingPtr(bindval, bind); | ||||
|     bind->env = envval; | ||||
|     bind->path = ruby_level_cfp->iseq->location.path; | ||||
|     bind->blockprocval = blockprocval; | ||||
|     bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp); | ||||
| 
 | ||||
|     return bindval; | ||||
| } | ||||
| 
 | ||||
| VALUE * | ||||
| rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) | ||||
| { | ||||
|  | @ -699,6 +732,7 @@ rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) | |||
|     NODE *node = 0; | ||||
|     ID minibuf[4], *dyns = minibuf; | ||||
|     VALUE idtmp = 0; | ||||
|     VALUE blockprocval = 0; | ||||
| 
 | ||||
|     if (dyncount < 0) return 0; | ||||
| 
 | ||||
|  | @ -719,7 +753,8 @@ rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) | |||
|     ALLOCV_END(idtmp); | ||||
| 
 | ||||
|     vm_set_eval_stack(th, iseqval, 0, base_block); | ||||
|     bind->env = rb_vm_make_env_object(th, th->cfp); | ||||
|     bind->env = vm_make_env_object(th, th->cfp, &blockprocval); | ||||
|     bind->blockprocval = blockprocval; | ||||
|     vm_pop_frame(th); | ||||
|     GetEnvPtr(bind->env, env); | ||||
| 
 | ||||
|  |  | |||
|  | @ -771,6 +771,7 @@ extern const rb_data_type_t ruby_binding_data_type; | |||
| typedef struct { | ||||
|     VALUE env; | ||||
|     VALUE path; | ||||
|     VALUE blockprocval;	/* for GC mark */ | ||||
|     unsigned short first_lineno; | ||||
| } rb_binding_t; | ||||
| 
 | ||||
|  | @ -887,6 +888,7 @@ rb_block_t *rb_vm_control_frame_block_ptr(rb_control_frame_t *cfp); | |||
| /* VM related object allocate functions */ | ||||
| VALUE rb_thread_alloc(VALUE klass); | ||||
| VALUE rb_proc_wrap(VALUE klass, rb_proc_t *); /* may use with rb_proc_alloc */ | ||||
| VALUE rb_binding_alloc(VALUE klass); | ||||
| 
 | ||||
| /* for debug */ | ||||
| extern void rb_vmdebug_stack_dump_raw(rb_thread_t *, rb_control_frame_t *); | ||||
|  | @ -908,6 +910,7 @@ int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, VALUE *klassp); | |||
| VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, | ||||
| 			int argc, const VALUE *argv, const rb_block_t *blockptr); | ||||
| VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass); | ||||
| VALUE rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp); | ||||
| VALUE rb_vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); | ||||
| VALUE rb_vm_env_local_variables(VALUE envval); | ||||
| VALUE rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 ktsj
						ktsj