mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information. (dfp[-1] points CREF) * compile.c, eval_intern.h, eval_method.c, load.c, proc.c, vm_dump.h, vm_core.h: ditto. * include/ruby/ruby.h, gc.c: remove T_VALUES because of above changes. * bootstraptest/test_eval.rb, test_knownbug.rb: move solved test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									2e5e857a0b
								
							
						
					
					
						commit
						385f0e8af6
					
				
					 18 changed files with 234 additions and 344 deletions
				
			
		
							
								
								
									
										14
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								ChangeLog
									
										
									
									
									
								
							|  | @ -1,3 +1,17 @@ | |||
| Mon May 19 11:32:47 2008  Koichi Sasada  <ko1@atdot.net> | ||||
| 
 | ||||
| 	* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling. | ||||
| 	  VM value stack frame of block contains cref information. | ||||
| 	 (dfp[-1] points CREF) | ||||
| 
 | ||||
| 	* compile.c, eval_intern.h, eval_method.c, load.c, proc.c, | ||||
| 	  vm_dump.h, vm_core.h: ditto. | ||||
| 
 | ||||
| 	* include/ruby/ruby.h, gc.c: remove T_VALUES because of above | ||||
| 	  changes. | ||||
| 
 | ||||
| 	* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test. | ||||
| 
 | ||||
| Sun May 18 22:26:51 2008  GOTOU Yuuzou  <gotoyuzo@notwork.org> | ||||
| 
 | ||||
| 	* lib/webrick/httpservlet/filehandler.rb: should normalize path | ||||
|  |  | |||
|  | @ -0,0 +1,9 @@ | |||
| def m | ||||
|   nil | ||||
| end | ||||
| 
 | ||||
| i=0 | ||||
| while i<800000 # benchmark loop 2 | ||||
|   i+=1 | ||||
|   m; m; m; m; m; m; m; m; | ||||
| end | ||||
|  | @ -208,3 +208,22 @@ assert_normal_exit %q{ | |||
|   end | ||||
|   Foo.add_method | ||||
| }, '[ruby-core:14556] reported by Frederick Cheung' | ||||
| 
 | ||||
| assert_equal 'ok', %q{ | ||||
|   class Module | ||||
|     def my_module_eval(&block) | ||||
|       module_eval(&block) | ||||
|     end | ||||
|   end | ||||
|   class String | ||||
|     Integer.my_module_eval do | ||||
|       def hoge; end | ||||
|     end | ||||
|   end | ||||
|   if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) && | ||||
|      !String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) | ||||
|     :ok | ||||
|   else | ||||
|     :ng | ||||
|   end | ||||
| }, "[ruby-dev:34236]" | ||||
|  |  | |||
|  | @ -136,26 +136,6 @@ assert_equal 'ok', %q{ | |||
|   end | ||||
| }, '[ruby-core:16010]' | ||||
| 
 | ||||
| 
 | ||||
| assert_equal 'ok', %q{ | ||||
|   class Module | ||||
|     def my_module_eval(&block) | ||||
|       module_eval(&block) | ||||
|     end | ||||
|   end | ||||
|   class String | ||||
|     Integer.my_module_eval do | ||||
|       def hoge; end | ||||
|     end | ||||
|   end | ||||
|   if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) && | ||||
|      !String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) | ||||
|     :ok | ||||
|   else | ||||
|     :ng | ||||
|   end | ||||
| }, "[ruby-dev:34236]" | ||||
| 
 | ||||
| assert_equal 'ok', %q{ | ||||
|   def m | ||||
|     t = Thread.new { while true do // =~ "" end } | ||||
|  |  | |||
							
								
								
									
										37
									
								
								compile.c
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								compile.c
									
										
									
									
									
								
							|  | @ -280,7 +280,7 @@ iseq_compile(VALUE self, NODE *node) | |||
|     } | ||||
| 
 | ||||
|     if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) { | ||||
| 	ADD_INSN2(ret, 0, getdynamic, INT2FIX(1), INT2FIX(0)); | ||||
| 	ADD_INSN2(ret, 0, getdynamic, INT2FIX(2), INT2FIX(0)); | ||||
| 	ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ ); | ||||
|     } | ||||
|     else { | ||||
|  | @ -771,7 +771,8 @@ iseq_set_exception_local_table(rb_iseq_t *iseq) | |||
| 	id_dollar_bang = rb_intern("#$!"); | ||||
|     } | ||||
|     iseq->local_table = (ID *)ALLOC_N(ID *, 1); | ||||
|     iseq->local_table_size = iseq->local_size = 1; | ||||
|     iseq->local_table_size = 1; | ||||
|     iseq->local_size = iseq->local_table_size + 1; | ||||
|     iseq->local_table[0] = id_dollar_bang; | ||||
|     return COMPILE_OK; | ||||
| } | ||||
|  | @ -992,12 +993,14 @@ iseq_set_local_table(rb_iseq_t *iseq, ID *tbl) | |||
|     } | ||||
| 
 | ||||
|     iseq->local_size = iseq->local_table_size = size; | ||||
| 
 | ||||
|     if (iseq->type == ISEQ_TYPE_METHOD || | ||||
| 	iseq->type == ISEQ_TYPE_CLASS  || | ||||
| 	iseq->type == ISEQ_TYPE_TOP) { | ||||
| 	iseq->local_size += 1 /* svar */; | ||||
|     } | ||||
|     iseq->local_size += 1; | ||||
|     /*
 | ||||
|       if (lfp == dfp ) { // top, class, method
 | ||||
| 	  dfp[-1]: svar | ||||
|       else {             // block
 | ||||
|           dfp[-1]: cref | ||||
|       } | ||||
|      */ | ||||
| 
 | ||||
