mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* compile.c (iseq_compile_each), vm_insnhelper.c (vm_invoke_block,
vm_throw): allow "return" and "yield" even in singleton class definition. based on a patch from wanabe <s.wanabe AT gmail.com> for "return". [ruby-core:21379] [ruby-dev:40975] * insns.def (defineclass): ditto (straightforwardly push block ptr, instead of dfp ptr with special flag). * vm_core.h (RUBY_VM_CLASS_SPECIAL_P): ditto (no longer needed). * proc.c (proc_new): ditto (remove handling for special flag). * bootstraptest/test_jump.rb: add tests for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									b664caeb78
								
							
						
					
					
						commit
						80f7f8d07e
					
				
					 8 changed files with 60 additions and 13 deletions
				
			
		
							
								
								
									
										16
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,19 @@
 | 
			
		|||
Mon May 10 02:58:33 2010  Yusuke Endoh  <mame@tsg.ne.jp>
 | 
			
		||||
 | 
			
		||||
	* compile.c (iseq_compile_each), vm_insnhelper.c (vm_invoke_block,
 | 
			
		||||
	  vm_throw): allow "return" and "yield" even in singleton class
 | 
			
		||||
	  definition.  based on a patch from wanabe <s.wanabe AT gmail.com>
 | 
			
		||||
	  for "return".  [ruby-core:21379] [ruby-dev:40975]
 | 
			
		||||
 | 
			
		||||
	* insns.def (defineclass): ditto (straightforwardly push block ptr,
 | 
			
		||||
	  instead of dfp ptr with special flag).
 | 
			
		||||
 | 
			
		||||
	* vm_core.h (RUBY_VM_CLASS_SPECIAL_P): ditto (no longer needed).
 | 
			
		||||
 | 
			
		||||
	* proc.c (proc_new): ditto (remove handling for special flag).
 | 
			
		||||
 | 
			
		||||
	* bootstraptest/test_jump.rb: add tests for above.
 | 
			
		||||
 | 
			
		||||
Mon May 10 02:29:51 2010  Yusuke Endoh  <mame@tsg.ne.jp>
 | 
			
		||||
 | 
			
		||||
	* cont.c (fiber_switch): raise FiberError when returning to dead
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -282,3 +282,27 @@ assert_normal_exit %q{
 | 
			
		|||
    break
 | 
			
		||||
  end
 | 
			
		||||
}, '[ruby-core:28172]'
 | 
			
		||||
 | 
			
		||||
assert_equal "true", %q{
 | 
			
		||||
  class Object
 | 
			
		||||
    def return_eigenclass
 | 
			
		||||
      class << self
 | 
			
		||||
        return self
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  s = "foo"
 | 
			
		||||
  s.return_eigenclass == class << s; self; end
 | 
			
		||||
}, '[ruby-core:21379]'
 | 
			
		||||
 | 
			
		||||
