2 * load methods from eval.c
6 #include "eval_intern.h"
8 #include "internal/dir.h"
9 #include "internal/error.h"
10 #include "internal/file.h"
11 #include "internal/hash.h"
12 #include "internal/load.h"
13 #include "internal/ruby_parser.h"
14 #include "internal/thread.h"
15 #include "internal/variable.h"
19 #include "ruby/encoding.h"
20 #include "ruby/util.h"
22 static VALUE ruby_dln_libmap
;
24 #define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
25 #define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
26 #define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
28 #if SIZEOF_VALUE <= SIZEOF_LONG
29 # define SVALUE2NUM(x) LONG2NUM((long)(x))
30 # define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LONG(x)
31 #elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
32 # define SVALUE2NUM(x) LL2NUM((LONG_LONG)(x))
33 # define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LL(x)
35 # error Need integer for VALUE
39 loadable_ext_rb
= (0+ /* .rb extension is the first in both tables */
40 1) /* offset by rb_find_file_ext() */
43 static const char *const loadable_ext
[] = {
48 static const char *const ruby_ext
[] = {
60 /* Construct expanded load path and store it to cache.
61 We rebuild load path partially if the cache is invalid.
62 We don't cache non string object and expand it every time. We ensure that
63 string objects in $LOAD_PATH are frozen.
66 rb_construct_expanded_load_path(rb_vm_t
*vm
, enum expand_type type
, int *has_relative
, int *has_non_cache
)
68 VALUE load_path
= vm
->load_path
;
69 VALUE expanded_load_path
= vm
->expanded_load_path
;
73 ary
= rb_ary_hidden_new(RARRAY_LEN(load_path
));
74 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
75 VALUE path
, as_str
, expanded_path
;
76 int is_string
, non_cache
;
78 as_str
= path
= RARRAY_AREF(load_path
, i
);
79 is_string
= RB_TYPE_P(path
, T_STRING
) ? 1 : 0;
80 non_cache
= !is_string
? 1 : 0;
81 as_str
= rb_get_path_check_to_string(path
);
82 as_cstr
= RSTRING_PTR(as_str
);
85 if ((type
== EXPAND_RELATIVE
&&
86 rb_is_absolute_path(as_cstr
)) ||
87 (type
== EXPAND_HOME
&&
88 (!as_cstr
[0] || as_cstr
[0] != '~')) ||
89 (type
== EXPAND_NON_CACHE
)) {
90 /* Use cached expanded path. */
91 rb_ary_push(ary
, RARRAY_AREF(expanded_load_path
, i
));
95 if (!*has_relative
&& !rb_is_absolute_path(as_cstr
))
97 if (!*has_non_cache
&& non_cache
)
99 /* Freeze only string object. We expand other objects every time. */
102 as_str
= rb_get_path_check_convert(as_str
);
103 expanded_path
= rb_check_realpath(Qnil
, as_str
, NULL
);
104 if (NIL_P(expanded_path
)) expanded_path
= as_str
;
105 rb_ary_push(ary
, rb_fstring(expanded_path
));
108 vm
->expanded_load_path
= ary
;
109 rb_ary_replace(vm
->load_path_snapshot
, vm
->load_path
);
113 get_expanded_load_path(rb_vm_t
*vm
)
115 const VALUE non_cache
= Qtrue
;
117 if (!rb_ary_shared_with_p(vm
->load_path_snapshot
, vm
->load_path
)) {
118 /* The load path was modified. Rebuild the expanded load path. */
119 int has_relative
= 0, has_non_cache
= 0;
120 rb_construct_expanded_load_path(vm
, EXPAND_ALL
, &has_relative
, &has_non_cache
);
122 vm
->load_path_check_cache
= rb_dir_getwd_ospath();
124 else if (has_non_cache
) {
125 /* Non string object. */
126 vm
->load_path_check_cache
= non_cache
;
129 vm
->load_path_check_cache
= 0;
132 else if (vm
->load_path_check_cache
== non_cache
) {
133 int has_relative
= 1, has_non_cache
= 1;
134 /* Expand only non-cacheable objects. */
135 rb_construct_expanded_load_path(vm
, EXPAND_NON_CACHE
,
136 &has_relative
, &has_non_cache
);
138 else if (vm
->load_path_check_cache
) {
139 int has_relative
= 1, has_non_cache
= 1;
140 VALUE cwd
= rb_dir_getwd_ospath();
141 if (!rb_str_equal(vm
->load_path_check_cache
, cwd
)) {
142 /* Current working directory or filesystem encoding was changed.
143 Expand relative load path and non-cacheable objects again. */
144 vm
->load_path_check_cache
= cwd
;
145 rb_construct_expanded_load_path(vm
, EXPAND_RELATIVE
,
146 &has_relative
, &has_non_cache
);
149 /* Expand only tilde (User HOME) and non-cacheable objects. */
150 rb_construct_expanded_load_path(vm
, EXPAND_HOME
,
151 &has_relative
, &has_non_cache
);
154 return vm
->expanded_load_path
;
158 rb_get_expanded_load_path(void)
160 return get_expanded_load_path(GET_VM());
164 load_path_getter(ID id
, VALUE
* p
)
166 rb_vm_t
*vm
= (void *)p
;
167 return vm
->load_path
;
171 get_loaded_features(rb_vm_t
*vm
)
173 return vm
->loaded_features
;
177 get_loaded_features_realpaths(rb_vm_t
*vm
)
179 return vm
->loaded_features_realpaths
;
183 get_loaded_features_realpath_map(rb_vm_t
*vm
)
185 return vm
->loaded_features_realpath_map
;
189 get_LOADED_FEATURES(ID _x
, VALUE
*_y
)
191 return get_loaded_features(GET_VM());
195 reset_loaded_features_snapshot(rb_vm_t
*vm
)
197 rb_ary_replace(vm
->loaded_features_snapshot
, vm
->loaded_features
);
200 static struct st_table
*
201 get_loaded_features_index_raw(rb_vm_t
*vm
)
203 return vm
->loaded_features_index
;
207 get_loading_table(rb_vm_t
*vm
)
209 return vm
->loading_table
;
213 feature_key(const char *str
, size_t len
)
215 return st_hash(str
, len
, 0xfea7009e);
219 is_rbext_path(VALUE feature_path
)
221 long len
= RSTRING_LEN(feature_path
);
222 long rbext_len
= rb_strlen_lit(".rb");
223 if (len
<= rbext_len
) return false;
224 return IS_RBEXT(RSTRING_PTR(feature_path
) + len
- rbext_len
);
227 typedef rb_darray(long) feature_indexes_t
;
229 struct features_index_add_single_args
{
236 features_index_add_single_callback(st_data_t
*key
, st_data_t
*value
, st_data_t raw_args
, int existing
)
238 struct features_index_add_single_args
*args
= (struct features_index_add_single_args
*)raw_args
;
239 rb_vm_t
*vm
= args
->vm
;
240 VALUE offset
= args
->offset
;
244 VALUE this_feature_index
= *value
;
246 if (FIXNUM_P(this_feature_index
)) {
247 VALUE loaded_features
= get_loaded_features(vm
);
248 VALUE this_feature_path
= RARRAY_AREF(loaded_features
, FIX2LONG(this_feature_index
));
250 feature_indexes_t feature_indexes
;
251 rb_darray_make(&feature_indexes
, 2);
252 int top
= (rb
&& !is_rbext_path(this_feature_path
)) ? 1 : 0;
253 rb_darray_set(feature_indexes
, top
^0, FIX2LONG(this_feature_index
));
254 rb_darray_set(feature_indexes
, top
^1, FIX2LONG(offset
));
256 RUBY_ASSERT(rb_darray_size(feature_indexes
) == 2);
257 // assert feature_indexes does not look like a special const
258 RUBY_ASSERT(!SPECIAL_CONST_P((VALUE
)feature_indexes
));
260 *value
= (st_data_t
)feature_indexes
;
263 feature_indexes_t feature_indexes
= (feature_indexes_t
)this_feature_index
;
267 VALUE loaded_features
= get_loaded_features(vm
);
268 for (size_t i
= 0; i
< rb_darray_size(feature_indexes
); ++i
) {
269 long idx
= rb_darray_get(feature_indexes
, i
);
270 VALUE this_feature_path
= RARRAY_AREF(loaded_features
, idx
);
271 Check_Type(this_feature_path
, T_STRING
);
272 if (!is_rbext_path(this_feature_path
)) {
279 rb_darray_append(&feature_indexes
, FIX2LONG(offset
));
280 /* darray may realloc which will change the pointer */
281 *value
= (st_data_t
)feature_indexes
;
284 long *ptr
= rb_darray_data_ptr(feature_indexes
);
285 long len
= rb_darray_size(feature_indexes
);
286 MEMMOVE(ptr
+ pos
, ptr
+ pos
+ 1, long, len
- pos
- 1);
287 ptr
[pos
] = FIX2LONG(offset
);
299 features_index_add_single(rb_vm_t
*vm
, const char* str
, size_t len
, VALUE offset
, bool rb
)
301 struct st_table
*features_index
;
302 st_data_t short_feature_key
;
304 Check_Type(offset
, T_FIXNUM
);
305 short_feature_key
= feature_key(str
, len
);
307 features_index
= get_loaded_features_index_raw(vm
);
309 struct features_index_add_single_args args
= {
315 st_update(features_index
, short_feature_key
, features_index_add_single_callback
, (st_data_t
)&args
);
318 /* Add to the loaded-features index all the required entries for
319 `feature`, located at `offset` in $LOADED_FEATURES. We add an
320 index entry at each string `short_feature` for which
321 feature == "#{prefix}#{short_feature}#{ext}"
322 where `ext` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
323 or ends in '/'. This maintains the invariant that `rb_feature_p()`
324 relies on for its fast lookup.
327 features_index_add(rb_vm_t
*vm
, VALUE feature
, VALUE offset
)
329 const char *feature_str
, *feature_end
, *ext
, *p
;
332 feature_str
= StringValuePtr(feature
);
333 feature_end
= feature_str
+ RSTRING_LEN(feature
);
335 for (ext
= feature_end
; ext
> feature_str
; ext
--)
336 if (*ext
== '.' || *ext
== '/')
342 /* Now `ext` points to the only string matching %r{^\.[^./]*$} that is
343 at the end of `feature`, or is NULL if there is no such string. */
345 p
= ext
? ext
: feature_end
;
348 while (p
>= feature_str
&& *p
!= '/')
352 /* Now *p == '/'. We reach this point for every '/' in `feature`. */
353 features_index_add_single(vm
, p
+ 1, feature_end
- p
- 1, offset
, false);
355 features_index_add_single(vm
, p
+ 1, ext
- p
- 1, offset
, rb
);
358 features_index_add_single(vm
, feature_str
, feature_end
- feature_str
, offset
, false);
360 features_index_add_single(vm
, feature_str
, ext
- feature_str
, offset
, rb
);
365 loaded_features_index_clear_i(st_data_t key
, st_data_t val
, st_data_t arg
)
367 VALUE obj
= (VALUE
)val
;
368 if (!SPECIAL_CONST_P(obj
)) {
369 rb_darray_free((void *)obj
);
375 rb_free_loaded_features_index(rb_vm_t
*vm
)
377 st_foreach(vm
->loaded_features_index
, loaded_features_index_clear_i
, 0);
378 st_free_table(vm
->loaded_features_index
);
382 get_loaded_features_index(rb_vm_t
*vm
)
387 if (!rb_ary_shared_with_p(vm
->loaded_features_snapshot
, vm
->loaded_features
)) {
388 /* The sharing was broken; something (other than us in rb_provide_feature())
389 modified loaded_features. Rebuild the index. */
390 st_foreach(vm
->loaded_features_index
, loaded_features_index_clear_i
, 0);
392 VALUE realpaths
= vm
->loaded_features_realpaths
;
393 VALUE realpath_map
= vm
->loaded_features_realpath_map
;
394 VALUE previous_realpath_map
= rb_hash_dup(realpath_map
);
395 rb_hash_clear(realpaths
);
396 rb_hash_clear(realpath_map
);
397 features
= vm
->loaded_features
;
398 for (i
= 0; i
< RARRAY_LEN(features
); i
++) {
400 as_str
= entry
= rb_ary_entry(features
, i
);
402 as_str
= rb_fstring(as_str
);
404 rb_ary_store(features
, i
, as_str
);
405 features_index_add(vm
, as_str
, INT2FIX(i
));
407 reset_loaded_features_snapshot(vm
);
409 features
= rb_ary_dup(vm
->loaded_features_snapshot
);
410 long j
= RARRAY_LEN(features
);
411 for (i
= 0; i
< j
; i
++) {
412 VALUE as_str
= rb_ary_entry(features
, i
);
413 VALUE realpath
= rb_hash_aref(previous_realpath_map
, as_str
);
414 if (NIL_P(realpath
)) {
415 realpath
= rb_check_realpath(Qnil
, as_str
, NULL
);
416 if (NIL_P(realpath
)) realpath
= as_str
;
417 realpath
= rb_fstring(realpath
);
419 rb_hash_aset(realpaths
, realpath
, Qtrue
);
420 rb_hash_aset(realpath_map
, as_str
, realpath
);
423 return vm
->loaded_features_index
;
426 /* This searches `load_path` for a value such that
427 name == "#{load_path[i]}/#{feature}"
428 if `feature` is a suffix of `name`, or otherwise
429 name == "#{load_path[i]}/#{feature}#{ext}"
430 for an acceptable string `ext`. It returns
431 `load_path[i].to_str` if found, else 0.
433 If type is 's', then `ext` is acceptable only if IS_DLEXT(ext);
434 if 'r', then only if IS_RBEXT(ext); otherwise `ext` may be absent
435 or have any value matching `%r{^\.[^./]*$}`.
438 loaded_feature_path(const char *name
, long vlen
, const char *feature
, long len
,
439 int type
, VALUE load_path
)
445 if (vlen
< len
+1) return 0;
446 if (strchr(feature
, '.') && !strncmp(name
+(vlen
-len
), feature
, len
)) {
450 for (e
= name
+ vlen
; name
!= e
&& *e
!= '.' && *e
!= '/'; --e
);
453 strncmp(e
-len
, feature
, len
))
455 plen
= e
- name
- len
;
457 if (plen
> 0 && name
[plen
-1] != '/') {
460 if (type
== 's' ? !IS_DLEXT(&name
[plen
+len
]) :
461 type
== 'r' ? !IS_RBEXT(&name
[plen
+len
]) :
465 /* Now name == "#{prefix}/#{feature}#{ext}" where ext is acceptable
466 (possibly empty) and prefix is some string of length plen. */
468 if (plen
> 0) --plen
; /* exclude '.' */
469 for (i
= 0; i
< RARRAY_LEN(load_path
); ++i
) {
470 VALUE p
= RARRAY_AREF(load_path
, i
);
471 const char *s
= StringValuePtr(p
);
472 long n
= RSTRING_LEN(p
);
474 if (n
!= plen
) continue;
475 if (n
&& strncmp(name
, s
, n
)) continue;
481 struct loaded_feature_searching
{
490 loaded_feature_path_i(st_data_t v
, st_data_t b
, st_data_t f
)
492 const char *s
= (const char *)v
;
493 struct loaded_feature_searching
*fp
= (struct loaded_feature_searching
*)f
;
494 VALUE p
= loaded_feature_path(s
, strlen(s
), fp
->name
, fp
->len
,
495 fp
->type
, fp
->load_path
);
496 if (!p
) return ST_CONTINUE
;
502 * Returns the type of already provided feature.
503 * 'r': ruby script (".rb")
504 * 's': shared object (".so"/"."DLEXT)
508 rb_feature_p(rb_vm_t
*vm
, const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
)
510 VALUE features
, this_feature_index
= Qnil
, v
, p
, load_path
= 0;
512 long i
, len
, elen
, n
;
513 st_table
*loading_tbl
, *features_index
;
521 len
= strlen(feature
) - elen
;
522 type
= rb
? 'r' : 's';
525 len
= strlen(feature
);
529 features
= get_loaded_features(vm
);
530 features_index
= get_loaded_features_index(vm
);
532 key
= feature_key(feature
, strlen(feature
));
533 /* We search `features` for an entry such that either
534 "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
536 "#{features[i]}" == "#{feature}#{e}"
537 Here `e` is an "allowed" extension -- either empty or one
538 of the extensions accepted by IS_RBEXT, IS_SOEXT, or
539 IS_DLEXT. Further, if `ext && rb` then `IS_RBEXT(e)`,
540 and if `ext && !rb` then `IS_SOEXT(e) || IS_DLEXT(e)`.
542 If `expanded`, then only the latter form (without load_path[j])
543 is accepted. Otherwise either form is accepted, *unless* `ext`
544 is false and an otherwise-matching entry of the first form is
545 preceded by an entry of the form
546 "#{features[i2]}" == "#{load_path[j2]}/#{feature}#{e2}"
547 where `e2` matches %r{^\.[^./]*$} but is not an allowed extension.
548 After a "distractor" entry of this form, only entries of the
549 form "#{feature}#{e}" are accepted.
551 In `rb_provide_feature()` and `get_loaded_features_index()` we
552 maintain an invariant that the array `this_feature_index` will
553 point to every entry in `features` which has the form
554 "#{prefix}#{feature}#{e}"
555 where `e` is empty or matches %r{^\.[^./]*$}, and `prefix` is empty
556 or ends in '/'. This includes both match forms above, as well
557 as any distractors, so we may ignore all other entries in `features`.
559 if (st_lookup(features_index
, key
, &data
) && !NIL_P(this_feature_index
= (VALUE
)data
)) {
560 for (size_t i
= 0; ; i
++) {
562 if (FIXNUM_P(this_feature_index
)) {
564 index
= FIX2LONG(this_feature_index
);
567 feature_indexes_t feature_indexes
= (feature_indexes_t
)this_feature_index
;
568 if (i
>= rb_darray_size(feature_indexes
)) break;
569 index
= rb_darray_get(feature_indexes
, i
);
572 v
= RARRAY_AREF(features
, index
);
573 f
= StringValuePtr(v
);
574 if ((n
= RSTRING_LEN(v
)) < len
) continue;
575 if (strncmp(f
, feature
, len
) != 0) {
576 if (expanded
) continue;
577 if (!load_path
) load_path
= get_expanded_load_path(vm
);
578 if (!(p
= loaded_feature_path(f
, n
, feature
, len
, type
, load_path
)))
581 f
+= RSTRING_LEN(p
) + 1;
583 if (!*(e
= f
+ len
)) {
587 if (*e
!= '.') continue;
588 if ((!rb
|| !ext
) && (IS_SOEXT(e
) || IS_DLEXT(e
))) {
591 if ((rb
|| !ext
) && (IS_RBEXT(e
))) {
597 loading_tbl
= get_loading_table(vm
);
600 struct loaded_feature_searching fs
;
604 fs
.load_path
= load_path
? load_path
: get_expanded_load_path(vm
);
606 st_foreach(loading_tbl
, loaded_feature_path_i
, (st_data_t
)&fs
);
607 if ((f
= fs
.result
) != 0) {
612 if (st_get_key(loading_tbl
, (st_data_t
)feature
, &data
)) {
613 if (fn
) *fn
= (const char*)data
;
619 static const char so_ext
[][4] = {
623 if (ext
&& *ext
) return 0;
624 bufstr
= rb_str_tmp_new(len
+ DLEXT_MAXLEN
);
625 buf
= RSTRING_PTR(bufstr
);
626 MEMCPY(buf
, feature
, char, len
);
627 for (i
= 0; (e
= loadable_ext
[i
]) != 0; i
++) {
628 strlcpy(buf
+ len
, e
, DLEXT_MAXLEN
+ 1);
629 if (st_get_key(loading_tbl
, (st_data_t
)buf
, &data
)) {
630 rb_str_resize(bufstr
, 0);
631 if (fn
) *fn
= (const char*)data
;
632 return i
? 's' : 'r';
635 for (i
= 0; i
< numberof(so_ext
); i
++) {
636 strlcpy(buf
+ len
, so_ext
[i
], DLEXT_MAXLEN
+ 1);
637 if (st_get_key(loading_tbl
, (st_data_t
)buf
, &data
)) {
638 rb_str_resize(bufstr
, 0);
639 if (fn
) *fn
= (const char*)data
;
643 rb_str_resize(bufstr
, 0);
648 if (!ext
) return 'u';
649 return !IS_RBEXT(ext
) ? 's' : 'r';
653 rb_provided(const char *feature
)
655 return rb_feature_provided(feature
, 0);
659 feature_provided(rb_vm_t
*vm
, const char *feature
, const char **loading
)
661 const char *ext
= strrchr(feature
, '.');
664 if (*feature
== '.' &&
665 (feature
[1] == '/' || strncmp(feature
+1, "./", 2) == 0)) {
666 fullpath
= rb_file_expand_path_fast(rb_get_path(rb_str_new2(feature
)), Qnil
);
667 feature
= RSTRING_PTR(fullpath
);
669 if (ext
&& !strchr(ext
, '/')) {
671 if (rb_feature_p(vm
, feature
, ext
, TRUE
, FALSE
, loading
)) return TRUE
;
674 else if (IS_SOEXT(ext
) || IS_DLEXT(ext
)) {
675 if (rb_feature_p(vm
, feature
, ext
, FALSE
, FALSE
, loading
)) return TRUE
;
679 if (rb_feature_p(vm
, feature
, 0, TRUE
, FALSE
, loading
))
681 RB_GC_GUARD(fullpath
);
686 rb_feature_provided(const char *feature
, const char **loading
)
688 return feature_provided(GET_VM(), feature
, loading
);
692 rb_provide_feature(rb_vm_t
*vm
, VALUE feature
)
696 features
= get_loaded_features(vm
);
697 if (OBJ_FROZEN(features
)) {
698 rb_raise(rb_eRuntimeError
,
699 "$LOADED_FEATURES is frozen; cannot append feature");
701 feature
= rb_fstring(feature
);
703 get_loaded_features_index(vm
);
704 // If loaded_features and loaded_features_snapshot share the same backing
705 // array, pushing into it would cause the whole array to be copied.
706 // To avoid this we first clear loaded_features_snapshot.
707 rb_ary_clear(vm
->loaded_features_snapshot
);
708 rb_ary_push(features
, feature
);
709 features_index_add(vm
, feature
, INT2FIX(RARRAY_LEN(features
)-1));
710 reset_loaded_features_snapshot(vm
);
714 rb_provide(const char *feature
)
716 rb_provide_feature(GET_VM(), rb_fstring_cstr(feature
));
719 NORETURN(static void load_failed(VALUE
));
722 realpath_internal_cached(VALUE hash
, VALUE path
)
724 VALUE ret
= rb_hash_aref(hash
, path
);
729 VALUE realpath
= rb_realpath_internal(Qnil
, path
, 1);
730 rb_hash_aset(hash
, rb_fstring(path
), rb_fstring(realpath
));
735 load_iseq_eval(rb_execution_context_t
*ec
, VALUE fname
)
737 const rb_iseq_t
*iseq
= rb_iseq_load_iseq(fname
);
740 rb_execution_context_t
*ec
= GET_EC();
741 VALUE v
= rb_vm_push_frame_fname(ec
, fname
);
743 rb_thread_t
*th
= rb_ec_thread_ptr(ec
);
744 VALUE realpath_map
= get_loaded_features_realpath_map(th
->vm
);
746 if (*rb_ruby_prism_ptr()) {
747 pm_parse_result_t result
= { 0 };
748 result
.options
.line
= 1;
750 VALUE error
= pm_load_parse_file(&result
, fname
);
753 iseq
= pm_iseq_new_top(&result
.node
, rb_fstring_lit("<top (required)>"), fname
, realpath_internal_cached(realpath_map
, fname
), NULL
);
754 pm_parse_result_free(&result
);
759 pm_parse_result_free(&result
);
766 VALUE parser
= rb_parser_new();
767 rb_parser_set_context(parser
, NULL
, FALSE
);
768 ast_value
= rb_parser_load_file(parser
, fname
);
769 ast
= rb_ruby_ast_data_get(ast_value
);
771 iseq
= rb_iseq_new_top(ast_value
, rb_fstring_lit("<top (required)>"),
772 fname
, realpath_internal_cached(realpath_map
, fname
), NULL
);
779 rb_exec_event_hook_script_compiled(ec
, iseq
, Qnil
);
783 static inline enum ruby_tag_type
784 load_wrapping(rb_execution_context_t
*ec
, VALUE fname
, VALUE load_wrapper
)
786 enum ruby_tag_type state
;
787 rb_thread_t
*th
= rb_ec_thread_ptr(ec
);
788 volatile VALUE wrapper
= th
->top_wrapper
;
789 volatile VALUE self
= th
->top_self
;
790 #if !defined __GNUC__
791 rb_thread_t
*volatile th0
= th
;
794 ec
->errinfo
= Qnil
; /* ensure */
796 /* load in module as toplevel */
797 th
->top_self
= rb_obj_clone(rb_vm_top_self());
798 th
->top_wrapper
= load_wrapper
;
799 rb_extend_object(th
->top_self
, th
->top_wrapper
);
802 state
= EC_EXEC_TAG();
803 if (state
== TAG_NONE
) {
804 load_iseq_eval(ec
, fname
);
808 #if !defined __GNUC__
810 fname
= RB_GC_GUARD(fname
);
813 th
->top_wrapper
= wrapper
;
818 raise_load_if_failed(rb_execution_context_t
*ec
, enum ruby_tag_type state
)
821 rb_vm_jump_tag_but_local_jump(state
);
824 if (!NIL_P(ec
->errinfo
)) {
825 rb_exc_raise(ec
->errinfo
);
830 rb_load_internal(VALUE fname
, VALUE wrap
)
832 rb_execution_context_t
*ec
= GET_EC();
833 enum ruby_tag_type state
= TAG_NONE
;
835 if (!RB_TYPE_P(wrap
, T_MODULE
)) {
836 wrap
= rb_module_new();
838 state
= load_wrapping(ec
, fname
, wrap
);
841 load_iseq_eval(ec
, fname
);
843 raise_load_if_failed(ec
, state
);
847 rb_load(VALUE fname
, int wrap
)
849 VALUE tmp
= rb_find_file(FilePathValue(fname
));
850 if (!tmp
) load_failed(fname
);
851 rb_load_internal(tmp
, RBOOL(wrap
));
855 rb_load_protect(VALUE fname
, int wrap
, int *pstate
)
857 enum ruby_tag_type state
;
859 EC_PUSH_TAG(GET_EC());
860 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
861 rb_load(fname
, wrap
);
865 if (state
!= TAG_NONE
) *pstate
= state
;
870 * load(filename, wrap=false) -> true
872 * Loads and executes the Ruby program in the file _filename_.
874 * If the filename is an absolute path (e.g. starts with '/'), the file
875 * will be loaded directly using the absolute path.
877 * If the filename is an explicit relative path (e.g. starts with './' or
878 * '../'), the file will be loaded using the relative path from the current
881 * Otherwise, the file will be searched for in the library
882 * directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
883 * If the file is found in a directory, it will attempt to load the file
884 * relative to that directory. If the file is not found in any of the
885 * directories in <code>$LOAD_PATH</code>, the file will be loaded using
886 * the relative path from the current directory.
888 * If the file doesn't exist when there is an attempt to load it, a
889 * LoadError will be raised.
891 * If the optional _wrap_ parameter is +true+, the loaded script will
892 * be executed under an anonymous module. If the optional _wrap_ parameter
893 * is a module, the loaded script will be executed under the given module.
894 * In no circumstance will any local variables in the loaded file be
895 * propagated to the loading environment.
899 rb_f_load(int argc
, VALUE
*argv
, VALUE _
)
901 VALUE fname
, wrap
, path
, orig_fname
;
903 rb_scan_args(argc
, argv
, "11", &fname
, &wrap
);
905 orig_fname
= rb_get_path_check_to_string(fname
);
906 fname
= rb_str_encode_ospath(orig_fname
);
907 RUBY_DTRACE_HOOK(LOAD_ENTRY
, RSTRING_PTR(orig_fname
));
909 path
= rb_find_file(fname
);
911 if (!rb_file_load_ok(RSTRING_PTR(fname
)))
912 load_failed(orig_fname
);
915 rb_load_internal(path
, wrap
);
917 RUBY_DTRACE_HOOK(LOAD_RETURN
, RSTRING_PTR(orig_fname
));
923 load_lock(rb_vm_t
*vm
, const char *ftptr
, bool warn
)
926 st_table
*loading_tbl
= get_loading_table(vm
);
928 if (!st_lookup(loading_tbl
, (st_data_t
)ftptr
, &data
)) {
930 ftptr
= ruby_strdup(ftptr
);
931 data
= (st_data_t
)rb_thread_shield_new();
932 st_insert(loading_tbl
, (st_data_t
)ftptr
, data
);
933 return (char *)ftptr
;
936 if (warn
&& rb_thread_shield_owned((VALUE
)data
)) {
937 VALUE warning
= rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr
);
938 rb_backtrace_each(rb_str_append
, warning
);
939 rb_warning("%"PRIsVALUE
, warning
);
941 switch (rb_thread_shield_wait((VALUE
)data
)) {
946 return (char *)ftptr
;
950 release_thread_shield(st_data_t
*key
, st_data_t
*value
, st_data_t done
, int existing
)
952 VALUE thread_shield
= (VALUE
)*value
;
953 if (!existing
) return ST_STOP
;
955 rb_thread_shield_destroy(thread_shield
);
956 /* Delete the entry even if there are waiting threads, because they
957 * won't load the file and won't delete the entry. */
959 else if (rb_thread_shield_release(thread_shield
)) {
968 load_unlock(rb_vm_t
*vm
, const char *ftptr
, int done
)
971 st_data_t key
= (st_data_t
)ftptr
;
972 st_table
*loading_tbl
= get_loading_table(vm
);
974 st_update(loading_tbl
, key
, release_thread_shield
, done
);
978 static VALUE
rb_require_string_internal(VALUE fname
, bool resurrect
);
982 * require(name) -> true or false
984 * Loads the given +name+, returning +true+ if successful and +false+ if the
985 * feature is already loaded.
987 * If the filename neither resolves to an absolute path nor starts with
988 * './' or '../', the file will be searched for in the library
989 * directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
990 * If the filename starts with './' or '../', resolution is based on Dir.pwd.
992 * If the filename has the extension ".rb", it is loaded as a source file; if
993 * the extension is ".so", ".o", or the default shared library extension on
994 * the current platform, Ruby loads the shared library as a Ruby extension.
995 * Otherwise, Ruby tries adding ".rb", ".so", and so on to the name until
996 * found. If the file named cannot be found, a LoadError will be raised.
998 * For Ruby extensions the filename given may use ".so" or ".o". For example,
999 * on macOS the socket extension is "socket.bundle" and
1000 * <code>require 'socket.so'</code> will load the socket extension.
1002 * The absolute path of the loaded file is added to
1003 * <code>$LOADED_FEATURES</code> (<code>$"</code>). A file will not be
1004 * loaded again if its path already appears in <code>$"</code>. For example,
1005 * <code>require 'a'; require './a'</code> will not load <code>a.rb</code>
1008 * require "my-library.rb"
1009 * require "db-driver"
1011 * Any constants or globals within the loaded source file will be available
1012 * in the calling program's global namespace. However, local variables will
1013 * not be propagated to the loading environment.
1018 rb_f_require(VALUE obj
, VALUE fname
)
1020 return rb_require_string(fname
);
1025 * require_relative(string) -> true or false
1027 * Ruby tries to load the library named _string_ relative to the directory
1028 * containing the requiring file. If the file does not exist a LoadError is
1029 * raised. Returns +true+ if the file was loaded and +false+ if the file was
1030 * already loaded before.
1033 rb_f_require_relative(VALUE obj
, VALUE fname
)
1035 VALUE base
= rb_current_realfilepath();
1037 rb_loaderror("cannot infer basepath");
1039 base
= rb_file_dirname(base
);
1040 return rb_require_string_internal(rb_file_absolute_path(fname
, base
), false);
1043 typedef int (*feature_func
)(rb_vm_t
*vm
, const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
);
1046 search_required(rb_vm_t
*vm
, VALUE fname
, volatile VALUE
*path
, feature_func rb_feature_p
)
1051 const char *loading
;
1054 ext
= strrchr(ftptr
= RSTRING_PTR(fname
), '.');
1055 if (ext
&& !strchr(ext
, '/')) {
1056 if (IS_RBEXT(ext
)) {
1057 if (rb_feature_p(vm
, ftptr
, ext
, TRUE
, FALSE
, &loading
)) {
1058 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
1061 if ((tmp
= rb_find_file(fname
)) != 0) {
1062 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
1063 if (!rb_feature_p(vm
, ftptr
, ext
, TRUE
, TRUE
, &loading
) || loading
)
1069 else if (IS_SOEXT(ext
)) {
1070 if (rb_feature_p(vm
, ftptr
, ext
, FALSE
, FALSE
, &loading
)) {
1071 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
1074 tmp
= rb_str_subseq(fname
, 0, ext
- RSTRING_PTR(fname
));
1075 rb_str_cat2(tmp
, DLEXT
);
1077 if ((tmp
= rb_find_file(tmp
)) != 0) {
1078 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
1079 if (!rb_feature_p(vm
, ftptr
, ext
, FALSE
, TRUE
, &loading
) || loading
)
1084 else if (IS_DLEXT(ext
)) {
1085 if (rb_feature_p(vm
, ftptr
, ext
, FALSE
, FALSE
, &loading
)) {
1086 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
1089 if ((tmp
= rb_find_file(fname
)) != 0) {
1090 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
1091 if (!rb_feature_p(vm
, ftptr
, ext
, FALSE
, TRUE
, &loading
) || loading
)
1097 else if ((ft
= rb_feature_p(vm
, ftptr
, 0, FALSE
, FALSE
, &loading
)) == 'r') {
1098 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
1102 const unsigned int type
= rb_find_file_ext(&tmp
, ft
== 's' ? ruby_ext
: loadable_ext
);
1104 // Check if it's a statically linked extension when
1105 // not already a feature and not found as a dynamic library.
1106 if (!ft
&& type
!= loadable_ext_rb
&& vm
->static_ext_inits
) {
1107 VALUE lookup_name
= tmp
;
1108 // Append ".so" if not already present so for example "etc" can find "etc.so".
1109 // We always register statically linked extensions with a ".so" extension.
1110 // See encinit.c and extinit.c (generated at build-time).
1112 lookup_name
= rb_str_dup(lookup_name
);
1113 rb_str_cat_cstr(lookup_name
, ".so");
1115 ftptr
= RSTRING_PTR(lookup_name
);
1116 if (st_lookup(vm
->static_ext_inits
, (st_data_t
)ftptr
, NULL
)) {
1117 *path
= rb_filesystem_str_new_cstr(ftptr
);
1125 goto feature_present
;
1126 ftptr
= RSTRING_PTR(tmp
);
1127 return rb_feature_p(vm
, ftptr
, 0, FALSE
, TRUE
, 0);
1131 goto feature_present
;
1134 case loadable_ext_rb
:
1135 ext
= strrchr(ftptr
= RSTRING_PTR(tmp
), '.');
1136 if (rb_feature_p(vm
, ftptr
, ext
, type
== loadable_ext_rb
, TRUE
, &loading
) && !loading
)
1140 return type
> loadable_ext_rb
? 's' : 'r';
1143 if (loading
) *path
= rb_filesystem_str_new_cstr(loading
);
1148 load_failed(VALUE fname
)
1150 rb_load_fail(fname
, "cannot load such file");
1154 load_ext(VALUE path
)
1156 rb_scope_visibility_set(METHOD_VISI_PUBLIC
);
1157 return (VALUE
)dln_load(RSTRING_PTR(path
));
1161 run_static_ext_init(rb_vm_t
*vm
, const char *feature
)
1163 st_data_t key
= (st_data_t
)feature
;
1164 st_data_t init_func
;
1166 if (vm
->static_ext_inits
&& st_delete(vm
->static_ext_inits
, &key
, &init_func
)) {
1167 ((void (*)(void))init_func
)();
1174 no_feature_p(rb_vm_t
*vm
, const char *feature
, const char *ext
, int rb
, int expanded
, const char **fn
)
1179 // Documented in doc/globals.rdoc
1181 rb_resolve_feature_path(VALUE klass
, VALUE fname
)
1187 fname
= rb_get_path(fname
);
1188 path
= rb_str_encode_ospath(fname
);
1189 found
= search_required(GET_VM(), path
, &path
, no_feature_p
);
1193 sym
= ID2SYM(rb_intern("rb"));
1196 sym
= ID2SYM(rb_intern("so"));
1202 return rb_ary_new_from_args(2, sym
, path
);
1206 ext_config_push(rb_thread_t
*th
, struct rb_ext_config
*prev
)
1208 *prev
= th
->ext_config
;
1209 th
->ext_config
= (struct rb_ext_config
){0};
1213 ext_config_pop(rb_thread_t
*th
, struct rb_ext_config
*prev
)
1215 th
->ext_config
= *prev
;
1219 rb_ext_ractor_safe(bool flag
)
1221 GET_THREAD()->ext_config
.ractor_safe
= flag
;
1226 * 0: if already loaded (false)
1227 * 1: successfully loaded (true)
1228 * <0: not found (LoadError)
1232 require_internal(rb_execution_context_t
*ec
, VALUE fname
, int exception
, bool warn
)
1234 volatile int result
= -1;
1235 rb_thread_t
*th
= rb_ec_thread_ptr(ec
);
1236 volatile const struct {
1237 VALUE wrapper
, self
, errinfo
;
1238 rb_execution_context_t
*ec
;
1240 th
->top_wrapper
, th
->top_self
, ec
->errinfo
,
1243 enum ruby_tag_type state
;
1244 char *volatile ftptr
= 0;
1246 volatile VALUE saved_path
;
1247 volatile VALUE realpath
= 0;
1248 VALUE realpaths
= get_loaded_features_realpaths(th
->vm
);
1249 VALUE realpath_map
= get_loaded_features_realpath_map(th
->vm
);
1250 volatile bool reset_ext_config
= false;
1251 struct rb_ext_config prev_ext_config
;
1253 path
= rb_str_encode_ospath(fname
);
1254 RUBY_DTRACE_HOOK(REQUIRE_ENTRY
, RSTRING_PTR(fname
));
1258 ec
->errinfo
= Qnil
; /* ensure */
1259 th
->top_wrapper
= 0;
1260 if ((state
= EC_EXEC_TAG()) == TAG_NONE
) {
1264 RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY
, RSTRING_PTR(fname
));
1265 found
= search_required(th
->vm
, path
, &saved_path
, rb_feature_p
);
1266 RUBY_DTRACE_HOOK(FIND_REQUIRE_RETURN
, RSTRING_PTR(fname
));
1270 if (!path
|| !(ftptr
= load_lock(th
->vm
, RSTRING_PTR(path
), warn
))) {
1274 result
= TAG_RETURN
;
1276 else if (found
== 's' && run_static_ext_init(th
->vm
, RSTRING_PTR(path
))) {
1277 result
= TAG_RETURN
;
1279 else if (RTEST(rb_hash_aref(realpaths
,
1280 realpath
= realpath_internal_cached(realpath_map
, path
)))) {
1286 load_iseq_eval(ec
, path
);
1290 reset_ext_config
= true;
1291 ext_config_push(th
, &prev_ext_config
);
1292 handle
= rb_vm_call_cfunc(rb_vm_top_self(), load_ext
,
1293 path
, VM_BLOCK_HANDLER_NONE
, path
);
1294 rb_hash_aset(ruby_dln_libmap
, path
, SVALUE2NUM((SIGNED_VALUE
)handle
));
1297 result
= TAG_RETURN
;
1304 rb_thread_t
*th2
= rb_ec_thread_ptr(ec
);
1305 th2
->top_self
= saved
.self
;
1306 th2
->top_wrapper
= saved
.wrapper
;
1307 if (reset_ext_config
) ext_config_pop(th2
, &prev_ext_config
);
1310 if (ftptr
) load_unlock(th2
->vm
, RSTRING_PTR(path
), !state
);
1313 if (state
== TAG_FATAL
|| state
== TAG_THROW
) {
1314 EC_JUMP_TAG(ec
, state
);
1316 else if (exception
) {
1317 /* usually state == TAG_RAISE only, except for
1318 * rb_iseq_load_iseq in load_iseq_eval case */
1319 VALUE exc
= rb_vm_make_jump_tag_but_local_jump(state
, Qundef
);
1320 if (!NIL_P(exc
)) ec
->errinfo
= exc
;
1323 else if (state
== TAG_RETURN
) {
1327 /* never TAG_RETURN */
1330 if (!NIL_P(ec
->errinfo
)) {
1331 if (!exception
) return TAG_RAISE
;
1332 rb_exc_raise(ec
->errinfo
);
1335 if (result
== TAG_RETURN
) {
1336 rb_provide_feature(th2
->vm
, path
);
1337 VALUE real
= realpath
;
1339 real
= rb_fstring(real
);
1340 rb_hash_aset(realpaths
, real
, Qtrue
);
1343 ec
->errinfo
= saved
.errinfo
;
1345 RUBY_DTRACE_HOOK(REQUIRE_RETURN
, RSTRING_PTR(fname
));
1351 rb_require_internal_silent(VALUE fname
)
1353 rb_execution_context_t
*ec
= GET_EC();
1354 return require_internal(ec
, fname
, 1, false);
1358 rb_require_internal(VALUE fname
)
1360 rb_execution_context_t
*ec
= GET_EC();
1361 return require_internal(ec
, fname
, 1, RTEST(ruby_verbose
));
1365 ruby_require_internal(const char *fname
, unsigned int len
)
1367 struct RString fake
;
1368 VALUE str
= rb_setup_fake_str(&fake
, fname
, len
, 0);
1369 rb_execution_context_t
*ec
= GET_EC();
1370 int result
= require_internal(ec
, str
, 0, RTEST(ruby_verbose
));
1371 rb_set_errinfo(Qnil
);
1372 return result
== TAG_RETURN
? 1 : result
? -1 : 0;
1376 rb_require_string(VALUE fname
)
1378 return rb_require_string_internal(FilePathValue(fname
), false);
1382 rb_require_string_internal(VALUE fname
, bool resurrect
)
1384 rb_execution_context_t
*ec
= GET_EC();
1385 int result
= require_internal(ec
, fname
, 1, RTEST(ruby_verbose
));
1387 if (result
> TAG_RETURN
) {
1388 EC_JUMP_TAG(ec
, result
);
1391 if (resurrect
) fname
= rb_str_resurrect(fname
);
1395 return RBOOL(result
);
1399 rb_require(const char *fname
)
1401 struct RString fake
;
1402 VALUE str
= rb_setup_fake_str(&fake
, fname
, strlen(fname
), 0);
1403 return rb_require_string_internal(str
, true);
1407 register_init_ext(st_data_t
*key
, st_data_t
*value
, st_data_t init
, int existing
)
1409 const char *name
= (char *)*key
;
1411 /* already registered */
1412 rb_warn("%s is already registered", name
);
1415 *value
= (st_data_t
)init
;
1420 // Private API for statically linked extensions.
1421 // Used with the ext/Setup file, the --with-setup and
1422 // --with-static-linked-ext configuration option, etc.
1424 ruby_init_ext(const char *name
, void (*init
)(void))
1426 st_table
*inits_table
;
1427 rb_vm_t
*vm
= GET_VM();
1429 if (feature_provided(vm
, name
, 0))
1432 inits_table
= vm
->static_ext_inits
;
1434 inits_table
= st_init_strtable();
1435 vm
->static_ext_inits
= inits_table
;
1437 st_update(inits_table
, (st_data_t
)name
, register_init_ext
, (st_data_t
)init
);
1442 * mod.autoload(const, filename) -> nil
1444 * Registers _filename_ to be loaded (using Kernel::require)
1445 * the first time that _const_ (which may be a String or
1446 * a symbol) is accessed in the namespace of _mod_.
1450 * A.autoload(:B, "b")
1451 * A::B.doit # autoloads "b"
1453 * If _const_ in _mod_ is defined as autoload, the file name to be
1454 * loaded is replaced with _filename_. If _const_ is defined but not
1455 * as autoload, does nothing.
1459 rb_mod_autoload(VALUE mod
, VALUE sym
, VALUE file
)
1461 ID id
= rb_to_id(sym
);
1463 FilePathValue(file
);
1464 rb_autoload_str(mod
, id
, file
);
1470 * mod.autoload?(name, inherit=true) -> String or nil
1472 * Returns _filename_ to be loaded if _name_ is registered as
1473 * +autoload+ in the namespace of _mod_ or one of its ancestors.
1477 * A.autoload(:B, "b")
1478 * A.autoload?(:B) #=> "b"
1480 * If +inherit+ is false, the lookup only checks the autoloads in the receiver:
1483 * autoload :CONST, "const.rb"
1489 * B.autoload?(:CONST) #=> "const.rb", found in A (ancestor)
1490 * B.autoload?(:CONST, false) #=> nil, not found in B itself
1495 rb_mod_autoload_p(int argc
, VALUE
*argv
, VALUE mod
)
1497 int recur
= (rb_check_arity(argc
, 1, 2) == 1) ? TRUE
: RTEST(argv
[1]);
1498 VALUE sym
= argv
[0];
1500 ID id
= rb_check_id(&sym
);
1504 return rb_autoload_at_p(mod
, id
, recur
);
1509 * autoload(const, filename) -> nil
1511 * Registers _filename_ to be loaded (using Kernel::require)
1512 * the first time that _const_ (which may be a String or
1513 * a symbol) is accessed.
1515 * autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
1517 * If _const_ is defined as autoload, the file name to be loaded is
1518 * replaced with _filename_. If _const_ is defined but not as
1519 * autoload, does nothing.
1523 rb_f_autoload(VALUE obj
, VALUE sym
, VALUE file
)
1525 VALUE klass
= rb_class_real(rb_vm_cbase());
1527 rb_raise(rb_eTypeError
, "Can not set autoload on singleton class");
1529 return rb_mod_autoload(klass
, sym
, file
);
1534 * autoload?(name, inherit=true) -> String or nil
1536 * Returns _filename_ to be loaded if _name_ is registered as
1537 * +autoload+ in the current namespace or one of its ancestors.
1540 * autoload?(:B) #=> "b"
1544 * autoload?(:D) #=> "d"
1545 * autoload?(:B) #=> nil
1550 * autoload?(:F) #=> "f"
1551 * autoload?(:B) #=> "b"
1556 rb_f_autoload_p(int argc
, VALUE
*argv
, VALUE obj
)
1558 /* use rb_vm_cbase() as same as rb_f_autoload. */
1559 VALUE klass
= rb_vm_cbase();
1563 return rb_mod_autoload_p(argc
, argv
, klass
);
1567 rb_ext_resolve_symbol(const char* fname
, const char* symbol
)
1573 VALUE fname_str
= rb_str_new_cstr(fname
);
1575 resolved
= rb_resolve_feature_path((VALUE
)NULL
, fname_str
);
1576 if (NIL_P(resolved
)) {
1577 ext
= strrchr(fname
, '.');
1578 if (!ext
|| !IS_SOEXT(ext
)) {
1579 rb_str_cat_cstr(fname_str
, ".so");
1581 if (rb_feature_p(GET_VM(), fname
, 0, FALSE
, FALSE
, 0)) {
1582 return dln_symbol(NULL
, symbol
);
1586 if (RARRAY_LEN(resolved
) != 2 || rb_ary_entry(resolved
, 0) != ID2SYM(rb_intern("so"))) {
1589 path
= rb_ary_entry(resolved
, 1);
1590 handle
= rb_hash_lookup(ruby_dln_libmap
, path
);
1591 if (NIL_P(handle
)) {
1594 return dln_symbol((void *)NUM2SVALUE(handle
), symbol
);
1600 rb_vm_t
*vm
= GET_VM();
1601 static const char var_load_path
[] = "$:";
1602 ID id_load_path
= rb_intern2(var_load_path
, sizeof(var_load_path
)-1);
1604 rb_define_hooked_variable(var_load_path
, (VALUE
*)vm
, load_path_getter
, rb_gvar_readonly_setter
);
1605 rb_alias_variable(rb_intern_const("$-I"), id_load_path
);
1606 rb_alias_variable(rb_intern_const("$LOAD_PATH"), id_load_path
);
1607 vm
->load_path
= rb_ary_new();
1608 vm
->expanded_load_path
= rb_ary_hidden_new(0);
1609 vm
->load_path_snapshot
= rb_ary_hidden_new(0);
1610 vm
->load_path_check_cache
= 0;
1611 rb_define_singleton_method(vm
->load_path
, "resolve_feature_path", rb_resolve_feature_path
, 1);
1613 rb_define_virtual_variable("$\"", get_LOADED_FEATURES
, 0);
1614 rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES
, 0);
1615 vm
->loaded_features
= rb_ary_new();
1616 vm
->loaded_features_snapshot
= rb_ary_hidden_new(0);
1617 vm
->loaded_features_index
= st_init_numtable();
1618 vm
->loaded_features_realpaths
= rb_hash_new();
1619 rb_obj_hide(vm
->loaded_features_realpaths
);
1620 vm
->loaded_features_realpath_map
= rb_hash_new();
1621 rb_obj_hide(vm
->loaded_features_realpath_map
);
1623 rb_define_global_function("load", rb_f_load
, -1);
1624 rb_define_global_function("require", rb_f_require
, 1);
1625 rb_define_global_function("require_relative", rb_f_require_relative
, 1);
1626 rb_define_method(rb_cModule
, "autoload", rb_mod_autoload
, 2);
1627 rb_define_method(rb_cModule
, "autoload?", rb_mod_autoload_p
, -1);
1628 rb_define_global_function("autoload", rb_f_autoload
, 2);
1629 rb_define_global_function("autoload?", rb_f_autoload_p
, -1);
1631 ruby_dln_libmap
= rb_hash_new_with_size(0);
1632 rb_vm_register_global_object(ruby_dln_libmap
);