|     debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size); | ||||
|     return COMPILE_OK; | ||||
|  | @ -3264,8 +3267,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |||
| 		  case NODE_ARRAY: | ||||
| 		    while (narg) { | ||||
| 			COMPILE(ret, "rescue arg", narg->nd_head); | ||||
| 			ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), | ||||
| 				  INT2FIX(0)); | ||||
| 			ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); | ||||
| 			ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1)); | ||||
| 			ADD_INSNL(ret, nd_line(node), branchif, label_hit); | ||||
| 			narg = narg->nd_next; | ||||
|  | @ -3274,8 +3276,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |||
| 		  case NODE_SPLAT: | ||||
| 		  case NODE_ARGSCAT: | ||||
| 		  case NODE_ARGSPUSH: | ||||
| 		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), | ||||
| 			      INT2FIX(0)); | ||||
| 		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); | ||||
| 		    COMPILE(ret, "rescue/cond splat", narg); | ||||
| 		    ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue); | ||||
| 		    ADD_INSN(ret, nd_line(node), swap); | ||||
|  | @ -3290,8 +3291,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |||
| 	    else { | ||||
| 		ADD_INSN1(ret, nd_line(node), putobject, | ||||
| 			  rb_eStandardError); | ||||
| 		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), | ||||
| 			  INT2FIX(0)); | ||||
| 		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); | ||||
| 		ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1)); | ||||
| 		ADD_INSNL(ret, nd_line(node), branchif, label_hit); | ||||
| 	    } | ||||
|  | @ -4012,8 +4012,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |||
| 	    if (idx < 0) { | ||||
| 		rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid)); | ||||
| 	    } | ||||
| 	    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx), | ||||
| 		      INT2FIX(lv)); | ||||
| 	    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx), INT2FIX(lv)); | ||||
| 	} | ||||
| 	break; | ||||
|       } | ||||
|  | @ -4485,8 +4484,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |||
|       case NODE_ERRINFO:{ | ||||
| 	if (!poped) { | ||||
| 	    if (iseq->type == ISEQ_TYPE_RESCUE) { | ||||
| 		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), | ||||
| 			  INT2FIX(0)); | ||||
| 		ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0)); | ||||
| 	    } | ||||
| 	    else { | ||||
| 		rb_iseq_t *ip = iseq; | ||||
|  | @ -4499,8 +4497,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) | |||
| 		    level++; | ||||
| 		} | ||||
| 		if (ip) { | ||||
| 		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1), | ||||
| 			      INT2FIX(level)); | ||||
| 		    ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(level)); | ||||
| 		} | ||||
| 		else { | ||||
| 		    ADD_INSN(ret, nd_line(node), putnil); | ||||
|  |  | |||
							
								
								
									
										143
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										143
									
								
								eval.c
									
										
									
									
									
								
							|  | @ -32,7 +32,7 @@ VALUE sysstack_error; | |||
| 
 | ||||
| static VALUE exception_error; | ||||
| 
 | ||||
| static VALUE eval(VALUE, VALUE, VALUE, const char *, int); | ||||
| static VALUE eval_string(VALUE, VALUE, VALUE, const char *, int); | ||||
| 
 | ||||
| static inline VALUE rb_yield_0(int argc, VALUE *argv); | ||||
| static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int); | ||||
|  | @ -264,7 +264,7 @@ ruby_run_node(void *n) | |||
| VALUE | ||||
| rb_eval_string(const char *str) | ||||
| { | ||||
|     return eval(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1); | ||||
|     return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1); | ||||
| } | ||||
| 
 | ||||
| VALUE | ||||
|  | @ -329,7 +329,7 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level) | |||
| 
 | ||||
|     PUSH_TAG(); | ||||
|     if ((state = EXEC_TAG()) == 0) { | ||||
| 	val = eval(rb_vm_top_self(), cmd, Qnil, 0, 0); | ||||
| 	val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0); | ||||
|     } | ||||
|     POP_TAG(); | ||||
| 
 | ||||
|  | @ -884,11 +884,12 @@ rb_iterator_p() | |||
| 
 | ||||
| 
 | ||||
| VALUE | ||||
| rb_f_block_given_p() | ||||
| rb_f_block_given_p(void) | ||||
| { | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_control_frame_t *cfp = th->cfp; | ||||
|     cfp = vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); | ||||
| 
 | ||||
|     if (GC_GUARDED_PTR_REF(cfp->lfp[0])) { | ||||
| 	return Qtrue; | ||||
|     } | ||||
|  | @ -1681,7 +1682,7 @@ rb_frame_self(void) | |||
| } | ||||
| 
 | ||||
| static VALUE | ||||
| eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | ||||
| eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line) | ||||
| { | ||||
|     int state; | ||||
|     VALUE result = Qundef; | ||||
|  | @ -1689,7 +1690,7 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | |||
|     rb_binding_t *bind = 0; | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_env_t *env = NULL; | ||||
|     NODE *stored_cref_stack = 0; | ||||
|     rb_block_t block; | ||||
| 
 | ||||
|     if (file == 0) { | ||||
| 	file = rb_sourcefile(); | ||||
|  | @ -1705,7 +1706,6 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | |||
| 	    if (rb_obj_is_kind_of(scope, rb_cBinding)) { | ||||
| 		GetBindingPtr(scope, bind); | ||||
| 		envval = bind->env; | ||||
| 		stored_cref_stack = bind->cref_stack; | ||||
| 	    } | ||||
| 	    else { | ||||
| 		rb_raise(rb_eTypeError, | ||||
|  | @ -1717,7 +1717,9 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | |||
| 	} | ||||
| 	else { | ||||
| 	    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); | ||||
| 	    th->base_block = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp); | ||||
| 	    block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp); | ||||
| 	    th->base_block = █ | ||||
| 	    th->base_block->self = self; | ||||
| 	    th->base_block->iseq = cfp->iseq;	/* TODO */ | ||||
| 	} | ||||
| 
 | ||||
|  | @ -1725,7 +1727,8 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | |||
| 	th->parse_in_eval++; | ||||
| 	iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line)); | ||||
| 	th->parse_in_eval--; | ||||
| 	rb_vm_set_eval_stack(th, iseqval); | ||||
| 
 | ||||
| 	rb_vm_set_eval_stack(th, iseqval, cref); | ||||
| 	th->base_block = 0; | ||||
| 
 | ||||
| 	if (0) {		/* for debug */ | ||||
|  | @ -1739,22 +1742,12 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | |||
| 	    bind->env = vm_make_env_object(th, th->cfp); | ||||
| 	} | ||||
| 
 | ||||
| 	/* push tag */ | ||||
| 	if (stored_cref_stack) { | ||||
| 	    stored_cref_stack = | ||||
| 	      vm_set_special_cref(th, env->block.lfp, stored_cref_stack); | ||||
| 	} | ||||
| 
 | ||||
| 	/* kick */ | ||||
| 	CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max); | ||||
| 	result = vm_eval_body(th); | ||||
|     } | ||||
|     POP_TAG(); | ||||
| 
 | ||||
|     if (stored_cref_stack) { | ||||
| 	vm_set_special_cref(th, env->block.lfp, stored_cref_stack); | ||||
|     } | ||||
| 
 | ||||
|     if (state) { | ||||
| 	if (state == TAG_RAISE) { | ||||
| 	    VALUE errinfo = th->errinfo; | ||||
|  | @ -1779,6 +1772,12 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line) | |||
|     return result; | ||||
| } | ||||
| 
 | ||||
| static VALUE | ||||
| eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line) | ||||
| { | ||||
|     return eval_string_with_cref(self, src, scope, 0, file, line); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  *  call-seq: | ||||
|  *     eval(string [, binding [, filename [,lineno]]])  => obj | ||||
|  | @ -1825,90 +1824,36 @@ rb_f_eval(int argc, VALUE *argv, VALUE self) | |||
| 
 | ||||
|     if (!NIL_P(vfile)) | ||||
| 	file = RSTRING_PTR(vfile); | ||||
|     return eval(self, src, scope, file, line); | ||||
| } | ||||
| 
 | ||||
| VALUE vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key); | ||||
| void vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, VALUE val); | ||||
| 
 | ||||
| /* function to call func under the specified class/module context */ | ||||
| static VALUE | ||||
| exec_under(VALUE (*func) (VALUE), VALUE under, VALUE self, VALUE args) | ||||
| { | ||||
|     VALUE val = Qnil;		/* OK */ | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_control_frame_t *cfp = th->cfp; | ||||
|     rb_control_frame_t *pcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); | ||||
|     VALUE stored_self = pcfp->self; | ||||
|     NODE *stored_cref = 0; | ||||
| 
 | ||||
|     rb_block_t block; | ||||
|     rb_block_t *blockptr; | ||||
|     int state; | ||||
| 
 | ||||
|     /* replace environment */ | ||||
|     pcfp->self = self; | ||||
|     if ((blockptr = GC_GUARDED_PTR_REF(*th->cfp->lfp)) != 0) { | ||||
| 	/* copy block info */ | ||||
| 	/* TODO: why? */ | ||||
| 	block = *blockptr; | ||||
| 	block.self = self; | ||||
| 	*th->cfp->lfp = GC_GUARDED_PTR(&block); | ||||
|     } | ||||
| 
 | ||||
