ruby-changes:21044
From: nahi <ko1@a...>
Date: Sat, 27 Aug 2011 11:19:52 +0900 (JST)
Subject: [ruby-changes:21044] nahi:r33093 (trunk): * Revert r33078. It caused a Rails application NoMethodError.
nahi 2011-08-27 11:19:42 +0900 (Sat, 27 Aug 2011) New Revision: 33093 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33093 Log: * Revert r33078. It caused a Rails application NoMethodError. /home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/utils.rb:157: warning: toplevel constant ScanError referenced by Regin::Parser::ScanError /home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/vendor/regin/regin/parser.rb:17:in `parse_regexp': undefined method `scan_str' for #<Regin::Parser:0x00000002344548> (NoMethodError) Modified files: trunk/ChangeLog trunk/test/ruby/test_autoload.rb trunk/variable.c trunk/vm_insnhelper.c Index: ChangeLog =================================================================== --- ChangeLog (revision 33092) +++ ChangeLog (revision 33093) @@ -1,3 +1,10 @@ +Sat Aug 27 11:18:12 2011 Hiroshi Nakamura <nahi@r...> + + * Revert r33078. It caused a Rails application NoMethodError. + + /home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/utils.rb:157: warning: toplevel constant ScanError referenced by Regin::Parser::ScanError + /home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/vendor/regin/regin/parser.rb:17:in `parse_regexp': undefined method `scan_str' for #<Regin::Parser:0x00000002344548> (NoMethodError) + Sat Aug 27 08:44:58 2011 Eric Hodel <drbrain@s...> * lib/rdoc: Import RDoc 3.9.4. Typo and grammar fixes by Luke Gruber. Index: variable.c =================================================================== --- variable.c (revision 33092) +++ variable.c (revision 33093) @@ -1445,63 +1445,12 @@ #define check_autoload_table(av) \ (struct st_table *)rb_check_typeddata((av), &autoload_data_type) -static VALUE -autoload_data(VALUE mod, ID id) -{ - struct st_table *tbl; - st_data_t val; - - if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || - !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { - return 0; - } - return (VALUE)val; -} - -struct autoload_data_i { - VALUE feature; - int safe_level; - VALUE thread; - VALUE value; -}; - -static void -autoload_i_mark(void *ptr) -{ - struct autoload_data_i *p = ptr; - rb_gc_mark(p->feature); - rb_gc_mark(p->thread); - rb_gc_mark(p->value); -} - -static void -autoload_i_free(void *ptr) -{ - struct autoload_data_i *p = ptr; - xfree(p); -} - -static size_t -autoload_i_memsize(const void *ptr) -{ - return sizeof(struct autoload_data_i); -} - -static const rb_data_type_t autoload_data_i_type = { - "autoload_i", - {autoload_i_mark, autoload_i_free, autoload_i_memsize,}, -}; - -#define check_autoload_data(av) \ - (struct autoload_data_i *)rb_check_typeddata((av), &autoload_data_i_type) - void rb_autoload(VALUE mod, ID id, const char *file) { st_data_t av; - VALUE ad, fn; + VALUE fn; struct st_table *tbl; - struct autoload_data_i *ele; if (!rb_is_const_id(id)) { rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id)); @@ -1524,20 +1473,13 @@ st_add_direct(tbl, (st_data_t)autoload, av); DATA_PTR(av) = tbl = st_init_numtable(); } - ad = TypedData_Wrap_Struct(0, &autoload_data_i_type, 0); - st_insert(tbl, (st_data_t)id, (st_data_t)ad); - DATA_PTR(ad) = ele = ALLOC(struct autoload_data_i); - fn = rb_str_new2(file); FL_UNSET(fn, FL_TAINT); OBJ_FREEZE(fn); - ele->feature = fn; - ele->safe_level = rb_safe_level(); - ele->thread = Qnil; - ele->value = Qundef; + st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0)); } -static void +static NODE* autoload_delete(VALUE mod, ID id) { st_data_t val, load = 0, n = id; @@ -1556,6 +1498,8 @@ st_delete(RCLASS_IV_TBL(mod), &n, &val); } } + + return (NODE *)load; } static VALUE @@ -1572,18 +1516,22 @@ return safe; } -static VALUE -check_autoload_required(VALUE mod, ID id, const char **loadingpath) +static NODE * +autoload_node(VALUE mod, ID id, const char **loadingpath) { - VALUE file, load; - struct autoload_data_i *ele; + VALUE file; + struct st_table *tbl; + st_data_t val; + NODE *load; const char *loading; int safe; - if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) { + if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || + !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) { return 0; } - file = ele->feature; + load = (NODE *)val; + file = load->nd_lit; Check_Type(file, T_STRING); if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) { rb_raise(rb_eArgError, "empty file name"); @@ -1602,7 +1550,7 @@ } static int -autoload_defined_p(VALUE mod, ID id) +autoload_node_id(VALUE mod, ID id) { struct st_table *tbl = RCLASS_CONST_TBL(mod); st_data_t val; @@ -1613,109 +1561,42 @@ return 1; } -int -rb_autoloading_value(VALUE mod, ID id, VALUE* value) -{ - VALUE load; - struct autoload_data_i *ele; - - if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) { - return 0; - } - if (ele->thread == rb_thread_current()) { - if (ele->value != Qundef) { - if (value) { - *value = ele->value; - } - return 1; - } - } - return 0; -} - -struct autoload_const_set_args { - VALUE mod; - ID id; - VALUE value; -}; - -static void -autoload_const_set(struct autoload_const_set_args* args) -{ - autoload_delete(args->mod, args->id); - rb_const_set(args->mod, args->id, args->value); -} - -static VALUE -autoload_require(struct autoload_data_i *ele) -{ - return rb_require_safe(ele->feature, ele->safe_level); -} - VALUE rb_autoload_load(VALUE mod, ID id) { - VALUE load, result; + VALUE file; + NODE *load; const char *loading = 0, *src; - struct autoload_data_i *ele; - int state = 0; - if (!autoload_defined_p(mod, id)) return Qfalse; - load = check_autoload_required(mod, id, &loading); + if (!autoload_node_id(mod, id)) return Qfalse; + load = autoload_node(mod, id, &loading); if (!load) return Qfalse; src = rb_sourcefile(); if (src && loading && strcmp(src, loading) == 0) return Qfalse; - - /* set ele->thread for a marker of autoloading thread */ - if (!(ele = check_autoload_data(load))) { - return Qfalse; - } - if (ele->thread == Qnil) { - ele->thread = rb_thread_current(); - } - /* autoload_data_i can be deleted by another thread while require */ - RB_GC_GUARD(load); - result = rb_protect((VALUE(*)(VALUE))autoload_require, (VALUE)ele, &state); - if (ele->thread == rb_thread_current()) { - ele->thread = Qnil; - } - if (state) rb_jump_tag(state); - - if (RTEST(result)) { - /* At the last, move a value defined in autoload to constant table */ - if (ele->value != Qundef) { - int safe_backup; - struct autoload_const_set_args args; - args.mod = mod; - args.id = id; - args.value = ele->value; - safe_backup = rb_safe_level(); - rb_set_safe_level_force(ele->safe_level); - rb_ensure((VALUE(*)(VALUE))autoload_const_set, (VALUE)&args, reset_safe, (VALUE)safe_backup); - } - } - return result; + file = load->nd_lit; + return rb_require_safe(file, (int)load->nd_nth); } VALUE rb_autoload_p(VALUE mod, ID id) { - VALUE load; - struct autoload_data_i *ele; + VALUE file; + NODE *load; + const char *loading = 0; - while (!autoload_defined_p(mod, id)) { + while (!autoload_node_id(mod, id)) { mod = RCLASS_SUPER(mod); if (!mod) return Qnil; } - load = check_autoload_required(mod, id, 0); + load = autoload_node(mod, id, &loading); if (!load) return Qnil; - return (ele = check_autoload_data(load)) ? ele->feature : Qnil; + return load && (file = load->nd_lit) ? file : Qnil; } static VALUE rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility) { - VALUE value, tmp, av; + VALUE value, tmp; int mod_retry = 0; tmp = klass; @@ -1732,7 +1613,6 @@ if (value == Qundef) { if (am == tmp) break; am = tmp; - if (rb_autoloading_value(tmp, id, &av)) return av; rb_autoload_load(tmp, id); continue; } @@ -1963,7 +1843,7 @@ if (visibility && ce->flag == CONST_PRIVATE) { return (int)Qfalse; } - if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) && !rb_autoloading_value(tmp, id, 0)) + if (ce->value == Qundef && !autoload_node(tmp, id, 0)) return (int)Qfalse; return (int)Qtrue; } @@ -2042,20 +1922,8 @@ if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) { rb_const_entry_t *ce = (rb_const_entry_t*)value; - if (ce->value == Qundef) { - VALUE load; - struct autoload_data_i *ele; - - load = autoload_data(klass, id); - /* for autoloading thread, keep the defined value to autoloading storage */ - if (load && (ele = check_autoload_data(load)) && (ele->thread == rb_thread_current())) { - rb_vm_change_state(); - ele->value = val; - return; - } - /* otherwise, allow to override */ + if (ce->value == Qundef) autoload_delete(klass, id); - } else { visibility = ce->flag; rb_warn("already initialized constant %s", rb_id2name(id)); Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 33092) +++ vm_insnhelper.c (revision 33093) @@ -1178,7 +1178,7 @@ cref = cref->nd_next; if (!NIL_P(klass)) { - VALUE av, am = 0; + VALUE am = 0; st_data_t data; search_continue: if (RCLASS_CONST_TBL(klass) && @@ -1188,7 +1188,6 @@ if (am == klass) break; am = klass; if (is_defined) return 1; - if (rb_autoloading_value(klass, id, &av)) return av; rb_autoload_load(klass, id); goto search_continue; } Index: test/ruby/test_autoload.rb =================================================================== --- test/ruby/test_autoload.rb (revision 33092) +++ test/ruby/test_autoload.rb (revision 33093) @@ -1,6 +1,4 @@ require 'test/unit' -require 'tempfile' -require 'thread' require_relative 'envutil' class TestAutoload < Test::Unit::TestCase @@ -55,112 +53,4 @@ assert_equal(tmpfile, b.autoload?(:X), bug4565) } end - - def test_require_explicit - file = Tempfile.open(['autoload', '.rb']) - file.puts 'class Object; AutoloadTest = 1; end' - file.close - add_autoload(file.path) - begin - assert_nothing_raised do - assert(require file.path) - assert_equal(1, ::AutoloadTest) - end - ensure - remove_autoload_constant - end - end - - def test_threaded_accessing_constant - file = Tempfile.open(['autoload', '.rb']) - file.puts 'sleep 0.5; class AutoloadTest; X = 1; end' - file.close - add_autoload(file.path) - begin - assert_nothing_raised do - t1 = Thread.new { ::AutoloadTest::X } - t2 = Thread.new { ::AutoloadTest::X } - [t1, t2].each(&:join) - end - ensure - remove_autoload_constant - end - end - - def test_threaded_accessing_inner_constant - file = Tempfile.open(['autoload', '.rb']) - file.puts 'class AutoloadTest; sleep 0.5; X = 1; end' - file.close - add_autoload(file.path) - begin - assert_nothing_raised do - t1 = Thread.new { ::AutoloadTest::X } - t2 = Thread.new { ::AutoloadTest::X } - [t1, t2].each(&:join) - end - ensure - remove_autoload_constant - end - end - - def test_nameerror_when_autoload_did_not_define_the_constant - file = Tempfile.open(['autoload', '.rb']) - file.puts '' - file.close - add_autoload(file.path) - begin - assert_raise(NameError) do - AutoloadTest - end - ensure - remove_autoload_constant - end - end - - def test_override_autoload - file = Tempfile.open(['autoload', '.rb']) - file.puts '' - file.close - add_autoload(file.path) - begin - eval %q(class AutoloadTest; end) - assert_equal(Class, AutoloadTest.class) - ensure - remove_autoload_constant - end - end - - def test_override_while_autoloading - file = Tempfile.open(['autoload', '.rb']) - file.puts 'class AutoloadTest; sleep 0.5; end' - file.close - add_autoload(file.path) - begin - # while autoloading... - t = Thread.new { AutoloadTest } - sleep 0.1 - # override it - eval %q(AutoloadTest = 1) - t.join - assert_equal(1, AutoloadTest) - ensure - remove_autoload_constant - end - end - - def add_autoload(path) - eval <<-END - class ::Object - autoload :AutoloadTest, #{path.dump} - end - END - end - - def remove_autoload_constant - eval <<-END - class ::Object - remove_const(:AutoloadTest) - end - END - end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/