@@ -357,6 +357,12 @@ typedef struct {
357357 arraylist_t fixup_types ; // a list of locations of types requiring (re)caching
358358 arraylist_t fixup_objs ; // a list of locations of objects requiring (re)caching
359359 arraylist_t ccallable_list ; // @ccallable entry points to install
360+ #ifdef _P64
361+ // On 64-bit, we can encode the "`depmods` index" in the reftag, so all we need is a mapping between
362+ // the buildid_idx & depmods_idx:
363+ jl_array_t * buildid_depmods_idxs ;
364+ // On 64bit, all the `link_ids_*` arrays below will be NULL.
365+ #endif
360366 // record of build_ids for all external linkages, in order of serialization for the current sysimg/pkgimg
361367 // conceptually, the base pointer for the jth externally-linked item is determined from
362368 // i = findfirst(==(link_ids[j]), jl_build_ids)
@@ -387,7 +393,8 @@ enum RefTags {
387393 SymbolRef , // symbols
388394 FunctionRef , // generic functions
389395 BuiltinFunctionRef , // builtin functions
390- ExternalLinkage // items defined externally (used when serializing packages)
396+ SysimageLinkage , // reference to the sysimage (from pkgimage)
397+ ExternalLinkage // reference to some other pkgimage
391398};
392399
393400// calling conventions for internal entry points.
@@ -405,9 +412,11 @@ typedef enum {
405412
406413#ifdef _P64
407414#define RELOC_TAG_OFFSET 61
415+ #define DEPS_IDX_OFFSET 40 // only on 64-bit can we encode the dependency-index as part of the tagged reloc
408416#else
409417// this supports up to 8 RefTags, 512MB of pointer data, and 4/2 (64/32-bit) GB of constant data.
410418#define RELOC_TAG_OFFSET 29
419+ #define DEPS_IDX_OFFSET RELOC_TAG_OFFSET
411420#endif
412421
413422#if RELOC_TAG_OFFSET <= 32
@@ -759,7 +768,7 @@ done_fields: ;
759768 }
760769 arraylist_push (& serialization_queue , (void * ) v );
761770 size_t idx = serialization_queue .len - 1 ;
762- assert (serialization_queue .len < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "too many items to serialize" );
771+ assert (serialization_queue .len < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "too many items to serialize" );
763772
764773 * bp = (void * )((char * )HT_NOTFOUND + 1 + idx );
765774}
@@ -864,29 +873,40 @@ static void write_pointer(ios_t *s) JL_NOTSAFEPOINT
864873static uintptr_t add_external_linkage (jl_serializer_state * s , jl_value_t * v , jl_array_t * link_ids ) {
865874 size_t i = external_blob_index (v );
866875 if (i < n_linkage_blobs ()) {
876+ // We found the sysimg/pkg that this item links against
877+ // Compute the relocation code
878+ size_t offset = (uintptr_t )v - (uintptr_t )jl_linkage_blobs .items [2 * i ];
879+ offset /= sizeof (void * );
880+ assert (offset < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "offset to external image too large" );
881+
882+ if (i == 0 )
883+ return ((uintptr_t )SysimageLinkage << RELOC_TAG_OFFSET ) + offset ; // sysimage
867884 assert (link_ids && jl_is_array (link_ids ));
885+ #ifdef _P64
886+ uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids );
887+ return ((uintptr_t )ExternalLinkage << RELOC_TAG_OFFSET )
888+ + (((uintptr_t )link_id_data [i ]) << DEPS_IDX_OFFSET ) + offset ; // on 64-bit, link_ids stores the mapping from build_id_idx -> deps_idx
889+ #else
890+ // On 32bit, we store the image key in `link_ids`
868891 assert (jl_build_ids && jl_is_array (jl_build_ids ));
869892 uint64_t * build_id_data = (uint64_t * )jl_array_data (jl_build_ids );
870- // We found the sysimg/pkg that this item links against
871- // Store the image key in `link_ids`
872893 jl_array_grow_end (link_ids , 1 );
873- uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids );
894+ uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids ); // wait until after the `grow`
874895 link_id_data [jl_array_len (link_ids )- 1 ] = build_id_data [i ];
875- // Compute the relocation code
876- size_t offset = (uintptr_t )v - (uintptr_t )jl_linkage_blobs .items [2 * i ];
877- offset /= sizeof (void * );
878- assert (offset < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "offset to external image too large" );
879- // 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);
880- // jl_(v);
881896 return ((uintptr_t )ExternalLinkage << RELOC_TAG_OFFSET ) + offset ;
897+ #endif
882898 }
883899 return 0 ;
884900}
885901
886902// Return the integer `id` for `v`. Generically this is looked up in `serialization_order`,
887903// but symbols, small integers, and a couple of special items (`nothing` and the root Task)
888904// have special handling.
905+ #ifdef _P64
906+ #define backref_id (s , v , link_ids ) _backref_id(s, (jl_value_t*)(v), s->buildid_depmods_idxs)
907+ #else
889908#define backref_id (s , v , link_ids ) _backref_id(s, (jl_value_t*)(v), link_ids)
909+ #endif
890910static uintptr_t _backref_id (jl_serializer_state * s , jl_value_t * v , jl_array_t * link_ids ) JL_NOTSAFEPOINT
891911{
892912 assert (v != NULL && "cannot get backref to NULL object" );
@@ -899,7 +919,7 @@ static uintptr_t _backref_id(jl_serializer_state *s, jl_value_t *v, jl_array_t *
899919 write_uint32 (s -> symbols , l );
900920 ios_write (s -> symbols , jl_symbol_name ((jl_sym_t * )v ), l + 1 );
901921 size_t offset = ++ nsym_tag ;
902- assert (offset < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "too many symbols" );
922+ assert (offset < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "too many symbols" );
903923 idx = (void * )((char * )HT_NOTFOUND + ((uintptr_t )SymbolRef << RELOC_TAG_OFFSET ) + offset );
904924 * pidx = idx ;
905925 }
@@ -1144,7 +1164,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
11441164 // write data and relocations
11451165 newa -> data = NULL ; // relocation offset
11461166 data /= sizeof (void * );
1147- assert (data < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "offset to constant data too large" );
1167+ assert (data < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "offset to constant data too large" );
11481168 arraylist_push (& s -> relocs_list , (void * )(reloc_offset + offsetof(jl_array_t , data ))); // relocation location
11491169 arraylist_push (& s -> relocs_list , (void * )(((uintptr_t )ConstDataRef << RELOC_TAG_OFFSET ) + data )); // relocation target
11501170 if (jl_is_cpointer_type (et )) {
@@ -1247,7 +1267,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
12471267 uintptr_t data = LLT_ALIGN (ios_pos (s -> const_data ), 8 );
12481268 write_padding (s -> const_data , data - ios_pos (s -> const_data ));
12491269 data /= sizeof (void * );
1250- assert (data < ((uintptr_t )1 << RELOC_TAG_OFFSET ) && "offset to constant data too large" );
1270+ assert (data < ((uintptr_t )1 << DEPS_IDX_OFFSET ) && "offset to constant data too large" );
12511271 arraylist_push (& s -> relocs_list , (void * )(reloc_offset + 8 )); // relocation location
12521272 arraylist_push (& s -> relocs_list , (void * )(((uintptr_t )ConstDataRef << RELOC_TAG_OFFSET ) + data )); // relocation target
12531273 void * pdata = jl_unbox_voidpointer (jl_get_nth_field (v , 2 ));
@@ -1534,6 +1554,8 @@ static uintptr_t get_reloc_for_item(uintptr_t reloc_item, size_t reloc_offset)
15341554 case FunctionRef :
15351555 assert (offset < JL_API_MAX && "unknown function pointer id" );
15361556 break ;
1557+ case SysimageLinkage :
1558+ break ;
15371559 case ExternalLinkage :
15381560 break ;
15391561 default :
@@ -1600,15 +1622,25 @@ static inline uintptr_t get_item_for_reloc(jl_serializer_state *s, uintptr_t bas
16001622 //default:
16011623 assert ("corrupt relocation item id" );
16021624 }
1625+ case SysimageLinkage :
1626+ assert (jl_linkage_blobs .len > 0 );
1627+ return (uintptr_t )jl_linkage_blobs .items [0 ] + offset * sizeof (void * );
16031628 case ExternalLinkage :
16041629 assert (link_ids );
1605- assert (link_index );
16061630 assert (jl_build_ids );
16071631 uint64_t * link_id_data = (uint64_t * )jl_array_data (link_ids );
16081632 uint64_t * build_id_data = (uint64_t * )jl_array_data (jl_build_ids );
1633+ #ifdef _P64
1634+ size_t depsidx = offset >> DEPS_IDX_OFFSET ;
1635+ offset &= ((size_t )1 << DEPS_IDX_OFFSET ) - 1 ;
1636+ assert (depsidx < jl_array_len (link_ids )); // on 64-bit, here link_ids is a build_id lookup by depmod index
1637+ uint64_t build_id = link_id_data [depsidx ];
1638+ #else
1639+ assert (link_index );
16091640 assert (0 <= * link_index && * link_index < jl_array_len (link_ids ));
16101641 uint64_t build_id = link_id_data [* link_index ];
16111642 * link_index += 1 ;
1643+ #endif
16121644 size_t i = 0 , nids = jl_array_len (jl_build_ids );
16131645 while (i < nids ) {
16141646 if (build_id == build_id_data [i ])
@@ -1800,8 +1832,12 @@ static jl_value_t *jl_delayed_reloc(jl_serializer_state *s, uintptr_t offset) JL
18001832 uintptr_t base = (uintptr_t )& s -> s -> buf [0 ];
18011833 size_t size = s -> s -> size ;
18021834 int link_index = 0 ;
1835+ #ifdef _P64
1836+ jl_value_t * ret = (jl_value_t * )get_item_for_reloc (s , base , size , offset , s -> buildid_depmods_idxs , & link_index );
1837+ #else
18031838 jl_value_t * ret = (jl_value_t * )get_item_for_reloc (s , base , size , offset , s -> link_ids_relocs , & link_index );
18041839 assert (link_index < jl_array_len (s -> link_ids_relocs ));
1840+ #endif
18051841 return ret ;
18061842}
18071843
@@ -1891,13 +1927,24 @@ static void jl_update_all_gvars(jl_serializer_state *s, jl_image_t *image, uint3
18911927 reloc_t * gvars = (reloc_t * )& s -> gvar_record -> buf [0 ];
18921928 int gvar_link_index = 0 ;
18931929 int external_fns_link_index = 0 ;
1930+ jl_array_t * link_ids = NULL ;
18941931 for (i = 0 ; i < l ; i ++ ) {
18951932 uintptr_t offset = gvars [i ];
18961933 uintptr_t v = 0 ;
18971934 if (i < external_fns_begin ) {
1898- v = get_item_for_reloc (s , base , size , offset , s -> link_ids_gvars , & gvar_link_index );
1935+ #ifdef _P64
1936+ link_ids = s -> buildid_depmods_idxs ;
1937+ #else
1938+ link_ids = s -> link_ids_gvars ;
1939+ #endif
1940+ v = get_item_for_reloc (s , base , size , offset , link_ids , & gvar_link_index );
18991941 } else {
1900- v = get_item_for_reloc (s , base , size , offset , s -> link_ids_external_fnvars , & external_fns_link_index );
1942+ #ifdef _P64
1943+ link_ids = s -> buildid_depmods_idxs ;
1944+ #else
1945+ link_ids = s -> link_ids_external_fnvars ;
1946+ #endif
1947+ v = get_item_for_reloc (s , base , size , offset , link_ids , & external_fns_link_index );
19011948 }
19021949 uintptr_t * gv = sysimg_gvars (image -> gvars_base , image -> gvars_offsets , i );
19031950 * gv = v ;
@@ -2218,7 +2265,7 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new
22182265}
22192266
22202267// In addition to the system image (where `worklist = NULL`), this can also save incremental images with external linkage
2221- static void jl_save_system_image_to_stream (ios_t * f ,
2268+ static void jl_save_system_image_to_stream (ios_t * f , jl_array_t * udeps ,
22222269 jl_array_t * worklist , jl_array_t * extext_methods ,
22232270 jl_array_t * new_specializations , jl_array_t * method_roots_list ,
22242271 jl_array_t * ext_targets , jl_array_t * edges ) JL_GC_DISABLED
@@ -2266,10 +2313,15 @@ static void jl_save_system_image_to_stream(ios_t *f,
22662313 arraylist_new (& s .fixup_types , 0 );
22672314 arraylist_new (& s .fixup_objs , 0 );
22682315 arraylist_new (& s .ccallable_list , 0 );
2316+ #ifdef _P64
2317+ s .buildid_depmods_idxs = image_to_depmodidx (jl_build_ids , udeps );
2318+ s .link_ids_relocs = s .link_ids_gctags = s .link_ids_gvars = s .link_ids_external_fnvars = NULL ;
2319+ #else
22692320 s .link_ids_relocs = jl_alloc_array_1d (jl_array_uint64_type , 0 );
22702321 s .link_ids_gctags = jl_alloc_array_1d (jl_array_uint64_type , 0 );
22712322 s .link_ids_gvars = jl_alloc_array_1d (jl_array_uint64_type , 0 );
22722323 s .link_ids_external_fnvars = jl_alloc_array_1d (jl_array_uint64_type , 0 );
2324+ #endif
22732325 htable_new (& s .callers_with_edges , 0 );
22742326 jl_value_t * * const * const tags = get_tags (); // worklist == NULL ? get_tags() : NULL;
22752327
@@ -2368,21 +2420,21 @@ static void jl_save_system_image_to_stream(ios_t *f,
23682420 jl_write_relocations (& s );
23692421 }
23702422
2371- if (sysimg .size > ((uintptr_t )1 << RELOC_TAG_OFFSET )) {
2423+ if (sysimg .size > ((uintptr_t )1 << DEPS_IDX_OFFSET )) {
23722424 jl_printf (
23732425 JL_STDERR ,
23742426 "ERROR: system image too large: sysimg.size is %jd but the limit is %" PRIxPTR "\n" ,
23752427 (intmax_t )sysimg .size ,
2376- ((uintptr_t )1 << RELOC_TAG_OFFSET )
2428+ ((uintptr_t )1 << DEPS_IDX_OFFSET )
23772429 );
23782430 jl_exit (1 );
23792431 }
2380- if (const_data .size / sizeof (void * ) > ((uintptr_t )1 << RELOC_TAG_OFFSET )) {
2432+ if (const_data .size / sizeof (void * ) > ((uintptr_t )1 << DEPS_IDX_OFFSET )) {
23812433 jl_printf (
23822434 JL_STDERR ,
23832435 "ERROR: system image too large: const_data.size is %jd but the limit is %" PRIxPTR "\n" ,
23842436 (intmax_t )const_data .size ,
2385- ((uintptr_t )1 << RELOC_TAG_OFFSET )* sizeof (void * )
2437+ ((uintptr_t )1 << DEPS_IDX_OFFSET )* sizeof (void * )
23862438 );
23872439 jl_exit (1 );
23882440 }
@@ -2458,6 +2510,7 @@ static void jl_save_system_image_to_stream(ios_t *f,
24582510 jl_write_value (& s , ext_targets );
24592511 jl_write_value (& s , edges );
24602512 }
2513+ #ifndef _P64
24612514 write_uint32 (f , jl_array_len (s .link_ids_gctags ));
24622515 ios_write (f , (char * )jl_array_data (s .link_ids_gctags ), jl_array_len (s .link_ids_gctags )* sizeof (uint64_t ));
24632516 write_uint32 (f , jl_array_len (s .link_ids_relocs ));
@@ -2466,6 +2519,7 @@ static void jl_save_system_image_to_stream(ios_t *f,
24662519 ios_write (f , (char * )jl_array_data (s .link_ids_gvars ), jl_array_len (s .link_ids_gvars )* sizeof (uint64_t ));
24672520 write_uint32 (f , jl_array_len (s .link_ids_external_fnvars ));
24682521 ios_write (f , (char * )jl_array_data (s .link_ids_external_fnvars ), jl_array_len (s .link_ids_external_fnvars )* sizeof (uint64_t ));
2522+ #endif
24692523 write_uint32 (f , external_fns_begin );
24702524 jl_write_arraylist (s .s , & s .ccallable_list );
24712525 }
@@ -2592,7 +2646,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
25922646 }
25932647 if (_native_data != NULL )
25942648 native_functions = * _native_data ;
2595- jl_save_system_image_to_stream (ff , worklist , extext_methods , new_specializations , method_roots_list , ext_targets , edges );
2649+ jl_save_system_image_to_stream (ff , * udeps , worklist , extext_methods , new_specializations , method_roots_list , ext_targets , edges );
25962650 if (_native_data != NULL )
25972651 native_functions = NULL ;
25982652 // make sure we don't run any Julia code concurrently before this point
@@ -2765,6 +2819,9 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
27652819 offset_ext_targets = jl_read_offset (& s );
27662820 offset_edges = jl_read_offset (& s );
27672821 }
2822+ #ifdef _P64
2823+ s .buildid_depmods_idxs = depmod_to_imageidx (depmods );
2824+ #else
27682825 size_t nlinks_gctags = read_uint32 (f );
27692826 if (nlinks_gctags > 0 ) {
27702827 s .link_ids_gctags = jl_alloc_array_1d (jl_array_uint64_type , nlinks_gctags );
@@ -2785,6 +2842,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
27852842 s .link_ids_external_fnvars = jl_alloc_array_1d (jl_array_uint64_type , nlinks_external_fnvars );
27862843 ios_read (f , (char * )jl_array_data (s .link_ids_external_fnvars ), nlinks_external_fnvars * sizeof (uint64_t ));
27872844 }
2845+ #endif
27882846 uint32_t external_fns_begin = read_uint32 (f );
27892847 jl_read_arraylist (s .s , ccallable_list ? ccallable_list : & s .ccallable_list );
27902848 if (s .incremental ) {
@@ -2811,10 +2869,19 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
28112869 * base = image_base ;
28122870
28132871 s .s = & sysimg ;
2814- jl_read_reloclist (& s , s .link_ids_gctags , GC_OLD ); // gctags
2872+ #ifdef _P64
2873+ jl_array_t * link_ids = NULL ;
2874+ #else
2875+ jl_array_t * link_ids = s .link_ids_gctags ;
2876+ #endif
2877+ jl_read_reloclist (& s , link_ids , GC_OLD ); // gctags
28152878 size_t sizeof_tags = ios_pos (& relocs );
28162879 (void )sizeof_tags ;
2817- jl_read_reloclist (& s , s .link_ids_relocs , 0 ); // general relocs
2880+ #ifdef _P64
2881+ #else
2882+ link_ids = s .link_ids_relocs ;
2883+ #endif
2884+ jl_read_reloclist (& s , link_ids , 0 ); // general relocs
28182885 // s.link_ids_gvars will be processed in `jl_update_all_gvars`
28192886 // s.link_ids_external_fns will be processed in `jl_update_all_gvars`
28202887 jl_update_all_gvars (& s , image , external_fns_begin ); // gvars relocs
0 commit comments