|     while (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { | ||||
| 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); | ||||
|     } | ||||
| 
 | ||||
|     stored_cref = (NODE *)vm_cfp_svar_get(th, cfp, 2); | ||||
|     vm_cfp_svar_set(th, cfp, 2, (VALUE)vm_cref_push(th, under, NOEX_PUBLIC)); | ||||
| 
 | ||||
|     PUSH_TAG(); | ||||
|     if ((state = EXEC_TAG()) == 0) { | ||||
| 	val = (*func) (args); | ||||
|     } | ||||
|     POP_TAG(); | ||||
| 
 | ||||
|     /* restore environment */ | ||||
|     vm_cfp_svar_set(th, cfp, 2, (VALUE)stored_cref); | ||||
|     pcfp->self = stored_self; | ||||
| 
 | ||||
|     if (state) { | ||||
| 	JUMP_TAG(state); | ||||
|     } | ||||
|     return val; | ||||
| } | ||||
| 
 | ||||
| static VALUE | ||||
| yield_under_i(VALUE arg) | ||||
| { | ||||
|     if (arg == Qundef) { | ||||
| 	return rb_yield_0(0, 0); | ||||
|     } | ||||
|     else { | ||||
| 	return rb_yield_0(RARRAY_LEN(arg), RARRAY_PTR(arg)); | ||||
|     } | ||||
|     return eval_string(self, src, scope, file, line); | ||||
| } | ||||
| 
 | ||||
| /* block eval under the class/module context */ | ||||
| static VALUE | ||||
| yield_under(VALUE under, VALUE self, VALUE values) | ||||
| { | ||||
|     return exec_under(yield_under_i, under, self, values); | ||||
| } | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_block_t block, *blockptr; | ||||
|     NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC); | ||||
| 
 | ||||
| static VALUE | ||||
| eval_under_i(VALUE arg) | ||||
| { | ||||
|     VALUE *args = (VALUE *)arg; | ||||
|     return eval(args[0], args[1], Qnil, (char *)args[2], (int)args[3]); | ||||
|     if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) { | ||||
| 	block = *blockptr; | ||||
| 	block.self = self; | ||||
| 	th->cfp->lfp[0] = GC_GUARDED_PTR(&block); | ||||
|     } | ||||
| 
 | ||||
|     if (values == Qundef) { | ||||
| 	return vm_yield_with_cref(th, 0, 0, cref); | ||||
|     } | ||||
|     else { | ||||
| 	return vm_yield_with_cref(th, RARRAY_LEN(values), RARRAY_PTR(values), cref); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* string eval under the class/module context */ | ||||
| static VALUE | ||||
| eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line) | ||||
| { | ||||
|     VALUE args[4]; | ||||
|     NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC); | ||||
| 
 | ||||
|     if (rb_safe_level() >= 4) { | ||||
| 	StringValue(src); | ||||
|  | @ -1916,11 +1861,8 @@ eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line) | |||
|     else { | ||||
| 	SafeStringValue(src); | ||||
|     } | ||||
|     args[0] = self; | ||||
|     args[1] = src; | ||||
|     args[2] = (VALUE)file; | ||||
|     args[3] = (VALUE)line; | ||||
|     return exec_under(eval_under_i, under, self, (VALUE)args); | ||||
| 
 | ||||
|     return eval_string_with_cref(self, src, Qnil, cref, file, line); | ||||
| } | ||||
| 
 | ||||
| static VALUE | ||||
|  | @ -1928,8 +1870,7 @@ specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self) | |||
| { | ||||
|     if (rb_block_given_p()) { | ||||
| 	if (argc > 0) { | ||||
| 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", | ||||
| 		     argc); | ||||
| 	    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc); | ||||
| 	} | ||||
| 	return yield_under(klass, self, Qundef); | ||||
|     } | ||||
|  | @ -2499,12 +2440,12 @@ errinfo_place(void) | |||
|     while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) { | ||||
| 	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { | ||||
| 	    if (cfp->iseq->type == ISEQ_TYPE_RESCUE) { | ||||
| 		return &cfp->dfp[-1]; | ||||
| 		return &cfp->dfp[-2]; | ||||
| 	    } | ||||
| 	    else if (cfp->iseq->type == ISEQ_TYPE_ENSURE && | ||||
| 		     TYPE(cfp->dfp[-1]) != T_NODE && | ||||
| 		     !FIXNUM_P(cfp->dfp[-1])) { | ||||
| 		return &cfp->dfp[-1]; | ||||
| 		     TYPE(cfp->dfp[-2]) != T_NODE && | ||||
| 		     !FIXNUM_P(cfp->dfp[-2])) { | ||||
| 		return &cfp->dfp[-2]; | ||||
| 	    } | ||||
| 	} | ||||
| 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); | ||||
|  |  | |||
|  | @ -225,11 +225,12 @@ NORETURN(void rb_print_undef(VALUE, ID, int)); | |||
| NORETURN(void vm_localjump_error(const char *, VALUE, int)); | ||||
| NORETURN(void vm_jump_tag_but_local_jump(int, VALUE)); | ||||
| 
 | ||||
| NODE *vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp); | ||||
| NODE *vm_cref_push(rb_thread_t *th, VALUE, int); | ||||
| NODE *vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack); | ||||
| VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val); | ||||
| 
 | ||||
| NODE *ruby_cref(void); | ||||
| 
 | ||||
| static rb_control_frame_t * | ||||
| vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp) | ||||
| { | ||||
|  | @ -242,22 +243,12 @@ vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static inline NODE * | ||||
| ruby_cref() | ||||
| { | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); | ||||
|     return vm_get_cref(th, cfp->iseq, cfp); | ||||
| } | ||||
| 
 | ||||
| VALUE vm_get_cbase(rb_thread_t *th); | ||||
| VALUE rb_obj_is_proc(VALUE); | ||||
| void rb_vm_check_redefinition_opt_method(NODE *node); | ||||
| VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockptr, VALUE filename); | ||||
| void rb_thread_terminate_all(void); | ||||
| void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq); | ||||
| void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq, NODE *cref); | ||||
| VALUE rb_vm_top_self(); | ||||
| 
 | ||||
| #define ruby_cbase() vm_get_cbase(GET_THREAD()) | ||||
| VALUE rb_vm_cbase(void); | ||||
| 
 | ||||
| #endif /* RUBY_EVAL_INTERN_H */ | ||||
|  |  | |||
|  | @ -463,7 +463,7 @@ rb_undef(VALUE klass, ID id) | |||
|     VALUE origin; | ||||
|     NODE *body; | ||||
| 
 | ||||
|     if (ruby_cbase() == rb_cObject && klass == rb_cObject) { | ||||
|     if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) { | ||||
| 	rb_secure(4); | ||||
|     } | ||||
|     if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { | ||||
|  |  | |||
							
								
								
									
										15
									
								
								gc.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								gc.c
									
										
									
									
									
								
							|  | @ -1280,15 +1280,6 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev) | |||
| 	} | ||||
| 	break; | ||||
| 
 | ||||
|       case T_VALUES: | ||||
| 	{ | ||||
|             rb_gc_mark(RVALUES(obj)->v1); | ||||
|             rb_gc_mark(RVALUES(obj)->v2); | ||||
|             ptr = RVALUES(obj)->v3; | ||||
|             goto again; | ||||
| 	} | ||||
| 	break; | ||||
| 
 | ||||
