Coverage Report

Created: 2026-06-03 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ruby/builtin.c
Line
Count
Source
1
#include "internal.h"
2
#include "internal/box.h"
3
#include "vm_core.h"
4
#include "iseq.h"
5
#include "builtin.h"
6
7
#include "builtin_binary.rbbin"
8
9
#ifndef BUILTIN_BINARY_SIZE
10
11
#define BUILTIN_LOADED(feature_name, iseq) ((void)0)
12
#include "mini_builtin.c"
13
14
#else
15
16
static const unsigned char *
17
bin4feature(const struct builtin_binary *bb, const char *feature, size_t *psize)
18
0
{
19
0
    *psize = bb->bin_size;
20
0
    return strcmp(bb->feature, feature) ? NULL : bb->bin;
21
0
}
22
23
static const unsigned char*
24
builtin_lookup(const char *feature, size_t *psize)
25
0
{
26
0
    static size_t index = 0;
27
0
    const unsigned char *bin = NULL;
28
29
    /*
30
     * Fast path:
31
     * builtin_binary is usually arranged in the same order
32
     * as features are looked up in miniruby, so try the next entry first.
33
     */
34
0
    if (builtin_binary[index].feature) {
35
0
        bin = bin4feature(&builtin_binary[index], feature, psize);
36
0
        index++;
37
0
    }
38
0
    if (bin) {
39
0
        return bin;
40
0
    }
41
42
    /*
43
     * Fallback:
44
     * In case the lookup order does not match the array order,
45
     * scan the entire table to find the feature.
46
     */
47
0
    for (const struct builtin_binary *bb = &builtin_binary[0];
48
0
         bb->feature;
49
0
         bb++) {
50
0
        bin = bin4feature(bb, feature, psize);
51
0
        if (bin) {
52
0
            break;
53
0
        }
54
0
    }
55
56
0
    return bin;
57
0
}
58
59
static void
60
load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table, const rb_box_t *target_box)
61
0
{
62
    // search binary
63
0
    size_t size;
64
0
    const unsigned char *bin = builtin_lookup(feature_name, &size);
65
0
    if (! bin) {
66
0
        rb_bug("builtin_lookup: can not find %s", feature_name);
67
0
    }
68
69
    // load binary
70
0
    rb_vm_t *vm = GET_VM();
71
0
    if (vm->builtin_function_table != NULL) rb_bug("vm->builtin_function_table should be NULL.");
72
0
    vm->builtin_function_table = table;
73
0
    const rb_iseq_t *iseq = rb_iseq_ibf_load_bytes((const char *)bin, size);
74
0
    ASSUME(iseq); // otherwise an exception should have raised
75
0
    vm->builtin_function_table = NULL;
76
77
    // exec
78
0
    rb_iseq_eval(rb_iseq_check(iseq), target_box);
79
0
}
80
81
void
82
rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table)
83
0
{
84
0
    load_with_builtin_functions(feature_name, table, rb_root_box());
85
0
}
86
87
VALUE
88
rb_define_gem_modules(VALUE flags_value, VALUE _)
89
0
{
90
0
    rb_box_gem_flags_t *flags = (rb_box_gem_flags_t *)flags_value;
91
92
0
    if (flags->gem) {
93
0
        rb_define_module("Gem");
94
0
        if (flags->error_highlight) {
95
0
            rb_define_module("ErrorHighlight");
96
0
        }
97
0
        if (flags->did_you_mean) {
98
0
            rb_define_module("DidYouMean");
99
0
        }
100
0
        if (flags->syntax_suggest) {
101
0
            rb_define_module("SyntaxSuggest");
102
0
        }
103
0
    }
104
105
0
    return Qnil;
106
0
}
107
108
void
109
rb_load_gem_prelude(VALUE box)
110
0
{
111
0
    load_with_builtin_functions("gem_prelude", NULL, (const rb_box_t *)box);
112
0
}
113
114
#endif
115
116
void
117
rb_free_loaded_builtin_table(void)
118
0
{
119
    // do nothing
120
0
}
121
122
void
123
Init_builtin(void)
124
9
{
125
    // nothing
126
9
}
127
128
void
129
Init_builtin_features(void)
130
0
{
131
132
0
#ifdef BUILTIN_BINARY_SIZE
133
134
0
    rb_load_gem_prelude((VALUE)rb_root_box());
135
136
0
    rb_load_gem_prelude((VALUE)rb_main_box());
137
138
0
#endif
139
140
0
}