assert_equal "true", %q{
 | 
			
		||||
  class Object
 | 
			
		||||
    def yield_eigenclass
 | 
			
		||||
      class << self
 | 
			
		||||
        yield self
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  s = "foo"
 | 
			
		||||
  s.yield_eigenclass {|c| c == class << s; self; end }
 | 
			
		||||
}, '[ruby-dev:40975]'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4225,7 +4225,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 | 
			
		|||
	rb_iseq_t *is = iseq;
 | 
			
		||||
 | 
			
		||||
	if (is) {
 | 
			
		||||
	    if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) {
 | 
			
		||||
	    if (is->type == ISEQ_TYPE_TOP) {
 | 
			
		||||
		COMPILE_ERROR((ERROR_ARGS "Invalid return"));
 | 
			
		||||
	    }
 | 
			
		||||
	    else {
 | 
			
		||||
| 
						 | 
				
			
			@ -4265,7 +4265,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 | 
			
		|||
	unsigned long flag = 0;
 | 
			
		||||
 | 
			
		||||
	INIT_ANCHOR(args);
 | 
			
		||||
	if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) {
 | 
			
		||||
	if (iseq->type == ISEQ_TYPE_TOP) {
 | 
			
		||||
	    COMPILE_ERROR((ERROR_ARGS "Invalid yield"));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -953,7 +953,7 @@ defineclass
 | 
			
		|||
 | 
			
		||||
    /* enter scope */
 | 
			
		||||
    vm_push_frame(th, class_iseq,
 | 
			
		||||
		  VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
 | 
			
		||||
		  VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(),
 | 
			
		||||
		  class_iseq->iseq_encoded, GET_SP(), 0,
 | 
			
		||||
		  class_iseq->local_size);
 | 
			
		||||
    RESTORE_REGS();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								proc.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -375,16 +375,14 @@ proc_new(VALUE klass, int is_lambda)
 | 
			
		|||
    rb_control_frame_t *cfp = th->cfp;
 | 
			
		||||
    rb_block_t *block;
 | 
			
		||||
 | 
			
		||||
    if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 &&
 | 
			
		||||
	!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
 | 
			
		||||
    if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
 | 
			
		||||
 | 
			
		||||
	block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
 | 
			
		||||
 | 
			
		||||
	if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 &&
 | 
			
		||||
	    !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
 | 
			
		||||
	if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
 | 
			
		||||
 | 
			
		||||
	    block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								vm.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -477,7 +477,6 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
 | 
			
		||||
	if (!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
 | 
			
		||||
	    rb_proc_t *p;
 | 
			
		||||
 | 
			
		||||
	    blockprocval = vm_make_proc_from_block(
 | 
			
		||||
| 
						 | 
				
			
			@ -486,7 +485,6 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
 | 
			
		|||
	    GetProcPtr(blockprocval, p);
 | 
			
		||||
	    *cfp->lfp = GC_GUARDED_PTR(&p->block);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    envval = rb_vm_make_env_object(th, cfp);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -597,8 +597,6 @@ typedef rb_control_frame_t *
 | 
			
		|||
#define RUBY_VM_NORMAL_ISEQ_P(ptr) \
 | 
			
		||||
  (ptr && !RUBY_VM_IFUNC_P(ptr))
 | 
			
		||||
 | 
			
		||||
#define RUBY_VM_CLASS_SPECIAL_P(ptr) (((VALUE)(ptr)) & 0x02)
 | 
			
		||||
 | 
			
		||||
#define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self))
 | 
			
		||||
#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \
 | 
			
		||||
  ((rb_control_frame_t *)((VALUE *)(b) - 5))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -913,8 +913,9 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
 | 
			
		|||
    const rb_block_t *block = GET_BLOCK_PTR();
 | 
			
		||||
    rb_iseq_t *iseq;
 | 
			
		||||
    int argc = (int)num;
 | 
			
		||||
    int type = GET_ISEQ()->local_iseq->type;
 | 
			
		||||
 | 
			
		||||
    if (GET_ISEQ()->local_iseq->type != ISEQ_TYPE_METHOD || block == 0) {
 | 
			
		||||
    if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) {
 | 
			
		||||
	rb_vm_localjump_error("no block given (yield)", Qnil, 0);
 | 
			
		||||
    }
 | 
			
		||||
    iseq = block->iseq;
 | 
			
		||||
| 
						 | 
				
			
			@ -1434,6 +1435,11 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
 | 
			
		|||
 | 
			
		||||
	      search_parent:
 | 
			
		||||
		if (cfp->iseq->type != ISEQ_TYPE_BLOCK) {
 | 
			
		||||
		    if (cfp->iseq->type == ISEQ_TYPE_CLASS) {
 | 
			
		||||
			cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
 | 
			
		||||
			dfp = cfp->dfp;
 | 
			
		||||
			goto search_parent;
 | 
			
		||||
		    }
 | 
			
		||||
		    dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
 | 
			
		||||
		    base_iseq = base_iseq->parent_iseq;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1499,10 +1505,17 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
 | 
			
		|||
	    else if (state == TAG_RETURN) {
 | 
			
		||||
		rb_control_frame_t *cfp = GET_CFP();
 | 
			
		||||
		VALUE *dfp = GET_DFP();
 | 
			
		||||
		VALUE * const lfp = GET_LFP();
 | 
			
		||||
		VALUE *lfp = GET_LFP();
 | 
			
		||||
 | 
			
		||||
		/* check orphan and get dfp */
 | 
			
		||||
		while ((VALUE *) cfp < th->stack + th->stack_size) {
 | 
			
		||||
		    if (!lfp) {
 | 
			
		||||
			lfp = cfp->lfp;
 | 
			
		||||
		    }
 | 
			
		||||
		    if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) {
 | 
			
		||||
			lfp = 0;
 | 
			
		||||
		    }
 | 
			
		||||
 | 
			
		||||
		    if (cfp->lfp == lfp) {
 | 
			
		||||
			if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
 | 
			
		||||
			    VALUE *tdfp = dfp;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue