@@ -356,6 +356,12 @@ typedef struct {
356
356
arraylist_t fixup_types ; // a list of locations of types requiring (re)caching
357
357
arraylist_t fixup_objs ; // a list of locations of objects requiring (re)caching
358
358
arraylist_t ccallable_list ; // @ccallable entry points to install
359
+ #ifdef _P64
360
+ // On 64-bit, we can encode the "`depmods` index" in the reftag, so all we need is a mapping between
361
+ // the buildid_idx & depmods_idx:
362
+ jl_array_t * buildid_depmods_idxs ;
363
+ // On 64bit, all the `link_ids_*` arrays below will be NULL.
364
+ #endif
359
365
// record of build_ids for all external linkages, in order of serialization for the current sysimg/pkgimg
360
366
// conceptually, the base pointer for the jth externally-linked item is determined from
361
367
// i = findfirst(==(link_ids[j]), jl_build_ids)
@@ -386,7 +392,8 @@ enum RefTags {
386
392
SymbolRef , // symbols
387
393
FunctionRef , // generic functions
388
394
BuiltinFunctionRef , // builtin functions
389
- ExternalLinkage // items defined externally (used when serializing packages)
395
+ SysimageLinkage , // reference to the sysimage (from pkgimage)
396
+ ExternalLinkage // reference to some other pkgimage
390
397
};
391
398
392
399
// calling conventions for internal entry points.
@@ -404,9 +411,11 @@ typedef enum {
404
411
405
412
#ifdef _P64
406
413
#define RELOC_TAG_OFFSET 61
414
+ #define DEPS_IDX_OFFSET 40 // only on 64-bit can we encode the dependency-index as part of the tagged reloc
407
415
#else
408
416
// this supports up to 8 RefTags, 512MB of pointer data, and 4/2 (64/32-bit) GB of constant data.
409
417
#define RELOC_TAG_OFFSET 29
418
+ #define DEPS_IDX_OFFSET RELOC_TAG_OFFSET
410
419
#endif
411
420
412
421
#if RELOC_TAG_OFFSET <= 32
@@ -758,7 +767,7 @@ done_fields: ;
758
767
}
759
768
arraylist_push (& serialization_queue , (void * ) v );
760
769
size_t idx = serialization_queue .len - 1 ;
761
- assert (serialization_queue .len < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "too many items to serialize" );
770
+ assert (serialization_queue .len < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "too many items to serialize" );
762
771
763
772
* bp = (void * )((char * )HT_NOTFOUND + 1 + idx );
764
773
}
@@ -863,29 +872,40 @@ static void write_pointer(ios_t *s) JL_NOTSAFEPOINT
863
872
static uintptr_t add_external_linkage (jl_serializer_state * s , jl_value_t * v , jl_array_t * link_ids ) {
864
873
size_t i = external_blob_index (v );
865
874
if (i < n_linkage_blobs ()) {
875
+ // We found the sysimg/pkg that this item links against
876
+ // Compute the relocation code
877
+ size_t offset = (uintptr_t )v - (uintptr_t )jl_linkage_blobs .items [2 * i ];
878
+ offset /= sizeof (void * );
879
+ assert (offset < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "offset to external image too large" );
880
+
881
+ if (i == 0 )
882
+ return ((uintptr_t )SysimageLinkage << RELOC_TAG_OFFSET ) + offset ; // sysimage
866
883
assert (link_ids && jl_is_array (link_ids ));
884
+ #ifdef _P64
885
+ uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids );
886
+ return ((uintptr_t )ExternalLinkage << RELOC_TAG_OFFSET )
887
+ + (((uintptr_t )link_id_data [i ]) << DEPS_IDX_OFFSET ) + offset ; // on 64-bit, link_ids stores the mapping from build_id_idx -> deps_idx
888
+ #else
889
+ // On 32bit, we store the image key in `link_ids`
867
890
assert (jl_build_ids && jl_is_array (jl_build_ids ));
868
891
uint64_t * build_id_data = (uint64_t * )jl_array_data (jl_build_ids );
869
- // We found the sysimg/pkg that this item links against
870
- // Store the image key in `link_ids`
871
892
jl_array_grow_end (link_ids , 1 );
872
- uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids );
893
+ uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids ); // wait until after the `grow`
873
894
link_id_data [jl_array_len (link_ids )- 1 ] = build_id_data [i ];
874
- // Compute the relocation code
875
- size_t offset = (uintptr_t )v - (uintptr_t )jl_linkage_blobs .items [2 * i ];
876
- offset /= sizeof (void * );
877
- assert (offset < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "offset to external image too large" );
878
- // jl_printf(JL_STDOUT, "External link %ld against blob %d with key %ld at position 0x%lx with offset 0x%lx to \n", jl_array_len(link_ids), i, build_id_data[i>>1], ios_pos(s->s), offset);
879
- // jl_(v);
880
895
return ((uintptr_t )ExternalLinkage << RELOC_TAG_OFFSET ) + offset ;
896
+ #endif
881
897
}
882
898
return 0 ;
883
899
}
884
900
885
901
// Return the integer `id` for `v`. Generically this is looked up in `serialization_order`,
886
902
// but symbols, small integers, and a couple of special items (`nothing` and the root Task)
887
903
// have special handling.
904
+ #ifdef _P64
905
+ #define backref_id (s , v , link_ids ) _backref_id(s, (jl_value_t*)(v), s->buildid_depmods_idxs)
906
+ #else
888
907
#define backref_id (s , v , link_ids ) _backref_id(s, (jl_value_t*)(v), link_ids)
908
+ #endif
889
909
static uintptr_t _backref_id (jl_serializer_state * s , jl_value_t * v , jl_array_t * link_ids ) JL_NOTSAFEPOINT
890
910
{
891
911
assert (v != NULL && "cannot get backref to NULL object" );
@@ -898,7 +918,7 @@ static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v, jl_array_t *
898
918
write_uint32 (s -> symbols , l );
899
919
ios_write (s -> symbols , jl_symbol_name ((jl_sym_t * )v ), l + 1 );
900
920
size_t offset = ++ nsym_tag ;
901
- assert (offset < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "too many symbols" );
921
+ assert (offset < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "too many symbols" );
902
922
idx = (void * )((char * )HT_NOTFOUND + ((uintptr_t )SymbolRef << RELOC_TAG_OFFSET ) + offset );
903
923
* pidx = idx ;
904
924
}
@@ -1143,7 +1163,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
1143
1163
// write data and relocations
1144
1164
newa -> data = NULL ; // relocation offset
1145
1165
data /= sizeof (void * );
1146
- assert (data < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "offset to constant data too large" );
1166
+ assert (data < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "offset to constant data too large" );
1147
1167
arraylist_push (& s -> relocs_list , (void * )(reloc_offset + offsetof(jl_array_t , data ))); // relocation location
1148
1168
arraylist_push (& s -> relocs_list , (void * )(((uintptr_t )ConstDataRef << RELOC_TAG_OFFSET ) + data )); // relocation target
1149
1169
if (jl_is_cpointer_type (et )) {
@@ -1246,7 +1266,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
1246
1266
uintptr_t data = LLT_ALIGN (ios_pos (s -> const_data ), 8 );
1247
1267
write_padding (s -> const_data , data - ios_pos (s -> const_data ));
1248
1268
data /= sizeof (void * );
1249
- assert (data < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "offset to constant data too large" );
1269
+ assert (data < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "offset to constant data too large" );
1250
1270
arraylist_push (& s -> relocs_list , (void * )(reloc_offset + 8 )); // relocation location
1251
1271
arraylist_push (& s -> relocs_list , (void * )(((uintptr_t )ConstDataRef << RELOC_TAG_OFFSET ) + data )); // relocation target
1252
1272
void * pdata = jl_unbox_voidpointer (jl_get_nth_field (v , 2 ));
@@ -1533,6 +1553,8 @@ static uintptr_t get_reloc_for_item(uintptr_t reloc_item, size_t reloc_offset)
1533
1553
case FunctionRef :
1534
1554
assert (offset < JL_API_MAX && "unknown function pointer id" );
1535
1555
break ;
1556
+ case SysimageLinkage :
1557
+ break ;
1536
1558
case ExternalLinkage :
1537
1559
break ;
1538
1560
default :
@@ -1599,15 +1621,25 @@ static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t bas
1599
1621
//default:
1600
1622
assert ("corrupt relocation item id" );
1601
1623
}
1624
+ case SysimageLinkage :
1625
+ assert (jl_linkage_blobs .len > 0 );
1626
+ return (uintptr_t )jl_linkage_blobs .items [0 ] + offset * sizeof (void * );
1602
1627
case ExternalLinkage :
1603
1628
assert (link_ids );
1604
- assert (link_index );
1605
1629
assert (jl_build_ids );
1606
1630
uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids );
1607
1631
uint64_t * build_id_data = (uint64_t * )jl_array_data (jl_build_ids );
1632
+ #ifdef _P64
1633
+ size_t depsidx = offset >> DEPS_IDX_OFFSET ;
1634
+ offset &= ((size_t )1 << DEPS_IDX_OFFSET ) - 1 ;
1635
+ assert (depsidx < jl_array_len (link_ids )); // on 64-bit, here link_ids is a build_id lookup by depmod index
1636
+ uint64_t build_id = link_id_data [depsidx ];
1637
+ #else
1638
+ assert (link_index );
1608
1639
assert (0 <= * link_index && * link_index < jl_array_len (link_ids ));
1609
1640
uint64_t build_id = link_id_data [* link_index ];
1610
1641
* link_index += 1 ;
1642
+ #endif
1611
1643
size_t i = 0 , nids = jl_array_len (jl_build_ids );
1612
1644
while (i < nids ) {
1613
1645
if (build_id == build_id_data [i ])
@@ -1799,8 +1831,12 @@ static jl_value_t *jl_delayed_reloc(jl_serializer_state *s, uintptr_t offset) JL
1799
1831
uintptr_t base = (uintptr_t )& s -> s -> buf [0 ];
1800
1832
size_t size = s -> s -> size ;
1801
1833
int link_index = 0 ;
1834
+ #ifdef _P64
1835
+ jl_value_t * ret = (jl_value_t * )get_item_for_reloc (s , base , size , offset , s -> buildid_depmods_idxs , & link_index );
1836
+ #else
1802
1837
jl_value_t * ret = (jl_value_t * )get_item_for_reloc (s , base , size , offset , s -> link_ids_relocs , & link_index );
1803
1838
assert (link_index < jl_array_len (s -> link_ids_relocs ));
1839
+ #endif
1804
1840
return ret ;
1805
1841
}
1806
1842
@@ -1890,13 +1926,24 @@ static void jl_update_all_gvars(jl_serializer_state *s, jl_image_t *image, uint3
1890
1926
reloc_t * gvars = (reloc_t * )& s -> gvar_record -> buf [0 ];
1891
1927
int gvar_link_index = 0 ;
1892
1928
int external_fns_link_index = 0 ;
1929
+ jl_array_t * link_ids = NULL ;
1893
1930
for (i = 0 ; i < l ; i ++ ) {
1894
1931
uintptr_t offset = gvars [i ];
1895
1932
uintptr_t v = 0 ;
1896
1933
if (i < external_fns_begin ) {
1897
- v = get_item_for_reloc (s , base , size , offset , s -> link_ids_gvars , & gvar_link_index );
1934
+ #ifdef _P64
1935
+ link_ids = s -> buildid_depmods_idxs ;
1936
+ #else
1937
+ link_ids = s -> link_ids_gvars ;
1938
+ #endif
1939
+ v = get_item_for_reloc (s , base , size , offset , link_ids , & gvar_link_index );
1898
1940
} else {
1899
- v = get_item_for_reloc (s , base , size , offset , s -> link_ids_external_fnvars , & external_fns_link_index );
1941
+ #ifdef _P64
1942
+ link_ids = s -> buildid_depmods_idxs ;
1943
+ #else
1944
+ link_ids = s -> link_ids_external_fnvars ;
1945
+ #endif
1946
+ v = get_item_for_reloc (s , base , size , offset , link_ids , & external_fns_link_index );
1900
1947
}
1901
1948
uintptr_t * gv = sysimg_gvars (image -> gvars_base , image -> gvars_offsets , i );
1902
1949
* gv = v ;
@@ -2221,7 +2268,7 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new
2221
2268
}
2222
2269
2223
2270
// In addition to the system image (where `worklist = NULL`), this can also save incremental images with external linkage
2224
- static void jl_save_system_image_to_stream (ios_t * f ,
2271
+ static void jl_save_system_image_to_stream (ios_t * f , jl_array_t * udeps ,
2225
2272
jl_array_t * worklist , jl_array_t * extext_methods ,
2226
2273
jl_array_t * new_specializations , jl_array_t * method_roots_list ,
2227
2274
jl_array_t * ext_targets , jl_array_t * edges ) JL_GC_DISABLED
@@ -2269,10 +2316,15 @@ static void jl_save_system_image_to_stream(ios_t *f,
2269
2316
arraylist_new (& s .fixup_types , 0 );
2270
2317
arraylist_new (& s .fixup_objs , 0 );
2271
2318
arraylist_new (& s .ccallable_list , 0 );
2319
+ #ifdef _P64
2320
+ s .buildid_depmods_idxs = image_to_depmodidx (jl_build_ids , udeps );
2321
+ s .link_ids_relocs = s .link_ids_gctags = s .link_ids_gvars = s .link_ids_external_fnvars = NULL ;
2322
+ #else
2272
2323
s .link_ids_relocs = jl_alloc_array_1d (jl_array_uint64_type , 0 );
2273
2324
s .link_ids_gctags = jl_alloc_array_1d (jl_array_uint64_type , 0 );
2274
2325
s .link_ids_gvars = jl_alloc_array_1d (jl_array_uint64_type , 0 );
2275
2326
s .link_ids_external_fnvars = jl_alloc_array_1d (jl_array_uint64_type , 0 );
2327
+ #endif
2276
2328
htable_new (& s .callers_with_edges , 0 );
2277
2329
jl_value_t * * const * const tags = get_tags (); // worklist == NULL ? get_tags() : NULL;
2278
2330
@@ -2371,21 +2423,21 @@ static void jl_save_system_image_to_stream(ios_t *f,
2371
2423
jl_write_relocations (& s );
2372
2424
}
2373
2425
2374
- if (sysimg .size > ((uintptr_t )1 << RELOC_TAG_OFFSET )) {
2426
+ if (sysimg .size > ((uintptr_t )1 << DEPS_IDX_OFFSET )) {
2375
2427
jl_printf (
2376
2428
JL_STDERR ,
2377
2429
"ERROR: system image too large: sysimg.size is %jd but the limit is %" PRIxPTR "\n" ,
2378
2430
(intmax_t )sysimg .size ,
2379
- ((uintptr_t )1 << RELOC_TAG_OFFSET )
2431
+ ((uintptr_t )1 << DEPS_IDX_OFFSET )
2380
2432
);
2381
2433
jl_exit (1 );
2382
2434
}
2383
- if (const_data .size / sizeof (void * ) > ((uintptr_t )1 << RELOC_TAG_OFFSET )) {
2435
+ if (const_data .size / sizeof (void * ) > ((uintptr_t )1 << DEPS_IDX_OFFSET )) {
2384
2436
jl_printf (
2385
2437
JL_STDERR ,
2386
2438
"ERROR: system image too large: const_data.size is %jd but the limit is %" PRIxPTR "\n" ,
2387
2439
(intmax_t )const_data .size ,
2388
- ((uintptr_t )1 << RELOC_TAG_OFFSET )* sizeof (void * )
2440
+ ((uintptr_t )1 << DEPS_IDX_OFFSET )* sizeof (void * )
2389
2441
);
2390
2442
jl_exit (1 );
2391
2443
}
@@ -2461,6 +2513,7 @@ static void jl_save_system_image_to_stream(ios_t *f,
2461
2513
jl_write_value (& s , ext_targets );
2462
2514
jl_write_value (& s , edges );
2463
2515
}
2516
+ #ifndef _P64
2464
2517
write_uint32 (f , jl_array_len (s .link_ids_gctags ));
2465
2518
ios_write (f , (char * )jl_array_data (s .link_ids_gctags ), jl_array_len (s .link_ids_gctags )* sizeof (uint64_t ));
2466
2519
write_uint32 (f , jl_array_len (s .link_ids_relocs ));
@@ -2469,6 +2522,7 @@ static void jl_save_system_image_to_stream(ios_t *f,
2469
2522
ios_write (f , (char * )jl_array_data (s .link_ids_gvars ), jl_array_len (s .link_ids_gvars )* sizeof (uint64_t ));
2470
2523
write_uint32 (f , jl_array_len (s .link_ids_external_fnvars ));
2471
2524
ios_write (f , (char * )jl_array_data (s .link_ids_external_fnvars ), jl_array_len (s .link_ids_external_fnvars )* sizeof (uint64_t ));
2525
+ #endif
2472
2526
write_uint32 (f , external_fns_begin );
2473
2527
jl_write_arraylist (s .s , & s .ccallable_list );
2474
2528
}
@@ -2585,7 +2639,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
2585
2639
* _native_data = jl_precompile (jl_options .compile_enabled == JL_OPTIONS_COMPILE_ALL );
2586
2640
}
2587
2641
native_functions = * _native_data ;
2588
- jl_save_system_image_to_stream (ff , worklist , extext_methods , new_specializations , method_roots_list , ext_targets , edges );
2642
+ jl_save_system_image_to_stream (ff , * udeps , worklist , extext_methods , new_specializations , method_roots_list , ext_targets , edges );
2589
2643
native_functions = NULL ;
2590
2644
if (worklist ) {
2591
2645
// Re-enable running julia code for postoutput hooks, atexit, etc.
@@ -2758,6 +2812,9 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
2758
2812
offset_ext_targets = jl_read_offset (& s );
2759
2813
offset_edges = jl_read_offset (& s );
2760
2814
}
2815
+ #ifdef _P64
2816
+ s .buildid_depmods_idxs = depmod_to_imageidx (depmods );
2817
+ #else
2761
2818
size_t nlinks_gctags = read_uint32 (f );
2762
2819
if (nlinks_gctags > 0 ) {
2763
2820
s .link_ids_gctags = jl_alloc_array_1d (jl_array_uint64_type , nlinks_gctags );
@@ -2778,6 +2835,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
2778
2835
s .link_ids_external_fnvars = jl_alloc_array_1d (jl_array_uint64_type , nlinks_external_fnvars );
2779
2836
ios_read (f , (char * )jl_array_data (s .link_ids_external_fnvars ), nlinks_external_fnvars * sizeof (uint64_t ));
2780
2837
}
2838
+ #endif
2781
2839
uint32_t external_fns_begin = read_uint32 (f );
2782
2840
jl_read_arraylist (s .s , ccallable_list ? ccallable_list : & s .ccallable_list );
2783
2841
if (s .incremental ) {
@@ -2804,10 +2862,19 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
2804
2862
* base = image_base ;
2805
2863
2806
2864
s .s = & sysimg ;
2807
- jl_read_reloclist (& s , s .link_ids_gctags , GC_OLD ); // gctags
2865
+ #ifdef _P64
2866
+ jl_array_t * link_ids = NULL ;
2867
+ #else
2868
+ jl_array_t * link_ids = s .link_ids_gctags ;
2869
+ #endif
2870
+ jl_read_reloclist (& s , link_ids , GC_OLD ); // gctags
2808
2871
size_t sizeof_tags = ios_pos (& relocs );
2809
2872
(void )sizeof_tags ;
2810
- jl_read_reloclist (& s , s .link_ids_relocs , 0 ); // general relocs
2873
+ #ifdef _P64
2874
+ #else
2875
+ link_ids = s .link_ids_relocs ;
2876
+ #endif
2877
+ jl_read_reloclist (& s , link_ids , 0 ); // general relocs
2811
2878
// s.link_ids_gvars will be processed in `jl_update_all_gvars`
2812
2879
// s.link_ids_external_fns will be processed in `jl_update_all_gvars`
2813
2880
jl_update_all_gvars (& s , image , external_fns_begin ); // gvars relocs
0 commit comments