|       default: | ||||
| 	rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s", | ||||
| 	       obj->as.basic.flags & T_MASK, obj, | ||||
|  | @ -1531,8 +1522,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj) | |||
| 
 | ||||
|       case T_FLOAT: | ||||
| 	break; | ||||
|       case T_VALUES: | ||||
| 	break; | ||||
| 
 | ||||
|       case T_BIGNUM: | ||||
| 	if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) { | ||||
|  | @ -1878,7 +1867,6 @@ os_obj_of(rb_objspace_t *objspace, VALUE of) | |||
| 		  case T_NONE: | ||||
| 		  case T_ICLASS: | ||||
| 		  case T_NODE: | ||||
| 		  case T_VALUES: | ||||
| 		    continue; | ||||
| 		  case T_CLASS: | ||||
| 		    if (FL_TEST(p, FL_SINGLETON)) continue; | ||||
|  | @ -2175,7 +2163,7 @@ id2ref(VALUE obj, VALUE objid) | |||
|     } | ||||
| 
 | ||||
|     if (!is_pointer_to_heap(objspace, (void *)ptr) || | ||||
| 	BUILTIN_TYPE(ptr) >= T_VALUES || BUILTIN_TYPE(ptr) == T_ICLASS) { | ||||
| 	BUILTIN_TYPE(ptr) > T_FIXNUM || BUILTIN_TYPE(ptr) == T_ICLASS) { | ||||
| 	rb_raise(rb_eRangeError, "%p is not id value", p0); | ||||
|     } | ||||
|     if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) { | ||||
|  | @ -2334,7 +2322,6 @@ count_objects(int argc, VALUE *argv, VALUE os) | |||
| 	    COUNT_TYPE(T_FALSE); | ||||
| 	    COUNT_TYPE(T_SYMBOL); | ||||
| 	    COUNT_TYPE(T_FIXNUM); | ||||
| 	    COUNT_TYPE(T_VALUES); | ||||
| 	    COUNT_TYPE(T_UNDEF); | ||||
| 	    COUNT_TYPE(T_NODE); | ||||
| 	    COUNT_TYPE(T_ICLASS); | ||||
|  |  | |||
|  | @ -262,7 +262,6 @@ enum ruby_value_type { | |||
|     RUBY_T_SYMBOL = 0x14, | ||||
|     RUBY_T_FIXNUM = 0x15, | ||||
| 
 | ||||
|     RUBY_T_VALUES = 0x1a, | ||||
|     RUBY_T_UNDEF  = 0x1b, | ||||
|     RUBY_T_NODE   = 0x1c, | ||||
|     RUBY_T_ICLASS = 0x1d, | ||||
|  | @ -292,7 +291,6 @@ enum ruby_value_type { | |||
| #define T_SYMBOL RUBY_T_SYMBOL | ||||
| #define T_RATIONAL RUBY_T_RATIONAL | ||||
| #define T_COMPLEX RUBY_T_COMPLEX | ||||
| #define T_VALUES RUBY_T_VALUES | ||||
| #define T_UNDEF  RUBY_T_UNDEF | ||||
| #define T_NODE   RUBY_T_NODE | ||||
| #define T_MASK   RUBY_T_MASK | ||||
|  | @ -438,13 +436,6 @@ struct RObject { | |||
|      RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \ | ||||
|      ROBJECT(o)->as.heap.iv_index_tbl) | ||||
| 
 | ||||
| struct RValues { | ||||
|     struct RBasic basic; | ||||
|     VALUE v1; | ||||
|     VALUE v2; | ||||
|     VALUE v3; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|     VALUE super; | ||||
|     struct st_table *iv_tbl; | ||||
|  | @ -654,7 +645,6 @@ struct RBignum { | |||
| #define RFILE(obj)   (R_CAST(RFile)(obj)) | ||||
| #define RRATIONAL(obj) (R_CAST(RRational)(obj)) | ||||
| #define RCOMPLEX(obj) (R_CAST(RComplex)(obj)) | ||||
| #define RVALUES(obj) (R_CAST(RValues)(obj)) | ||||
| 
 | ||||
| #define FL_SINGLETON FL_USER0 | ||||
| #define FL_MARK      (((VALUE)1)<<5) | ||||
|  |  | |||
							
								
								
									
										20
									
								
								insns.def
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								insns.def
									
										
									
									
									
								
							|  | @ -183,7 +183,8 @@ getclassvariable | |||
| () | ||||
| (VALUE val) | ||||
| { | ||||
|     val = rb_cvar_get(vm_get_cvar_base(th, GET_ISEQ()), id); | ||||
|     NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
|     val = rb_cvar_get(vm_get_cvar_base(cref), id); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -197,7 +198,8 @@ setclassvariable | |||
| (VALUE val) | ||||
| () | ||||
| { | ||||
|     rb_cvar_set(vm_get_cvar_base(th, GET_ISEQ()), id, val); | ||||
|     NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
|     rb_cvar_set(vm_get_cvar_base(cref), id, val); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -317,7 +319,7 @@ putcbase | |||
| () | ||||
| (VALUE val) | ||||
| { | ||||
|     val = vm_get_cbase(th); | ||||
|     val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -723,8 +725,8 @@ definemethod | |||
| (VALUE obj) | ||||
| () | ||||
| { | ||||
|     vm_define_method(th, obj, id, body, is_singleton, | ||||
| 		     get_cref(GET_ISEQ(), GET_LFP())); | ||||
|     NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
|     vm_define_method(th, obj, id, body, is_singleton, cref); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  | @ -744,7 +746,7 @@ alias | |||
| 	rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2)); | ||||
|     } | ||||
|     else { | ||||
| 	klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss; | ||||
| 	klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
| 	rb_alias(klass, SYM2ID(sym1), SYM2ID(sym2)); | ||||
|     } | ||||
| } | ||||
|  | @ -760,7 +762,7 @@ undef | |||
| (VALUE sym) | ||||
| () | ||||
| { | ||||
|     VALUE klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss; | ||||
|     VALUE klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
|     rb_undef(klass, SYM2ID(sym)); | ||||
|     INC_VM_STATE_VERSION(); | ||||
| } | ||||
|  | @ -787,7 +789,7 @@ defined | |||
| 	} | ||||
| 	break; | ||||
|       case DEFINED_IVAR2: | ||||
| 	klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss; | ||||
| 	klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
| 	break; | ||||
|       case DEFINED_GVAR: | ||||
| 	if (rb_gvar_defined((struct global_entry *)(obj & ~1))) { | ||||
|  | @ -795,7 +797,7 @@ defined | |||
| 	} | ||||
| 	break; | ||||
|       case DEFINED_CVAR: | ||||
| 	klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss; | ||||
| 	klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP()); | ||||
| 	if (rb_cvar_defined(klass, SYM2ID(obj))) { | ||||
| 	    expr_type = "class variable"; | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										6
									
								
								load.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								load.c
									
										
									
									
									
								
							|  | @ -650,7 +650,7 @@ rb_mod_autoload_p(VALUE mod, VALUE sym) | |||
| static VALUE | ||||
| rb_f_autoload(VALUE obj, VALUE sym, VALUE file) | ||||
| { | ||||
|     VALUE klass = ruby_cbase(); | ||||
|     VALUE klass = rb_vm_cbase(); | ||||
|     if (NIL_P(klass)) { | ||||
| 	rb_raise(rb_eTypeError, "Can not set autoload on singleton class"); | ||||
|     } | ||||
|  | @ -664,8 +664,8 @@ rb_f_autoload(VALUE obj, VALUE sym, VALUE file) | |||
| static VALUE | ||||
| rb_f_autoload_p(VALUE obj, VALUE sym) | ||||
| { | ||||
|     /* use ruby_cbase() as same as rb_f_autoload. */ | ||||
|     VALUE klass = ruby_cbase(); | ||||
|     /* use rb_vm_cbase() as same as rb_f_autoload. */ | ||||
|     VALUE klass = rb_vm_cbase(); | ||||
|     if (NIL_P(klass)) { | ||||
| 	return Qnil; | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										6
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -50,7 +50,6 @@ proc_mark(void *ptr) | |||
| 	proc = ptr; | ||||
| 	RUBY_MARK_UNLESS_NULL(proc->envval); | ||||
| 	RUBY_MARK_UNLESS_NULL(proc->blockprocval); | ||||
| 	RUBY_MARK_UNLESS_NULL((VALUE)proc->special_cref_stack); | ||||
| 	RUBY_MARK_UNLESS_NULL(proc->block.proc); | ||||
| 	RUBY_MARK_UNLESS_NULL(proc->block.self); | ||||
| 	if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) { | ||||
|  | @ -94,7 +93,6 @@ proc_dup(VALUE self) | |||
|     dst->block.proc = procval; | ||||
|     dst->envval = src->envval; | ||||
|     dst->safe_level = dst->safe_level; | ||||
|     dst->special_cref_stack = src->special_cref_stack; | ||||
|     dst->is_lambda = src->is_lambda; | ||||
| 
 | ||||
|     return procval; | ||||
|  | @ -241,7 +239,6 @@ binding_mark(void *ptr) | |||
|     if (ptr) { | ||||
| 	bind = ptr; | ||||
| 	RUBY_MARK_UNLESS_NULL(bind->env); | ||||
| 	RUBY_MARK_UNLESS_NULL((VALUE)bind->cref_stack); | ||||
|     } | ||||
|     RUBY_MARK_LEAVE("binding"); | ||||
| } | ||||
|  | @ -264,7 +261,6 @@ binding_dup(VALUE self) | |||
|     GetBindingPtr(self, src); | ||||
|     GetBindingPtr(bindval, dst); | ||||
|     dst->env = src->env; | ||||
|     dst->cref_stack = src->cref_stack; | ||||
|     return bindval; | ||||
| } | ||||
| 
 | ||||
|  | @ -286,7 +282,6 @@ rb_binding_new(void) | |||
| 
 | ||||
|     GetBindingPtr(bindval, bind); | ||||
|     bind->env = vm_make_env_object(th, cfp); | ||||
|     bind->cref_stack = ruby_cref(); | ||||
|     return bindval; | ||||
| } | ||||
| 
 | ||||
|  | @ -1587,7 +1582,6 @@ proc_binding(VALUE self) | |||
|     } | ||||
| 
 | ||||
|     bind->env = proc->envval; | ||||
|     bind->cref_stack = proc->special_cref_stack; | ||||
|     return bindval; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| #define RUBY_VERSION "1.9.0" | ||||
| #define RUBY_RELEASE_DATE "2008-05-18" | ||||
| #define RUBY_RELEASE_DATE "2008-05-19" | ||||
| #define RUBY_VERSION_CODE 190 | ||||
| #define RUBY_RELEASE_CODE 20080518 | ||||
| #define RUBY_RELEASE_CODE 20080519 | ||||
| #define RUBY_PATCHLEVEL 0 | ||||
| 
 | ||||
| #define RUBY_VERSION_MAJOR 1 | ||||
|  | @ -9,7 +9,7 @@ | |||
| #define RUBY_VERSION_TEENY 0 | ||||
| #define RUBY_RELEASE_YEAR 2008 | ||||
| #define RUBY_RELEASE_MONTH 5 | ||||
| #define RUBY_RELEASE_DAY 18 | ||||
| #define RUBY_RELEASE_DAY 19 | ||||
| 
 | ||||
| #ifdef RUBY_EXTERN | ||||
| RUBY_EXTERN const char ruby_version[]; | ||||
|  | @ -46,7 +46,7 @@ RUBY_EXTERN const char ruby_copyright[]; | |||
| 
 | ||||
| # define RUBY_DESCRIPTION	    \ | ||||
|     "ruby "RUBY_VERSION		    \ | ||||
|     " ("RUBY_RELEASE_DATE" "	    \ | ||||
|     "2008-05-19"	    \ | ||||
|     RUBY_RELEASE_STR" "		    \ | ||||
|     STRINGIZE(RUBY_RELEASE_NUM)") " \ | ||||
|     "["RUBY_PLATFORM"]" | ||||
|  |  | |||
							
								
								
									
										130
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										130
									
								
								vm.c
									
										
									
									
									
								
							|  | @ -79,7 +79,7 @@ rb_vm_set_top_stack(rb_thread_t *th, VALUE iseqval) | |||
| } | ||||
| 
 | ||||
| void | ||||
| rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval) | ||||
| rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval, NODE *cref) | ||||
| { | ||||
|     rb_iseq_t *iseq; | ||||
|     rb_block_t *block = th->base_block; | ||||
|  | @ -90,6 +90,10 @@ rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval) | |||
|     vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self, | ||||
| 		  GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded, | ||||
| 		  th->cfp->sp, block->lfp, iseq->local_size); | ||||
| 
 | ||||
