diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-12-06 12:28:09 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-12-06 12:28:09 +0000 |
commit | 7f17ce149a1b1840021c553c5cc24d65ea333e12 (patch) | |
tree | 15ff527ef2510581d4f8f2129e6adee597c65453 | |
parent | 75632170414b1aa033593e490e5d55a9faed4316 (diff) | |
download | ruby-7f17ce149a1b1840021c553c5cc24d65ea333e12.tar.gz |
introduce rb_autoload_str to replace rb_autoload
rb_autoload_str may be safer by preventing premature GC. It
can also be more efficient by passing a pre-frozen string that
can be deduped using rb_fstring. Common autoload callers (e.g.
rubygems, rdoc) already use string literals as the file
argument.
There seems to be no reason to expose rb_autoload_str to the
public C API since autoload is not performance-critical.
Applications may declare autoloads in Ruby code or via
rb_funcall; so merely deprecate rb_autoload without exposing
rb_autoload_str to new users.
Running: valgrind -v ruby -rrdoc -rubygems -e exit
shows a minor memory reduction (32-bit userspace)
before:
in use at exit: 1,600,621 bytes in 28,819 blocks
total heap usage: 55,786 allocs, 26,967 frees, 6,693,790 bytes allocated
after:
in use at exit: 1,599,778 bytes in 28,789 blocks
total heap usage: 55,739 allocs, 26,950 frees, 6,692,973 bytes allocated
* include/ruby/intern.h (rb_autoload): deprecate
* internal.h (rb_autoload_str): declare
* load.c (rb_mod_autoload): use rb_autoload_str
* variable.c (rb_autoload): become compatibility wrapper
(rb_autoload_str): hoisted out from old rb_autoload
[ruby-core:71369] [Feature #11664]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52909 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | include/ruby/intern.h | 2 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | load.c | 2 | ||||
-rw-r--r-- | variable.c | 24 |
6 files changed, 32 insertions, 8 deletions
@@ -1,3 +1,12 @@ +Sun Dec 6 19:52:31 2015 Eric Wong <e@80x24.org> + + * include/ruby/intern.h (rb_autoload): deprecate + * internal.h (rb_autoload_str): declare + * load.c (rb_mod_autoload): use rb_autoload_str + * variable.c (rb_autoload): become compatibility wrapper + (rb_autoload_str): hoisted out from old rb_autoload + [ruby-core:71369] [Feature #11664] + Sun Dec 6 19:02:55 2015 Kazuhiro NISHIYAMA <zn@mbf.nifty.com> * configure.in: add missing x. @@ -241,6 +241,8 @@ with all sufficient information, see the ChangeLog file. * rb_time_timespec_new() is added to create a time object with epoch, nanosecond, and UTC/localtime/time offset arguments. [Feature #11558] +* rb_autoload() deprecated, use rb_funcall() instead. [Feature #11664] + === Build system updates === Implementation changes diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 3fb1637593..d43dc67780 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -937,7 +937,7 @@ VALUE rb_path_to_class(VALUE); VALUE rb_path2class(const char*); void rb_name_class(VALUE, ID); VALUE rb_class_name(VALUE); -void rb_autoload(VALUE, ID, const char*); +DEPRECATED(void rb_autoload(VALUE, ID, const char*)); VALUE rb_autoload_load(VALUE, ID); VALUE rb_autoload_p(VALUE, ID); VALUE rb_f_trace_var(int, const VALUE*); diff --git a/internal.h b/internal.h index 1018d0bd30..df594c171f 100644 --- a/internal.h +++ b/internal.h @@ -1205,6 +1205,7 @@ size_t rb_generic_ivar_memsize(VALUE); VALUE rb_search_class_path(VALUE); VALUE rb_attr_delete(VALUE, ID); VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef); +void rb_autoload_str(VALUE mod, ID id, VALUE file); /* version.c */ extern const char ruby_engine[]; @@ -1099,7 +1099,7 @@ rb_mod_autoload(VALUE mod, VALUE sym, VALUE file) ID id = rb_to_id(sym); FilePathValue(file); - rb_autoload(mod, id, RSTRING_PTR(file)); + rb_autoload_str(mod, id, file); return Qnil; } diff --git a/variable.c b/variable.c index 18a70a0c8d..f6dd3ee47d 100644 --- a/variable.c +++ b/variable.c @@ -1916,8 +1916,17 @@ static const rb_data_type_t autoload_data_i_type = { void rb_autoload(VALUE mod, ID id, const char *file) { + if (!file || !*file) { + rb_raise(rb_eArgError, "empty file name"); + } + rb_autoload_str(mod, id, rb_fstring_cstr(file)); +} + +void +rb_autoload_str(VALUE mod, ID id, VALUE file) +{ st_data_t av; - VALUE ad, fn; + VALUE ad; struct st_table *tbl; struct autoload_data_i *ele; rb_const_entry_t *ce; @@ -1926,7 +1935,9 @@ rb_autoload(VALUE mod, ID id, const char *file) rb_raise(rb_eNameError, "autoload must be constant name: %"PRIsVALUE"", QUOTE_ID(id)); } - if (!file || !*file) { + + Check_Type(file, T_STRING); + if (!RSTRING_LEN(file)) { rb_raise(rb_eArgError, "empty file name"); } @@ -1947,12 +1958,13 @@ rb_autoload(VALUE mod, ID id, const char *file) RB_OBJ_WRITTEN(mod, Qnil, av); DATA_PTR(av) = tbl = st_init_numtable(); } - fn = rb_str_new2(file); - FL_UNSET(fn, FL_TAINT); - OBJ_FREEZE(fn); ad = TypedData_Make_Struct(0, struct autoload_data_i, &autoload_data_i_type, ele); - ele->feature = fn; + if (OBJ_TAINTED(file)) { + file = rb_str_dup(file); + FL_UNSET(file, FL_TAINT); + } + ele->feature = rb_fstring(file); ele->safe_level = rb_safe_level(); ele->value = Qundef; ele->state = 0; |