Ruby 4.1.0dev (2026-08-19 revision 39d4744b681360fb16407b521beaa9d870befe9d)
builtin.c (39d4744b681360fb16407b521beaa9d870befe9d)
1#include "internal.h"
2#include "internal/box.h"
3#include "internal/string.h"
4#include "internal/variable.h"
5#include "vm_core.h"
6#include "iseq.h"
7#include "builtin.h"
8
9#include "builtin_binary.rbbin"
10
11#ifndef BUILTIN_BINARY_SIZE
12
13#define BUILTIN_LOADED(feature_name, iseq) ((void)0)
14#include "mini_builtin.c"
15
16#else
17
18static const unsigned char *
19bin4feature(const struct builtin_binary *bb, const char *feature, size_t *psize)
20{
21 *psize = bb->bin_size;
22 return strcmp(bb->feature, feature) ? NULL : bb->bin;
23}
24
25static const unsigned char*
26builtin_lookup(const char *feature, size_t *psize)
27{
28 static size_t index = 0;
29 const unsigned char *bin = NULL;
30
31 /*
32 * Fast path:
33 * builtin_binary is usually arranged in the same order
34 * as features are looked up in miniruby, so try the next entry first.
35 */
36 if (builtin_binary[index].feature) {
37 bin = bin4feature(&builtin_binary[index], feature, psize);
38 index++;
39 }
40 if (bin) {
41 return bin;
42 }
43
44 /*
45 * Fallback:
46 * In case the lookup order does not match the array order,
47 * scan the entire table to find the feature.
48 */
49 for (const struct builtin_binary *bb = &builtin_binary[0];
50 bb->feature;
51 bb++) {
52 bin = bin4feature(bb, feature, psize);
53 if (bin) {
54 break;
55 }
56 }
57
58 return bin;
59}
60
61static void
62load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table, const rb_box_t *target_box)
63{
64 // search binary
65 size_t size;
66 const unsigned char *bin = builtin_lookup(feature_name, &size);
67 if (! bin) {
68 rb_bug("builtin_lookup: can not find %s", feature_name);
69 }
70
71 // load binary
72 rb_vm_t *vm = GET_VM();
73 if (vm->builtin_function_table != NULL) rb_bug("vm->builtin_function_table should be NULL.");
74 vm->builtin_function_table = table;
75 const rb_iseq_t *iseq = rb_iseq_ibf_load_bytes((const char *)bin, size);
76 ASSUME(iseq); // otherwise an exception should have raised
77 vm->builtin_function_table = NULL;
78
79 // exec
80 rb_iseq_eval(rb_iseq_check(iseq), target_box);
81}
82
83void
84rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table)
85{
86 load_with_builtin_functions(feature_name, table, rb_root_box());
87}
88
90rb_define_gem_modules(VALUE flags_value, VALUE _)
91{
92 rb_box_gem_flags_t *flags = (rb_box_gem_flags_t *)flags_value;
93
94 if (flags->gem) {
95 rb_define_module("Gem");
96 // Make the error decoration gems autoload on first constant access.
97 // error.c loads them for error display on the first error
98 // (or eagerly via Process.warmup).
99 if (flags->error_highlight) {
100 rb_autoload_str(rb_cObject, rb_intern("ErrorHighlight"), rb_fstring_cstr("error_highlight"));
101 }
102 if (flags->did_you_mean) {
103 rb_autoload_str(rb_cObject, rb_intern("DidYouMean"), rb_fstring_cstr("did_you_mean"));
104 }
105 if (flags->syntax_suggest) {
106 rb_autoload_str(rb_cObject, rb_intern("SyntaxSuggest"), rb_fstring_cstr("syntax_suggest"));
107 }
108 }
109
110 return Qnil;
111}
112
113void
114rb_load_gem_prelude(VALUE box)
115{
116 load_with_builtin_functions("gem_prelude", NULL, (const rb_box_t *)box);
117}
118
119#endif
120
121void
122rb_free_loaded_builtin_table(void)
123{
124 // do nothing
125}
126
127void
128Init_builtin(void)
129{
130 // nothing
131}
132
133void
134Init_builtin_features(void)
135{
136
137#ifdef BUILTIN_BINARY_SIZE
138
139 rb_load_gem_prelude((VALUE)rb_root_box());
140
141 rb_load_gem_prelude((VALUE)rb_main_box());
142
143#endif
144
145}
#define ASSUME
Old name of RBIMPL_ASSUME.
Definition assume.h:27
#define Qnil
Old name of RUBY_Qnil.
VALUE rb_cObject
Object class.
Definition object.c:58
Defines RBIMPL_HAS_BUILTIN.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
Internal header for Ruby Box.
Definition box.h:14
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40