|     if (cref) { | ||||
| 	th->cfp->dfp[-1] = (VALUE)cref; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Env */ | ||||
|  | @ -263,12 +267,6 @@ vm_make_env_each(rb_thread_t *th, rb_control_frame_t *cfp, | |||
|     env->block.dfp = cfp->dfp; | ||||
|     env->block.iseq = cfp->iseq; | ||||
| 
 | ||||
|     if (VMDEBUG && | ||||
| 	(!(cfp->lfp[-1] == Qnil || | ||||
| 	  BUILTIN_TYPE(cfp->lfp[-1]) == T_VALUES))) { | ||||
| 	rb_bug("invalid svar"); | ||||
|     } | ||||
| 
 | ||||
|     if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { | ||||
| 	/* TODO */ | ||||
| 	env->block.iseq = 0; | ||||
|  | @ -389,7 +387,6 @@ vm_make_proc(rb_thread_t *th, | |||
|     proc->block.proc = procval; | ||||
|     proc->envval = envval; | ||||
|     proc->safe_level = th->safe_level; | ||||
|     proc->special_cref_stack = lfp_get_special_cref(block->lfp); | ||||
| 
 | ||||
|     if (VMDEBUG) { | ||||
| 	if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) { | ||||
|  | @ -540,8 +537,8 @@ rb_call_super(int argc, const VALUE *argv) | |||
| /* C -> Ruby: block */ | ||||
| 
 | ||||
| static VALUE | ||||
| invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, | ||||
| 	     int argc, VALUE *argv, rb_block_t *blockptr) | ||||
| invoke_block_from_c(rb_thread_t *th, rb_block_t *block, VALUE self, | ||||
| 		    int argc, VALUE *argv, rb_block_t *blockptr, NODE *cref) | ||||
| { | ||||
|     VALUE val; | ||||
|     if (BUILTIN_TYPE(block->iseq) != T_NODE) { | ||||
|  | @ -566,6 +563,7 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, | |||
| 		      self, GC_GUARDED_PTR(block->dfp), | ||||
| 		      iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp, | ||||
| 		      iseq->local_size - arg_size); | ||||
| 	th->cfp->dfp[-1] = (VALUE)cref; | ||||
| 
 | ||||
| 	val = vm_eval_body(th); | ||||
|     } | ||||
|  | @ -576,7 +574,7 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self, | |||
| } | ||||
| 
 | ||||
| VALUE | ||||
| vm_yield(rb_thread_t *th, int argc, VALUE *argv) | ||||
| vm_yield_with_cref(rb_thread_t *th, int argc, VALUE *argv, NODE *cref) | ||||
| { | ||||
|     rb_block_t *block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]); | ||||
| 
 | ||||
|  | @ -584,7 +582,13 @@ vm_yield(rb_thread_t *th, int argc, VALUE *argv) | |||
| 	vm_localjump_error("no block given", Qnil, 0); | ||||
|     } | ||||
| 
 | ||||
|     return invoke_block(th, block, block->self, argc, argv, 0); | ||||
|     return invoke_block_from_c(th, block, block->self, argc, argv, 0, cref); | ||||
| } | ||||
| 
 | ||||
