bootsnap 1.9.4 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +76 -3
- data/LICENSE.txt +1 -1
- data/README.md +4 -4
- data/exe/bootsnap +1 -1
- data/ext/bootsnap/bootsnap.c +47 -84
- data/ext/bootsnap/extconf.rb +13 -11
- data/lib/bootsnap/bundler.rb +1 -0
- data/lib/bootsnap/cli/worker_pool.rb +1 -0
- data/lib/bootsnap/cli.rb +49 -49
- data/lib/bootsnap/compile_cache/iseq.rb +16 -11
- data/lib/bootsnap/compile_cache/json.rb +18 -9
- data/lib/bootsnap/compile_cache/yaml.rb +264 -77
- data/lib/bootsnap/compile_cache.rb +11 -7
- data/lib/bootsnap/explicit_require.rb +4 -3
- data/lib/bootsnap/load_path_cache/cache.rb +46 -30
- data/lib/bootsnap/load_path_cache/change_observer.rb +2 -0
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +26 -72
- data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +1 -0
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +32 -34
- data/lib/bootsnap/load_path_cache/path.rb +29 -5
- data/lib/bootsnap/load_path_cache/path_scanner.rb +6 -5
- data/lib/bootsnap/load_path_cache/store.rb +36 -13
- data/lib/bootsnap/load_path_cache.rb +16 -24
- data/lib/bootsnap/setup.rb +2 -1
- data/lib/bootsnap/version.rb +2 -1
- data/lib/bootsnap.rb +111 -99
- metadata +6 -77
- data/lib/bootsnap/load_path_cache/realpath_cache.rb +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 761e97c3b4772e9c0af1bd8391d70dddebd94addf88e9295e72a790a85deb5e0
|
|
4
|
+
data.tar.gz: 17f80fcf67adc6a4e7f9fb475d3e7d5c008c89b491e23804da1f2603e859888c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dca99dc5e57a644e627e8705958c8c4916a9c444c2a64788fd4214aa174d6c3eed7fc15ef7bdb6e06922fb8d1eef3beeff08e316aadbc3015a36e82b1a232309
|
|
7
|
+
data.tar.gz: 1c9ffc9c5c04694f4838693edda976f58925649f7b14411d61bec64eca10bb04548c5bb4e2be6ff897c8d5a0e929aa2cd885d017ccd1770530971fedba831ec3
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# Unreleased
|
|
2
2
|
|
|
3
|
+
# 1.12.0
|
|
4
|
+
|
|
5
|
+
* `bootsnap precompile` CLI will now also precompile `Rakefile` and `.rake` files.
|
|
6
|
+
|
|
7
|
+
* Stop decorating `Module#autoload` as it was only useful for supporting Ruby 2.2 and older.
|
|
8
|
+
|
|
9
|
+
* Remove `uname` and other patform specific version from the cache keys. `RUBY_PLATFORM + RUBY_REVISION` should be
|
|
10
|
+
enough to ensure bytecode compatibility. This should improve caching for alpine based setups. See #409.
|
|
11
|
+
|
|
12
|
+
# 1.11.1
|
|
13
|
+
|
|
14
|
+
* Fix the `can't modify frozen Hash` error on load path cache mutation. See #411.
|
|
15
|
+
|
|
16
|
+
# 1.11.0
|
|
17
|
+
|
|
18
|
+
* Drop dependency on `fileutils`.
|
|
19
|
+
|
|
20
|
+
* Better respect `Kernel#require` duck typing. While it almost never comes up in practice, `Kernel#require`
|
|
21
|
+
follow a fairly intricate duck-typing protocol on its argument implemented as `rb_get_path(VALUE)` in MRI.
|
|
22
|
+
So when applicable we bind `rb_get_path` and use it for improved compatibility. See #396 and #406.
|
|
23
|
+
|
|
24
|
+
* Get rid of the `Kernel.require_relative` decorator by resolving `$LOAD_PATH` members to their real path.
|
|
25
|
+
This way we handle symlinks in `$LOAD_PATH` much more efficiently. See #402 for the detailed explanation.
|
|
26
|
+
|
|
27
|
+
* Drop support for Ruby 2.3 (to allow getting rid of the `Kernel.require_relative` decorator).
|
|
28
|
+
|
|
29
|
+
# 1.10.3
|
|
30
|
+
|
|
31
|
+
* Fix Regexp and Date type support in YAML compile cache. (#400)
|
|
32
|
+
|
|
33
|
+
* Improve the YAML compile cache to support `UTF-8` symbols. (#398, #399)
|
|
34
|
+
[The default `MessagePack` symbol serializer assumes all symbols are ASCII](https://github.com/msgpack/msgpack-ruby/pull/211),
|
|
35
|
+
because of this, non-ASCII compatible symbol would be restored with `ASCII_8BIT` encoding (AKA `BINARY`).
|
|
36
|
+
Bootsnap now properly cache them in `UTF-8`.
|
|
37
|
+
|
|
38
|
+
Note that the above only apply for actual YAML symbols (e..g `--- :foo`).
|
|
39
|
+
The issue is still present for string keys parsed with `YAML.load_file(..., symbolize_names: true)`, that is a bug
|
|
40
|
+
in `msgpack` that will hopefully be solved soon, see: https://github.com/msgpack/msgpack-ruby/pull/246
|
|
41
|
+
|
|
42
|
+
* Entirely disable the YAML compile cache if `Encoding.default_internal` is set to an encoding not supported by `msgpack`. (#398)
|
|
43
|
+
`Psych` coerce strings to `Encoding.default_internal`, but `MessagePack` doesn't. So in this scenario we can't provide
|
|
44
|
+
YAML caching at all without returning the strings in the wrong encoding.
|
|
45
|
+
This never came up in practice but might as well be safe.
|
|
46
|
+
|
|
47
|
+
# 1.10.2
|
|
48
|
+
|
|
49
|
+
* Reduce the `Kernel.require` extra stack frames some more. Now bootsnap should only add one extra frame per `require` call.
|
|
50
|
+
|
|
51
|
+
* Better check `freeze` option support in JSON compile cache.
|
|
52
|
+
Previously `JSON.load_file(..., freeze: true)` would be cached even when the msgpack version is missing support for it.
|
|
53
|
+
|
|
54
|
+
# 1.10.1
|
|
55
|
+
|
|
56
|
+
* Fix `Kernel#autoload`'s fallback path always being executed.
|
|
57
|
+
|
|
58
|
+
* Consider `unlink` failing with `ENOENT` as a success.
|
|
59
|
+
|
|
60
|
+
# 1.10.0
|
|
61
|
+
|
|
62
|
+
* Delay requiring `FileUtils`. (#285)
|
|
63
|
+
`FileUtils` can be installed as a gem, so it's best to wait for bundler to have setup the load path before requiring it.
|
|
64
|
+
|
|
65
|
+
* Improve support of Psych 4. (#392)
|
|
66
|
+
Since `1.8.0`, `YAML.load_file` was no longer cached when Psych 4 was used. This is because `load_file` loads
|
|
67
|
+
in safe mode by default, so the Bootsnap cache could defeat that safety.
|
|
68
|
+
Now when precompiling YAML files, Bootsnap first try to parse them in safe mode, and if it can't fallback to unsafe mode,
|
|
69
|
+
and the cache contains a flag that records whether it was generated in safe mode or not.
|
|
70
|
+
`YAML.unsafe_load_file` will use safe caches just fine, but `YAML.load_file` will fallback to uncached YAML parsing
|
|
71
|
+
if the cache was generated using unsafe parsing.
|
|
72
|
+
|
|
73
|
+
* Minimize the Kernel.require extra stack frames. (#393)
|
|
74
|
+
This should reduce the noise generated by bootsnap on `LoadError`.
|
|
75
|
+
|
|
3
76
|
# 1.9.4
|
|
4
77
|
|
|
5
78
|
* Ignore absolute paths in the loaded feature index. (#385)
|
|
@@ -34,7 +107,7 @@
|
|
|
34
107
|
|
|
35
108
|
# 1.8.0
|
|
36
109
|
|
|
37
|
-
* Improve support for
|
|
110
|
+
* Improve support for Psych 4. (#368)
|
|
38
111
|
|
|
39
112
|
# 1.7.7
|
|
40
113
|
|
|
@@ -52,8 +125,8 @@
|
|
|
52
125
|
|
|
53
126
|
# 1.7.4
|
|
54
127
|
|
|
55
|
-
* Stop raising errors when
|
|
56
|
-
if somehow it can't be saved,
|
|
128
|
+
* Stop raising errors when encountering various file system errors. The cache is now best effort,
|
|
129
|
+
if somehow it can't be saved, bootsnap will gracefully fallback to the original operation (e.g. `Kernel.require`).
|
|
57
130
|
(#353, #177, #262)
|
|
58
131
|
|
|
59
132
|
# 1.7.3
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -41,7 +41,7 @@ getting progressively slower, this is almost certainly the cause.**
|
|
|
41
41
|
It's technically possible to simply specify `gem 'bootsnap', require: 'bootsnap/setup'`, but it's
|
|
42
42
|
important to load Bootsnap as early as possible to get maximum performance improvement.
|
|
43
43
|
|
|
44
|
-
You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/
|
|
44
|
+
You can see how this require works [here](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/setup.rb).
|
|
45
45
|
|
|
46
46
|
If you are not using Rails, or if you are but want more control over things, add this to your
|
|
47
47
|
application setup immediately after `require 'bundler/setup'` (i.e. as early as possible: the sooner
|
|
@@ -161,7 +161,7 @@ The only directories considered "stable" are things under the Ruby install prefi
|
|
|
161
161
|
"volatile".
|
|
162
162
|
|
|
163
163
|
In addition to the [`Bootsnap::LoadPathCache::Cache`
|
|
164
|
-
source](https://github.com/Shopify/bootsnap/blob/
|
|
164
|
+
source](https://github.com/Shopify/bootsnap/blob/main/lib/bootsnap/load_path_cache/cache.rb),
|
|
165
165
|
this diagram may help clarify how entry resolution works:
|
|
166
166
|
|
|
167
167
|

|
|
@@ -232,9 +232,9 @@ Bootsnap writes a cache file containing a 64 byte header followed by the cache c
|
|
|
232
232
|
is a cache key including several fields:
|
|
233
233
|
|
|
234
234
|
* `version`, hardcoded in bootsnap. Essentially a schema version;
|
|
235
|
-
* `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable
|
|
235
|
+
* `ruby_platform`, A hash of `RUBY_PLATFORM` (e.g. x86_64-linux-gnu) variable.
|
|
236
236
|
* `compile_option`, which changes with `RubyVM::InstructionSequence.compile_option` does;
|
|
237
|
-
* `ruby_revision`,
|
|
237
|
+
* `ruby_revision`, A hash of `RUBY_REVISION`, the exact version of Ruby;
|
|
238
238
|
* `size`, the size of the source file;
|
|
239
239
|
* `mtime`, the last-modification timestamp of the source file when it was compiled; and
|
|
240
240
|
* `data_size`, the number of bytes following the header, which we need to read it into a buffer.
|
data/exe/bootsnap
CHANGED
data/ext/bootsnap/bootsnap.c
CHANGED
|
@@ -19,12 +19,6 @@
|
|
|
19
19
|
#include <errno.h>
|
|
20
20
|
#include <fcntl.h>
|
|
21
21
|
#include <sys/stat.h>
|
|
22
|
-
#ifndef _WIN32
|
|
23
|
-
#include <sys/utsname.h>
|
|
24
|
-
#endif
|
|
25
|
-
#ifdef __GLIBC__
|
|
26
|
-
#include <gnu/libc-version.h>
|
|
27
|
-
#endif
|
|
28
22
|
|
|
29
23
|
/* 1000 is an arbitrary limit; FNV64 plus some slashes brings the cap down to
|
|
30
24
|
* 981 for the cache dir */
|
|
@@ -75,7 +69,7 @@ struct bs_cache_key {
|
|
|
75
69
|
STATIC_ASSERT(sizeof(struct bs_cache_key) == KEY_SIZE);
|
|
76
70
|
|
|
77
71
|
/* Effectively a schema version. Bumping invalidates all previous caches */
|
|
78
|
-
static const uint32_t current_version =
|
|
72
|
+
static const uint32_t current_version = 4;
|
|
79
73
|
|
|
80
74
|
/* hash of e.g. "x86_64-darwin17", invalidating when ruby is recompiled on a
|
|
81
75
|
* new OS ABI, etc. */
|
|
@@ -91,8 +85,7 @@ static mode_t current_umask;
|
|
|
91
85
|
static VALUE rb_mBootsnap;
|
|
92
86
|
static VALUE rb_mBootsnap_CompileCache;
|
|
93
87
|
static VALUE rb_mBootsnap_CompileCache_Native;
|
|
94
|
-
static VALUE
|
|
95
|
-
static ID uncompilable;
|
|
88
|
+
static VALUE rb_cBootsnap_CompileCache_UNCOMPILABLE;
|
|
96
89
|
static ID instrumentation_method;
|
|
97
90
|
static VALUE sym_miss;
|
|
98
91
|
static VALUE sym_stale;
|
|
@@ -120,10 +113,8 @@ static uint32_t get_ruby_platform(void);
|
|
|
120
113
|
* exception.
|
|
121
114
|
*/
|
|
122
115
|
static int bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * output_data);
|
|
123
|
-
static VALUE prot_storage_to_output(VALUE arg);
|
|
124
116
|
static VALUE prot_input_to_output(VALUE arg);
|
|
125
117
|
static void bs_input_to_output(VALUE handler, VALUE args, VALUE input_data, VALUE * output_data, int * exception_tag);
|
|
126
|
-
static VALUE prot_input_to_storage(VALUE arg);
|
|
127
118
|
static int bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data);
|
|
128
119
|
struct s2o_data;
|
|
129
120
|
struct i2o_data;
|
|
@@ -138,6 +129,12 @@ bs_rb_coverage_running(VALUE self)
|
|
|
138
129
|
return RTEST(cov) ? Qtrue : Qfalse;
|
|
139
130
|
}
|
|
140
131
|
|
|
132
|
+
static VALUE
|
|
133
|
+
bs_rb_get_path(VALUE self, VALUE fname)
|
|
134
|
+
{
|
|
135
|
+
return rb_get_path(fname);
|
|
136
|
+
}
|
|
137
|
+
|
|
141
138
|
/*
|
|
142
139
|
* Ruby C extensions are initialized by calling Init_<extname>.
|
|
143
140
|
*
|
|
@@ -149,14 +146,17 @@ void
|
|
|
149
146
|
Init_bootsnap(void)
|
|
150
147
|
{
|
|
151
148
|
rb_mBootsnap = rb_define_module("Bootsnap");
|
|
149
|
+
|
|
150
|
+
rb_define_singleton_method(rb_mBootsnap, "rb_get_path", bs_rb_get_path, 1);
|
|
151
|
+
|
|
152
152
|
rb_mBootsnap_CompileCache = rb_define_module_under(rb_mBootsnap, "CompileCache");
|
|
153
153
|
rb_mBootsnap_CompileCache_Native = rb_define_module_under(rb_mBootsnap_CompileCache, "Native");
|
|
154
|
-
|
|
154
|
+
rb_cBootsnap_CompileCache_UNCOMPILABLE = rb_const_get(rb_mBootsnap_CompileCache, rb_intern("UNCOMPILABLE"));
|
|
155
|
+
rb_global_variable(&rb_cBootsnap_CompileCache_UNCOMPILABLE);
|
|
155
156
|
|
|
156
157
|
current_ruby_revision = get_ruby_revision();
|
|
157
158
|
current_ruby_platform = get_ruby_platform();
|
|
158
159
|
|
|
159
|
-
uncompilable = rb_intern("__bootsnap_uncompilable__");
|
|
160
160
|
instrumentation_method = rb_intern("_instrument");
|
|
161
161
|
|
|
162
162
|
sym_miss = ID2SYM(rb_intern("miss"));
|
|
@@ -199,29 +199,6 @@ bs_compile_option_crc32_set(VALUE self, VALUE crc32_v)
|
|
|
199
199
|
return Qnil;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
/*
|
|
203
|
-
* We use FNV1a-64 to derive cache paths. The choice is somewhat arbitrary but
|
|
204
|
-
* it has several nice properties:
|
|
205
|
-
*
|
|
206
|
-
* - Tiny implementation
|
|
207
|
-
* - No external dependency
|
|
208
|
-
* - Solid performance
|
|
209
|
-
* - Solid randomness
|
|
210
|
-
* - 32 bits doesn't feel collision-resistant enough; 64 is nice.
|
|
211
|
-
*/
|
|
212
|
-
static uint64_t
|
|
213
|
-
fnv1a_64_iter_cstr(uint64_t h, const char *str)
|
|
214
|
-
{
|
|
215
|
-
unsigned char *s = (unsigned char *)str;
|
|
216
|
-
|
|
217
|
-
while (*s) {
|
|
218
|
-
h ^= (uint64_t)*s++;
|
|
219
|
-
h += (h << 1) + (h << 4) + (h << 5) + (h << 7) + (h << 8) + (h << 40);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return h;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
202
|
static uint64_t
|
|
226
203
|
fnv1a_64_iter(uint64_t h, const VALUE str)
|
|
227
204
|
{
|
|
@@ -266,10 +243,6 @@ get_ruby_revision(void)
|
|
|
266
243
|
/*
|
|
267
244
|
* When ruby's version doesn't change, but it's recompiled on a different OS
|
|
268
245
|
* (or OS version), we need to invalidate the cache.
|
|
269
|
-
*
|
|
270
|
-
* We actually factor in some extra information here, to be extra confident
|
|
271
|
-
* that we don't try to re-use caches that will not be compatible, by factoring
|
|
272
|
-
* in utsname.version.
|
|
273
246
|
*/
|
|
274
247
|
static uint32_t
|
|
275
248
|
get_ruby_platform(void)
|
|
@@ -279,22 +252,7 @@ get_ruby_platform(void)
|
|
|
279
252
|
|
|
280
253
|
ruby_platform = rb_const_get(rb_cObject, rb_intern("RUBY_PLATFORM"));
|
|
281
254
|
hash = fnv1a_64(ruby_platform);
|
|
282
|
-
|
|
283
|
-
#ifdef _WIN32
|
|
284
|
-
return (uint32_t)(hash >> 32) ^ (uint32_t)GetVersion();
|
|
285
|
-
#elif defined(__GLIBC__)
|
|
286
|
-
hash = fnv1a_64_iter_cstr(hash, gnu_get_libc_version());
|
|
287
|
-
return (uint32_t)(hash >> 32);
|
|
288
|
-
#else
|
|
289
|
-
struct utsname utsname;
|
|
290
|
-
|
|
291
|
-
/* Not worth crashing if this fails; lose extra cache invalidation potential */
|
|
292
|
-
if (uname(&utsname) >= 0) {
|
|
293
|
-
hash = fnv1a_64_iter_cstr(hash, utsname.version);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
255
|
return (uint32_t)(hash >> 32);
|
|
297
|
-
#endif
|
|
298
256
|
}
|
|
299
257
|
|
|
300
258
|
/*
|
|
@@ -426,6 +384,7 @@ open_current_file(char * path, struct bs_cache_key * key, const char ** errno_pr
|
|
|
426
384
|
#define ERROR_WITH_ERRNO -1
|
|
427
385
|
#define CACHE_MISS -2
|
|
428
386
|
#define CACHE_STALE -3
|
|
387
|
+
#define CACHE_UNCOMPILABLE -4
|
|
429
388
|
|
|
430
389
|
/*
|
|
431
390
|
* Read the cache key from the given fd, which must have position 0 (e.g.
|
|
@@ -507,14 +466,14 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
|
|
|
507
466
|
if (data_size > 100000000000) {
|
|
508
467
|
*errno_provenance = "bs_fetch:fetch_cached_data:datasize";
|
|
509
468
|
errno = EINVAL; /* because wtf? */
|
|
510
|
-
ret =
|
|
469
|
+
ret = ERROR_WITH_ERRNO;
|
|
511
470
|
goto done;
|
|
512
471
|
}
|
|
513
472
|
data = ALLOC_N(char, data_size);
|
|
514
473
|
nread = read(fd, data, data_size);
|
|
515
474
|
if (nread < 0) {
|
|
516
475
|
*errno_provenance = "bs_fetch:fetch_cached_data:read";
|
|
517
|
-
ret =
|
|
476
|
+
ret = ERROR_WITH_ERRNO;
|
|
518
477
|
goto done;
|
|
519
478
|
}
|
|
520
479
|
if (nread != data_size) {
|
|
@@ -525,6 +484,10 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
|
|
|
525
484
|
storage_data = rb_str_new(data, data_size);
|
|
526
485
|
|
|
527
486
|
*exception_tag = bs_storage_to_output(handler, args, storage_data, output_data);
|
|
487
|
+
if (*output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
|
|
488
|
+
ret = CACHE_UNCOMPILABLE;
|
|
489
|
+
goto done;
|
|
490
|
+
}
|
|
528
491
|
ret = 0;
|
|
529
492
|
done:
|
|
530
493
|
if (data != NULL) xfree(data);
|
|
@@ -737,7 +700,15 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
|
737
700
|
&output_data, &exception_tag, &errno_provenance
|
|
738
701
|
);
|
|
739
702
|
if (exception_tag != 0) goto raise;
|
|
740
|
-
else if (res ==
|
|
703
|
+
else if (res == CACHE_UNCOMPILABLE) {
|
|
704
|
+
/* If fetch_cached_data returned `Uncompilable` we fallback to `input_to_output`
|
|
705
|
+
This happens if we have say, an unsafe YAML cache, but try to load it in safe mode */
|
|
706
|
+
if (bs_read_contents(current_fd, current_key.size, &contents, &errno_provenance) < 0) goto fail_errno;
|
|
707
|
+
input_data = rb_str_new(contents, current_key.size);
|
|
708
|
+
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
|
709
|
+
if (exception_tag != 0) goto raise;
|
|
710
|
+
goto succeed;
|
|
711
|
+
} else if (res == CACHE_MISS || res == CACHE_STALE) valid_cache = 0;
|
|
741
712
|
else if (res == ERROR_WITH_ERRNO) goto fail_errno;
|
|
742
713
|
else if (!NIL_P(output_data)) goto succeed; /* fast-path, goal */
|
|
743
714
|
}
|
|
@@ -754,7 +725,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
|
754
725
|
if (exception_tag != 0) goto raise;
|
|
755
726
|
/* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
|
|
756
727
|
* to cache anything; just return input_to_output(input_data) */
|
|
757
|
-
if (storage_data ==
|
|
728
|
+
if (storage_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
|
|
758
729
|
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
|
759
730
|
if (exception_tag != 0) goto raise;
|
|
760
731
|
goto succeed;
|
|
@@ -772,12 +743,20 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
|
772
743
|
exception_tag = bs_storage_to_output(handler, args, storage_data, &output_data);
|
|
773
744
|
if (exception_tag != 0) goto raise;
|
|
774
745
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
746
|
+
if (output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
|
|
747
|
+
/* If storage_to_output returned `Uncompilable` we fallback to `input_to_output` */
|
|
748
|
+
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
|
749
|
+
if (exception_tag != 0) goto raise;
|
|
750
|
+
} else if (NIL_P(output_data)) {
|
|
751
|
+
/* If output_data is nil, delete the cache entry and generate the output
|
|
752
|
+
* using input_to_output */
|
|
778
753
|
if (unlink(cache_path) < 0) {
|
|
779
|
-
|
|
780
|
-
|
|
754
|
+
/* If the cache was already deleted, it might be that another process did it before us.
|
|
755
|
+
* No point raising an error */
|
|
756
|
+
if (errno != ENOENT) {
|
|
757
|
+
errno_provenance = "bs_fetch:unlink";
|
|
758
|
+
goto fail_errno;
|
|
759
|
+
}
|
|
781
760
|
}
|
|
782
761
|
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
|
783
762
|
if (exception_tag != 0) goto raise;
|
|
@@ -856,7 +835,7 @@ bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
|
856
835
|
|
|
857
836
|
/* If input_to_storage raised Bootsnap::CompileCache::Uncompilable, don't try
|
|
858
837
|
* to cache anything; just return false */
|
|
859
|
-
if (storage_data ==
|
|
838
|
+
if (storage_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
|
|
860
839
|
goto fail;
|
|
861
840
|
}
|
|
862
841
|
/* If storage_data isn't a string, we can't cache it */
|
|
@@ -919,7 +898,7 @@ struct i2s_data {
|
|
|
919
898
|
};
|
|
920
899
|
|
|
921
900
|
static VALUE
|
|
922
|
-
|
|
901
|
+
try_storage_to_output(VALUE arg)
|
|
923
902
|
{
|
|
924
903
|
struct s2o_data * data = (struct s2o_data *)arg;
|
|
925
904
|
return rb_funcall(data->handler, rb_intern("storage_to_output"), 2, data->storage_data, data->args);
|
|
@@ -934,7 +913,7 @@ bs_storage_to_output(VALUE handler, VALUE args, VALUE storage_data, VALUE * outp
|
|
|
934
913
|
.args = args,
|
|
935
914
|
.storage_data = storage_data,
|
|
936
915
|
};
|
|
937
|
-
*output_data = rb_protect(
|
|
916
|
+
*output_data = rb_protect(try_storage_to_output, (VALUE)&s2o_data, &state);
|
|
938
917
|
return state;
|
|
939
918
|
}
|
|
940
919
|
|
|
@@ -963,22 +942,6 @@ try_input_to_storage(VALUE arg)
|
|
|
963
942
|
return rb_funcall(data->handler, rb_intern("input_to_storage"), 2, data->input_data, data->pathval);
|
|
964
943
|
}
|
|
965
944
|
|
|
966
|
-
static VALUE
|
|
967
|
-
rescue_input_to_storage(VALUE arg, VALUE e)
|
|
968
|
-
{
|
|
969
|
-
return uncompilable;
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
static VALUE
|
|
973
|
-
prot_input_to_storage(VALUE arg)
|
|
974
|
-
{
|
|
975
|
-
struct i2s_data * data = (struct i2s_data *)arg;
|
|
976
|
-
return rb_rescue2(
|
|
977
|
-
try_input_to_storage, (VALUE)data,
|
|
978
|
-
rescue_input_to_storage, Qnil,
|
|
979
|
-
rb_eBootsnap_CompileCache_Uncompilable, 0);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
945
|
static int
|
|
983
946
|
bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval, VALUE * storage_data)
|
|
984
947
|
{
|
|
@@ -988,6 +951,6 @@ bs_input_to_storage(VALUE handler, VALUE args, VALUE input_data, VALUE pathval,
|
|
|
988
951
|
.input_data = input_data,
|
|
989
952
|
.pathval = pathval,
|
|
990
953
|
};
|
|
991
|
-
*storage_data = rb_protect(
|
|
954
|
+
*storage_data = rb_protect(try_input_to_storage, (VALUE)&i2s_data, &state);
|
|
992
955
|
return state;
|
|
993
956
|
}
|
data/ext/bootsnap/extconf.rb
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require("mkmf")
|
|
3
4
|
|
|
4
|
-
if RUBY_ENGINE ==
|
|
5
|
-
$CFLAGS <<
|
|
6
|
-
$CFLAGS <<
|
|
5
|
+
if RUBY_ENGINE == "ruby"
|
|
6
|
+
$CFLAGS << " -O3 "
|
|
7
|
+
$CFLAGS << " -std=c99"
|
|
7
8
|
|
|
8
9
|
# ruby.h has some -Wpedantic fails in some cases
|
|
9
10
|
# (e.g. https://github.com/Shopify/bootsnap/issues/15)
|
|
10
|
-
unless [
|
|
11
|
-
$CFLAGS <<
|
|
12
|
-
$CFLAGS <<
|
|
13
|
-
$CFLAGS <<
|
|
14
|
-
$CFLAGS <<
|
|
11
|
+
unless ["0", "", nil].include?(ENV["BOOTSNAP_PEDANTIC"])
|
|
12
|
+
$CFLAGS << " -Wall"
|
|
13
|
+
$CFLAGS << " -Werror"
|
|
14
|
+
$CFLAGS << " -Wextra"
|
|
15
|
+
$CFLAGS << " -Wpedantic"
|
|
15
16
|
|
|
16
|
-
$CFLAGS <<
|
|
17
|
-
$CFLAGS <<
|
|
18
|
-
$CFLAGS <<
|
|
17
|
+
$CFLAGS << " -Wno-unused-parameter" # VALUE self has to be there but we don't care what it is.
|
|
18
|
+
$CFLAGS << " -Wno-keyword-macro" # hiding return
|
|
19
|
+
$CFLAGS << " -Wno-gcc-compat" # ruby.h 2.6.0 on macos 10.14, dunno
|
|
20
|
+
$CFLAGS << " -Wno-compound-token-split-by-macro"
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
create_makefile("bootsnap/bootsnap")
|
data/lib/bootsnap/bundler.rb
CHANGED