aboutsummaryrefslogtreecommitdiffstats
path: root/load.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-11-03 00:35:49 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-11-03 00:35:49 +0000
commit86ffd21c399dc1a08cdf0832394f36a49946749c (patch)
tree76b8e8b936e14af8620740030c63cc3dd53e5d65 /load.c
parent3c8072937c66f7536edfc3f18e76d969cdd62a93 (diff)
downloadruby-86ffd21c399dc1a08cdf0832394f36a49946749c.tar.gz
load.c: defer initalization of static-linked-ext
* load.c (rb_feature_p): deal with default loadable suffixes. * load.c (load_lock): initialize statically linked extensions. * load.c (search_required, rb_require_safe): deal with statically linked extensions. * load.c (ruby_init_ext): defer initalization of statically linked extensions until required actually. [Bug #8883] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43514 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'load.c')
-rw-r--r--load.c63
1 files changed, 47 insertions, 16 deletions
diff --git a/load.c b/load.c
index fbf65e38f5..141c02f33b 100644
--- a/load.c
+++ b/load.c
@@ -8,6 +8,7 @@
#include "dln.h"
#include "eval_intern.h"
#include "probes.h"
+#include "node.h"
VALUE ruby_dln_librefs;
@@ -482,6 +483,9 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
else {
VALUE bufstr;
char *buf;
+ static const char so_ext[][4] = {
+ ".so", ".o",
+ };
if (ext && *ext) return 0;
bufstr = rb_str_tmp_new(len + DLEXT_MAXLEN);
@@ -495,6 +499,14 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
return i ? 's' : 'r';
}
}
+ for (i = 0; i < numberof(so_ext); i++) {
+ strlcpy(buf + len, so_ext[i], DLEXT_MAXLEN + 1);
+ if (st_get_key(loading_tbl, (st_data_t)buf, &data)) {
+ rb_str_resize(bufstr, 0);
+ if (fn) *fn = (const char*)data;
+ return 's';
+ }
+ }
rb_str_resize(bufstr, 0);
}
}
@@ -709,6 +721,14 @@ load_lock(const char *ftptr)
st_insert(loading_tbl, (st_data_t)ftptr, data);
return (char *)ftptr;
}
+ else if (RB_TYPE_P((VALUE)data, T_NODE) && nd_type((VALUE)data) == NODE_MEMO) {
+ NODE *memo = RNODE(data);
+ void (*init)(void) = (void (*)(void))memo->nd_cfnc;
+ data = (st_data_t)rb_thread_shield_new();
+ st_insert(loading_tbl, (st_data_t)ftptr, data);
+ (*init)();
+ return (char *)"";
+ }
if (RTEST(ruby_verbose)) {
rb_warning("loading in progress, circular require considered harmful - %s", ftptr);
rb_backtrace_print_to(rb_stderr);
@@ -881,13 +901,16 @@ search_required(VALUE fname, volatile VALUE *path, int safe_level)
switch (type) {
case 0:
if (ft)
- break;
+ goto statically_linked;
ftptr = RSTRING_PTR(tmp);
return rb_feature_p(ftptr, 0, FALSE, TRUE, 0);
default:
- if (ft)
- break;
+ if (ft) {
+ statically_linked:
+ if (loading) *path = rb_filesystem_str_new_cstr(loading);
+ return ft;
+ }
case 1:
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (rb_feature_p(ftptr, ext, !--type, TRUE, &loading) && !loading)
@@ -957,6 +980,10 @@ rb_require_safe(VALUE fname, int safe)
if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
result = Qfalse;
}
+ else if (!*ftptr) {
+ rb_provide_feature(path);
+ result = Qtrue;
+ }
else {
switch (found) {
case 'r':
@@ -1005,26 +1032,30 @@ rb_require(const char *fname)
return rb_require_safe(fn, rb_safe_level());
}
-static VALUE
-init_ext_call(VALUE arg)
+static int
+register_init_ext(st_data_t *key, st_data_t *value, st_data_t init, int existing)
{
- SCOPE_SET(NOEX_PUBLIC);
- (*(void (*)(void))arg)();
- return Qnil;
+ const char *name = (char *)*key;
+ if (existing) {
+ /* already registered */
+ rb_warn("%s is already registered", name);
+ }
+ else {
+ *value = (st_data_t)NEW_MEMO(init, 0, 0);
+ *key = (st_data_t)ruby_strdup(name);
+ }
+ return ST_CONTINUE;
}
RUBY_FUNC_EXPORTED void
ruby_init_ext(const char *name, void (*init)(void))
{
- char* const lock_key = load_lock(name);
- if (lock_key) {
- VALUE feature = rb_usascii_str_new_cstr(name);
- OBJ_FREEZE(feature);
- rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init,
- 0, feature);
- rb_provide_feature(feature);
- load_unlock(lock_key, 1);
+ st_table *loading_tbl = get_loading_table();
+
+ if (!loading_tbl) {
+ GET_VM()->loading_table = loading_tbl = st_init_strtable();
}
+ st_update(loading_tbl, (st_data_t)name, register_init_ext, (st_data_t)init);
}
/*