| VALUE | ||||
| vm_yield(rb_thread_t *th, int argc, VALUE *argv) | ||||
| { | ||||
|     return vm_yield_with_cref(th, argc, argv, (NODE *)Qnil); | ||||
| } | ||||
| 
 | ||||
| VALUE | ||||
|  | @ -594,14 +598,12 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, | |||
|     VALUE val = Qundef; | ||||
|     int state; | ||||
|     volatile int stored_safe = th->safe_level; | ||||
|     volatile NODE *stored_special_cref_stack = | ||||
|       lfp_set_special_cref(proc->block.lfp, proc->special_cref_stack); | ||||
|     rb_control_frame_t * volatile cfp = th->cfp; | ||||
| 
 | ||||
|     TH_PUSH_TAG(th); | ||||
|     if ((state = EXEC_TAG()) == 0) { | ||||
| 	th->safe_level = proc->safe_level; | ||||
| 	val = invoke_block(th, &proc->block, self, argc, argv, blockptr); | ||||
| 	val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, (NODE *)Qnil); | ||||
|     } | ||||
|     TH_POP_TAG(); | ||||
| 
 | ||||
|  | @ -609,8 +611,6 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, | |||
| 	th->safe_level = stored_safe; | ||||
|     } | ||||
| 
 | ||||
|     lfp_set_special_cref(proc->block.lfp, (NODE*)stored_special_cref_stack); | ||||
| 
 | ||||
|     if (state) { | ||||
| 	if (state == TAG_RETURN && proc->is_lambda) { | ||||
| 	    VALUE err = th->errinfo; | ||||
|  | @ -773,8 +773,6 @@ vm_backtrace(rb_thread_t *th, int lev) | |||
|     return ary; | ||||
| } | ||||
| 
 | ||||
| /* cref */ | ||||
| 
 | ||||
| static void | ||||
| check_svar(void) | ||||
| { | ||||
|  | @ -783,7 +781,7 @@ check_svar(void) | |||
|     while ((void *)(cfp + 1) < (void *)(th->stack + th->stack_size)) { | ||||
| 	/* printf("cfp: %p\n", cfp->type); */ | ||||
| 	if (cfp->lfp && cfp->lfp[-1] != Qnil && | ||||
| 	    TYPE(cfp->lfp[-1]) != T_VALUES) { | ||||
| 	    TYPE(cfp->lfp[-1]) != T_NODE) { | ||||
| 	    /* dp(cfp->lfp[-1]); */ | ||||
| 	    rb_bug("!!!invalid svar!!!"); | ||||
| 	} | ||||
|  | @ -791,30 +789,12 @@ check_svar(void) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static NODE * | ||||
| lfp_set_special_cref(VALUE *lfp, NODE * cref) | ||||
| { | ||||
|     struct RValues *values = (void *) lfp[-1]; | ||||
|     NODE *old_cref; | ||||
| 
 | ||||
|     if (VMDEBUG) { | ||||
| 	check_svar(); | ||||
|     } | ||||
| 
 | ||||
|     if (cref == 0 && ((VALUE)values == Qnil || values->basic.klass == 0)) { | ||||
| 	old_cref = 0; | ||||
|     } | ||||
|     else { | ||||
| 	old_cref = (NODE *)lfp_svar_get(GET_THREAD(), lfp, 2); | ||||
| 	lfp_svar_set(GET_THREAD(), lfp, 2, (VALUE)cref); | ||||
|     } | ||||
|     return old_cref; | ||||
| } | ||||
| 
 | ||||
| NODE * | ||||
| vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack) | ||||
| ruby_cref(void) | ||||
| { | ||||
|     return lfp_set_special_cref(lfp, cref_stack); | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); | ||||
|     return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp); | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
|  | @ -829,12 +809,6 @@ debug_cref(NODE *cref) | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| NODE * | ||||
| vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp) | ||||
| { | ||||
|     return get_cref(iseq, cfp->lfp); | ||||
| } | ||||
| 
 | ||||
| NODE * | ||||
| vm_cref_push(rb_thread_t *th, VALUE klass, int noex) | ||||
| { | ||||
|  | @ -842,16 +816,15 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex) | |||
|     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); | ||||
| 
 | ||||
|     cref->nd_file = 0; | ||||
|     cref->nd_next = get_cref(cfp->iseq, cfp->lfp); | ||||
|     cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp); | ||||
|     cref->nd_visi = noex; | ||||
|     return cref; | ||||
| } | ||||
| 
 | ||||
| VALUE | ||||
| vm_get_cbase(rb_thread_t *th) | ||||
| static inline VALUE | ||||
| vm_get_cbase(rb_iseq_t *iseq, VALUE *lfp, VALUE *dfp) | ||||
| { | ||||
|     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); | ||||
|     NODE *cref = get_cref(cfp->iseq, cfp->lfp); | ||||
|     NODE *cref = vm_get_cref(iseq, lfp, dfp); | ||||
|     VALUE klass = Qundef; | ||||
| 
 | ||||
|     while (cref) { | ||||
|  | @ -860,9 +833,18 @@ vm_get_cbase(rb_thread_t *th) | |||
| 	} | ||||
| 	cref = cref->nd_next; | ||||
|     } | ||||
| 
 | ||||
|     return klass; | ||||
| } | ||||
| 
 | ||||
| VALUE | ||||
| rb_vm_cbase(void) | ||||
| { | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp); | ||||
|     return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp); | ||||
| } | ||||
| 
 | ||||
| /* jump */ | ||||
| 
 | ||||
| static VALUE | ||||
|  | @ -1038,16 +1020,16 @@ vm_init_redefined_flag(void) | |||
|   C1      : pushed by send insn (CFUNC) | ||||
| 
 | ||||
