mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* compile.c (compile_cpath, iseq_compile_each): reverted
constant/class variable lookup in instance_eval etc. to the behavior of 1.8. * eval.c (rb_mod_nesting): ditto. * insns.def (putspecialobject, defineclass): ditto. * node.h (NODE_FL_CREF_PUSHED_BY_EVAL): ditto. * vm_core.h (VM_SPECIAL_OBJECT_CONST_BASE): ditto. * vm_eval.c (yield_under, eval_under): ditto. * vm_insnhelper.c (vm_cref_push, vm_get_const_base, vm_get_ev_const, vm_get_cvar_base): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25984 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									9998481d4e
								
							
						
					
					
						commit
						7dbfe89630
					
				
					 10 changed files with 105 additions and 22 deletions
				
			
		
							
								
								
									
										19
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,22 @@
 | 
			
		|||
Fri Dec  4 03:10:38 2009  Shugo Maeda  <shugo@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* compile.c (compile_cpath, iseq_compile_each): reverted
 | 
			
		||||
	  constant/class variable lookup in instance_eval etc. to the
 | 
			
		||||
	  behavior of 1.8.
 | 
			
		||||
 | 
			
		||||
	* eval.c (rb_mod_nesting): ditto.
 | 
			
		||||
 | 
			
		||||
	* insns.def (putspecialobject, defineclass): ditto.
 | 
			
		||||
 | 
			
		||||
	* node.h (NODE_FL_CREF_PUSHED_BY_EVAL): ditto.
 | 
			
		||||
 | 
			
		||||
	* vm_core.h (VM_SPECIAL_OBJECT_CONST_BASE): ditto.
 | 
			
		||||
 | 
			
		||||
	* vm_eval.c (yield_under, eval_under): ditto.
 | 
			
		||||
 | 
			
		||||
	* vm_insnhelper.c (vm_cref_push, vm_get_const_base,
 | 
			
		||||
	  vm_get_ev_const, vm_get_cvar_base): ditto.
 | 
			
		||||
 | 
			
		||||
