aboutsummaryrefslogtreecommitdiffstats
path: root/variable.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-06 12:28:09 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-12-06 12:28:09 +0000
commit7f17ce149a1b1840021c553c5cc24d65ea333e12 (patch)
tree15ff527ef2510581d4f8f2129e6adee597c65453 /variable.c
parent75632170414b1aa033593e490e5d55a9faed4316 (diff)
downloadruby-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
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c24
1 files changed, 18 insertions, 6 deletions
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;