|   struct CONTROL_FRAME { | ||||
|     VALUE *pc;                  // cfp[0]
 | ||||
|     VALUE *sp;                  // cfp[1]
 | ||||
|     VALUE *bp;                  // cfp[2]
 | ||||
|     rb_iseq_t *iseq;            // cfp[3]
 | ||||
|     VALUE flag;                 // cfp[4]
 | ||||
|     VALUE self;                 // cfp[5]
 | ||||
|     VALUE *lfp;                 // cfp[6]
 | ||||
|     VALUE *dfp;                 // cfp[7]
 | ||||
|     rb_iseq_t * block_iseq;     // cfp[8]
 | ||||
|     VALUE proc;                 // cfp[9] always 0
 | ||||
|     VALUE *pc;                  // cfp[0], program counter
 | ||||
|     VALUE *sp;                  // cfp[1], stack pointer
 | ||||
|     VALUE *bp;                  // cfp[2], base pointer
 | ||||
|     rb_iseq_t *iseq;            // cfp[3], iseq
 | ||||
|     VALUE flag;                 // cfp[4], magic
 | ||||
|     VALUE self;                 // cfp[5], self
 | ||||
|     VALUE *lfp;                 // cfp[6], local frame pointer
 | ||||
|     VALUE *dfp;                 // cfp[7], dynamic frame pointer
 | ||||
|     rb_iseq_t * block_iseq;     // cfp[8], block iseq
 | ||||
|     VALUE proc;                 // cfp[9], always 0
 | ||||
|   }; | ||||
| 
 | ||||
|   struct BLOCK { | ||||
|  | @ -1055,15 +1037,11 @@ vm_init_redefined_flag(void) | |||
|     VALUE *lfp; | ||||
|     VALUE *dfp; | ||||
|     rb_iseq_t *block_iseq; | ||||
|   }; | ||||
| 
 | ||||
|   struct PROC { | ||||
|     VALUE  proc_sig = 0; | ||||
|     struct BLOCK; | ||||
|     VALUE proc; | ||||
|   }; | ||||
| 
 | ||||
|   struct METHOD_CONTROL_FRAME { | ||||
|     struct CONTROL_FRAME; | ||||
|     rb_control_frame_t frame; | ||||
|   }; | ||||
| 
 | ||||
|   struct METHOD_FRAME { | ||||
|  | @ -1073,12 +1051,13 @@ vm_init_redefined_flag(void) | |||
|     VALUE param0; | ||||
|     ... | ||||
|     VALUE paramN; | ||||
|     VALUE cref; | ||||
|     VALUE special;                         // lfp [1]
 | ||||
|     struct block_object *block_ptr | 0x01; // lfp [0]
 | ||||
|   }; | ||||
| 
 | ||||
|   struct BLOCK_CONTROL_FRAME { | ||||
|     struct STACK_FRAME; | ||||
|     rb_control_frame_t frame; | ||||
|   }; | ||||
| 
 | ||||
|   struct BLOCK_FRAME { | ||||
|  | @ -1088,17 +1067,19 @@ vm_init_redefined_flag(void) | |||
|     VALUE param0; | ||||
|     ... | ||||
|     VALUE paramN; | ||||
|     VALUE cref; | ||||
|     VALUE *(prev_ptr | 0x01); // DFP[0]
 | ||||
|   }; | ||||
| 
 | ||||
|   struct CLASS_CONTROL_FRAME { | ||||
|     struct STACK_FRAME; | ||||
|     rb_control_frame_t frame; | ||||
|   }; | ||||
| 
 | ||||
|   struct CLASS_FRAME { | ||||
|     VALUE param0; | ||||
|     ... | ||||
|     VALUE paramN; | ||||
|     VALUE cref; | ||||
|     VALUE prev_dfp; // for frame jump
 | ||||
|   }; | ||||
| 
 | ||||
|  | @ -1125,11 +1106,6 @@ vm_init_redefined_flag(void) | |||
|     VALUE *dfp;                      // lfp
 | ||||
|     rb_iseq_t * block_iseq; // 0
 | ||||
|   }; | ||||
| 
 | ||||
|   struct C_METHDO_FRAME{ | ||||
|     VALUE block_ptr; | ||||
|     VALUE special; | ||||
|   }; | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1315,7 +1291,7 @@ vm_eval_body(rb_thread_t *th) | |||
| 	    cfp->sp[0] = err; | ||||
| 	    vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK, | ||||
| 			  cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded, | ||||
| 			  cfp->sp + 1, cfp->lfp, catch_iseq->local_size - 1); | ||||
| 			  cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1); | ||||
| 
 | ||||
| 	    state = 0; | ||||
| 	    th->errinfo = Qnil; | ||||
|  |  | |||
|  | @ -497,8 +497,6 @@ typedef struct { | |||
|     int safe_level; | ||||
|     int is_from_method; | ||||
|     int is_lambda; | ||||
| 
 | ||||
|     NODE *special_cref_stack; | ||||
| } rb_proc_t; | ||||
| 
 | ||||
| #define GetEnvPtr(obj, ptr) \ | ||||
|  | @ -517,7 +515,6 @@ typedef struct { | |||
| 
 | ||||
| typedef struct { | ||||
|     VALUE env; | ||||
|     NODE *cref_stack; | ||||
| } rb_binding_t; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -614,6 +611,7 @@ VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp); | |||
| VALUE vm_backtrace(rb_thread_t *, int); | ||||
| 
 | ||||
| VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv); | ||||
| VALUE vm_yield_with_cref(rb_thread_t *th, int argc, VALUE *argv, NODE *cref); | ||||
| VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid, | ||||
| 	       int argc, const VALUE *argv, NODE *body, int nosuper); | ||||
| 
 | ||||