Thu Dec 3 20:27:27 2009  Martin Duerst  <duerst@it.aoyama.ac.jp>
 | 
			
		||||
 | 
			
		||||
	* enc/trans/gb18030-tbl.rb: Fix omission of C1 region in code table
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2549,7 +2549,8 @@ compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
 | 
			
		|||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	/* class at cbase Foo */
 | 
			
		||||
	ADD_INSN1(ret, nd_line(cpath), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
 | 
			
		||||
	ADD_INSN1(ret, nd_line(cpath), putspecialobject,
 | 
			
		||||
		  INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
 | 
			
		||||
	return Qtrue;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3710,7 +3711,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if (node->nd_vid) {
 | 
			
		||||
	    ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
 | 
			
		||||
	    ADD_INSN1(ret, nd_line(node), putspecialobject,
 | 
			
		||||
		      INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
 | 
			
		||||
	    ADD_INSN1(ret, nd_line(node), setconstant, ID2SYM(node->nd_vid));
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -274,7 +274,8 @@ rb_mod_nesting(void)
 | 
			
		|||
 | 
			
		||||
    while (cref && cref->nd_next) {
 | 
			
		||||
	VALUE klass = cref->nd_clss;
 | 
			
		||||
	if (!NIL_P(klass)) {
 | 
			
		||||
	if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
 | 
			
		||||
	    !NIL_P(klass)) {
 | 
			
		||||
	    rb_ary_push(ary, klass);
 | 
			
		||||
	}
 | 
			
		||||
	cref = cref->nd_next;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -343,6 +343,9 @@ putspecialobject
 | 
			
		|||
      case VM_SPECIAL_OBJECT_CBASE:
 | 
			
		||||
	val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
 | 
			
		||||
	break;
 | 
			
		||||
      case VM_SPECIAL_OBJECT_CONST_BASE:
 | 
			
		||||
	val = vm_get_const_base(GET_ISEQ(), GET_LFP(), GET_DFP());
 | 
			
		||||
	break;
 | 
			
		||||
      default:
 | 
			
		||||
	rb_bug("putspecialobject insn: unknown value_type");
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -944,7 +947,7 @@ defineclass
 | 
			
		|||
	rb_bug("unknown defineclass type: %d", (int)define_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC));
 | 
			
		||||
    COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC, NULL));
 | 
			
		||||
 | 
			
		||||
    /* enter scope */
 | 
			
		||||
    vm_push_frame(th, class_iseq,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								node.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								node.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -262,6 +262,7 @@ typedef struct RNode {
 | 
			
		|||
 | 
			
		||||
/* 0..4:T_TYPES, 5:FL_MARK, 6:reserved, 7:NODE_FL_NEWLINE */
 | 
			
		||||
#define NODE_FL_NEWLINE (((VALUE)1)<<7)
 | 
			
		||||
#define NODE_FL_CREF_PUSHED_BY_EVAL NODE_FL_NEWLINE
 | 
			
		||||
 | 
			
		||||
#define NODE_TYPESHIFT 8
 | 
			
		||||
#define NODE_TYPEMASK  (((VALUE)0x7f)<<NODE_TYPESHIFT)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,10 +216,29 @@ class TestModule < Test::Unit::TestCase
 | 
			
		|||
                 remove_rake_mixins(remove_json_mixins(remove_pp_mixins(String.ancestors))))
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  CLASS_EVAL = 2
 | 
			
		||||
  @@class_eval = 'b'
 | 
			
		||||
 | 
			
		||||
  def test_class_eval
 | 
			
		||||
    Other.class_eval("CLASS_EVAL = 1")
 | 
			
		||||
    assert_equal(1, Other::CLASS_EVAL)
 | 
			
		||||
    assert(Other.constants.include?(:CLASS_EVAL))
 | 
			
		||||
    assert_equal(2, Other.class_eval { CLASS_EVAL })
 | 
			
		||||
 | 
			
		||||
    Other.class_eval("@@class_eval = 'a'")
 | 
			
		||||
    assert_equal('a', Other.class_variable_get(:@@class_eval))
 | 
			
		||||
    assert_equal('b', Other.class_eval { @@class_eval })
 | 
			
		||||
 | 
			
		||||
    Other.class_eval do
 | 
			
		||||
      module_function
 | 
			
		||||
 | 
			
		||||
      def class_eval_test
 | 
			
		||||
        "foo"
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
    assert("foo", Other.class_eval_test)
 | 
			
		||||
 | 
			
		||||
    assert_equal([Other], Other.class_eval { |*args| args })
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_const_defined?
 | 
			
		||||
| 
						 | 
				
			
			@ -451,7 +470,7 @@ class TestModule < Test::Unit::TestCase
 | 
			
		|||
 | 
			
		||||
  def test_class_variable_get
 | 
			
		||||
    c = Class.new
 | 
			
		||||
    c.class_eval { @@foo = :foo }
 | 
			
		||||
    c.class_eval('@@foo = :foo')
 | 
			
		||||
    assert_equal(:foo, c.class_variable_get(:@@foo))
 | 
			
		||||
    assert_raise(NameError) { c.class_variable_get(:@@bar) } # c.f. instance_variable_get
 | 
			
		||||
    assert_raise(NameError) { c.class_variable_get(:foo) }
 | 
			
		||||
| 
						 | 
				
			
			@ -460,13 +479,13 @@ class TestModule < Test::Unit::TestCase
 | 
			
		|||
  def test_class_variable_set
 | 
			
		||||
    c = Class.new
 | 
			
		||||
    c.class_variable_set(:@@foo, :foo)
 | 
			
		||||
    assert_equal(:foo, c.class_eval { @@foo })
 | 
			
		||||
    assert_equal(:foo, c.class_eval('@@foo'))
 | 
			
		||||
    assert_raise(NameError) { c.class_variable_set(:foo, 1) }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_class_variable_defined
 | 
			
		||||
    c = Class.new
 | 
			
		||||
    c.class_eval { @@foo = :foo }
 | 
			
		||||
    c.class_eval('@@foo = :foo')
 | 
			
		||||
    assert_equal(true, c.class_variable_defined?(:@@foo))
 | 
			
		||||
    assert_equal(false, c.class_variable_defined?(:@@bar))
 | 
			
		||||
    assert_raise(NameError) { c.class_variable_defined?(:foo) }
 | 
			
		||||
| 
						 | 
				
			
			@ -474,7 +493,7 @@ class TestModule < Test::Unit::TestCase
 | 
			
		|||
 | 
			
		||||
  def test_remove_class_variable
 | 
			
		||||
    c = Class.new
 | 
			
		||||
    c.class_eval { @@foo = :foo }
 | 
			
		||||
    c.class_eval('@@foo = :foo')
 | 
			
		||||
    c.class_eval { remove_class_variable(:@@foo) }
 | 
			
		||||
    assert_equal(false, c.class_variable_defined?(:@@foo))
 | 
			
		||||
  end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -416,12 +416,20 @@ class TestObject < Test::Unit::TestCase
 | 
			
		|||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class InstanceExec
 | 
			
		||||
    INSTANCE_EXEC = 123
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_instance_exec
 | 
			
		||||
    x = 1.instance_exec(42) {|a| self + a }
 | 
			
		||||
    assert_equal(43, x)
 | 
			
		||||
 | 
			
		||||
    x = "foo".instance_exec("bar") {|a| self + a }
 | 
			
		||||
    assert_equal("foobar", x)
 | 
			
		||||
 | 
			
		||||
    assert_raise(NameError) do
 | 
			
		||||
      InstanceExec.new.instance_exec { INSTANCE_EXEC }
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_extend
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -524,8 +524,9 @@ typedef struct {
 | 
			
		|||
#define VM_CALL_SUPER_BIT          (0x01 << 7)
 | 
			
		||||
#define VM_CALL_OPT_SEND_BIT       (0x01 << 8)
 | 
			
		||||
 | 
			
		||||
#define VM_SPECIAL_OBJECT_VMCORE   0x01
 | 
			
		||||
#define VM_SPECIAL_OBJECT_CBASE    0x02
 | 
			
		||||
#define VM_SPECIAL_OBJECT_VMCORE       0x01
 | 
			
		||||
#define VM_SPECIAL_OBJECT_CBASE        0x02
 | 
			
		||||
#define VM_SPECIAL_OBJECT_CONST_BASE  0x03
 | 
			
		||||
 | 
			
		||||
#define VM_FRAME_MAGIC_METHOD 0x11
 | 
			
		||||
#define VM_FRAME_MAGIC_BLOCK  0x21
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								vm_eval.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								vm_eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -17,7 +17,7 @@ static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *a
 | 
			
		|||
static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
 | 
			
		||||
static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
 | 
			
		||||
static int vm_backtrace_each(rb_thread_t *th, int lev, rb_backtrace_iter_func *iter, void *arg);
 | 
			
		||||
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex);
 | 
			
		||||
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
 | 
			
		||||
static VALUE vm_exec(rb_thread_t *th);
 | 
			
		||||
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
 | 
			
		||||
static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
 | 
			
		||||
| 
						 | 
				
			
			@ -1161,16 +1161,18 @@ yield_under(VALUE under, VALUE self, VALUE values)
 | 
			
		|||
{
 | 
			
		||||
    rb_thread_t *th = GET_THREAD();
 | 
			
		||||
    rb_block_t block, *blockptr;
 | 
			
		||||
    NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC);
 | 
			
		||||
    NODE *cref;
 | 
			
		||||
 | 
			
		||||
    if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
 | 
			
		||||
	block = *blockptr;
 | 
			
		||||
	block.self = self;
 | 
			
		||||
	th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
 | 
			
		||||
    }
 | 
			
		||||
    cref = vm_cref_push(th, under, NOEX_PUBLIC, &block);
 | 
			
		||||
    cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
 | 
			
		||||
 | 
			
		||||
    if (values == Qundef) {
 | 
			
		||||
	return vm_yield_with_cref(th, 0, 0, cref);
 | 
			
		||||
	return vm_yield_with_cref(th, 1, &self, cref);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
 | 
			
		||||
| 
						 | 
				
			
			@ -1181,7 +1183,7 @@ yield_under(VALUE under, VALUE self, VALUE values)
 | 
			
		|||
static VALUE
 | 
			
		||||
eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
 | 
			
		||||
{
 | 
			
		||||
    NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC);
 | 
			
		||||
    NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
 | 
			
		||||
 | 
			
		||||
    if (rb_safe_level() >= 4) {
 | 
			
		||||
	StringValue(src);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1066,14 +1066,17 @@ vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static NODE *
 | 
			
		||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
 | 
			
		||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
 | 
			
		||||
{
 | 
			
		||||
    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
 | 
			
		||||
    NODE *cref = NEW_BLOCK(klass);
 | 
			
		||||
    cref->nd_file = 0;
 | 
			
		||||
    cref->nd_visi = noex;
 | 
			
		||||
 | 
			
		||||
    if (cfp) {
 | 
			
		||||
    if (blockptr) {
 | 
			
		||||
	cref->nd_next = vm_get_cref(blockptr->iseq, blockptr->lfp, blockptr->dfp);
 | 
			
		||||
    }
 | 
			
		||||
    else if (cfp) {
 | 
			
		||||
	cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1096,6 +1099,23 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 | 
			
		|||
    return klass;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline VALUE
 | 
			
		||||
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
 | 
			
		||||
{
 | 
			
		||||
    NODE *cref = vm_get_cref(iseq, lfp, dfp);
 | 
			
		||||
    VALUE klass = Qundef;
 | 
			
		||||
 | 
			
		||||
    while (cref) {
 | 
			
		||||
	if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
 | 
			
		||||
	    (klass = cref->nd_clss) != 0) {
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
	cref = cref->nd_next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return klass;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
vm_check_if_namespace(VALUE klass)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1117,12 +1137,16 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
 | 
			
		|||
 | 
			
		||||
    if (orig_klass == Qnil) {
 | 
			
		||||
	/* in current lexical scope */
 | 
			
		||||
	const NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
 | 
			
		||||
	const NODE *cref = root_cref;
 | 
			
		||||
	const NODE *cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
 | 
			
		||||
	const NODE *root_cref = NULL;
 | 
			
		||||
	VALUE klass = orig_klass;
 | 
			
		||||
 | 
			
		||||
	while (cref && cref->nd_next) {
 | 
			
		||||
	    klass = cref->nd_clss;
 | 
			
		||||
	    if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL)) {
 | 
			
		||||
		klass = cref->nd_clss;
 | 
			
		||||
		if (root_cref == NULL)
 | 
			
		||||
		    root_cref = cref;
 | 
			
		||||
	    }
 | 
			
		||||
	    cref = cref->nd_next;
 | 
			
		||||
 | 
			
		||||
	    if (!NIL_P(klass)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1149,8 +1173,10 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* search self */
 | 
			
		||||
	klass = root_cref->nd_clss;
 | 
			
		||||
	if (NIL_P(klass)) {
 | 
			
		||||
	if (root_cref && !NIL_P(root_cref->nd_clss)) {
 | 
			
		||||
	    klass = root_cref->nd_clss;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    klass = CLASS_OF(th->cfp->self);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1178,7 +1204,8 @@ vm_get_cvar_base(NODE *cref)
 | 
			
		|||
    VALUE klass;
 | 
			
		||||
 | 
			
		||||
    while (cref && cref->nd_next &&
 | 
			
		||||
	   (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
 | 
			
		||||
	   (NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON) ||
 | 
			
		||||
	    (cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL))) {
 | 
			
		||||
	cref = cref->nd_next;
 | 
			
		||||
 | 
			
		||||
	if (!cref->nd_next) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue