34
34
35
35
#define MAX_CREATE_TEMPFILE_ATTEMPT 3
36
36
37
+ #define BUNDLE_PATH "$BUNDLE_PATH/"
37
38
/*
38
39
* An instance of this key is written as the first 64 bytes of each cache file.
39
40
* The mtime and size members track whether the file contents have changed, and
@@ -87,6 +88,8 @@ static VALUE rb_mBootsnap;
87
88
static VALUE rb_mBootsnap_CompileCache ;
88
89
static VALUE rb_mBootsnap_CompileCache_Native ;
89
90
static VALUE rb_eBootsnap_CompileCache_Uncompilable ;
91
+ static char * bundle_path = NULL ;
92
+ static size_t bundle_path_size = 0 ;
90
93
static ID uncompilable ;
91
94
92
95
/* Functions exposed as module functions on Bootsnap::CompileCache::Native */
@@ -96,7 +99,7 @@ static VALUE bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE
96
99
97
100
/* Helpers */
98
101
static uint64_t fnv1a_64 (const char * str );
99
- static void bs_cache_path (const char * cachedir , const char * path , char (* cache_path )[MAX_CACHEPATH_SIZE ]);
102
+ static void bs_cache_path (const char * cachedir , const char * path , const long path_length , char (* cache_path )[MAX_CACHEPATH_SIZE ]);
100
103
static int bs_read_key (int fd , struct bs_cache_key * key );
101
104
static int cache_key_equal (struct bs_cache_key * k1 , struct bs_cache_key * k2 );
102
105
static VALUE bs_fetch (char * path , VALUE path_v , char * cache_path , VALUE handler , VALUE args );
@@ -144,6 +147,13 @@ Init_bootsnap(void)
144
147
rb_mBootsnap_CompileCache_Native = rb_define_module_under (rb_mBootsnap_CompileCache , "Native" );
145
148
rb_eBootsnap_CompileCache_Uncompilable = rb_define_class_under (rb_mBootsnap_CompileCache , "Uncompilable" , rb_eStandardError );
146
149
150
+ VALUE rb_bundle_path = rb_const_get (rb_mBootsnap , rb_intern ("BUNDLE_PATH" ));
151
+ if (RTEST (rb_bundle_path )) {
152
+ bundle_path = ALLOC_N (char , RSTRING_LEN (rb_bundle_path ) + 1 );
153
+ memcpy (bundle_path , RSTRING_PTR (rb_bundle_path ), RSTRING_LEN (rb_bundle_path ) + 1 );
154
+ bundle_path_size = strlen (bundle_path );
155
+ }
156
+
147
157
current_ruby_revision = get_ruby_revision ();
148
158
current_ruby_platform = get_ruby_platform ();
149
159
@@ -267,9 +277,18 @@ get_ruby_platform(void)
267
277
* The path will look something like: <cachedir>/12/34567890abcdef
268
278
*/
269
279
static void
270
- bs_cache_path (const char * cachedir , const char * path , char (* cache_path )[MAX_CACHEPATH_SIZE ])
280
+ bs_cache_path (const char * cachedir , const char * path , const long path_length , char (* cache_path )[MAX_CACHEPATH_SIZE ])
271
281
{
272
- uint64_t hash = fnv1a_64 (path );
282
+ uint64_t hash ;
283
+ if (bundle_path && !strncmp (bundle_path , path , bundle_path_size )) {
284
+ long canonical_path_size = path_length + strlen (BUNDLE_PATH ) - bundle_path_size + 1 ;
285
+ char * canonical_path = ALLOCA_N (char , canonical_path_size );
286
+ memcpy (canonical_path , BUNDLE_PATH , strlen (BUNDLE_PATH ));
287
+ memcpy (canonical_path + strlen (BUNDLE_PATH ), path + bundle_path_size , path_length - bundle_path_size + 1 );
288
+ hash = fnv1a_64 (canonical_path );
289
+ } else {
290
+ hash = fnv1a_64 (path );
291
+ }
273
292
uint8_t first_byte = (hash >> (64 - 8 ));
274
293
uint64_t remainder = hash & 0x00ffffffffffffff ;
275
294
@@ -314,12 +333,13 @@ bs_rb_fetch(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler, VALUE arg
314
333
rb_raise (rb_eArgError , "cachedir too long" );
315
334
}
316
335
317
- char * cachedir = RSTRING_PTR (cachedir_v );
318
- char * path = RSTRING_PTR (path_v );
336
+ char * cachedir = RSTRING_PTR (cachedir_v );
337
+ char * path = RSTRING_PTR (path_v );
338
+ long path_length = RSTRING_LEN (path_v );
319
339
char cache_path [MAX_CACHEPATH_SIZE ];
320
340
321
341
/* generate cache path to cache_path */
322
- bs_cache_path (cachedir , path , & cache_path );
342
+ bs_cache_path (cachedir , path , path_length , & cache_path );
323
343
324
344
return bs_fetch (path , path_v , cache_path , handler , args );
325
345
}
@@ -341,12 +361,13 @@ bs_rb_precompile(VALUE self, VALUE cachedir_v, VALUE path_v, VALUE handler)
341
361
rb_raise (rb_eArgError , "cachedir too long" );
342
362
}
343
363
344
- char * cachedir = RSTRING_PTR (cachedir_v );
345
- char * path = RSTRING_PTR (path_v );
364
+ char * cachedir = RSTRING_PTR (cachedir_v );
365
+ char * path = RSTRING_PTR (path_v );
366
+ long path_length = RSTRING_LEN (path_v );
346
367
char cache_path [MAX_CACHEPATH_SIZE ];
347
368
348
369
/* generate cache path to cache_path */
349
- bs_cache_path (cachedir , path , & cache_path );
370
+ bs_cache_path (cachedir , path , path_length , & cache_path );
350
371
351
372
return bs_precompile (path , path_v , cache_path , handler );
352
373
}
0 commit comments