|  |  | |||
|  | @ -140,7 +140,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) | |||
| void | ||||
| vm_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp) | ||||
| { | ||||
| #if 0 | ||||
| #if 1 | ||||
|     VALUE *sp = cfp->sp, *bp = cfp->bp; | ||||
|     VALUE *lfp = cfp->lfp; | ||||
|     VALUE *dfp = cfp->dfp; | ||||
|  | @ -174,6 +174,13 @@ vm_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp) | |||
|     fprintf(stderr, "---------------------------\n"); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| vm_stack_dump_raw_current(void) | ||||
| { | ||||
|     rb_thread_t *th = GET_THREAD(); | ||||
|     vm_stack_dump_raw(th, th->cfp); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| env_dump_raw(rb_env_t *env, VALUE *lfp, VALUE *dfp) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										109
									
								
								vm_insnhelper.c
									
										
									
									
									
								
							
							
						
						
									
										109
									
								
								vm_insnhelper.c
									
										
									
									
									
								
							|  | @ -29,6 +29,8 @@ vm_push_frame(rb_thread_t *th, rb_iseq_t *iseq, VALUE type, | |||
|     rb_control_frame_t *cfp; | ||||
|     int i; | ||||
| 
 | ||||
|     /* setup vm value stack */ | ||||
|      | ||||
|     /* nil initialize */ | ||||
|     for (i=0; i < local_size; i++) { | ||||
| 	*sp = Qnil; | ||||
|  | @ -43,6 +45,8 @@ vm_push_frame(rb_thread_t *th, rb_iseq_t *iseq, VALUE type, | |||
| 	lfp = sp; | ||||
|     } | ||||
| 
 | ||||
|     /* setup vm control frame stack */ | ||||
| 
 | ||||
|     cfp = th->cfp = th->cfp - 1; | ||||
|     cfp->pc = pc; | ||||
|     cfp->sp = sp + 1; | ||||
|  | @ -827,45 +831,24 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n | |||
|     } | ||||
| } | ||||
| 
 | ||||
| /* cref */ | ||||
| /* svar */ | ||||
| 
 | ||||
| static NODE * | ||||
| lfp_get_special_cref(VALUE *lfp) | ||||
| { | ||||
|     struct RValues *values; | ||||
|     if (((VALUE)(values = (void *)lfp[-1])) != Qnil && values->basic.klass) { | ||||
| 	return (NODE *)values->basic.klass; | ||||
|     } | ||||
|     else { | ||||
| 	return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static struct RValues * | ||||
| new_value(void) | ||||
| { | ||||
|     struct RValues *val = RVALUES(rb_newobj()); | ||||
|     OBJSETUP(val, 0, T_VALUES); | ||||
|     val->v1 = val->v2 = val->v3 = Qnil; | ||||
|     return val; | ||||
| } | ||||
| 
 | ||||
| static struct RValues * | ||||
| static inline NODE * | ||||
| lfp_svar_place(rb_thread_t *th, VALUE *lfp) | ||||
| { | ||||
|     struct RValues *svar; | ||||
|     NODE *svar; | ||||
| 
 | ||||
|     if (th->local_lfp != lfp) { | ||||
| 	svar = (struct RValues *)lfp[-1]; | ||||
| 	svar = (NODE *)lfp[-1]; | ||||
| 	if ((VALUE)svar == Qnil) { | ||||
| 	    svar = new_value(); | ||||
| 	    svar = NEW_IF(Qnil, Qnil, Qnil); | ||||
| 	    lfp[-1] = (VALUE)svar; | ||||
| 	} | ||||
|     } | ||||
|     else { | ||||
| 	svar = (struct RValues *)th->local_svar; | ||||
| 	svar = (NODE *)th->local_svar; | ||||
| 	if ((VALUE)svar == Qnil) { | ||||
| 	    svar = new_value(); | ||||
| 	    svar = NEW_IF(Qnil, Qnil, Qnil); | ||||
| 	    th->local_svar = (VALUE)svar; | ||||
| 	} | ||||
|     } | ||||
|  | @ -875,17 +858,15 @@ lfp_svar_place(rb_thread_t *th, VALUE *lfp) | |||
| static VALUE | ||||
| lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key) | ||||
| { | ||||
|     struct RValues *svar = lfp_svar_place(th, lfp); | ||||
|     NODE *svar = lfp_svar_place(th, lfp); | ||||
| 
 | ||||
|     switch (key) { | ||||
|       case 0: | ||||
| 	return svar->v1; | ||||
| 	return svar->u1.value; | ||||
|       case 1: | ||||
| 	return svar->v2; | ||||
|       case 2: | ||||
| 	return svar->basic.klass; | ||||
| 	return svar->u2.value; | ||||
|       default: { | ||||
| 	VALUE hash = svar->v3; | ||||
| 	VALUE hash = svar->u3.value; | ||||
| 
 | ||||
| 	if (hash == Qnil) { | ||||
| 	    return Qnil; | ||||
|  | @ -900,45 +881,26 @@ lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key) | |||
| static void | ||||
| lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val) | ||||
| { | ||||
|     struct RValues *svar = lfp_svar_place(th, lfp); | ||||
|     NODE *svar = lfp_svar_place(th, lfp); | ||||
| 
 | ||||
|     switch (key) { | ||||
|       case 0: | ||||
| 	svar->v1 = val; | ||||
| 	svar->u1.value = val; | ||||
| 	return; | ||||
|       case 1: | ||||
| 	svar->v2 = val; | ||||
| 	return; | ||||
|       case 2: | ||||
| 	svar->basic.klass = val; | ||||
| 	svar->u2.value = val; | ||||
| 	return; | ||||
|       default: { | ||||
| 	VALUE hash = svar->v3; | ||||
| 	VALUE hash = svar->u3.value; | ||||
| 
 | ||||
| 	if (hash == Qnil) { | ||||
| 	    svar->v3 = hash = rb_hash_new(); | ||||
| 	    svar->u3.value = hash = rb_hash_new(); | ||||
| 	} | ||||
| 	rb_hash_aset(hash, key, val); | ||||
|       } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static NODE * | ||||
| get_cref(rb_iseq_t *iseq, VALUE *lfp) | ||||
| { | ||||
|     NODE *cref; | ||||
|     if ((cref = lfp_get_special_cref(lfp)) != 0) { | ||||
| 	/* */ | ||||
|     } | ||||
|     else if ((cref = iseq->cref_stack) != 0) { | ||||
| 	/* */ | ||||
|     } | ||||
|     else { | ||||
| 	rb_bug("get_cref: unreachable"); | ||||
|     } | ||||
|     return cref; | ||||
| } | ||||
| 
 | ||||
| static inline VALUE | ||||
| vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type) | ||||
| { | ||||
|  | @ -976,6 +938,30 @@ vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type) | |||
|     return val; | ||||
| } | ||||
| 
 | ||||
| static NODE * | ||||
| vm_get_cref(rb_iseq_t *iseq, const VALUE * const lfp, const VALUE *dfp) | ||||
| { | ||||
|     NODE *cref = 0; | ||||
| 
 | ||||
|     while (1) { | ||||
| 	if (lfp == dfp) { | ||||
| 	    cref = iseq->cref_stack; | ||||
| 	    break; | ||||
| 	} | ||||
| 	else if (dfp[-1] != Qnil) { | ||||
| 	    cref = (NODE *)dfp[-1]; | ||||
| 	    break; | ||||
| 	} | ||||
| 	dfp = GET_PREV_DFP(dfp); | ||||
|     } | ||||
| 
 | ||||
|     if (cref == 0) { | ||||
| 	rb_bug("vm_get_cref: unreachable"); | ||||
|     } | ||||
|     return cref; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static inline void | ||||
| vm_check_if_namespace(VALUE klass) | ||||
| { | ||||
|  | @ -997,7 +983,7 @@ vm_get_ev_const(rb_thread_t *th, rb_iseq_t *iseq, | |||
| 
 | ||||
|     if (klass == Qnil) { | ||||
| 	/* in current lexical scope */ | ||||
| 	NODE *root_cref = get_cref(iseq, th->cfp->lfp); | ||||
| 	NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp); | ||||
| 	NODE *cref = root_cref; | ||||
| 
 | ||||
| 	while (cref && cref->nd_next) { | ||||
|  | @ -1054,9 +1040,8 @@ vm_get_ev_const(rb_thread_t *th, rb_iseq_t *iseq, | |||
| } | ||||
| 
 | ||||
| static inline VALUE | ||||
| vm_get_cvar_base(rb_thread_t *th, rb_iseq_t *iseq) | ||||
| vm_get_cvar_base(NODE *cref) | ||||
| { | ||||
|     NODE *cref = get_cref(iseq, th->cfp->lfp); | ||||
|     VALUE klass = Qnil; | ||||
| 
 | ||||
|     if (cref) { | ||||
|  | @ -1076,8 +1061,8 @@ vm_define_method(rb_thread_t *th, VALUE obj, | |||
| 		   ID id, rb_iseq_t *miseq, rb_num_t is_singleton, NODE *cref) | ||||
| { | ||||
|     NODE *newbody; | ||||
|     int noex = cref->nd_visi; | ||||
|     VALUE klass = cref->nd_clss; | ||||
|     int noex = cref->nd_visi; | ||||
| 
 | ||||
|     if (is_singleton) { | ||||
| 	if (FIXNUM_P(obj) || SYMBOL_P(obj)) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 ko1
						ko1