LCOV - code coverage report
Current view: top level - src - dump.c (source / functions) Hit Total Coverage
Test: [build process] commit ef510b1f346f4c9f9d86eaceace5ca54961a1dbc Lines: 711 2162 32.9 %
Date: 2022-07-17 01:01:28 Functions: 33 76 43.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 336 1285 26.1 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : /*
       4                 :            :   saving and restoring precompiled modules (.ji files)
       5                 :            : */
       6                 :            : #include <stdlib.h>
       7                 :            : #include <string.h>
       8                 :            : 
       9                 :            : #include "julia.h"
      10                 :            : #include "julia_internal.h"
      11                 :            : #include "julia_gcext.h"
      12                 :            : #include "builtin_proto.h"
      13                 :            : #include "serialize.h"
      14                 :            : 
      15                 :            : #ifndef _OS_WINDOWS_
      16                 :            : #include <dlfcn.h>
      17                 :            : #endif
      18                 :            : 
      19                 :            : #include "valgrind.h"
      20                 :            : #include "julia_assert.h"
      21                 :            : 
      22                 :            : #ifdef __cplusplus
      23                 :            : extern "C" {
      24                 :            : #endif
      25                 :            : 
      26                 :            : // This file, together with ircode.c, allows (de)serialization between
      27                 :            : // modules and *.ji cache files. `jl_save_incremental` gets called as the final step
      28                 :            : // during package precompilation, and `_jl_restore_incremental` by `using SomePkg`
      29                 :            : // whenever `SomePkg` has not yet been loaded.
      30                 :            : 
      31                 :            : // Types, methods, and method instances form a graph that may have cycles, so
      32                 :            : // serialization has to break these cycles. This is handled via "backreferences,"
      33                 :            : // referring to already (de)serialized items by an index. It is critial to ensure
      34                 :            : // that the indexes of these backreferences align precisely during serialization
      35                 :            : // and deserialization, to ensure that these integer indexes mean the same thing
      36                 :            : // under both circumstances. Consequently, if you are modifying this file, be
      37                 :            : // careful to match the sequence, if necessary reserving space for something that will
      38                 :            : // be updated later.
      39                 :            : 
      40                 :            : // It is also necessary to save & restore references to externally-defined
      41                 :            : // objects, e.g., for package methods that call methods defined in Base or
      42                 :            : // elsewhere. Consequently during deserialization there's a distinction between
      43                 :            : // "reference" types, methods, and method instances (essentially like a
      44                 :            : // GlobalRef), and "recached" version that refer to the actual entity in the
      45                 :            : // running session. As a concrete example, types have a module in which they are
      46                 :            : // defined, but once defined those types can be used by any dependent package.
      47                 :            : // We don't store the full type definition again in that dependent package, we
      48                 :            : // just encode a reference to that type. In the running session, such references
      49                 :            : // are merely pointers to the type-cache, but the specific address is obviously
      50                 :            : // not likely to be reproducible across sessions (it will differ between the
      51                 :            : // session in which you precompile and the session in which you're using the
      52                 :            : // package). Hence, during serialization we recode them as "verbose" references
      53                 :            : // (that follow Julia syntax to allow them to be reconstructed), but on
      54                 :            : // deserialization we have to replace those verbose references with the
      55                 :            : // appropriate pointer in the user's running session. We complete
      56                 :            : // deserialization before beginning the process of recaching, because we need
      57                 :            : // the backreferences during deserialization and the actual objects during
      58                 :            : // recaching.
      59                 :            : 
      60                 :            : // Finally, because our backedge graph is not bidirectional, special handling is
      61                 :            : // required to identify backedges from external methods that call internal methods.
      62                 :            : // These get set aside and restored at the end of deserialization.
      63                 :            : 
      64                 :            : // In broad terms, the major steps in serialization are:
      65                 :            : // - starting from a "worklist" of modules, write the header. This stores things
      66                 :            : //   like the Julia build this was precompiled for, the package dependencies,
      67                 :            : //   the list of include files, file modification times, etc.
      68                 :            : // - gather the collection of items to be written to this precompile file. This
      69                 :            : //   includes accessible from the module's binding table (if they are owned by a
      70                 :            : //   worklist module), but also includes things like methods added to external
      71                 :            : //   functions, instances of external methods that were newly type-inferred
      72                 :            : //   while precompiling a worklist module, and backedges of callees that were
      73                 :            : //   called by methods in this package. By and large, these latter items are not
      74                 :            : //   referenced by the module(s) in the package, and so these have to be
      75                 :            : //   extracted by traversing the entire system searching for things that do link
      76                 :            : //   back to a module in the worklist.
      77                 :            : // - serialize all the items. The first time we encounter an item, we serialized
      78                 :            : //   it, and on future references (pointers) to that item we replace them with
      79                 :            : //   with a backreference.  `jl_serialize_*` functions handle this work.
      80                 :            : // - write source text for the files that defined the package. This is primarily
      81                 :            : //   to support Revise.jl.
      82                 :            : 
      83                 :            : // Deserialization is the mirror image of serialization, but in some ways is
      84                 :            : // trickier:
      85                 :            : // - we have to merge items into the running session (recaching as described
      86                 :            : //   above) and handle cases like having two dependent packages caching the same
      87                 :            : //   MethodInstance of a dependency
      88                 :            : // - we have to check for invalidation---the user might have loaded other
      89                 :            : //   packages that define methods that supersede some of the dispatches chosen
      90                 :            : //   when the package was precompiled, or this package might define methods that
      91                 :            : //   supercede dispatches for previously-loaded packages. These two
      92                 :            : //   possibilities are checked during backedge and method insertion,
      93                 :            : //   respectively.
      94                 :            : // Both of these mean that deserialization requires one to look up a lot of
      95                 :            : // things in the running session; for example, for invalidation checks we have
      96                 :            : // to do type-intersection between signatures used for MethodInstances and the
      97                 :            : // current session's full MethodTable. In practice, such steps dominate package
      98                 :            : // loading time (it has very little to do with I/O or deserialization
      99                 :            : // performance). Paradoxically, sometimes storing more code in a package can
     100                 :            : // lead to faster performance: references to things in the same .ji file can be
     101                 :            : // precomputed, but external references have to be looked up. You can see this
     102                 :            : // effect in the benchmarks for #43990, where storing external MethodInstances
     103                 :            : // and CodeInstances (more code than was stored previously) actually decreased
     104                 :            : // load times for many packages.
     105                 :            : 
     106                 :            : // Note that one should prioritize deserialization performance over serialization performance,
     107                 :            : // since deserialization may be performed much more often than serialization.
     108                 :            : // Certain items are preprocessed during serialization to save work when they are
     109                 :            : // later deserialized.
     110                 :            : 
     111                 :            : 
     112                 :            : // TODO: put WeakRefs on the weak_refs list during deserialization
     113                 :            : // TODO: handle finalizers
     114                 :            : 
     115                 :            : // type => tag hash for a few core types (e.g., Expr, PhiNode, etc)
     116                 :            : static htable_t ser_tag;
     117                 :            : // tag => type mapping, the reverse of ser_tag
     118                 :            : static jl_value_t *deser_tag[256];
     119                 :            : // hash of some common symbols, encoded as CommonSym_tag plus 1 byte
     120                 :            : static htable_t common_symbol_tag;
     121                 :            : static jl_value_t *deser_symbols[256];
     122                 :            : 
     123                 :            : // table of all objects that have been deserialized, indexed by pos
     124                 :            : // (the order in the serializer stream). the low
     125                 :            : // bit is reserved for flagging certain entries and pos is
     126                 :            : // left shift by 1
     127                 :            : static htable_t backref_table;    // pos = backref_table[obj]
     128                 :            : static int backref_table_numel;
     129                 :            : static arraylist_t backref_list;  // obj = backref_list[pos]
     130                 :            : 
     131                 :            : // set of all CodeInstances yet to be (in)validated
     132                 :            : static htable_t new_code_instance_validate;
     133                 :            : 
     134                 :            : // list of (jl_value_t **loc, size_t pos) entries
     135                 :            : // for anything that was flagged by the deserializer for later
     136                 :            : // type-rewriting of some sort. pos is the index in backref_list.
     137                 :            : static arraylist_t flagref_list;
     138                 :            : // ref => value hash for looking up the "real" entity from
     139                 :            : // the deserialized ref. Used for entities that must be unique,
     140                 :            : // like types, methods, and method instances
     141                 :            : static htable_t uniquing_table;
     142                 :            : 
     143                 :            : // list of (size_t pos, itemkey) entries
     144                 :            : // for the serializer to mark values in need of rework
     145                 :            : // during deserialization later
     146                 :            : // This includes items that need rehashing (IdDict, TypeMapLevels)
     147                 :            : // and modules.
     148                 :            : static arraylist_t reinit_list;
     149                 :            : 
     150                 :            : // list of modules being serialized
     151                 :            : // This is not quite globally rooted, but we take care to only
     152                 :            : // ever assigned rooted values here.
     153                 :            : static jl_array_t *serializer_worklist JL_GLOBALLY_ROOTED;
     154                 :            : // The set of external MethodInstances we want to serialize
     155                 :            : // (methods owned by other modules that were first inferred for a
     156                 :            : //  module currently being serialized)
     157                 :            : static htable_t external_mis;
     158                 :            : // Inference tracks newly-inferred MethodInstances during precompilation
     159                 :            : // and registers them by calling jl_set_newly_inferred
     160                 :            : static jl_array_t *newly_inferred JL_GLOBALLY_ROOTED;
     161                 :            : 
     162                 :            : // New roots to add to Methods. These can't be added until after
     163                 :            : // recaching is complete, so we have to hold on to them separately
     164                 :            : // Stored as method => (worklist_key, newroots)
     165                 :            : // The worklist_key is the uuid of the module that triggered addition
     166                 :            : // of `newroots`. This is needed because CodeInstances reference
     167                 :            : // their roots by "index", and we use a bipartite index
     168                 :            : // (module_uuid, integer_index) to make indexes "relocatable"
     169                 :            : // (meaning that users can load modules in different orders and
     170                 :            : //  so the absolute integer index of a root is not reproducible).
     171                 :            : // See the "root blocks" section of method.c for more detail.
     172                 :            : static htable_t queued_method_roots;
     173                 :            : 
     174                 :            : // inverse of backedges graph (caller=>callees hash)
     175                 :            : htable_t edges_map;
     176                 :            : 
     177                 :            : // list of requested ccallable signatures
     178                 :            : static arraylist_t ccallable_list;
     179                 :            : 
     180                 :            : typedef struct {
     181                 :            :     ios_t *s;
     182                 :            :     jl_ptls_t ptls;
     183                 :            :     jl_array_t *loaded_modules_array;
     184                 :            : } jl_serializer_state;
     185                 :            : 
     186                 :            : static jl_value_t *jl_idtable_type = NULL;
     187                 :            : static jl_typename_t *jl_idtable_typename = NULL;
     188                 :            : static jl_value_t *jl_bigint_type = NULL;
     189                 :            : static int gmp_limb_size = 0;
     190                 :            : 
     191                 :        564 : static void write_uint64(ios_t *s, uint64_t i) JL_NOTSAFEPOINT
     192                 :            : {
     193                 :        564 :     ios_write(s, (char*)&i, 8);
     194                 :        564 : }
     195                 :            : 
     196                 :          4 : static void write_float64(ios_t *s, double x) JL_NOTSAFEPOINT
     197                 :            : {
     198                 :          4 :     write_uint64(s, *((uint64_t*)&x));
     199                 :          4 : }
     200                 :            : 
     201                 :  116105000 : void *jl_lookup_ser_tag(jl_value_t *v)
     202                 :            : {
     203                 :  116105000 :     return ptrhash_get(&ser_tag, v);
     204                 :            : }
     205                 :            : 
     206                 :    8253400 : void *jl_lookup_common_symbol(jl_value_t *v)
     207                 :            : {
     208                 :    8253400 :     return ptrhash_get(&common_symbol_tag, v);
     209                 :            : }
     210                 :            : 
     211                 :   75068100 : jl_value_t *jl_deser_tag(uint8_t tag)
     212                 :            : {
     213                 :   75068100 :     return deser_tag[tag];
     214                 :            : }
     215                 :            : 
     216                 :    7441660 : jl_value_t *jl_deser_symbol(uint8_t tag)
     217                 :            : {
     218                 :    7441660 :     return deser_symbols[tag];
     219                 :            : }
     220                 :            : 
     221                 :          0 : uint64_t jl_worklist_key(jl_array_t *worklist)
     222                 :            : {
     223         [ #  # ]:          0 :     assert(jl_is_array(worklist));
     224                 :          0 :     size_t len = jl_array_len(worklist);
     225         [ #  # ]:          0 :     if (len > 0) {
     226                 :          0 :         jl_module_t *topmod = (jl_module_t*)jl_array_ptr_ref(worklist, len-1);
     227         [ #  # ]:          0 :         assert(jl_is_module(topmod));
     228                 :          0 :         return topmod->build_id;
     229                 :            :     }
     230                 :          0 :     return 0;
     231                 :            : }
     232                 :            : 
     233                 :            : // --- serialize ---
     234                 :            : 
     235                 :            : #define jl_serialize_value(s, v) jl_serialize_value_((s), (jl_value_t*)(v), 0)
     236                 :            : static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED;
     237                 :            : 
     238                 :          0 : static void jl_serialize_cnull(jl_serializer_state *s, jl_value_t *t)
     239                 :            : {
     240                 :          0 :     backref_table_numel++;
     241                 :          0 :     write_uint8(s->s, TAG_CNULL);
     242                 :          0 :     jl_serialize_value(s, t);
     243                 :          0 : }
     244                 :            : 
     245                 :     227440 : static int module_in_worklist(jl_module_t *mod) JL_NOTSAFEPOINT
     246                 :            : {
     247                 :     227440 :     int i, l = jl_array_len(serializer_worklist);
     248         [ +  + ]:     454810 :     for (i = 0; i < l; i++) {
     249                 :     227440 :         jl_module_t *workmod = (jl_module_t*)jl_array_ptr_ref(serializer_worklist, i);
     250   [ +  -  +  + ]:     227440 :         if (jl_is_module(workmod) && jl_is_submodule(mod, workmod))
     251                 :         70 :             return 1;
     252                 :            :     }
     253                 :     227370 :     return 0;
     254                 :            : }
     255                 :            : 
     256                 :     245494 : static int method_instance_in_queue(jl_method_instance_t *mi)
     257                 :            : {
     258                 :     245494 :     return ptrhash_get(&external_mis, mi) != HT_NOTFOUND;
     259                 :            : }
     260                 :            : 
     261                 :            : // compute whether a type references something internal to worklist
     262                 :            : // and thus could not have existed before deserialize
     263                 :            : // and thus does not need delayed unique-ing
     264                 :         54 : static int type_in_worklist(jl_datatype_t *dt) JL_NOTSAFEPOINT
     265                 :            : {
     266         [ +  + ]:         54 :     if (module_in_worklist(dt->name->module))
     267                 :         14 :         return 1;
     268                 :         40 :     int i, l = jl_svec_len(dt->parameters);
     269         [ +  + ]:         64 :     for (i = 0; i < l; i++) {
     270                 :         28 :         jl_value_t *p = jl_unwrap_unionall(jl_tparam(dt, i));
     271                 :            :         // TODO: what about Union and TypeVar??
     272   [ +  +  +  + ]:         28 :         if (type_in_worklist((jl_datatype_t*)(jl_is_datatype(p) ? p : jl_typeof(p))))
     273                 :          4 :             return 1;
     274                 :            :     }
     275                 :         36 :     return 0;
     276                 :            : }
     277                 :            : 
     278                 :            : static int type_recursively_external(jl_datatype_t *dt);
     279                 :            : 
     280                 :         10 : static int type_parameter_recursively_external(jl_value_t *p0) JL_NOTSAFEPOINT
     281                 :            : {
     282         [ +  + ]:         10 :     if (!jl_is_concrete_type(p0))
     283                 :          4 :         return 0;
     284                 :          6 :     jl_datatype_t *p = (jl_datatype_t*)p0;
     285                 :            :     //while (jl_is_unionall(p)) {
     286                 :            :     //    if (!type_parameter_recursively_external(((jl_unionall_t*)p)->var->lb))
     287                 :            :     //        return 0;
     288                 :            :     //    if (!type_parameter_recursively_external(((jl_unionall_t*)p)->var->ub))
     289                 :            :     //        return 0;
     290                 :            :     //    p = (jl_datatype_t*)((jl_unionall_t*)p)->body;
     291                 :            :     //}
     292         [ +  + ]:          6 :     if (module_in_worklist(p->name->module))
     293                 :          2 :         return 0;
     294         [ -  + ]:          4 :     if (p->name->wrapper != (jl_value_t*)p0) {
     295         [ #  # ]:          0 :         if (!type_recursively_external(p))
     296                 :          0 :             return 0;
     297                 :            :     }
     298                 :          4 :     return 1;
     299                 :            : }
     300                 :            : 
     301                 :            : // returns true if all of the parameters are tag 6 or 7
     302                 :         14 : static int type_recursively_external(jl_datatype_t *dt) JL_NOTSAFEPOINT
     303                 :            : {
     304         [ +  + ]:         14 :     if (!dt->isconcretetype)
     305                 :          8 :         return 0;
     306         [ -  + ]:          6 :     if (jl_svec_len(dt->parameters) == 0)
     307                 :          0 :         return 1;
     308                 :            : 
     309                 :          6 :     int i, l = jl_svec_len(dt->parameters);
     310         [ +  - ]:         10 :     for (i = 0; i < l; i++) {
     311         [ +  + ]:         10 :         if (!type_parameter_recursively_external(jl_tparam(dt, i)))
     312                 :          6 :             return 0;
     313                 :            :     }
     314                 :          0 :     return 1;
     315                 :            : }
     316                 :            : 
     317                 :            : // When we infer external method instances, ensure they link back to the
     318                 :            : // package. Otherwise they might be, e.g., for external macros
     319                 :          0 : static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited)
     320                 :            : {
     321                 :          0 :     void **bp = ptrhash_bp(visited, mi);
     322                 :            :     // HT_NOTFOUND: not yet analyzed
     323                 :            :     // HT_NOTFOUND + 1: doesn't link back
     324                 :            :     // HT_NOTFOUND + 2: does link back
     325         [ #  # ]:          0 :     if (*bp != HT_NOTFOUND)
     326                 :          0 :         return (char*)*bp - (char*)HT_NOTFOUND - 1;
     327                 :          0 :     *bp = (void*)((char*)HT_NOTFOUND + 1);  // preliminarily mark as "not found"
     328                 :          0 :     jl_module_t *mod = mi->def.module;
     329         [ #  # ]:          0 :     if (jl_is_method(mod))
     330                 :          0 :         mod = ((jl_method_t*)mod)->module;
     331         [ #  # ]:          0 :     assert(jl_is_module(mod));
     332   [ #  #  #  # ]:          0 :     if (mi->precompiled || module_in_worklist(mod)) {
     333                 :          0 :         *bp = (void*)((char*)HT_NOTFOUND + 2);      // found
     334                 :          0 :         return 1;
     335                 :            :     }
     336         [ #  # ]:          0 :     if (!mi->backedges) {
     337                 :          0 :         return 0;
     338                 :            :     }
     339                 :          0 :     size_t i, n = jl_array_len(mi->backedges);
     340         [ #  # ]:          0 :     for (i = 0; i < n; i++) {
     341                 :          0 :         jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, i);
     342         [ #  # ]:          0 :         if (has_backedge_to_worklist(be, visited)) {
     343                 :          0 :             bp = ptrhash_bp(visited, mi);           // re-acquire since rehashing might change the location
     344                 :          0 :             *bp = (void*)((char*)HT_NOTFOUND + 2);  // found
     345                 :          0 :             return 1;
     346                 :            :         }
     347                 :            :     }
     348                 :          0 :     return 0;
     349                 :            : }
     350                 :            : 
     351                 :            : // given the list of MethodInstances that were inferred during the
     352                 :            : // build, select those that are external and have at least one
     353                 :            : // relocatable CodeInstance.
     354                 :          4 : static size_t queue_external_mis(jl_array_t *list)
     355                 :            : {
     356                 :          4 :     size_t i, n = 0;
     357                 :            :     htable_t visited;
     358         [ +  - ]:          4 :     if (list) {
     359         [ -  + ]:          4 :         assert(jl_is_array(list));
     360                 :          4 :         size_t n0 = jl_array_len(list);
     361                 :          4 :         htable_new(&visited, n0);
     362         [ -  + ]:          4 :         for (i = 0; i < n0; i++) {
     363                 :          0 :             jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
     364         [ #  # ]:          0 :             assert(jl_is_method_instance(mi));
     365         [ #  # ]:          0 :             if (jl_is_method(mi->def.value)) {
     366                 :          0 :                 jl_method_t *m = mi->def.method;
     367         [ #  # ]:          0 :                 if (!module_in_worklist(m->module)) {
     368                 :          0 :                     jl_code_instance_t *ci = mi->cache;
     369                 :          0 :                     int relocatable = 0;
     370         [ #  # ]:          0 :                     while (ci) {
     371                 :          0 :                         relocatable |= ci->relocatability;
     372                 :          0 :                         ci = ci->next;
     373                 :            :                     }
     374   [ #  #  #  # ]:          0 :                     if (relocatable && ptrhash_get(&external_mis, mi) == HT_NOTFOUND) {
     375         [ #  # ]:          0 :                         if (has_backedge_to_worklist(mi, &visited)) {
     376                 :          0 :                             ptrhash_put(&external_mis, mi, mi);
     377                 :          0 :                             n++;
     378                 :            :                         }
     379                 :            :                     }
     380                 :            :                 }
     381                 :            :             }
     382                 :            :         }
     383                 :          4 :         htable_free(&visited);
     384                 :            :     }
     385                 :          4 :     return n;
     386                 :            : }
     387                 :            : 
     388                 :         40 : static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_GC_DISABLED
     389                 :            : {
     390                 :         40 :     int tag = 0;
     391                 :         40 :     int internal = module_in_worklist(dt->name->module);
     392   [ +  +  +  + ]:         40 :     if (!internal && jl_unwrap_unionall(dt->name->wrapper) == (jl_value_t*)dt) {
     393                 :          4 :         tag = 6; // external primary type
     394                 :            :     }
     395   [ +  +  +  + ]:         36 :     else if (jl_is_tuple_type(dt) ? !dt->isconcretetype : dt->hasfreetypevars) {
     396                 :         12 :         tag = 0; // normal struct
     397                 :            :     }
     398         [ +  + ]:         24 :     else if (internal) {
     399         [ +  - ]:         10 :         if (jl_unwrap_unionall(dt->name->wrapper) == (jl_value_t*)dt) // comes up often since functions create types
     400                 :         10 :             tag = 5; // internal, and not in the typename cache
     401                 :            :         else
     402                 :          0 :             tag = 10; // anything else that's internal (just may need recaching)
     403                 :            :     }
     404         [ -  + ]:         14 :     else if (type_recursively_external(dt)) {
     405                 :          0 :         tag = 7; // external type that can be immediately recreated (with apply_type)
     406                 :            :     }
     407         [ +  + ]:         14 :     else if (type_in_worklist(dt)) {
     408                 :          2 :         tag = 11; // external, but definitely new (still needs caching, but not full unique-ing)
     409                 :            :     }
     410                 :            :     else {
     411                 :            :         // this is eligible for (and possibly requires) unique-ing later,
     412                 :            :         // so flag this in the backref table as special
     413                 :         12 :         uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, dt);
     414         [ -  + ]:         12 :         assert(*bp != (uintptr_t)HT_NOTFOUND);
     415                 :         12 :         *bp |= 1;
     416                 :         12 :         tag = 12;
     417                 :            :     }
     418                 :            : 
     419                 :         40 :     char *dtname = jl_symbol_name(dt->name->name);
     420                 :         40 :     size_t dtnl = strlen(dtname);
     421   [ +  -  -  +  :         40 :     if (dtnl > 4 && strcmp(&dtname[dtnl - 4], "##kw") == 0 && !internal && tag != 0) {
             -  -  -  - ]
     422                 :            :         /* XXX: yuck, this is horrible, but the auto-generated kw types from the serializer isn't a real type, so we *must* be very careful */
     423         [ #  # ]:          0 :         assert(tag == 6); // other struct types should never exist
     424                 :          0 :         tag = 9;
     425   [ #  #  #  # ]:          0 :         if (jl_type_type_mt->kwsorter != NULL && dt == (jl_datatype_t*)jl_typeof(jl_type_type_mt->kwsorter)) {
     426                 :          0 :             dt = jl_datatype_type; // any representative member with this MethodTable
     427                 :            :         }
     428   [ #  #  #  # ]:          0 :         else if (jl_nonfunction_mt->kwsorter != NULL && dt == (jl_datatype_t*)jl_typeof(jl_nonfunction_mt->kwsorter)) {
     429                 :          0 :             dt = jl_symbol_type; // any representative member with this MethodTable
     430                 :            :         }
     431                 :            :         else {
     432                 :            :             // search for the representative member of this MethodTable
     433                 :          0 :             jl_methtable_t *mt = dt->name->mt;
     434                 :          0 :             size_t l = strlen(jl_symbol_name(mt->name));
     435                 :            :             char *prefixed;
     436                 :          0 :             prefixed = (char*)malloc_s(l + 2);
     437                 :          0 :             prefixed[0] = '#';
     438                 :          0 :             strcpy(&prefixed[1], jl_symbol_name(mt->name));
     439                 :            :             // remove ##kw suffix
     440                 :          0 :             prefixed[l-3] = 0;
     441                 :          0 :             jl_sym_t *tname = jl_symbol(prefixed);
     442                 :          0 :             free(prefixed);
     443                 :          0 :             jl_value_t *primarydt = jl_get_global(mt->module, tname);
     444         [ #  # ]:          0 :             if (!primarydt)
     445                 :          0 :                 primarydt = jl_get_global(mt->module, mt->name);
     446                 :          0 :             primarydt = jl_unwrap_unionall(primarydt);
     447         [ #  # ]:          0 :             assert(jl_is_datatype(primarydt));
     448   [ #  #  #  # ]:          0 :             assert(primarydt == (jl_value_t*)jl_any_type || jl_typeof(((jl_datatype_t*)primarydt)->name->mt->kwsorter) == (jl_value_t*)dt);
     449                 :          0 :             dt = (jl_datatype_t*)primarydt;
     450                 :            :         }
     451                 :            :     }
     452                 :            : 
     453                 :         40 :     write_uint8(s->s, TAG_DATATYPE);
     454                 :         40 :     write_uint8(s->s, tag);
     455   [ +  +  -  + ]:         40 :     if (tag == 6 || tag == 7) {
     456                 :            :         // for tag==6, copy its typevars in case there are references to them elsewhere
     457                 :          4 :         jl_serialize_value(s, dt->name);
     458                 :          4 :         jl_serialize_value(s, dt->parameters);
     459                 :          4 :         return;
     460                 :            :     }
     461         [ -  + ]:         36 :     if (tag == 9) {
     462                 :          0 :         jl_serialize_value(s, dt);
     463                 :          0 :         return;
     464                 :            :     }
     465                 :            : 
     466                 :         36 :     write_int32(s->s, dt->size);
     467                 :         36 :     int has_instance = (dt->instance != NULL);
     468                 :         36 :     int has_layout = (dt->layout != NULL);
     469                 :         36 :     write_uint8(s->s, has_layout | (has_instance << 1));
     470                 :         36 :     write_uint8(s->s, dt->hasfreetypevars
     471                 :            :             | (dt->isconcretetype << 1)
     472                 :            :             | (dt->isdispatchtuple << 2)
     473                 :            :             | (dt->isbitstype << 3)
     474                 :            :             | (dt->zeroinit << 4)
     475                 :            :             | (dt->has_concrete_subtype << 5)
     476                 :            :             | (dt->cached_by_hash << 6));
     477                 :         36 :     write_int32(s->s, dt->hash);
     478                 :            : 
     479         [ +  + ]:         36 :     if (has_layout) {
     480                 :         16 :         uint8_t layout = 0;
     481         [ -  + ]:         16 :         if (dt->layout == ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type))->layout) {
     482                 :          0 :             layout = 1;
     483                 :            :         }
     484         [ -  + ]:         16 :         else if (dt->layout == jl_nothing_type->layout) {
     485                 :          0 :             layout = 2;
     486                 :            :         }
     487         [ -  + ]:         16 :         else if (dt->layout == ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->layout) {
     488                 :          0 :             layout = 3;
     489                 :            :         }
     490                 :         16 :         write_uint8(s->s, layout);
     491         [ +  - ]:         16 :         if (layout == 0) {
     492                 :         16 :             uint32_t nf = dt->layout->nfields;
     493                 :         16 :             uint32_t np = dt->layout->npointers;
     494                 :         16 :             size_t fieldsize = jl_fielddesc_size(dt->layout->fielddesc_type);
     495                 :         16 :             ios_write(s->s, (const char*)dt->layout, sizeof(*dt->layout));
     496                 :         16 :             size_t fldsize = nf * fieldsize;
     497         [ -  + ]:         16 :             if (dt->layout->first_ptr != -1)
     498                 :          0 :                 fldsize += np << dt->layout->fielddesc_type;
     499                 :         16 :             ios_write(s->s, (const char*)(dt->layout + 1), fldsize);
     500                 :            :         }
     501                 :            :     }
     502                 :            : 
     503         [ +  + ]:         36 :     if (has_instance)
     504                 :         12 :         jl_serialize_value(s, dt->instance);
     505                 :         36 :     jl_serialize_value(s, dt->name);
     506                 :         36 :     jl_serialize_value(s, dt->parameters);
     507                 :         36 :     jl_serialize_value(s, dt->super);
     508                 :         36 :     jl_serialize_value(s, dt->types);
     509                 :            : }
     510                 :            : 
     511                 :          4 : static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m)
     512                 :            : {
     513                 :          4 :     write_uint8(s->s, TAG_MODULE);
     514                 :          4 :     jl_serialize_value(s, m->name);
     515                 :            :     size_t i;
     516         [ -  + ]:          4 :     if (!module_in_worklist(m)) {
     517         [ #  # ]:          0 :         if (m == m->parent) {
     518                 :            :             // top-level module
     519                 :          0 :             write_int8(s->s, 2);
     520                 :          0 :             int j = 0;
     521         [ #  # ]:          0 :             for (i = 0; i < jl_array_len(s->loaded_modules_array); i++) {
     522                 :          0 :                 jl_module_t *mi = (jl_module_t*)jl_array_ptr_ref(s->loaded_modules_array, i);
     523         [ #  # ]:          0 :                 if (!module_in_worklist(mi)) {
     524         [ #  # ]:          0 :                     if (m == mi) {
     525                 :          0 :                         write_int32(s->s, j);
     526                 :          0 :                         return;
     527                 :            :                     }
     528                 :          0 :                     j++;
     529                 :            :                 }
     530                 :            :             }
     531                 :          0 :             assert(0 && "top level module not found in modules array");
     532                 :            :         }
     533                 :            :         else {
     534                 :          0 :             write_int8(s->s, 1);
     535                 :          0 :             jl_serialize_value(s, m->parent);
     536                 :            :         }
     537                 :          0 :         return;
     538                 :            :     }
     539                 :          4 :     write_int8(s->s, 0);
     540                 :          4 :     jl_serialize_value(s, m->parent);
     541                 :          4 :     void **table = m->bindings.table;
     542         [ +  + ]:         68 :     for (i = 0; i < m->bindings.size; i += 2) {
     543         [ +  + ]:         64 :         if (table[i+1] != HT_NOTFOUND) {
     544                 :         24 :             jl_serialize_value(s, (jl_value_t*)table[i]);
     545                 :         24 :             jl_binding_t *b = (jl_binding_t*)table[i+1];
     546                 :         24 :             jl_serialize_value(s, b->name);
     547                 :         24 :             jl_value_t *e = jl_atomic_load_relaxed(&b->value);
     548   [ -  +  -  -  :         24 :             if (!b->constp && e && jl_is_cpointer(e) && jl_unbox_voidpointer(e) != (void*)-1 && jl_unbox_voidpointer(e) != NULL)
          -  -  -  -  -  
                      - ]
     549                 :            :                 // reset Ptr fields to C_NULL (but keep MAP_FAILED / INVALID_HANDLE)
     550                 :          0 :                 jl_serialize_cnull(s, jl_typeof(e));
     551                 :            :             else
     552                 :         24 :                 jl_serialize_value(s, e);
     553                 :         24 :             jl_serialize_value(s, jl_atomic_load_relaxed(&b->globalref));
     554                 :         24 :             jl_serialize_value(s, b->owner);
     555                 :         24 :             jl_serialize_value(s, jl_atomic_load_relaxed(&b->ty));
     556                 :         24 :             write_int8(s->s, (b->deprecated<<3) | (b->constp<<2) | (b->exportp<<1) | (b->imported));
     557                 :            :         }
     558                 :            :     }
     559                 :          4 :     jl_serialize_value(s, NULL);
     560                 :          4 :     write_int32(s->s, m->usings.len);
     561         [ +  + ]:         12 :     for(i=0; i < m->usings.len; i++) {
     562                 :          8 :         jl_serialize_value(s, (jl_value_t*)m->usings.items[i]);
     563                 :            :     }
     564                 :          4 :     write_uint8(s->s, m->istopmod);
     565                 :          4 :     write_uint64(s->s, m->uuid.hi);
     566                 :          4 :     write_uint64(s->s, m->uuid.lo);
     567                 :          4 :     write_uint64(s->s, m->build_id);
     568                 :          4 :     write_int32(s->s, m->counter);
     569                 :          4 :     write_int32(s->s, m->nospecialize);
     570                 :          4 :     write_uint8(s->s, m->optlevel);
     571                 :          4 :     write_uint8(s->s, m->compile);
     572                 :          4 :     write_uint8(s->s, m->infer);
     573                 :          4 :     write_uint8(s->s, m->max_methods);
     574                 :            : }
     575                 :            : 
     576                 :       1096 : static int jl_serialize_generic(jl_serializer_state *s, jl_value_t *v) JL_GC_DISABLED
     577                 :            : {
     578         [ +  + ]:       1096 :     if (v == NULL) {
     579                 :        138 :         write_uint8(s->s, TAG_NULL);
     580                 :        138 :         return 1;
     581                 :            :     }
     582                 :            : 
     583                 :        958 :     void *tag = ptrhash_get(&ser_tag, v);
     584         [ +  + ]:        958 :     if (tag != HT_NOTFOUND) {
     585                 :        358 :         uint8_t t8 = (intptr_t)tag;
     586         [ +  + ]:        358 :         if (t8 <= LAST_TAG)
     587                 :          4 :             write_uint8(s->s, 0);
     588                 :        358 :         write_uint8(s->s, t8);
     589                 :        358 :         return 1;
     590                 :            :     }
     591                 :            : 
     592         [ +  + ]:        600 :     if (jl_is_symbol(v)) {
     593                 :        152 :         void *idx = ptrhash_get(&common_symbol_tag, v);
     594         [ +  + ]:        152 :         if (idx != HT_NOTFOUND) {
     595                 :         24 :             write_uint8(s->s, TAG_COMMONSYM);
     596                 :         24 :             write_uint8(s->s, (uint8_t)(size_t)idx);
     597                 :         24 :             return 1;
     598                 :            :         }
     599                 :            :     }
     600         [ +  + ]:        448 :     else if (v == (jl_value_t*)jl_core_module) {
     601                 :         24 :         write_uint8(s->s, TAG_CORE);
     602                 :         24 :         return 1;
     603                 :            :     }
     604         [ +  + ]:        424 :     else if (v == (jl_value_t*)jl_base_module) {
     605                 :          4 :         write_uint8(s->s, TAG_BASE);
     606                 :          4 :         return 1;
     607                 :            :     }
     608                 :            : 
     609   [ +  +  -  + ]:        548 :     if (jl_typeis(v, jl_string_type) && jl_string_len(v) == 0) {
     610                 :          0 :         jl_serialize_value(s, jl_an_empty_string);
     611                 :          0 :         return 1;
     612                 :            :     }
     613         [ +  - ]:        548 :     else if (!jl_is_uint8(v)) {
     614                 :        548 :         void **bp = ptrhash_bp(&backref_table, v);
     615         [ +  + ]:        548 :         if (*bp != HT_NOTFOUND) {
     616                 :        266 :             uintptr_t pos = (char*)*bp - (char*)HT_NOTFOUND - 1;
     617         [ +  - ]:        266 :             if (pos < 65536) {
     618                 :        266 :                 write_uint8(s->s, TAG_SHORT_BACKREF);
     619                 :        266 :                 write_uint16(s->s, pos);
     620                 :            :             }
     621                 :            :             else {
     622                 :          0 :                 write_uint8(s->s, TAG_BACKREF);
     623                 :          0 :                 write_int32(s->s, pos);
     624                 :            :             }
     625                 :        266 :             return 1;
     626                 :            :         }
     627                 :        282 :         intptr_t pos = backref_table_numel++;
     628         [ -  + ]:        282 :         if (((jl_datatype_t*)(jl_typeof(v)))->name == jl_idtable_typename) {
     629                 :            :             // will need to rehash this, later (after types are fully constructed)
     630                 :          0 :             arraylist_push(&reinit_list, (void*)pos);
     631                 :          0 :             arraylist_push(&reinit_list, (void*)1);
     632                 :            :         }
     633         [ +  + ]:        282 :         if (jl_is_module(v)) {
     634                 :          4 :             jl_module_t *m = (jl_module_t*)v;
     635   [ +  -  -  + ]:          4 :             if (module_in_worklist(m) && !module_in_worklist(m->parent)) {
     636                 :            :                 // will need to reinsert this into parent bindings, later (in case of any errors during reinsert)
     637                 :          0 :                 arraylist_push(&reinit_list, (void*)pos);
     638                 :          0 :                 arraylist_push(&reinit_list, (void*)2);
     639                 :            :             }
     640                 :            :         }
     641                 :            :         // TypeMapLevels need to be rehashed
     642         [ +  + ]:        282 :         if (jl_is_mtable(v)) {
     643                 :         10 :             arraylist_push(&reinit_list, (void*)pos);
     644                 :         10 :             arraylist_push(&reinit_list, (void*)3);
     645                 :            :         }
     646                 :        282 :         pos <<= 1;
     647                 :        282 :         ptrhash_put(&backref_table, v, (char*)HT_NOTFOUND + pos + 1);
     648                 :            :     }
     649                 :            : 
     650                 :        282 :     return 0;
     651                 :            : }
     652                 :            : 
     653                 :          0 : static void jl_serialize_code_instance(jl_serializer_state *s, jl_code_instance_t *codeinst, int skip_partial_opaque, int internal) JL_GC_DISABLED
     654                 :            : {
     655         [ #  # ]:          0 :     if (internal > 2) {
     656   [ #  #  #  # ]:          0 :         while (codeinst && !codeinst->relocatability)
     657                 :          0 :             codeinst = codeinst->next;
     658                 :            :     }
     659         [ #  # ]:          0 :     if (jl_serialize_generic(s, (jl_value_t*)codeinst)) {
     660                 :          0 :         return;
     661                 :            :     }
     662         [ #  # ]:          0 :     assert(codeinst != NULL); // handle by jl_serialize_generic, but this makes clang-sa happy
     663                 :            : 
     664                 :          0 :     int validate = 0;
     665         [ #  # ]:          0 :     if (codeinst->max_world == ~(size_t)0)
     666                 :          0 :         validate = 1; // can check on deserialize if this cache entry is still valid
     667                 :          0 :     int flags = validate << 0;
     668         [ #  # ]:          0 :     if (codeinst->invoke == jl_fptr_const_return)
     669                 :          0 :         flags |= 1 << 2;
     670         [ #  # ]:          0 :     if (codeinst->precompile)
     671                 :          0 :         flags |= 1 << 3;
     672                 :            : 
     673                 :            :     // CodeInstances with PartialOpaque return type are currently not allowed
     674                 :            :     // to be cached. We skip them in serialization here, forcing them to
     675                 :            :     // be re-infered on reload.
     676   [ #  #  #  # ]:          0 :     int write_ret_type = validate || codeinst->min_world == 0;
     677   [ #  #  #  # ]:          0 :     if (write_ret_type && codeinst->rettype_const &&
     678         [ #  # ]:          0 :             jl_typeis(codeinst->rettype_const, jl_partial_opaque_type)) {
     679         [ #  # ]:          0 :         if (skip_partial_opaque) {
     680                 :          0 :             jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque, internal);
     681                 :          0 :             return;
     682                 :            :         }
     683                 :            :         else {
     684                 :          0 :             jl_error("Cannot serialize CodeInstance with PartialOpaque rettype");
     685                 :            :         }
     686                 :            :     }
     687                 :            : 
     688                 :          0 :     write_uint8(s->s, TAG_CODE_INSTANCE);
     689                 :          0 :     write_uint8(s->s, flags);
     690                 :          0 :     write_uint32(s->s, codeinst->ipo_purity_bits);
     691                 :          0 :     write_uint32(s->s, codeinst->purity_bits);
     692                 :          0 :     jl_serialize_value(s, (jl_value_t*)codeinst->def);
     693         [ #  # ]:          0 :     if (write_ret_type) {
     694                 :          0 :         jl_serialize_value(s, codeinst->inferred);
     695                 :          0 :         jl_serialize_value(s, codeinst->rettype_const);
     696                 :          0 :         jl_serialize_value(s, codeinst->rettype);
     697                 :          0 :         jl_serialize_value(s, codeinst->argescapes);
     698                 :            :     }
     699                 :            :     else {
     700                 :            :         // skip storing useless data
     701                 :          0 :         jl_serialize_value(s, NULL);
     702                 :          0 :         jl_serialize_value(s, NULL);
     703                 :          0 :         jl_serialize_value(s, jl_any_type);
     704                 :          0 :         jl_serialize_value(s, jl_nothing);
     705                 :            :     }
     706                 :          0 :     write_uint8(s->s, codeinst->relocatability);
     707                 :          0 :     jl_serialize_code_instance(s, codeinst->next, skip_partial_opaque, internal);
     708                 :            : }
     709                 :            : 
     710                 :            : enum METHOD_SERIALIZATION_MODE {
     711                 :            :     METHOD_INTERNAL = 1,
     712                 :            :     METHOD_EXTERNAL_MT = 2,
     713                 :            :     METHOD_HAS_NEW_ROOTS = 4,
     714                 :            : };
     715                 :            : 
     716                 :       1096 : static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED
     717                 :            : {
     718         [ +  + ]:       1096 :     if (jl_serialize_generic(s, v)) {
     719                 :        814 :         return;
     720                 :            :     }
     721                 :            : 
     722                 :            :     size_t i;
     723         [ +  + ]:        282 :     if (jl_is_svec(v)) {
     724                 :         26 :         size_t l = jl_svec_len(v);
     725         [ +  - ]:         26 :         if (l <= 255) {
     726                 :         26 :             write_uint8(s->s, TAG_SVEC);
     727                 :         26 :             write_uint8(s->s, (uint8_t)l);
     728                 :            :         }
     729                 :            :         else {
     730                 :          0 :             write_uint8(s->s, TAG_LONG_SVEC);
     731                 :          0 :             write_int32(s->s, l);
     732                 :            :         }
     733         [ +  + ]:         80 :         for (i = 0; i < l; i++) {
     734                 :         54 :             jl_serialize_value(s, jl_svecref(v, i));
     735                 :            :         }
     736                 :            :     }
     737         [ +  + ]:        256 :     else if (jl_is_symbol(v)) {
     738                 :         36 :         size_t l = strlen(jl_symbol_name((jl_sym_t*)v));
     739         [ +  - ]:         36 :         if (l <= 255) {
     740                 :         36 :             write_uint8(s->s, TAG_SYMBOL);
     741                 :         36 :             write_uint8(s->s, (uint8_t)l);
     742                 :            :         }
     743                 :            :         else {
     744                 :          0 :             write_uint8(s->s, TAG_LONG_SYMBOL);
     745                 :          0 :             write_int32(s->s, l);
     746                 :            :         }
     747                 :         36 :         ios_write(s->s, jl_symbol_name((jl_sym_t*)v), l);
     748                 :            :     }
     749         [ +  + ]:        220 :     else if (jl_is_array(v)) {
     750                 :         62 :         jl_array_t *ar = (jl_array_t*)v;
     751                 :         62 :         jl_value_t *et = jl_tparam0(jl_typeof(ar));
     752                 :         62 :         int isunion = jl_is_uniontype(et);
     753   [ +  -  +  - ]:         62 :         if (ar->flags.ndims == 1 && ar->elsize <= 0x1f) {
     754                 :         62 :             write_uint8(s->s, TAG_ARRAY1D);
     755                 :         62 :             write_uint8(s->s, (ar->flags.ptrarray << 7) | (ar->flags.hasptr << 6) | (isunion << 5) | (ar->elsize & 0x1f));
     756                 :            :         }
     757                 :            :         else {
     758                 :          0 :             write_uint8(s->s, TAG_ARRAY);
     759                 :          0 :             write_uint16(s->s, ar->flags.ndims);
     760                 :          0 :             write_uint16(s->s, (ar->flags.ptrarray << 15) | (ar->flags.hasptr << 14) | (isunion << 13) | (ar->elsize & 0x1fff));
     761                 :            :         }
     762         [ +  + ]:        124 :         for (i = 0; i < ar->flags.ndims; i++)
     763                 :         62 :             jl_serialize_value(s, jl_box_long(jl_array_dim(ar,i)));
     764                 :         62 :         jl_serialize_value(s, jl_typeof(ar));
     765                 :         62 :         size_t l = jl_array_len(ar);
     766         [ +  + ]:         62 :         if (ar->flags.ptrarray) {
     767         [ +  + ]:         72 :             for (i = 0; i < l; i++) {
     768                 :         38 :                 jl_value_t *e = jl_array_ptr_ref(v, i);
     769   [ +  -  -  +  :         38 :                 if (e && jl_is_cpointer(e) && jl_unbox_voidpointer(e) != (void*)-1 && jl_unbox_voidpointer(e) != NULL)
             -  -  -  - ]
     770                 :            :                     // reset Ptr elements to C_NULL (but keep MAP_FAILED / INVALID_HANDLE)
     771                 :          0 :                     jl_serialize_cnull(s, jl_typeof(e));
     772                 :            :                 else
     773                 :         38 :                     jl_serialize_value(s, e);
     774                 :            :             }
     775                 :            :         }
     776         [ -  + ]:         28 :         else if (ar->flags.hasptr) {
     777                 :          0 :             const char *data = (const char*)jl_array_data(ar);
     778                 :          0 :             uint16_t elsz = ar->elsize;
     779                 :          0 :             size_t j, np = ((jl_datatype_t*)et)->layout->npointers;
     780         [ #  # ]:          0 :             for (i = 0; i < l; i++) {
     781                 :          0 :                 const char *start = data;
     782         [ #  # ]:          0 :                 for (j = 0; j < np; j++) {
     783                 :          0 :                     uint32_t ptr = jl_ptr_offset((jl_datatype_t*)et, j);
     784                 :          0 :                     const jl_value_t *const *fld = &((const jl_value_t *const *)data)[ptr];
     785         [ #  # ]:          0 :                     if ((const char*)fld != start)
     786                 :          0 :                         ios_write(s->s, start, (const char*)fld - start);
     787                 :            :                     JL_GC_PROMISE_ROOTED(*fld);
     788                 :          0 :                     jl_serialize_value(s, *fld);
     789                 :          0 :                     start = (const char*)&fld[1];
     790                 :            :                 }
     791                 :          0 :                 data += elsz;
     792         [ #  # ]:          0 :                 if (data != start)
     793                 :          0 :                     ios_write(s->s, start, data - start);
     794                 :            :             }
     795                 :            :         }
     796         [ -  + ]:         28 :         else if (jl_is_cpointer_type(et)) {
     797                 :            :             // reset Ptr elements to C_NULL
     798                 :          0 :             const void **data = (const void**)jl_array_data(ar);
     799         [ #  # ]:          0 :             for (i = 0; i < l; i++) {
     800                 :          0 :                 const void *e = data[i];
     801         [ #  # ]:          0 :                 if (e != (void*)-1)
     802                 :          0 :                     e = NULL;
     803                 :          0 :                 ios_write(s->s, (const char*)&e, sizeof(e));
     804                 :            :             }
     805                 :            :         }
     806                 :            :         else {
     807                 :         28 :             ios_write(s->s, (char*)jl_array_data(ar), l * ar->elsize);
     808   [ +  -  -  + ]:         28 :             if (jl_array_isbitsunion(ar))
     809                 :          0 :                 ios_write(s->s, jl_array_typetagdata(ar), l);
     810                 :            :         }
     811                 :            :     }
     812         [ +  + ]:        158 :     else if (jl_is_datatype(v)) {
     813                 :         40 :         jl_serialize_datatype(s, (jl_datatype_t*)v);
     814                 :            :     }
     815         [ -  + ]:        118 :     else if (jl_is_unionall(v)) {
     816                 :          0 :         write_uint8(s->s, TAG_UNIONALL);
     817                 :          0 :         jl_datatype_t *d = (jl_datatype_t*)jl_unwrap_unionall(v);
     818   [ #  #  #  #  :          0 :         if (jl_is_datatype(d) && d->name->wrapper == v &&
                   #  # ]
     819                 :          0 :             !module_in_worklist(d->name->module)) {
     820                 :          0 :             write_uint8(s->s, 1);
     821                 :          0 :             jl_serialize_value(s, d->name->module);
     822                 :          0 :             jl_serialize_value(s, d->name->name);
     823                 :            :         }
     824                 :            :         else {
     825                 :          0 :             write_uint8(s->s, 0);
     826                 :          0 :             jl_serialize_value(s, ((jl_unionall_t*)v)->var);
     827                 :          0 :             jl_serialize_value(s, ((jl_unionall_t*)v)->body);
     828                 :            :         }
     829                 :            :     }
     830         [ -  + ]:        118 :     else if (jl_is_typevar(v)) {
     831                 :          0 :         write_uint8(s->s, TAG_TVAR);
     832                 :          0 :         jl_serialize_value(s, ((jl_tvar_t*)v)->name);
     833                 :          0 :         jl_serialize_value(s, ((jl_tvar_t*)v)->lb);
     834                 :          0 :         jl_serialize_value(s, ((jl_tvar_t*)v)->ub);
     835                 :            :     }
     836         [ +  + ]:        118 :     else if (jl_is_method(v)) {
     837                 :         14 :         write_uint8(s->s, TAG_METHOD);
     838                 :         14 :         jl_method_t *m = (jl_method_t*)v;
     839                 :         14 :         uint64_t key = 0;
     840                 :         14 :         int serialization_mode = 0, nwithkey = 0;
     841   [ +  -  +  - ]:         14 :         if (m->is_for_opaque_closure || module_in_worklist(m->module))
     842                 :         14 :             serialization_mode |= METHOD_INTERNAL;
     843         [ -  + ]:         14 :         if (!(serialization_mode & METHOD_INTERNAL)) {
     844                 :          0 :             key = jl_worklist_key(serializer_worklist);
     845                 :          0 :             nwithkey = nroots_with_key(m, key);
     846         [ #  # ]:          0 :             if (nwithkey > 0)
     847                 :          0 :                 serialization_mode |= METHOD_HAS_NEW_ROOTS;
     848                 :            :         }
     849         [ -  + ]:         14 :         if (!(serialization_mode & METHOD_INTERNAL)) {
     850                 :            :             // flag this in the backref table as special
     851                 :          0 :             uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v);
     852         [ #  # ]:          0 :             assert(*bp != (uintptr_t)HT_NOTFOUND);
     853                 :          0 :             *bp |= 1;
     854                 :            :         }
     855                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->sig);
     856                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->module);
     857         [ -  + ]:         14 :         if (m->external_mt != NULL) {
     858         [ #  # ]:          0 :             assert(jl_typeis(m->external_mt, jl_methtable_type));
     859                 :          0 :             jl_methtable_t *mt = (jl_methtable_t*)m->external_mt;
     860         [ #  # ]:          0 :             if (!module_in_worklist(mt->module)) {
     861                 :          0 :                 serialization_mode |= METHOD_EXTERNAL_MT;
     862                 :            :             }
     863                 :            :         }
     864                 :         14 :         write_uint8(s->s, serialization_mode);
     865         [ -  + ]:         14 :         if (serialization_mode & METHOD_EXTERNAL_MT) {
     866                 :            :             // We reference this method table by module and binding
     867                 :          0 :             jl_methtable_t *mt = (jl_methtable_t*)m->external_mt;
     868                 :          0 :             jl_serialize_value(s, mt->module);
     869                 :          0 :             jl_serialize_value(s, mt->name);
     870                 :            :         }
     871                 :            :         else {
     872                 :         14 :             jl_serialize_value(s, (jl_value_t*)m->external_mt);
     873                 :            :         }
     874         [ -  + ]:         14 :         if (!(serialization_mode & METHOD_INTERNAL)) {
     875         [ #  # ]:          0 :             if (serialization_mode & METHOD_HAS_NEW_ROOTS) {
     876                 :            :                 // Serialize the roots that belong to key
     877                 :          0 :                 write_uint64(s->s, key);
     878                 :          0 :                 write_int32(s->s, nwithkey);
     879                 :          0 :                 rle_iter_state rootiter = rle_iter_init(0);
     880                 :          0 :                 uint64_t *rletable = NULL;
     881                 :          0 :                 size_t nblocks2 = 0, nroots = jl_array_len(m->roots);
     882         [ #  # ]:          0 :                 if (m->root_blocks) {
     883                 :          0 :                     rletable = (uint64_t*)jl_array_data(m->root_blocks);
     884                 :          0 :                     nblocks2 = jl_array_len(m->root_blocks);
     885                 :            :                 }
     886                 :            :                 // this visits every item, if it becomes a bottlneck we could hop blocks
     887         [ #  # ]:          0 :                 while (rle_iter_increment(&rootiter, nroots, rletable, nblocks2))
     888         [ #  # ]:          0 :                     if (rootiter.key == key)
     889                 :          0 :                         jl_serialize_value(s, jl_array_ptr_ref(m->roots, rootiter.i));
     890                 :            :             }
     891                 :          0 :             return;
     892                 :            :         }
     893                 :         14 :         jl_serialize_value(s, m->specializations);
     894                 :         14 :         jl_serialize_value(s, jl_atomic_load_relaxed(&m->speckeyset));
     895                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->name);
     896                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->file);
     897                 :         14 :         write_int32(s->s, m->line);
     898                 :         14 :         write_int32(s->s, m->called);
     899                 :         14 :         write_int32(s->s, m->nargs);
     900                 :         14 :         write_int32(s->s, m->nospecialize);
     901                 :         14 :         write_int32(s->s, m->nkw);
     902                 :         14 :         write_int8(s->s, m->isva);
     903                 :         14 :         write_int8(s->s, m->pure);
     904                 :         14 :         write_int8(s->s, m->is_for_opaque_closure);
     905                 :         14 :         write_int8(s->s, m->constprop);
     906                 :         14 :         write_uint8(s->s, m->purity.bits);
     907                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->slot_syms);
     908                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->roots);
     909                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->root_blocks);
     910                 :         14 :         write_int32(s->s, m->nroots_sysimg);
     911                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->ccallable);
     912                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->source);
     913                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->unspecialized);
     914                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->generator);
     915                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->invokes);
     916                 :         14 :         jl_serialize_value(s, (jl_value_t*)m->recursion_relation);
     917                 :            :     }
     918         [ -  + ]:        104 :     else if (jl_is_method_instance(v)) {
     919                 :          0 :         jl_method_instance_t *mi = (jl_method_instance_t*)v;
     920   [ #  #  #  # ]:          0 :         if (jl_is_method(mi->def.value) && mi->def.method->is_for_opaque_closure) {
     921                 :          0 :             jl_error("unimplemented: serialization of MethodInstances for OpaqueClosure");
     922                 :            :         }
     923                 :          0 :         write_uint8(s->s, TAG_METHOD_INSTANCE);
     924                 :          0 :         int internal = 0;
     925         [ #  # ]:          0 :         if (!jl_is_method(mi->def.method))
     926                 :          0 :             internal = 1;
     927         [ #  # ]:          0 :         else if (module_in_worklist(mi->def.method->module))
     928                 :          0 :             internal = 2;
     929         [ #  # ]:          0 :         else if (ptrhash_get(&external_mis, (void*)mi) != HT_NOTFOUND)
     930                 :          0 :             internal = 3;
     931                 :          0 :         write_uint8(s->s, internal);
     932         [ #  # ]:          0 :         if (!internal) {
     933                 :            :             // also flag this in the backref table as special
     934                 :          0 :             uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v);
     935         [ #  # ]:          0 :             assert(*bp != (uintptr_t)HT_NOTFOUND);
     936                 :          0 :             *bp |= 1;
     937                 :            :         }
     938         [ #  # ]:          0 :         if (internal == 1)
     939                 :          0 :             jl_serialize_value(s, (jl_value_t*)mi->uninferred);
     940                 :          0 :         jl_serialize_value(s, (jl_value_t*)mi->specTypes);
     941                 :          0 :         jl_serialize_value(s, mi->def.value);
     942         [ #  # ]:          0 :         if (!internal)
     943                 :          0 :             return;
     944                 :          0 :         jl_serialize_value(s, (jl_value_t*)mi->sparam_vals);
     945                 :          0 :         jl_array_t *backedges = mi->backedges;
     946         [ #  # ]:          0 :         if (backedges) {
     947                 :            :             // filter backedges to only contain pointers
     948                 :            :             // to items that we will actually store (internal >= 2)
     949                 :          0 :             size_t ins, i, l = jl_array_len(backedges);
     950                 :          0 :             jl_method_instance_t **b_edges = (jl_method_instance_t**)jl_array_data(backedges);
     951         [ #  # ]:          0 :             for (ins = i = 0; i < l; i++) {
     952                 :          0 :                 jl_method_instance_t *backedge = b_edges[i];
     953   [ #  #  #  # ]:          0 :                 if (module_in_worklist(backedge->def.method->module) || method_instance_in_queue(backedge)) {
     954                 :          0 :                     b_edges[ins++] = backedge;
     955                 :            :                 }
     956                 :            :             }
     957         [ #  # ]:          0 :             if (ins != l)
     958                 :          0 :                 jl_array_del_end(backedges, l - ins);
     959         [ #  # ]:          0 :             if (ins == 0)
     960                 :          0 :                 backedges = NULL;
     961                 :            :         }
     962                 :          0 :         jl_serialize_value(s, (jl_value_t*)backedges);
     963                 :          0 :         jl_serialize_value(s, (jl_value_t*)NULL); //callbacks
     964                 :          0 :         jl_serialize_code_instance(s, mi->cache, 1, internal);
     965                 :            :     }
     966         [ -  + ]:        104 :     else if (jl_is_code_instance(v)) {
     967                 :          0 :         jl_serialize_code_instance(s, (jl_code_instance_t*)v, 0, 2);
     968                 :            :     }
     969         [ +  + ]:        104 :     else if (jl_typeis(v, jl_module_type)) {
     970                 :          4 :         jl_serialize_module(s, (jl_module_t*)v);
     971                 :            :     }
     972         [ -  + ]:        100 :     else if (jl_typeis(v, jl_task_type)) {
     973                 :          0 :         jl_error("Task cannot be serialized");
     974                 :            :     }
     975         [ -  + ]:        100 :     else if (jl_typeis(v, jl_opaque_closure_type)) {
     976                 :          0 :         jl_error("Live opaque closures cannot be serialized");
     977                 :            :     }
     978         [ +  + ]:        100 :     else if (jl_typeis(v, jl_string_type)) {
     979                 :         16 :         write_uint8(s->s, TAG_STRING);
     980                 :         16 :         write_int32(s->s, jl_string_len(v));
     981                 :         16 :         ios_write(s->s, jl_string_data(v), jl_string_len(v));
     982                 :            :     }
     983         [ +  + ]:         84 :     else if (jl_typeis(v, jl_int64_type)) {
     984                 :         14 :         void *data = jl_data_ptr(v);
     985   [ +  -  +  - ]:         14 :         if (*(int64_t*)data >= INT16_MIN && *(int64_t*)data <= INT16_MAX) {
     986                 :         14 :             write_uint8(s->s, TAG_SHORTER_INT64);
     987                 :         14 :             write_uint16(s->s, (uint16_t)*(int64_t*)data);
     988                 :            :         }
     989   [ #  #  #  # ]:          0 :         else if (*(int64_t*)data >= S32_MIN && *(int64_t*)data <= S32_MAX) {
     990                 :          0 :             write_uint8(s->s, TAG_SHORT_INT64);
     991                 :          0 :             write_int32(s->s, (int32_t)*(int64_t*)data);
     992                 :            :         }
     993                 :            :         else {
     994                 :          0 :             write_uint8(s->s, TAG_INT64);
     995                 :          0 :             write_int64(s->s, *(int64_t*)data);
     996                 :            :         }
     997                 :            :     }
     998         [ -  + ]:         70 :     else if (jl_typeis(v, jl_int32_type)) {
     999                 :          0 :         void *data = jl_data_ptr(v);
    1000   [ #  #  #  # ]:          0 :         if (*(int32_t*)data >= INT16_MIN && *(int32_t*)data <= INT16_MAX) {
    1001                 :          0 :             write_uint8(s->s, TAG_SHORT_INT32);
    1002                 :          0 :             write_uint16(s->s, (uint16_t)*(int32_t*)data);
    1003                 :            :         }
    1004                 :            :         else {
    1005                 :          0 :             write_uint8(s->s, TAG_INT32);
    1006                 :          0 :             write_int32(s->s, *(int32_t*)data);
    1007                 :            :         }
    1008                 :            :     }
    1009         [ -  + ]:         70 :     else if (jl_typeis(v, jl_uint8_type)) {
    1010                 :          0 :         write_uint8(s->s, TAG_UINT8);
    1011                 :          0 :         write_int8(s->s, *(int8_t*)jl_data_ptr(v));
    1012                 :            :     }
    1013   [ -  +  -  - ]:         70 :     else if (jl_is_cpointer(v) && jl_unbox_voidpointer(v) == NULL) {
    1014                 :          0 :         write_uint8(s->s, TAG_CNULL);
    1015                 :          0 :         jl_serialize_value(s, jl_typeof(v));
    1016                 :          0 :         return;
    1017                 :            :     }
    1018   [ +  -  -  + ]:         70 :     else if (jl_bigint_type && jl_typeis(v, jl_bigint_type)) {
    1019                 :          0 :         write_uint8(s->s, TAG_SHORT_GENERAL);
    1020                 :          0 :         write_uint8(s->s, jl_datatype_size(jl_bigint_type));
    1021                 :          0 :         jl_serialize_value(s, jl_bigint_type);
    1022                 :          0 :         jl_value_t *sizefield = jl_get_nth_field(v, 1);
    1023                 :          0 :         jl_serialize_value(s, sizefield);
    1024                 :          0 :         void *data = jl_unbox_voidpointer(jl_get_nth_field(v, 2));
    1025                 :          0 :         int32_t sz = jl_unbox_int32(sizefield);
    1026         [ #  # ]:          0 :         size_t nb = (sz == 0 ? 1 : (sz < 0 ? -sz : sz)) * gmp_limb_size;
    1027                 :          0 :         ios_write(s->s, (char*)data, nb);
    1028                 :            :     }
    1029                 :            :     else {
    1030                 :         70 :         jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v);
    1031         [ +  + ]:         70 :         if (v == t->instance) {
    1032         [ -  + ]:         12 :             if (!type_in_worklist(t)) {
    1033                 :            :                 // also flag this in the backref table as special
    1034                 :            :                 // if it might not be unique (is external)
    1035                 :          0 :                 uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v);
    1036         [ #  # ]:          0 :                 assert(*bp != (uintptr_t)HT_NOTFOUND);
    1037                 :          0 :                 *bp |= 1;
    1038                 :            :             }
    1039                 :         12 :             write_uint8(s->s, TAG_SINGLETON);
    1040                 :         12 :             jl_serialize_value(s, t);
    1041                 :         12 :             return;
    1042                 :            :         }
    1043         [ -  + ]:         58 :         assert(!t->instance && "detected singleton construction corruption");
    1044                 :            : 
    1045         [ +  + ]:         58 :         if (t == jl_typename_type) {
    1046                 :         30 :             void *bttag = ptrhash_get(&ser_tag, ((jl_typename_t*)t)->wrapper);
    1047         [ -  + ]:         30 :             if (bttag != HT_NOTFOUND) {
    1048                 :          0 :                 write_uint8(s->s, TAG_BITYPENAME);
    1049                 :          0 :                 write_uint8(s->s, (uint8_t)(intptr_t)bttag);
    1050                 :          0 :                 return;
    1051                 :            :             }
    1052                 :            :         }
    1053         [ +  - ]:         58 :         if (t->size <= 255) {
    1054                 :         58 :             write_uint8(s->s, TAG_SHORT_GENERAL);
    1055                 :         58 :             write_uint8(s->s, t->size);
    1056                 :            :         }
    1057                 :            :         else {
    1058                 :          0 :             write_uint8(s->s, TAG_GENERAL);
    1059                 :          0 :             write_int32(s->s, t->size);
    1060                 :            :         }
    1061                 :         58 :         jl_serialize_value(s, t);
    1062         [ +  + ]:         58 :         if (t == jl_typename_type) {
    1063                 :         30 :             jl_typename_t *tn = (jl_typename_t*)v;
    1064                 :         30 :             int internal = module_in_worklist(tn->module);
    1065                 :         30 :             write_uint8(s->s, internal);
    1066                 :         30 :             jl_serialize_value(s, tn->module);
    1067                 :         30 :             jl_serialize_value(s, tn->name);
    1068         [ +  + ]:         30 :             if (internal) {
    1069                 :         10 :                 jl_serialize_value(s, tn->names);
    1070                 :         10 :                 jl_serialize_value(s, tn->wrapper);
    1071                 :         10 :                 jl_serialize_value(s, tn->mt);
    1072                 :         10 :                 ios_write(s->s, (char*)&tn->hash, sizeof(tn->hash));
    1073                 :         10 :                 write_uint8(s->s, tn->abstract | (tn->mutabl << 1) | (tn->mayinlinealloc << 2));
    1074                 :         10 :                 write_uint8(s->s, tn->max_methods);
    1075         [ +  - ]:         10 :                 if (!tn->abstract)
    1076                 :         10 :                     write_uint16(s->s, tn->n_uninitialized);
    1077         [ -  + ]:         10 :                 size_t nb = tn->atomicfields ? (jl_svec_len(tn->names) + 31) / 32 * sizeof(uint32_t) : 0;
    1078                 :         10 :                 write_int32(s->s, nb);
    1079         [ -  + ]:         10 :                 if (nb)
    1080                 :          0 :                     ios_write(s->s, (char*)tn->atomicfields, nb);
    1081         [ -  + ]:         10 :                 nb = tn->constfields ? (jl_svec_len(tn->names) + 31) / 32 * sizeof(uint32_t) : 0;
    1082                 :         10 :                 write_int32(s->s, nb);
    1083         [ -  + ]:         10 :                 if (nb)
    1084                 :          0 :                     ios_write(s->s, (char*)tn->constfields, nb);
    1085                 :            :             }
    1086                 :         30 :             return;
    1087                 :            :         }
    1088                 :            : 
    1089         [ -  + ]:         28 :         if (jl_is_foreign_type(t)) {
    1090                 :          0 :             jl_error("Cannot serialize instances of foreign datatypes");
    1091                 :            :         }
    1092                 :            : 
    1093                 :         28 :         char *data = (char*)jl_data_ptr(v);
    1094                 :         28 :         size_t i, j, np = t->layout->npointers;
    1095                 :         28 :         uint32_t nf = t->layout->nfields;
    1096                 :         28 :         char *last = data;
    1097         [ +  - ]:        296 :         for (i = 0, j = 0; i < nf+1; i++) {
    1098         [ +  + ]:        296 :             char *ptr = data + (i < nf ? jl_field_offset(t, i) : jl_datatype_size(t));
    1099         [ +  + ]:        296 :             if (j < np) {
    1100                 :        214 :                 char *prevptr = (char*)&((jl_value_t**)data)[jl_ptr_offset(t, j)];
    1101         [ +  + ]:        334 :                 while (ptr > prevptr) {
    1102                 :            :                     // previous field contained pointers; write them and their interleaved data
    1103         [ +  + ]:        148 :                     if (prevptr > last)
    1104                 :         24 :                         ios_write(s->s, last, prevptr - last);
    1105                 :        148 :                     jl_value_t *e = *(jl_value_t**)prevptr;
    1106                 :            :                     JL_GC_PROMISE_ROOTED(e);
    1107   [ +  +  +  +  :        148 :                     if (t->name->mutabl && e && jl_field_isptr(t, i - 1) && jl_is_cpointer(e) &&
          +  -  -  +  -  
                      - ]
    1108         [ #  # ]:          0 :                         jl_unbox_voidpointer(e) != (void*)-1 && jl_unbox_voidpointer(e) != NULL)
    1109                 :            :                         // reset Ptr fields to C_NULL (but keep MAP_FAILED / INVALID_HANDLE)
    1110                 :          0 :                         jl_serialize_cnull(s, jl_typeof(e));
    1111                 :            :                     else
    1112                 :        148 :                         jl_serialize_value(s, e);
    1113                 :        148 :                     last = prevptr + sizeof(jl_value_t*);
    1114                 :        148 :                     j++;
    1115         [ +  + ]:        148 :                     if (j < np)
    1116                 :        120 :                         prevptr = (char*)&((jl_value_t**)data)[jl_ptr_offset(t, j)];
    1117                 :            :                     else
    1118                 :         28 :                         break;
    1119                 :            :                 }
    1120                 :            :             }
    1121         [ +  + ]:        296 :             if (i == nf)
    1122                 :         28 :                 break;
    1123   [ +  +  -  +  :        268 :             if (t->name->mutabl && jl_is_cpointer_type(jl_field_type(t, i)) && *(void**)ptr != (void*)-1) {
                   -  - ]
    1124         [ #  # ]:          0 :                 if (ptr > last)
    1125                 :          0 :                     ios_write(s->s, last, ptr - last);
    1126                 :          0 :                 char *n = NULL;
    1127                 :          0 :                 ios_write(s->s, (char*)&n, sizeof(n));
    1128                 :          0 :                 last = ptr + sizeof(n);
    1129                 :            :             }
    1130                 :            :         }
    1131                 :         28 :         char *ptr = data + jl_datatype_size(t);
    1132         [ +  + ]:         28 :         if (ptr > last)
    1133                 :         24 :             ios_write(s->s, last, ptr - last);
    1134                 :            :     }
    1135                 :            : }
    1136                 :            : 
    1137                 :            : // Used to serialize the external method instances queued in queued_method_roots (from newly_inferred)
    1138                 :          4 : static void serialize_htable_keys(jl_serializer_state *s, htable_t *ht, int nitems)
    1139                 :            : {
    1140                 :          4 :     write_int32(s->s, nitems);
    1141                 :          4 :     void **table = ht->table;
    1142                 :          4 :     size_t i, n = 0, sz = ht->size;
    1143                 :            :     (void)n;
    1144         [ +  + ]:         68 :     for (i = 0; i < sz; i += 2) {
    1145         [ -  + ]:         64 :         if (table[i+1] != HT_NOTFOUND) {
    1146                 :          0 :             jl_serialize_value(s, (jl_value_t*)table[i]);
    1147                 :          0 :             n += 1;
    1148                 :            :         }
    1149                 :            :     }
    1150         [ -  + ]:          4 :     assert(n == nitems);
    1151                 :          4 : }
    1152                 :            : 
    1153                 :            : // Create the forward-edge map (caller => callees)
    1154                 :            : // the intent of these functions is to invert the backedges tree
    1155                 :            : // for anything that points to a method not part of the worklist
    1156                 :            : // or method instances not in the queue
    1157                 :            : //
    1158                 :            : // from MethodTables
    1159                 :      44432 : static void jl_collect_missing_backedges_to_mod(jl_methtable_t *mt)
    1160                 :            : {
    1161                 :      44432 :     jl_array_t *backedges = mt->backedges;
    1162         [ +  + ]:      44432 :     if (backedges) {
    1163                 :        612 :         size_t i, l = jl_array_len(backedges);
    1164         [ +  + ]:       4484 :         for (i = 1; i < l; i += 2) {
    1165                 :       3872 :             jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i);
    1166                 :       3872 :             jl_value_t *missing_callee = jl_array_ptr_ref(backedges, i - 1);  // signature of abstract callee
    1167                 :       3872 :             jl_array_t **edges = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller);
    1168         [ +  + ]:       3872 :             if (*edges == HT_NOTFOUND)
    1169                 :        388 :                 *edges = jl_alloc_vec_any(0);
    1170                 :       3872 :             jl_array_ptr_1d_push(*edges, missing_callee);
    1171                 :            :         }
    1172                 :            :     }
    1173                 :      44432 : }
    1174                 :            : 
    1175                 :            : // from MethodInstances
    1176                 :     141578 : static void collect_backedges(jl_method_instance_t *callee) JL_GC_DISABLED
    1177                 :            : {
    1178                 :     141578 :     jl_array_t *backedges = callee->backedges;
    1179         [ +  + ]:     141578 :     if (backedges) {
    1180                 :     124072 :         size_t i, l = jl_array_len(backedges);
    1181         [ +  + ]:     556810 :         for (i = 0; i < l; i++) {
    1182                 :     432738 :             jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i);
    1183                 :     432738 :             jl_array_t **edges = (jl_array_t**)ptrhash_bp(&edges_map, caller);
    1184         [ +  + ]:     432738 :             if (*edges == HT_NOTFOUND)
    1185                 :     103528 :                 *edges = jl_alloc_vec_any(0);
    1186                 :     432738 :             jl_array_ptr_1d_push(*edges, (jl_value_t*)callee);
    1187                 :            :         }
    1188                 :            :     }
    1189                 :     141578 : }
    1190                 :            : 
    1191                 :            : 
    1192                 :            : // For functions owned by modules not on the worklist, call this on each method.
    1193                 :            : // - if the method is owned by a worklist module, add it to the list of things to be
    1194                 :            : //   fully serialized
    1195                 :            : // - otherwise (i.e., if it's an external method), check all of its specializations.
    1196                 :            : //   Collect backedges from those that are not being fully serialized.
    1197                 :     122680 : static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) JL_GC_DISABLED
    1198                 :            : {
    1199                 :     122680 :     jl_array_t *s = (jl_array_t*)closure;
    1200                 :     122680 :     jl_method_t *m = ml->func.method;
    1201         [ -  + ]:     122680 :     if (module_in_worklist(m->module)) {
    1202                 :          0 :         jl_array_ptr_1d_push(s, (jl_value_t*)m);
    1203                 :          0 :         jl_array_ptr_1d_push(s, (jl_value_t*)ml->simplesig);
    1204                 :            :     }
    1205                 :            :     else {
    1206                 :     122680 :         jl_svec_t *specializations = m->specializations;
    1207                 :     122680 :         size_t i, l = jl_svec_len(specializations);
    1208         [ +  + ]:     439724 :         for (i = 0; i < l; i++) {
    1209                 :     317044 :             jl_method_instance_t *callee = (jl_method_instance_t*)jl_svecref(specializations, i);
    1210   [ +  +  +  - ]:     317044 :             if ((jl_value_t*)callee != jl_nothing && !method_instance_in_queue(callee))
    1211                 :     141578 :                 collect_backedges(callee);
    1212                 :            :         }
    1213                 :            :     }
    1214                 :     122680 :     return 1;
    1215                 :            : }
    1216                 :            : 
    1217                 :      44432 : static void jl_collect_methtable_from_mod(jl_array_t *s, jl_methtable_t *mt) JL_GC_DISABLED
    1218                 :            : {
    1219                 :      44432 :     jl_typemap_visitor(mt->defs, jl_collect_methcache_from_mod, (void*)s);
    1220                 :      44432 : }
    1221                 :            : 
    1222                 :            : // Collect methods of external functions defined by modules in the worklist
    1223                 :            : // "extext" = "extending external"
    1224                 :            : // Also collect relevant backedges
    1225                 :        512 : static void jl_collect_extext_methods_from_mod(jl_array_t *s, jl_module_t *m) JL_GC_DISABLED
    1226                 :            : {
    1227         [ +  + ]:        512 :     if (module_in_worklist(m))
    1228                 :          4 :         return;
    1229                 :            :     size_t i;
    1230                 :        508 :     void **table = m->bindings.table;
    1231         [ +  + ]:     359036 :     for (i = 1; i < m->bindings.size; i += 2) {
    1232         [ +  + ]:     358528 :         if (table[i] != HT_NOTFOUND) {
    1233                 :     126798 :             jl_binding_t *b = (jl_binding_t*)table[i];
    1234   [ +  +  +  +  :     126798 :             if (b->owner == m && b->value && b->constp) {
                   +  + ]
    1235                 :      99172 :                 jl_value_t *bv = jl_unwrap_unionall(b->value);
    1236         [ +  + ]:      99172 :                 if (jl_is_datatype(bv)) {
    1237                 :      49912 :                     jl_typename_t *tn = ((jl_datatype_t*)bv)->name;
    1238   [ +  +  +  +  :      49912 :                     if (tn->module == m && tn->name == b->name && tn->wrapper == b->value) {
                   +  - ]
    1239                 :      48880 :                         jl_methtable_t *mt = tn->mt;
    1240         [ +  + ]:      48880 :                         if (mt != NULL &&
    1241         [ +  - ]:      48868 :                                 (jl_value_t*)mt != jl_nothing &&
    1242   [ +  +  +  + ]:      48868 :                                 (mt != jl_type_type_mt && mt != jl_nonfunction_mt)) {
    1243                 :      44424 :                             jl_collect_methtable_from_mod(s, mt);
    1244                 :      44424 :                             jl_collect_missing_backedges_to_mod(mt);
    1245                 :            :                         }
    1246                 :            :                     }
    1247                 :            :                 }
    1248         [ +  + ]:      49260 :                 else if (jl_is_module(b->value)) {
    1249                 :        984 :                     jl_module_t *child = (jl_module_t*)b->value;
    1250   [ +  +  +  +  :        984 :                     if (child != m && child->parent == m && child->name == b->name) {
                   +  - ]
    1251                 :            :                         // this is the original/primary binding for the submodule
    1252                 :        340 :                         jl_collect_extext_methods_from_mod(s, (jl_module_t*)b->value);
    1253                 :            :                     }
    1254                 :            :                 }
    1255         [ -  + ]:      48276 :                 else if (jl_is_mtable(b->value)) {
    1256                 :          0 :                     jl_methtable_t *mt = (jl_methtable_t*)b->value;
    1257   [ #  #  #  # ]:          0 :                     if (mt->module == m && mt->name == b->name) {
    1258                 :            :                         // this is probably an external method table, so let's assume so
    1259                 :            :                         // as there is no way to precisely distinguish them,
    1260                 :            :                         // and the rest of this serializer does not bother
    1261                 :            :                         // to handle any method tables specially
    1262                 :          0 :                         jl_collect_methtable_from_mod(s, (jl_methtable_t*)bv);
    1263                 :            :                     }
    1264                 :            :                 }
    1265                 :            :             }
    1266                 :            :         }
    1267                 :            :     }
    1268                 :            : }
    1269                 :            : 
    1270                 :            : // flatten the backedge map reachable from caller into callees
    1271                 :          0 : static void jl_collect_backedges_to(jl_method_instance_t *caller, htable_t *all_callees) JL_GC_DISABLED
    1272                 :            : {
    1273                 :          0 :     jl_array_t **pcallees = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller),
    1274                 :          0 :                 *callees = *pcallees;
    1275         [ #  # ]:          0 :     if (callees != HT_NOTFOUND) {
    1276                 :          0 :         *pcallees = (jl_array_t*) HT_NOTFOUND;
    1277                 :          0 :         size_t i, l = jl_array_len(callees);
    1278         [ #  # ]:          0 :         for (i = 0; i < l; i++) {
    1279                 :          0 :             jl_value_t *c = jl_array_ptr_ref(callees, i);
    1280                 :          0 :             ptrhash_put(all_callees, c, c);
    1281         [ #  # ]:          0 :             if (jl_is_method_instance(c)) {
    1282                 :          0 :                 jl_collect_backedges_to((jl_method_instance_t*)c, all_callees);
    1283                 :            :             }
    1284                 :            :         }
    1285                 :            :     }
    1286                 :          0 : }
    1287                 :            : 
    1288                 :            : // Extract `edges` and `ext_targets` from `edges_map`
    1289                 :            : // This identifies internal->external edges in the call graph, pulling them out for special treatment.
    1290                 :          4 : static void jl_collect_backedges( /* edges */ jl_array_t *s, /* ext_targets */ jl_array_t *t)
    1291                 :            : {
    1292                 :            :     htable_t all_targets;         // target => tgtindex mapping
    1293                 :            :     htable_t all_callees;         // MIs called by worklist methods (eff. Set{MethodInstance})
    1294                 :          4 :     htable_new(&all_targets, 0);
    1295                 :          4 :     htable_new(&all_callees, 0);
    1296                 :            :     size_t i;
    1297                 :          4 :     void **table = edges_map.table;    // edges is caller => callees
    1298         [ +  + ]:     262148 :     for (i = 0; i < edges_map.size; i += 2) {
    1299                 :     262144 :         jl_method_instance_t *caller = (jl_method_instance_t*)table[i];
    1300                 :     262144 :         jl_array_t *callees = (jl_array_t*)table[i + 1];
    1301   [ +  +  +  -  :     262144 :         if (callees != HT_NOTFOUND && (module_in_worklist(caller->def.method->module) || method_instance_in_queue(caller))) {
                   -  + ]
    1302                 :          0 :             size_t i, l = jl_array_len(callees);
    1303         [ #  # ]:          0 :             for (i = 0; i < l; i++) {
    1304                 :          0 :                 jl_value_t *c = jl_array_ptr_ref(callees, i);
    1305                 :          0 :                 ptrhash_put(&all_callees, c, c);
    1306         [ #  # ]:          0 :                 if (jl_is_method_instance(c)) {
    1307                 :          0 :                     jl_collect_backedges_to((jl_method_instance_t*)c, &all_callees);
    1308                 :            :                 }
    1309                 :            :             }
    1310                 :          0 :             callees = jl_alloc_array_1d(jl_array_int32_type, 0);
    1311                 :          0 :             void **pc = all_callees.table;
    1312                 :            :             size_t j;
    1313                 :          0 :             int valid = 1;
    1314   [ #  #  #  # ]:          0 :             for (j = 0; valid && j < all_callees.size; j += 2) {
    1315         [ #  # ]:          0 :                 if (pc[j + 1] != HT_NOTFOUND) {
    1316                 :          0 :                     jl_value_t *callee = (jl_value_t*)pc[j];
    1317                 :          0 :                     void *target = ptrhash_get(&all_targets, (void*)callee);
    1318         [ #  # ]:          0 :                     if (target == HT_NOTFOUND) {
    1319                 :          0 :                         jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee;
    1320                 :            :                         jl_value_t *sig;
    1321         [ #  # ]:          0 :                         if (jl_is_method_instance(callee)) {
    1322                 :          0 :                             sig = callee_mi->specTypes;
    1323                 :            :                         }
    1324                 :            :                         else {
    1325                 :          0 :                             sig = callee;
    1326                 :            :                         }
    1327                 :          0 :                         size_t min_valid = 0;
    1328                 :          0 :                         size_t max_valid = ~(size_t)0;
    1329                 :          0 :                         int ambig = 0;
    1330                 :          0 :                         jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_atomic_load_acquire(&jl_world_counter), &min_valid, &max_valid, &ambig);
    1331         [ #  # ]:          0 :                         if (matches == jl_false) {
    1332                 :          0 :                             valid = 0;
    1333                 :          0 :                             break;
    1334                 :            :                         }
    1335                 :            :                         size_t k;
    1336         [ #  # ]:          0 :                         for (k = 0; k < jl_array_len(matches); k++) {
    1337                 :          0 :                             jl_method_match_t *match = (jl_method_match_t *)jl_array_ptr_ref(matches, k);
    1338                 :          0 :                             jl_array_ptr_set(matches, k, match->method);
    1339                 :            :                         }
    1340                 :          0 :                         jl_array_ptr_1d_push(t, callee);
    1341                 :          0 :                         jl_array_ptr_1d_push(t, matches);
    1342                 :          0 :                         target = (char*)HT_NOTFOUND + jl_array_len(t) / 2;
    1343                 :          0 :                         ptrhash_put(&all_targets, (void*)callee, target);
    1344                 :            :                     }
    1345                 :          0 :                     jl_array_grow_end(callees, 1);
    1346                 :          0 :                     ((int32_t*)jl_array_data(callees))[jl_array_len(callees) - 1] = (char*)target - (char*)HT_NOTFOUND - 1;
    1347                 :            :                 }
    1348                 :            :             }
    1349                 :          0 :             htable_reset(&all_callees, 100);
    1350         [ #  # ]:          0 :             if (valid) {
    1351                 :          0 :                 jl_array_ptr_1d_push(s, (jl_value_t*)caller);
    1352                 :          0 :                 jl_array_ptr_1d_push(s, (jl_value_t*)callees);
    1353                 :            :             }
    1354                 :            :         }
    1355                 :            :     }
    1356                 :          4 :     htable_free(&all_targets);
    1357                 :          4 :     htable_free(&all_callees);
    1358                 :          4 : }
    1359                 :            : 
    1360                 :            : // serialize information about all loaded modules
    1361                 :          4 : static void write_mod_list(ios_t *s, jl_array_t *a)
    1362                 :            : {
    1363                 :            :     size_t i;
    1364                 :          4 :     size_t len = jl_array_len(a);
    1365         [ +  + ]:        180 :     for (i = 0; i < len; i++) {
    1366                 :        176 :         jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(a, i);
    1367         [ -  + ]:        176 :         assert(jl_is_module(m));
    1368         [ +  + ]:        176 :         if (!module_in_worklist(m)) {
    1369                 :        172 :             const char *modname = jl_symbol_name(m->name);
    1370                 :        172 :             size_t l = strlen(modname);
    1371                 :        172 :             write_int32(s, l);
    1372                 :        172 :             ios_write(s, modname, l);
    1373                 :        172 :             write_uint64(s, m->uuid.hi);
    1374                 :        172 :             write_uint64(s, m->uuid.lo);
    1375                 :        172 :             write_uint64(s, m->build_id);
    1376                 :            :         }
    1377                 :            :     }
    1378                 :          4 :     write_int32(s, 0);
    1379                 :          4 : }
    1380                 :            : 
    1381                 :            : // "magic" string and version header of .ji file
    1382                 :            : static const int JI_FORMAT_VERSION = 11;
    1383                 :            : static const char JI_MAGIC[] = "\373jli\r\n\032\n"; // based on PNG signature
    1384                 :            : static const uint16_t BOM = 0xFEFF; // byte-order marker
    1385                 :          4 : static void write_header(ios_t *s)
    1386                 :            : {
    1387                 :          4 :     ios_write(s, JI_MAGIC, strlen(JI_MAGIC));
    1388                 :          4 :     write_uint16(s, JI_FORMAT_VERSION);
    1389                 :          4 :     ios_write(s, (char *) &BOM, 2);
    1390                 :          4 :     write_uint8(s, sizeof(void*));
    1391                 :          4 :     ios_write(s, JL_BUILD_UNAME, strlen(JL_BUILD_UNAME)+1);
    1392                 :          4 :     ios_write(s, JL_BUILD_ARCH, strlen(JL_BUILD_ARCH)+1);
    1393                 :          4 :     ios_write(s, JULIA_VERSION_STRING, strlen(JULIA_VERSION_STRING)+1);
    1394                 :          4 :     const char *branch = jl_git_branch(), *commit = jl_git_commit();
    1395                 :          4 :     ios_write(s, branch, strlen(branch)+1);
    1396                 :          4 :     ios_write(s, commit, strlen(commit)+1);
    1397                 :          4 : }
    1398                 :            : 
    1399                 :            : // serialize information about the result of deserializing this file
    1400                 :          4 : static void write_work_list(ios_t *s)
    1401                 :            : {
    1402                 :          4 :     int i, l = jl_array_len(serializer_worklist);
    1403         [ +  + ]:          8 :     for (i = 0; i < l; i++) {
    1404                 :          4 :         jl_module_t *workmod = (jl_module_t*)jl_array_ptr_ref(serializer_worklist, i);
    1405   [ +  -  +  - ]:          4 :         if (workmod->parent == jl_main_module || workmod->parent == workmod) {
    1406                 :          4 :             size_t l = strlen(jl_symbol_name(workmod->name));
    1407                 :          4 :             write_int32(s, l);
    1408                 :          4 :             ios_write(s, jl_symbol_name(workmod->name), l);
    1409                 :          4 :             write_uint64(s, workmod->uuid.hi);
    1410                 :          4 :             write_uint64(s, workmod->uuid.lo);
    1411                 :          4 :             write_uint64(s, workmod->build_id);
    1412                 :            :         }
    1413                 :            :     }
    1414                 :          4 :     write_int32(s, 0);
    1415                 :          4 : }
    1416                 :            : 
    1417                 :          0 : static void write_module_path(ios_t *s, jl_module_t *depmod) JL_NOTSAFEPOINT
    1418                 :            : {
    1419   [ #  #  #  # ]:          0 :     if (depmod->parent == jl_main_module || depmod->parent == depmod)
    1420                 :          0 :         return;
    1421                 :          0 :     const char *mname = jl_symbol_name(depmod->name);
    1422                 :          0 :     size_t slen = strlen(mname);
    1423                 :          0 :     write_module_path(s, depmod->parent);
    1424                 :          0 :     write_int32(s, slen);
    1425                 :          0 :     ios_write(s, mname, slen);
    1426                 :            : }
    1427                 :            : 
    1428                 :            : // Cache file header
    1429                 :            : // Serialize the global Base._require_dependencies array of pathnames that
    1430                 :            : // are include dependencies. Also write Preferences and return
    1431                 :            : // the location of the srctext "pointer" in the header index.
    1432                 :          4 : static int64_t write_dependency_list(ios_t *s, jl_array_t **udepsp)
    1433                 :            : {
    1434                 :          4 :     int64_t initial_pos = 0;
    1435                 :          4 :     int64_t pos = 0;
    1436                 :            :     static jl_array_t *deps = NULL;
    1437         [ +  - ]:          4 :     if (!deps)
    1438                 :          4 :         deps = (jl_array_t*)jl_get_global(jl_base_module, jl_symbol("_require_dependencies"));
    1439                 :            : 
    1440                 :            :     // unique(deps) to eliminate duplicates while preserving order:
    1441                 :            :     // we preserve order so that the topmost included .jl file comes first
    1442                 :            :     static jl_value_t *unique_func = NULL;
    1443         [ +  - ]:          4 :     if (!unique_func)
    1444                 :          4 :         unique_func = jl_get_global(jl_base_module, jl_symbol("unique"));
    1445                 :          4 :     jl_value_t *uniqargs[2] = {unique_func, (jl_value_t*)deps};
    1446                 :          4 :     jl_task_t *ct = jl_current_task;
    1447                 :          4 :     size_t last_age = ct->world_age;
    1448                 :          4 :     ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
    1449   [ +  -  +  - ]:          4 :     jl_array_t *udeps = (*udepsp = deps && unique_func ? (jl_array_t*)jl_apply(uniqargs, 2) : NULL);
    1450                 :          4 :     ct->world_age = last_age;
    1451                 :            : 
    1452                 :            :     // write a placeholder for total size so that we can quickly seek past all of the
    1453                 :            :     // dependencies if we don't need them
    1454                 :          4 :     initial_pos = ios_pos(s);
    1455                 :          4 :     write_uint64(s, 0);
    1456         [ +  - ]:          4 :     if (udeps) {
    1457                 :          4 :         size_t i, l = jl_array_len(udeps);
    1458         [ +  + ]:          8 :         for (i = 0; i < l; i++) {
    1459                 :          4 :             jl_value_t *deptuple = jl_array_ptr_ref(udeps, i);
    1460                 :          4 :             jl_value_t *dep = jl_fieldref(deptuple, 1);              // file abspath
    1461                 :          4 :             size_t slen = jl_string_len(dep);
    1462                 :          4 :             write_int32(s, slen);
    1463                 :          4 :             ios_write(s, jl_string_data(dep), slen);
    1464                 :          4 :             write_float64(s, jl_unbox_float64(jl_fieldref(deptuple, 2)));  // mtime
    1465                 :          4 :             jl_module_t *depmod = (jl_module_t*)jl_fieldref(deptuple, 0);  // evaluating module
    1466                 :          4 :             jl_module_t *depmod_top = depmod;
    1467   [ +  +  +  - ]:          8 :             while (depmod_top->parent != jl_main_module && depmod_top->parent != depmod_top)
    1468                 :          4 :                 depmod_top = depmod_top->parent;
    1469                 :          4 :             unsigned provides = 0;
    1470                 :          4 :             size_t j, lj = jl_array_len(serializer_worklist);
    1471         [ +  + ]:          8 :             for (j = 0; j < lj; j++) {
    1472                 :          4 :                 jl_module_t *workmod = (jl_module_t*)jl_array_ptr_ref(serializer_worklist, j);
    1473   [ +  -  +  - ]:          4 :                 if (workmod->parent == jl_main_module || workmod->parent == workmod) {
    1474                 :          4 :                     ++provides;
    1475         [ -  + ]:          4 :                     if (workmod == depmod_top) {
    1476                 :          0 :                         write_int32(s, provides);
    1477                 :          0 :                         write_module_path(s, depmod);
    1478                 :          0 :                         break;
    1479                 :            :                     }
    1480                 :            :                 }
    1481                 :            :             }
    1482                 :          4 :             write_int32(s, 0);
    1483                 :            :         }
    1484                 :          4 :         write_int32(s, 0); // terminator, for ease of reading
    1485                 :            : 
    1486                 :            :         // Calculate Preferences hash for current package.
    1487                 :          4 :         jl_value_t *prefs_hash = NULL;
    1488                 :          4 :         jl_value_t *prefs_list = NULL;
    1489                 :          4 :         JL_GC_PUSH1(&prefs_list);
    1490         [ +  - ]:          4 :         if (jl_base_module) {
    1491                 :            :             // Toplevel module is the module we're currently compiling, use it to get our preferences hash
    1492                 :          4 :             jl_value_t * toplevel = (jl_value_t*)jl_get_global(jl_base_module, jl_symbol("__toplevel__"));
    1493                 :          4 :             jl_value_t * prefs_hash_func = jl_get_global(jl_base_module, jl_symbol("get_preferences_hash"));
    1494                 :          4 :             jl_value_t * get_compiletime_prefs_func = jl_get_global(jl_base_module, jl_symbol("get_compiletime_preferences"));
    1495                 :            : 
    1496   [ +  -  +  -  :          4 :             if (toplevel && prefs_hash_func && get_compiletime_prefs_func) {
                   +  - ]
    1497                 :            :                 // Temporary invoke in newest world age
    1498                 :          4 :                 size_t last_age = ct->world_age;
    1499                 :          4 :                 ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
    1500                 :            : 
    1501                 :            :                 // call get_compiletime_prefs(__toplevel__)
    1502                 :          4 :                 jl_value_t *args[3] = {get_compiletime_prefs_func, (jl_value_t*)toplevel, NULL};
    1503                 :          4 :                 prefs_list = (jl_value_t*)jl_apply(args, 2);
    1504                 :            : 
    1505                 :            :                 // Call get_preferences_hash(__toplevel__, prefs_list)
    1506                 :          4 :                 args[0] = prefs_hash_func;
    1507                 :          4 :                 args[2] = prefs_list;
    1508                 :          4 :                 prefs_hash = (jl_value_t*)jl_apply(args, 3);
    1509                 :            : 
    1510                 :            :                 // Reset world age to normal
    1511                 :          4 :                 ct->world_age = last_age;
    1512                 :            :             }
    1513                 :            :         }
    1514                 :            : 
    1515                 :            :         // If we successfully got the preferences, write it out, otherwise write `0` for this `.ji` file.
    1516   [ +  -  +  - ]:          8 :         if (prefs_hash != NULL && prefs_list != NULL) {
    1517                 :          4 :             size_t i, l = jl_array_len(prefs_list);
    1518         [ -  + ]:          4 :             for (i = 0; i < l; i++) {
    1519                 :          0 :                 jl_value_t *pref_name = jl_array_ptr_ref(prefs_list, i);
    1520                 :          0 :                 size_t slen = jl_string_len(pref_name);
    1521                 :          0 :                 write_int32(s, slen);
    1522                 :          0 :                 ios_write(s, jl_string_data(pref_name), slen);
    1523                 :            :             }
    1524                 :          4 :             write_int32(s, 0); // terminator
    1525                 :          4 :             write_uint64(s, jl_unbox_uint64(prefs_hash));
    1526                 :            :         } else {
    1527                 :            :             // This is an error path, but let's at least generate a valid `.ji` file.
    1528                 :            :             // We declare an empty list of preference names, followed by a zero-hash.
    1529                 :            :             // The zero-hash is not what would be generated for an empty set of preferences,
    1530                 :            :             // and so this `.ji` file will be invalidated by a future non-erroring pass
    1531                 :            :             // through this function.
    1532                 :          0 :             write_int32(s, 0);
    1533                 :          0 :             write_uint64(s, 0);
    1534                 :            :         }
    1535                 :          4 :         JL_GC_POP(); // for prefs_list
    1536                 :            : 
    1537                 :            :         // write a dummy file position to indicate the beginning of the source-text
    1538                 :          4 :         pos = ios_pos(s);
    1539                 :          4 :         ios_seek(s, initial_pos);
    1540                 :          4 :         write_uint64(s, pos - initial_pos);
    1541                 :          4 :         ios_seek(s, pos);
    1542                 :          4 :         write_int64(s, 0);
    1543                 :            :     }
    1544                 :          4 :     return pos;
    1545                 :            : }
    1546                 :            : 
    1547                 :            : // --- deserialize ---
    1548                 :            : 
    1549                 :            : static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED;
    1550                 :            : 
    1551                 :          0 : static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_value_t **loc) JL_GC_DISABLED
    1552                 :            : {
    1553         [ #  # ]:          0 :     assert(pos == backref_list.len - 1 && "nothing should have been deserialized since assigning pos");
    1554                 :          0 :     int tag = read_uint8(s->s);
    1555   [ #  #  #  # ]:          0 :     if (tag == 6 || tag == 7) {
    1556                 :          0 :         jl_typename_t *name = (jl_typename_t*)jl_deserialize_value(s, NULL);
    1557                 :          0 :         jl_value_t *dtv = name->wrapper;
    1558                 :          0 :         jl_svec_t *parameters = (jl_svec_t*)jl_deserialize_value(s, NULL);
    1559                 :          0 :         dtv = jl_apply_type(dtv, jl_svec_data(parameters), jl_svec_len(parameters));
    1560                 :          0 :         backref_list.items[pos] = dtv;
    1561                 :          0 :         return dtv;
    1562                 :            :     }
    1563         [ #  # ]:          0 :     if (tag == 9) {
    1564                 :          0 :         jl_datatype_t *primarydt = (jl_datatype_t*)jl_deserialize_value(s, NULL);
    1565                 :          0 :         jl_value_t *dtv = jl_typeof(jl_get_kwsorter((jl_value_t*)primarydt));
    1566                 :          0 :         backref_list.items[pos] = dtv;
    1567                 :          0 :         return dtv;
    1568                 :            :     }
    1569   [ #  #  #  #  :          0 :     if (!(tag == 0 || tag == 5 || tag == 10 || tag == 11 || tag == 12)) {
          #  #  #  #  #  
                      # ]
    1570                 :          0 :         assert(0 && "corrupt deserialization state");
    1571                 :            :         abort();
    1572                 :            :     }
    1573                 :          0 :     jl_datatype_t *dt = jl_new_uninitialized_datatype();
    1574                 :          0 :     backref_list.items[pos] = dt;
    1575   [ #  #  #  # ]:          0 :     if (loc != NULL && loc != HT_NOTFOUND)
    1576                 :          0 :         *loc = (jl_value_t*)dt;
    1577                 :          0 :     size_t size = read_int32(s->s);
    1578                 :          0 :     uint8_t flags = read_uint8(s->s);
    1579                 :          0 :     uint8_t memflags = read_uint8(s->s);
    1580                 :          0 :     dt->size = size;
    1581                 :          0 :     int has_layout = flags & 1;
    1582                 :          0 :     int has_instance = (flags >> 1) & 1;
    1583                 :          0 :     dt->hasfreetypevars = memflags & 1;
    1584                 :          0 :     dt->isconcretetype = (memflags >> 1) & 1;
    1585                 :          0 :     dt->isdispatchtuple = (memflags >> 2) & 1;
    1586                 :          0 :     dt->isbitstype = (memflags >> 3) & 1;
    1587                 :          0 :     dt->zeroinit = (memflags >> 4) & 1;
    1588                 :          0 :     dt->has_concrete_subtype = (memflags >> 5) & 1;
    1589                 :          0 :     dt->cached_by_hash = (memflags >> 6) & 1;
    1590                 :          0 :     dt->hash = read_int32(s->s);
    1591                 :            : 
    1592         [ #  # ]:          0 :     if (has_layout) {
    1593                 :          0 :         uint8_t layout = read_uint8(s->s);
    1594         [ #  # ]:          0 :         if (layout == 1) {
    1595                 :          0 :             dt->layout = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type))->layout;
    1596                 :            :         }
    1597         [ #  # ]:          0 :         else if (layout == 2) {
    1598                 :          0 :             dt->layout = jl_nothing_type->layout;
    1599                 :            :         }
    1600         [ #  # ]:          0 :         else if (layout == 3) {
    1601                 :          0 :             dt->layout = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->layout;
    1602                 :            :         }
    1603                 :            :         else {
    1604         [ #  # ]:          0 :             assert(layout == 0);
    1605                 :            :             jl_datatype_layout_t buffer;
    1606                 :          0 :             ios_readall(s->s, (char*)&buffer, sizeof(buffer));
    1607                 :          0 :             uint32_t nf = buffer.nfields;
    1608                 :          0 :             uint32_t np = buffer.npointers;
    1609                 :          0 :             uint8_t fielddesc_type = buffer.fielddesc_type;
    1610         [ #  # ]:          0 :             size_t fielddesc_size = nf > 0 ? jl_fielddesc_size(fielddesc_type) : 0;
    1611                 :          0 :             size_t fldsize = nf * fielddesc_size;
    1612         [ #  # ]:          0 :             if (buffer.first_ptr != -1)
    1613                 :          0 :                 fldsize += np << fielddesc_type;
    1614                 :          0 :             jl_datatype_layout_t *layout = (jl_datatype_layout_t*)jl_gc_perm_alloc(
    1615                 :            :                     sizeof(jl_datatype_layout_t) + fldsize,
    1616                 :            :                     0, 4, 0);
    1617                 :          0 :             *layout = buffer;
    1618                 :          0 :             ios_readall(s->s, (char*)(layout + 1), fldsize);
    1619                 :          0 :             dt->layout = layout;
    1620                 :            :         }
    1621                 :            :     }
    1622                 :            : 
    1623   [ #  #  #  #  :          0 :     if (tag == 10 || tag == 11 || tag == 12) {
                   #  # ]
    1624         [ #  # ]:          0 :         assert(pos > 0);
    1625         [ #  # ]:          0 :         arraylist_push(&flagref_list, loc == HT_NOTFOUND ? NULL : loc);
    1626                 :          0 :         arraylist_push(&flagref_list, (void*)(uintptr_t)pos);
    1627                 :          0 :         ptrhash_put(&uniquing_table, dt, NULL);
    1628                 :            :     }
    1629                 :            : 
    1630         [ #  # ]:          0 :     if (has_instance) {
    1631         [ #  # ]:          0 :         assert(dt->isconcretetype && "there shouldn't be an instance on an abstract type");
    1632                 :          0 :         dt->instance = jl_deserialize_value(s, &dt->instance);
    1633                 :          0 :         jl_gc_wb(dt, dt->instance);
    1634                 :            :     }
    1635                 :          0 :     dt->name = (jl_typename_t*)jl_deserialize_value(s, (jl_value_t**)&dt->name);
    1636                 :          0 :     jl_gc_wb(dt, dt->name);
    1637                 :          0 :     dt->parameters = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&dt->parameters);
    1638                 :          0 :     jl_gc_wb(dt, dt->parameters);
    1639                 :          0 :     dt->super = (jl_datatype_t*)jl_deserialize_value(s, (jl_value_t**)&dt->super);
    1640                 :          0 :     jl_gc_wb(dt, dt->super);
    1641                 :          0 :     dt->types = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&dt->types);
    1642         [ #  # ]:          0 :     if (dt->types) jl_gc_wb(dt, dt->types);
    1643                 :            : 
    1644                 :          0 :     return (jl_value_t*)dt;
    1645                 :            : }
    1646                 :            : 
    1647                 :          0 : static jl_value_t *jl_deserialize_value_svec(jl_serializer_state *s, uint8_t tag, jl_value_t **loc) JL_GC_DISABLED
    1648                 :            : {
    1649                 :            :     size_t i, len;
    1650         [ #  # ]:          0 :     if (tag == TAG_SVEC)
    1651                 :          0 :         len = read_uint8(s->s);
    1652                 :            :     else
    1653                 :          0 :         len = read_int32(s->s);
    1654                 :          0 :     jl_svec_t *sv = jl_alloc_svec(len);
    1655         [ #  # ]:          0 :     if (loc != NULL)
    1656                 :          0 :         *loc = (jl_value_t*)sv;
    1657                 :          0 :     arraylist_push(&backref_list, (jl_value_t*)sv);
    1658                 :          0 :     jl_value_t **data = jl_svec_data(sv);
    1659         [ #  # ]:          0 :     for (i = 0; i < len; i++) {
    1660                 :          0 :         data[i] = jl_deserialize_value(s, &data[i]);
    1661                 :            :     }
    1662                 :          0 :     return (jl_value_t*)sv;
    1663                 :            : }
    1664                 :            : 
    1665                 :          0 : static jl_value_t *jl_deserialize_value_symbol(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED
    1666                 :            : {
    1667                 :            :     size_t len;
    1668         [ #  # ]:          0 :     if (tag == TAG_SYMBOL)
    1669                 :          0 :         len = read_uint8(s->s);
    1670                 :            :     else
    1671                 :          0 :         len = read_int32(s->s);
    1672         [ #  # ]:          0 :     char *name = (char*)(len >= 256 ? malloc_s(len + 1) : alloca(len + 1));
    1673                 :          0 :     ios_readall(s->s, name, len);
    1674                 :          0 :     name[len] = '\0';
    1675                 :          0 :     jl_value_t *sym = (jl_value_t*)jl_symbol(name);
    1676         [ #  # ]:          0 :     if (len >= 256)
    1677                 :          0 :         free(name);
    1678                 :          0 :     arraylist_push(&backref_list, sym);
    1679                 :          0 :     return sym;
    1680                 :            : }
    1681                 :            : 
    1682                 :          0 : static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED
    1683                 :            : {
    1684                 :            :     int16_t i, ndims;
    1685                 :            :     int isptr, isunion, hasptr, elsize;
    1686         [ #  # ]:          0 :     if (tag == TAG_ARRAY1D) {
    1687                 :          0 :         ndims = 1;
    1688                 :          0 :         elsize = read_uint8(s->s);
    1689                 :          0 :         isptr = (elsize >> 7) & 1;
    1690                 :          0 :         hasptr = (elsize >> 6) & 1;
    1691                 :          0 :         isunion = (elsize >> 5) & 1;
    1692                 :          0 :         elsize = elsize & 0x1f;
    1693                 :            :     }
    1694                 :            :     else {
    1695                 :          0 :         ndims = read_uint16(s->s);
    1696                 :          0 :         elsize = read_uint16(s->s);
    1697                 :          0 :         isptr = (elsize >> 15) & 1;
    1698                 :          0 :         hasptr = (elsize >> 14) & 1;
    1699                 :          0 :         isunion = (elsize >> 13) & 1;
    1700                 :          0 :         elsize = elsize & 0x1fff;
    1701                 :            :     }
    1702                 :          0 :     uintptr_t pos = backref_list.len;
    1703                 :          0 :     arraylist_push(&backref_list, NULL);
    1704                 :          0 :     size_t *dims = (size_t*)alloca(ndims * sizeof(size_t));
    1705         [ #  # ]:          0 :     for (i = 0; i < ndims; i++) {
    1706                 :          0 :         dims[i] = jl_unbox_long(jl_deserialize_value(s, NULL));
    1707                 :            :     }
    1708                 :          0 :     jl_array_t *a = jl_new_array_for_deserialization(
    1709                 :            :             (jl_value_t*)NULL, ndims, dims, !isptr, hasptr, isunion, elsize);
    1710                 :          0 :     backref_list.items[pos] = a;
    1711                 :          0 :     jl_value_t *aty = jl_deserialize_value(s, &jl_astaggedvalue(a)->type);
    1712                 :          0 :     jl_set_typeof(a, aty);
    1713         [ #  # ]:          0 :     if (a->flags.ptrarray) {
    1714                 :          0 :         jl_value_t **data = (jl_value_t**)jl_array_data(a);
    1715                 :          0 :         size_t i, numel = jl_array_len(a);
    1716         [ #  # ]:          0 :         for (i = 0; i < numel; i++) {
    1717                 :          0 :             data[i] = jl_deserialize_value(s, &data[i]);
    1718                 :            :             //if (data[i]) // not needed because `a` is new (gc is disabled)
    1719                 :            :             //    jl_gc_wb(a, data[i]);
    1720                 :            :         }
    1721         [ #  # ]:          0 :         assert(jl_astaggedvalue(a)->bits.gc == GC_CLEAN); // gc is disabled
    1722                 :            :     }
    1723         [ #  # ]:          0 :     else if (a->flags.hasptr) {
    1724                 :          0 :         size_t i, numel = jl_array_len(a);
    1725                 :          0 :         char *data = (char*)jl_array_data(a);
    1726                 :          0 :         uint16_t elsz = a->elsize;
    1727                 :          0 :         jl_datatype_t *et = (jl_datatype_t*)jl_tparam0(jl_typeof(a));
    1728                 :          0 :         size_t j, np = et->layout->npointers;
    1729         [ #  # ]:          0 :         for (i = 0; i < numel; i++) {
    1730                 :          0 :             char *start = data;
    1731         [ #  # ]:          0 :             for (j = 0; j < np; j++) {
    1732                 :          0 :                 uint32_t ptr = jl_ptr_offset(et, j);
    1733                 :          0 :                 jl_value_t **fld = &((jl_value_t**)data)[ptr];
    1734         [ #  # ]:          0 :                 if ((char*)fld != start)
    1735                 :          0 :                     ios_readall(s->s, start, (const char*)fld - start);
    1736                 :          0 :                 *fld = jl_deserialize_value(s, fld);
    1737                 :            :                 //if (*fld) // not needed because `a` is new (gc is disabled)
    1738                 :            :                 //    jl_gc_wb(a, *fld);
    1739                 :          0 :                 start = (char*)&fld[1];
    1740                 :            :             }
    1741                 :          0 :             data += elsz;
    1742         [ #  # ]:          0 :             if (data != start)
    1743                 :          0 :                 ios_readall(s->s, start, data - start);
    1744                 :            :         }
    1745         [ #  # ]:          0 :         assert(jl_astaggedvalue(a)->bits.gc == GC_CLEAN); // gc is disabled
    1746                 :            :     }
    1747                 :            :     else {
    1748   [ #  #  #  # ]:          0 :         size_t extra = jl_array_isbitsunion(a) ? jl_array_len(a) : 0;
    1749                 :          0 :         size_t tot = jl_array_len(a) * a->elsize + extra;
    1750                 :          0 :         ios_readall(s->s, (char*)jl_array_data(a), tot);
    1751                 :            :     }
    1752                 :          0 :     return (jl_value_t*)a;
    1753                 :            : }
    1754                 :            : 
    1755                 :          0 : static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
    1756                 :            : {
    1757                 :            :     jl_method_t *m =
    1758                 :          0 :         (jl_method_t*)jl_gc_alloc(s->ptls, sizeof(jl_method_t),
    1759                 :            :                                   jl_method_type);
    1760                 :          0 :     memset(m, 0, sizeof(jl_method_t));
    1761                 :          0 :     uintptr_t pos = backref_list.len;
    1762                 :          0 :     arraylist_push(&backref_list, m);
    1763                 :          0 :     m->sig = (jl_value_t*)jl_deserialize_value(s, (jl_value_t**)&m->sig);
    1764                 :          0 :     jl_gc_wb(m, m->sig);
    1765                 :          0 :     m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module);
    1766                 :          0 :     jl_gc_wb(m, m->module);
    1767                 :          0 :     int serialization_mode = read_uint8(s->s);
    1768         [ #  # ]:          0 :     if (serialization_mode & METHOD_EXTERNAL_MT) {
    1769                 :          0 :         jl_module_t *mt_mod = (jl_module_t*)jl_deserialize_value(s, NULL);
    1770                 :          0 :         jl_sym_t *mt_name = (jl_sym_t*)jl_deserialize_value(s, NULL);
    1771                 :          0 :         m->external_mt = jl_get_global(mt_mod, mt_name);
    1772                 :          0 :         jl_gc_wb(m, m->external_mt);
    1773         [ #  # ]:          0 :         assert(jl_typeis(m->external_mt, jl_methtable_type));
    1774                 :            :     }
    1775                 :            :     else {
    1776                 :          0 :         m->external_mt = jl_deserialize_value(s, &m->external_mt);
    1777                 :          0 :         jl_gc_wb(m, m->external_mt);
    1778                 :            :     }
    1779         [ #  # ]:          0 :     if (!(serialization_mode & METHOD_INTERNAL)) {
    1780   [ #  #  #  # ]:          0 :         assert(loc != NULL && loc != HT_NOTFOUND);
    1781                 :          0 :         arraylist_push(&flagref_list, loc);
    1782                 :          0 :         arraylist_push(&flagref_list, (void*)pos);
    1783         [ #  # ]:          0 :         if (serialization_mode & METHOD_HAS_NEW_ROOTS) {
    1784                 :          0 :             uint64_t key = read_uint64(s->s);
    1785                 :          0 :             int i, nnew = read_int32(s->s);
    1786                 :          0 :             jl_array_t *newroots = jl_alloc_vec_any(nnew);
    1787                 :          0 :             jl_value_t **data = (jl_value_t**)jl_array_data(newroots);
    1788         [ #  # ]:          0 :             for (i = 0; i < nnew; i++)
    1789                 :          0 :                 data[i] = jl_deserialize_value(s, &(data[i]));
    1790                 :            :             // Storing the new roots in `m->roots` risks losing them due to recaching
    1791                 :            :             // (which replaces pointers to `m` with ones to the "live" method).
    1792                 :            :             // Put them in separate storage so we can find them later.
    1793         [ #  # ]:          0 :             assert(ptrhash_get(&queued_method_roots, m) == HT_NOTFOUND);
    1794                 :            :             // In storing the key, on 32-bit platforms we need two slots. Might as well do this for all platforms.
    1795                 :          0 :             jl_svec_t *qmrval = jl_alloc_svec_uninit(3);    // GC is disabled
    1796                 :          0 :             jl_svec_data(qmrval)[0] = (jl_value_t*)(uintptr_t)(key & ((((uint64_t)1) << 32) - 1));          // lo bits
    1797                 :          0 :             jl_svec_data(qmrval)[1] = (jl_value_t*)(uintptr_t)((key >> 32) & ((((uint64_t)1) << 32) - 1));  // hi bits
    1798                 :          0 :             jl_svec_data(qmrval)[2] = (jl_value_t*)newroots;
    1799                 :          0 :             ptrhash_put(&queued_method_roots, m, qmrval);
    1800                 :            :         }
    1801                 :          0 :         return (jl_value_t*)m;
    1802                 :            :     }
    1803                 :          0 :     m->specializations = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->specializations);
    1804                 :          0 :     jl_gc_wb(m, m->specializations);
    1805                 :          0 :     jl_array_t *speckeyset = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->speckeyset);
    1806                 :          0 :     jl_atomic_store_relaxed(&m->speckeyset, speckeyset);
    1807                 :          0 :     jl_gc_wb(m, speckeyset);
    1808                 :          0 :     m->name = (jl_sym_t*)jl_deserialize_value(s, NULL);
    1809                 :          0 :     jl_gc_wb(m, m->name);
    1810                 :          0 :     m->file = (jl_sym_t*)jl_deserialize_value(s, NULL);
    1811                 :          0 :     m->line = read_int32(s->s);
    1812                 :          0 :     m->primary_world = jl_atomic_load_acquire(&jl_world_counter);
    1813                 :          0 :     m->deleted_world = ~(size_t)0;
    1814                 :          0 :     m->called = read_int32(s->s);
    1815                 :          0 :     m->nargs = read_int32(s->s);
    1816                 :          0 :     m->nospecialize = read_int32(s->s);
    1817                 :          0 :     m->nkw = read_int32(s->s);
    1818                 :          0 :     m->isva = read_int8(s->s);
    1819                 :          0 :     m->pure = read_int8(s->s);
    1820                 :          0 :     m->is_for_opaque_closure = read_int8(s->s);
    1821                 :          0 :     m->constprop = read_int8(s->s);
    1822                 :          0 :     m->purity.bits = read_uint8(s->s);
    1823                 :          0 :     m->slot_syms = jl_deserialize_value(s, (jl_value_t**)&m->slot_syms);
    1824                 :          0 :     jl_gc_wb(m, m->slot_syms);
    1825                 :          0 :     m->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->roots);
    1826         [ #  # ]:          0 :     if (m->roots)
    1827                 :          0 :         jl_gc_wb(m, m->roots);
    1828                 :          0 :     m->root_blocks = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->root_blocks);
    1829         [ #  # ]:          0 :     if (m->root_blocks)
    1830                 :          0 :         jl_gc_wb(m, m->root_blocks);
    1831                 :          0 :     m->nroots_sysimg = read_int32(s->s);
    1832                 :          0 :     m->ccallable = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->ccallable);
    1833         [ #  # ]:          0 :     if (m->ccallable) {
    1834                 :          0 :         jl_gc_wb(m, m->ccallable);
    1835                 :          0 :         arraylist_push(&ccallable_list, m->ccallable);
    1836                 :            :     }
    1837                 :          0 :     m->source = jl_deserialize_value(s, &m->source);
    1838         [ #  # ]:          0 :     if (m->source)
    1839                 :          0 :         jl_gc_wb(m, m->source);
    1840                 :          0 :     m->unspecialized = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&m->unspecialized);
    1841         [ #  # ]:          0 :     if (m->unspecialized)
    1842                 :          0 :         jl_gc_wb(m, m->unspecialized);
    1843                 :          0 :     m->generator = jl_deserialize_value(s, (jl_value_t**)&m->generator);
    1844         [ #  # ]:          0 :     if (m->generator)
    1845                 :          0 :         jl_gc_wb(m, m->generator);
    1846                 :          0 :     m->invokes = jl_deserialize_value(s, (jl_value_t**)&m->invokes);
    1847                 :          0 :     jl_gc_wb(m, m->invokes);
    1848                 :          0 :     m->recursion_relation = jl_deserialize_value(s, (jl_value_t**)&m->recursion_relation);
    1849         [ #  # ]:          0 :     if (m->recursion_relation)
    1850                 :          0 :         jl_gc_wb(m, m->recursion_relation);
    1851                 :          0 :     JL_MUTEX_INIT(&m->writelock);
    1852                 :          0 :     return (jl_value_t*)m;
    1853                 :            : }
    1854                 :            : 
    1855                 :          0 : static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
    1856                 :            : {
    1857                 :            :     jl_method_instance_t *mi =
    1858                 :          0 :         (jl_method_instance_t*)jl_gc_alloc(s->ptls, sizeof(jl_method_instance_t),
    1859                 :            :                                        jl_method_instance_type);
    1860                 :          0 :     memset(mi, 0, sizeof(jl_method_instance_t));
    1861                 :          0 :     uintptr_t pos = backref_list.len;
    1862                 :          0 :     arraylist_push(&backref_list, mi);
    1863                 :          0 :     int internal = read_uint8(s->s);
    1864         [ #  # ]:          0 :     if (internal == 1) {
    1865                 :          0 :         mi->uninferred = jl_deserialize_value(s, &mi->uninferred);
    1866                 :          0 :         jl_gc_wb(mi, mi->uninferred);
    1867                 :            :     }
    1868                 :          0 :     mi->specTypes = (jl_value_t*)jl_deserialize_value(s, (jl_value_t**)&mi->specTypes);
    1869                 :          0 :     jl_gc_wb(mi, mi->specTypes);
    1870                 :          0 :     mi->def.value = jl_deserialize_value(s, &mi->def.value);
    1871                 :          0 :     jl_gc_wb(mi, mi->def.value);
    1872                 :            : 
    1873         [ #  # ]:          0 :     if (!internal) {
    1874   [ #  #  #  # ]:          0 :         assert(loc != NULL && loc != HT_NOTFOUND);
    1875                 :          0 :         arraylist_push(&flagref_list, loc);
    1876                 :          0 :         arraylist_push(&flagref_list, (void*)pos);
    1877                 :          0 :         return (jl_value_t*)mi;
    1878                 :            :     }
    1879                 :            : 
    1880                 :          0 :     mi->sparam_vals = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&mi->sparam_vals);
    1881                 :          0 :     jl_gc_wb(mi, mi->sparam_vals);
    1882                 :          0 :     mi->backedges = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&mi->backedges);
    1883         [ #  # ]:          0 :     if (mi->backedges)
    1884                 :          0 :         jl_gc_wb(mi, mi->backedges);
    1885                 :          0 :     mi->callbacks = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&mi->callbacks);
    1886         [ #  # ]:          0 :     if (mi->callbacks)
    1887                 :          0 :         jl_gc_wb(mi, mi->callbacks);
    1888                 :          0 :     mi->cache = (jl_code_instance_t*)jl_deserialize_value(s, (jl_value_t**)&mi->cache);
    1889         [ #  # ]:          0 :     if (mi->cache)
    1890                 :          0 :         jl_gc_wb(mi, mi->cache);
    1891                 :          0 :     return (jl_value_t*)mi;
    1892                 :            : }
    1893                 :            : 
    1894                 :          0 : static jl_value_t *jl_deserialize_value_code_instance(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
    1895                 :            : {
    1896                 :            :     jl_code_instance_t *codeinst =
    1897                 :          0 :         (jl_code_instance_t*)jl_gc_alloc(s->ptls, sizeof(jl_code_instance_t), jl_code_instance_type);
    1898                 :          0 :     memset(codeinst, 0, sizeof(jl_code_instance_t));
    1899                 :          0 :     arraylist_push(&backref_list, codeinst);
    1900                 :          0 :     int flags = read_uint8(s->s);
    1901                 :          0 :     int validate = (flags >> 0) & 3;
    1902                 :          0 :     int constret = (flags >> 2) & 1;
    1903                 :          0 :     codeinst->ipo_purity_bits = read_uint32(s->s);
    1904                 :          0 :     codeinst->purity_bits = read_uint32(s->s);
    1905                 :          0 :     codeinst->def = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&codeinst->def);
    1906                 :          0 :     jl_gc_wb(codeinst, codeinst->def);
    1907                 :          0 :     codeinst->inferred = jl_deserialize_value(s, &codeinst->inferred);
    1908                 :          0 :     jl_gc_wb(codeinst, codeinst->inferred);
    1909                 :          0 :     codeinst->rettype_const = jl_deserialize_value(s, &codeinst->rettype_const);
    1910         [ #  # ]:          0 :     if (codeinst->rettype_const)
    1911                 :          0 :         jl_gc_wb(codeinst, codeinst->rettype_const);
    1912                 :          0 :     codeinst->rettype = jl_deserialize_value(s, &codeinst->rettype);
    1913                 :          0 :     jl_gc_wb(codeinst, codeinst->rettype);
    1914                 :          0 :     codeinst->argescapes = jl_deserialize_value(s, &codeinst->argescapes);
    1915                 :          0 :     jl_gc_wb(codeinst, codeinst->argescapes);
    1916         [ #  # ]:          0 :     if (constret)
    1917                 :          0 :         codeinst->invoke = jl_fptr_const_return;
    1918         [ #  # ]:          0 :     if ((flags >> 3) & 1)
    1919                 :          0 :         codeinst->precompile = 1;
    1920                 :          0 :     codeinst->relocatability = read_uint8(s->s);
    1921         [ #  # ]:          0 :     assert(codeinst->relocatability <= 1);
    1922                 :          0 :     codeinst->next = (jl_code_instance_t*)jl_deserialize_value(s, (jl_value_t**)&codeinst->next);
    1923                 :          0 :     jl_gc_wb(codeinst, codeinst->next);
    1924         [ #  # ]:          0 :     if (validate) {
    1925                 :          0 :         codeinst->min_world = jl_atomic_load_acquire(&jl_world_counter);
    1926                 :          0 :         ptrhash_put(&new_code_instance_validate, codeinst, (void*)(~(uintptr_t)HT_NOTFOUND));   // "HT_FOUND"
    1927                 :            :     }
    1928                 :          0 :     return (jl_value_t*)codeinst;
    1929                 :            : }
    1930                 :            : 
    1931                 :          0 : static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) JL_GC_DISABLED
    1932                 :            : {
    1933                 :          0 :     uintptr_t pos = backref_list.len;
    1934                 :          0 :     arraylist_push(&backref_list, NULL);
    1935                 :          0 :     jl_sym_t *mname = (jl_sym_t*)jl_deserialize_value(s, NULL);
    1936                 :          0 :     int ref_only = read_uint8(s->s);
    1937         [ #  # ]:          0 :     if (ref_only) {
    1938                 :            :         jl_value_t *m_ref;
    1939         [ #  # ]:          0 :         if (ref_only == 1)
    1940                 :          0 :             m_ref = jl_get_global((jl_module_t*)jl_deserialize_value(s, NULL), mname);
    1941                 :            :         else
    1942                 :          0 :             m_ref = jl_array_ptr_ref(s->loaded_modules_array, read_int32(s->s));
    1943                 :          0 :         backref_list.items[pos] = m_ref;
    1944                 :          0 :         return m_ref;
    1945                 :            :     }
    1946                 :          0 :     jl_module_t *m = jl_new_module(mname);
    1947                 :          0 :     backref_list.items[pos] = m;
    1948                 :          0 :     m->parent = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->parent);
    1949                 :          0 :     jl_gc_wb(m, m->parent);
    1950                 :            : 
    1951                 :          0 :     while (1) {
    1952                 :          0 :         jl_sym_t *asname = (jl_sym_t*)jl_deserialize_value(s, NULL);
    1953         [ #  # ]:          0 :         if (asname == NULL)
    1954                 :          0 :             break;
    1955                 :          0 :         jl_binding_t *b = jl_get_binding_wr(m, asname, 1);
    1956                 :          0 :         b->name = (jl_sym_t*)jl_deserialize_value(s, (jl_value_t**)&b->name);
    1957                 :          0 :         jl_value_t *bvalue = jl_deserialize_value(s, (jl_value_t**)&b->value);
    1958                 :          0 :         *(jl_value_t**)&b->value = bvalue;
    1959         [ #  # ]:          0 :         if (bvalue != NULL) jl_gc_wb(m, bvalue);
    1960                 :          0 :         jl_value_t *bglobalref = jl_deserialize_value(s, (jl_value_t**)&b->globalref);
    1961                 :          0 :         *(jl_value_t**)&b->globalref = bglobalref;
    1962         [ #  # ]:          0 :         if (bglobalref != NULL) jl_gc_wb(m, bglobalref);
    1963                 :          0 :         b->owner = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&b->owner);
    1964         [ #  # ]:          0 :         if (b->owner != NULL) jl_gc_wb(m, b->owner);
    1965                 :          0 :         jl_value_t *bty = jl_deserialize_value(s, (jl_value_t**)&b->ty);
    1966                 :          0 :         *(jl_value_t**)&b->ty = bty;
    1967                 :          0 :         int8_t flags = read_int8(s->s);
    1968                 :          0 :         b->deprecated = (flags>>3) & 1;
    1969                 :          0 :         b->constp = (flags>>2) & 1;
    1970                 :          0 :         b->exportp = (flags>>1) & 1;
    1971                 :          0 :         b->imported = (flags) & 1;
    1972                 :            :     }
    1973                 :          0 :     size_t i = m->usings.len;
    1974                 :          0 :     size_t ni = read_int32(s->s);
    1975                 :          0 :     arraylist_grow(&m->usings, ni);
    1976                 :          0 :     ni += i;
    1977         [ #  # ]:          0 :     while (i < ni) {
    1978                 :          0 :         m->usings.items[i] = jl_deserialize_value(s, (jl_value_t**)&m->usings.items[i]);
    1979                 :          0 :         i++;
    1980                 :            :     }
    1981                 :          0 :     m->istopmod = read_uint8(s->s);
    1982                 :          0 :     m->uuid.hi = read_uint64(s->s);
    1983                 :          0 :     m->uuid.lo = read_uint64(s->s);
    1984                 :          0 :     m->build_id = read_uint64(s->s);
    1985                 :          0 :     m->counter = read_int32(s->s);
    1986                 :          0 :     m->nospecialize = read_int32(s->s);
    1987                 :          0 :     m->optlevel = read_int8(s->s);
    1988                 :          0 :     m->compile = read_int8(s->s);
    1989                 :          0 :     m->infer = read_int8(s->s);
    1990                 :          0 :     m->max_methods = read_int8(s->s);
    1991                 :          0 :     m->primary_world = jl_atomic_load_acquire(&jl_world_counter);
    1992                 :          0 :     return (jl_value_t*)m;
    1993                 :            : }
    1994                 :            : 
    1995                 :          0 : static jl_value_t *jl_deserialize_value_singleton(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
    1996                 :            : {
    1997                 :          0 :     jl_value_t *v = (jl_value_t*)jl_gc_alloc(s->ptls, 0, NULL);
    1998                 :          0 :     uintptr_t pos = backref_list.len;
    1999                 :          0 :     arraylist_push(&backref_list, (void*)v);
    2000                 :            :     // TODO: optimize the case where the value can easily be obtained
    2001                 :            :     // from an external module (tag == 6) as dt->instance
    2002         [ #  # ]:          0 :     assert(loc != HT_NOTFOUND);
    2003                 :            :     // if loc == NULL, then the caller can't provide the address where the instance will be
    2004                 :            :     // stored. this happens if a field might store a 0-size value, but the field itself is
    2005                 :            :     // not 0 size, e.g. `::Union{Int,Nothing}`
    2006         [ #  # ]:          0 :     if (loc != NULL) {
    2007                 :          0 :         arraylist_push(&flagref_list, loc);
    2008                 :          0 :         arraylist_push(&flagref_list, (void*)pos);
    2009                 :            :     }
    2010                 :          0 :     jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s, (jl_value_t**)HT_NOTFOUND); // no loc, since if dt is replaced, then dt->instance would be also
    2011                 :          0 :     jl_set_typeof(v, dt);
    2012         [ #  # ]:          0 :     if (dt->instance == NULL)
    2013                 :          0 :         return v;
    2014                 :          0 :     return dt->instance;
    2015                 :            : }
    2016                 :            : 
    2017                 :          0 : static void jl_deserialize_struct(jl_serializer_state *s, jl_value_t *v) JL_GC_DISABLED
    2018                 :            : {
    2019                 :          0 :     jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(v);
    2020                 :          0 :     char *data = (char*)jl_data_ptr(v);
    2021                 :          0 :     size_t i, np = dt->layout->npointers;
    2022                 :          0 :     char *start = data;
    2023         [ #  # ]:          0 :     for (i = 0; i < np; i++) {
    2024                 :          0 :         uint32_t ptr = jl_ptr_offset(dt, i);
    2025                 :          0 :         jl_value_t **fld = &((jl_value_t**)data)[ptr];
    2026         [ #  # ]:          0 :         if ((char*)fld != start)
    2027                 :          0 :             ios_readall(s->s, start, (const char*)fld - start);
    2028                 :          0 :         *fld = jl_deserialize_value(s, fld);
    2029                 :            :         //if (*fld)// a is new (gc is disabled)
    2030                 :            :         //    jl_gc_wb(a, *fld);
    2031                 :          0 :         start = (char*)&fld[1];
    2032                 :            :     }
    2033                 :          0 :     data += jl_datatype_size(dt);
    2034         [ #  # ]:          0 :     if (data != start)
    2035                 :          0 :         ios_readall(s->s, start, data - start);
    2036         [ #  # ]:          0 :     if (dt == jl_typemap_entry_type) {
    2037                 :          0 :         jl_typemap_entry_t *entry = (jl_typemap_entry_t*)v;
    2038         [ #  # ]:          0 :         if (entry->max_world == ~(size_t)0) {
    2039         [ #  # ]:          0 :             if (entry->min_world > 1) {
    2040                 :            :                 // update world validity to reflect current state of the counter
    2041                 :          0 :                 entry->min_world = jl_atomic_load_acquire(&jl_world_counter);
    2042                 :            :             }
    2043                 :            :         }
    2044                 :            :         else {
    2045                 :            :             // garbage entry - delete it :(
    2046                 :          0 :             entry->min_world = 1;
    2047                 :          0 :             entry->max_world = 0;
    2048                 :            :         }
    2049                 :            :     }
    2050                 :          0 : }
    2051                 :            : 
    2052                 :          0 : static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, jl_value_t **loc) JL_GC_DISABLED
    2053                 :            : {
    2054         [ #  # ]:          0 :     int32_t sz = (tag == TAG_SHORT_GENERAL ? read_uint8(s->s) : read_int32(s->s));
    2055                 :          0 :     jl_value_t *v = jl_gc_alloc(s->ptls, sz, NULL);
    2056                 :          0 :     jl_set_typeof(v, (void*)(intptr_t)0x50);
    2057                 :          0 :     uintptr_t pos = backref_list.len;
    2058                 :          0 :     arraylist_push(&backref_list, v);
    2059                 :          0 :     jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s, &jl_astaggedvalue(v)->type);
    2060   [ #  #  #  # ]:          0 :     assert(sz != 0 || loc);
    2061         [ #  # ]:          0 :     if (dt == jl_typename_type) {
    2062                 :          0 :         int internal = read_uint8(s->s);
    2063                 :            :         jl_typename_t *tn;
    2064         [ #  # ]:          0 :         if (internal) {
    2065                 :          0 :             tn = (jl_typename_t*)jl_gc_alloc(
    2066                 :            :                     s->ptls, sizeof(jl_typename_t), jl_typename_type);
    2067                 :          0 :             memset(tn, 0, sizeof(jl_typename_t));
    2068                 :          0 :             tn->cache = jl_emptysvec; // the cache is refilled later (tag 5)
    2069                 :          0 :             tn->linearcache = jl_emptysvec; // the cache is refilled later (tag 5)
    2070                 :          0 :             backref_list.items[pos] = tn;
    2071                 :            :         }
    2072                 :          0 :         jl_module_t *m = (jl_module_t*)jl_deserialize_value(s, NULL);
    2073                 :          0 :         jl_sym_t *sym = (jl_sym_t*)jl_deserialize_value(s, NULL);
    2074         [ #  # ]:          0 :         if (internal) {
    2075                 :          0 :             tn->module = m;
    2076                 :          0 :             tn->name = sym;
    2077                 :          0 :             tn->names = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&tn->names);
    2078                 :          0 :             jl_gc_wb(tn, tn->names);
    2079                 :          0 :             tn->wrapper = jl_deserialize_value(s, &tn->wrapper);
    2080                 :          0 :             jl_gc_wb(tn, tn->wrapper);
    2081                 :          0 :             tn->Typeofwrapper = NULL;
    2082                 :          0 :             tn->mt = (jl_methtable_t*)jl_deserialize_value(s, (jl_value_t**)&tn->mt);
    2083                 :          0 :             jl_gc_wb(tn, tn->mt);
    2084                 :          0 :             ios_read(s->s, (char*)&tn->hash, sizeof(tn->hash));
    2085                 :          0 :             int8_t flags = read_int8(s->s);
    2086                 :          0 :             tn->abstract = flags & 1;
    2087                 :          0 :             tn->mutabl = (flags>>1) & 1;
    2088                 :          0 :             tn->mayinlinealloc = (flags>>2) & 1;
    2089                 :          0 :             tn->max_methods = read_uint8(s->s);
    2090         [ #  # ]:          0 :             if (tn->abstract)
    2091                 :          0 :                 tn->n_uninitialized = 0;
    2092                 :            :             else
    2093                 :          0 :                 tn->n_uninitialized = read_uint16(s->s);
    2094                 :          0 :             size_t nfields = read_int32(s->s);
    2095         [ #  # ]:          0 :             if (nfields) {
    2096                 :          0 :                 tn->atomicfields = (uint32_t*)malloc(nfields);
    2097                 :          0 :                 ios_read(s->s, (char*)tn->atomicfields, nfields);
    2098                 :            :             }
    2099                 :          0 :             nfields = read_int32(s->s);
    2100         [ #  # ]:          0 :             if (nfields) {
    2101                 :          0 :                 tn->constfields = (uint32_t*)malloc(nfields);
    2102                 :          0 :                 ios_read(s->s, (char*)tn->constfields, nfields);
    2103                 :            :             }
    2104                 :            :         }
    2105                 :            :         else {
    2106                 :          0 :             jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(jl_get_global(m, sym));
    2107         [ #  # ]:          0 :             assert(jl_is_datatype(dt));
    2108                 :          0 :             tn = dt->name;
    2109                 :          0 :             backref_list.items[pos] = tn;
    2110                 :            :         }
    2111                 :          0 :         return (jl_value_t*)tn;
    2112                 :            :     }
    2113                 :          0 :     jl_set_typeof(v, dt);
    2114         [ #  # ]:          0 :     if ((jl_value_t*)dt == jl_bigint_type) {
    2115                 :          0 :         jl_value_t *sizefield = jl_deserialize_value(s, NULL);
    2116                 :          0 :         int32_t sz = jl_unbox_int32(sizefield);
    2117         [ #  # ]:          0 :         int32_t nw = (sz == 0 ? 1 : (sz < 0 ? -sz : sz));
    2118                 :          0 :         size_t nb = nw * gmp_limb_size;
    2119                 :          0 :         void *buf = jl_gc_counted_malloc(nb);
    2120         [ #  # ]:          0 :         if (buf == NULL)
    2121                 :          0 :             jl_throw(jl_memory_exception);
    2122                 :          0 :         ios_readall(s->s, (char*)buf, nb);
    2123                 :          0 :         jl_set_nth_field(v, 0, jl_box_int32(nw));
    2124                 :          0 :         jl_set_nth_field(v, 1, sizefield);
    2125                 :          0 :         jl_set_nth_field(v, 2, jl_box_voidpointer(buf));
    2126                 :            :     }
    2127                 :            :     else {
    2128                 :          0 :         jl_deserialize_struct(s, v);
    2129                 :            :     }
    2130                 :          0 :     return v;
    2131                 :            : }
    2132                 :            : 
    2133                 :          0 : static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
    2134                 :            : {
    2135         [ #  # ]:          0 :     assert(!ios_eof(s->s));
    2136                 :            :     jl_value_t *v;
    2137                 :            :     size_t n;
    2138                 :            :     uintptr_t pos;
    2139                 :          0 :     uint8_t tag = read_uint8(s->s);
    2140         [ #  # ]:          0 :     if (tag > LAST_TAG)
    2141                 :          0 :         return deser_tag[tag];
    2142   [ #  #  #  #  :          0 :     switch (tag) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    2143                 :          0 :     case TAG_NULL: return NULL;
    2144                 :          0 :     case 0:
    2145                 :          0 :         tag = read_uint8(s->s);
    2146                 :          0 :         return deser_tag[tag];
    2147                 :          0 :     case TAG_BACKREF: JL_FALLTHROUGH; case TAG_SHORT_BACKREF: ;
    2148         [ #  # ]:          0 :         uintptr_t offs = (tag == TAG_BACKREF) ? read_int32(s->s) : read_uint16(s->s);
    2149                 :          0 :         int isflagref = 0;
    2150                 :          0 :         isflagref = !!(offs & 1);
    2151                 :          0 :         offs >>= 1;
    2152                 :            :         // assert(offs >= 0); // offs is unsigned so this is always true
    2153         [ #  # ]:          0 :         assert(offs < backref_list.len);
    2154                 :          0 :         jl_value_t *bp = (jl_value_t*)backref_list.items[offs];
    2155         [ #  # ]:          0 :         assert(bp);
    2156   [ #  #  #  # ]:          0 :         if (isflagref && loc != HT_NOTFOUND) {
    2157         [ #  # ]:          0 :             if (loc != NULL) {
    2158                 :            :                 // as in jl_deserialize_value_singleton, the caller won't have a place to
    2159                 :            :                 // store this reference given a field type like Union{Int,Nothing}
    2160                 :          0 :                 arraylist_push(&flagref_list, loc);
    2161                 :          0 :                 arraylist_push(&flagref_list, (void*)(uintptr_t)-1);
    2162                 :            :             }
    2163                 :            :         }
    2164                 :          0 :         return (jl_value_t*)bp;
    2165                 :          0 :     case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC:
    2166                 :          0 :         return jl_deserialize_value_svec(s, tag, loc);
    2167                 :          0 :     case TAG_COMMONSYM:
    2168                 :          0 :         return deser_symbols[read_uint8(s->s)];
    2169                 :          0 :     case TAG_SYMBOL: JL_FALLTHROUGH; case TAG_LONG_SYMBOL:
    2170                 :          0 :         return jl_deserialize_value_symbol(s, tag);
    2171                 :          0 :     case TAG_ARRAY: JL_FALLTHROUGH; case TAG_ARRAY1D:
    2172                 :          0 :         return jl_deserialize_value_array(s, tag);
    2173                 :          0 :     case TAG_UNIONALL:
    2174                 :          0 :         pos = backref_list.len;
    2175                 :          0 :         arraylist_push(&backref_list, NULL);
    2176         [ #  # ]:          0 :         if (read_uint8(s->s)) {
    2177                 :          0 :             jl_module_t *m = (jl_module_t*)jl_deserialize_value(s, NULL);
    2178                 :          0 :             jl_sym_t *sym = (jl_sym_t*)jl_deserialize_value(s, NULL);
    2179                 :          0 :             jl_value_t *v = jl_get_global(m, sym);
    2180         [ #  # ]:          0 :             assert(jl_is_unionall(v));
    2181                 :          0 :             backref_list.items[pos] = v;
    2182                 :          0 :             return v;
    2183                 :            :         }
    2184                 :          0 :         v = jl_gc_alloc(s->ptls, sizeof(jl_unionall_t), jl_unionall_type);
    2185                 :          0 :         backref_list.items[pos] = v;
    2186                 :          0 :         ((jl_unionall_t*)v)->var = (jl_tvar_t*)jl_deserialize_value(s, (jl_value_t**)&((jl_unionall_t*)v)->var);
    2187                 :          0 :         jl_gc_wb(v, ((jl_unionall_t*)v)->var);
    2188                 :          0 :         ((jl_unionall_t*)v)->body = jl_deserialize_value(s, &((jl_unionall_t*)v)->body);
    2189                 :          0 :         jl_gc_wb(v, ((jl_unionall_t*)v)->body);
    2190                 :          0 :         return v;
    2191                 :          0 :     case TAG_TVAR:
    2192                 :          0 :         v = jl_gc_alloc(s->ptls, sizeof(jl_tvar_t), jl_tvar_type);
    2193                 :          0 :         jl_tvar_t *tv = (jl_tvar_t*)v;
    2194                 :          0 :         arraylist_push(&backref_list, tv);
    2195                 :          0 :         tv->name = (jl_sym_t*)jl_deserialize_value(s, NULL);
    2196                 :          0 :         jl_gc_wb(tv, tv->name);
    2197                 :          0 :         tv->lb = jl_deserialize_value(s, &tv->lb);
    2198                 :          0 :         jl_gc_wb(tv, tv->lb);
    2199                 :          0 :         tv->ub = jl_deserialize_value(s, &tv->ub);
    2200                 :          0 :         jl_gc_wb(tv, tv->ub);
    2201                 :          0 :         return (jl_value_t*)tv;
    2202                 :          0 :     case TAG_METHOD:
    2203                 :          0 :         return jl_deserialize_value_method(s, loc);
    2204                 :          0 :     case TAG_METHOD_INSTANCE:
    2205                 :          0 :         return jl_deserialize_value_method_instance(s, loc);
    2206                 :          0 :     case TAG_CODE_INSTANCE:
    2207                 :          0 :         return jl_deserialize_value_code_instance(s, loc);
    2208                 :          0 :     case TAG_MODULE:
    2209                 :          0 :         return jl_deserialize_value_module(s);
    2210                 :          0 :     case TAG_SHORTER_INT64:
    2211                 :          0 :         v = jl_box_int64((int16_t)read_uint16(s->s));
    2212                 :          0 :         arraylist_push(&backref_list, v);
    2213                 :          0 :         return v;
    2214                 :          0 :     case TAG_SHORT_INT64:
    2215                 :          0 :         v = jl_box_int64(read_int32(s->s));
    2216                 :          0 :         arraylist_push(&backref_list, v);
    2217                 :          0 :         return v;
    2218                 :          0 :     case TAG_INT64:
    2219                 :          0 :         v = jl_box_int64((int64_t)read_uint64(s->s));
    2220                 :          0 :         arraylist_push(&backref_list, v);
    2221                 :          0 :         return v;
    2222                 :          0 :     case TAG_SHORT_INT32:
    2223                 :          0 :         v = jl_box_int32((int16_t)read_uint16(s->s));
    2224                 :          0 :         arraylist_push(&backref_list, v);
    2225                 :          0 :         return v;
    2226                 :          0 :     case TAG_INT32:
    2227                 :          0 :         v = jl_box_int32(read_int32(s->s));
    2228                 :          0 :         arraylist_push(&backref_list, v);
    2229                 :          0 :         return v;
    2230                 :          0 :     case TAG_UINT8:
    2231                 :          0 :         return jl_box_uint8(read_uint8(s->s));
    2232                 :          0 :     case TAG_SINGLETON:
    2233                 :          0 :         return jl_deserialize_value_singleton(s, loc);
    2234                 :          0 :     case TAG_CORE:
    2235                 :          0 :         return (jl_value_t*)jl_core_module;
    2236                 :          0 :     case TAG_BASE:
    2237                 :          0 :         return (jl_value_t*)jl_base_module;
    2238                 :          0 :     case TAG_CNULL:
    2239                 :          0 :         v = jl_gc_alloc(s->ptls, sizeof(void*), NULL);
    2240                 :          0 :         jl_set_typeof(v, (void*)(intptr_t)0x50);
    2241                 :          0 :         *(void**)v = NULL;
    2242                 :          0 :         uintptr_t pos = backref_list.len;
    2243                 :          0 :         arraylist_push(&backref_list, v);
    2244                 :          0 :         jl_set_typeof(v, jl_deserialize_value(s, &jl_astaggedvalue(v)->type));
    2245                 :          0 :         return v;
    2246                 :          0 :     case TAG_BITYPENAME:
    2247                 :          0 :         v = deser_tag[read_uint8(s->s)];
    2248                 :          0 :         return (jl_value_t*)((jl_datatype_t*)jl_unwrap_unionall(v))->name;
    2249                 :          0 :     case TAG_STRING:
    2250                 :          0 :         n = read_int32(s->s);
    2251                 :          0 :         v = jl_alloc_string(n);
    2252                 :          0 :         arraylist_push(&backref_list, v);
    2253                 :          0 :         ios_readall(s->s, jl_string_data(v), n);
    2254                 :          0 :         return v;
    2255                 :          0 :     case TAG_DATATYPE:
    2256                 :          0 :         pos = backref_list.len;
    2257                 :          0 :         arraylist_push(&backref_list, NULL);
    2258                 :          0 :         return jl_deserialize_datatype(s, pos, loc);
    2259                 :          0 :     default:
    2260   [ #  #  #  # ]:          0 :         assert(tag == TAG_GENERAL || tag == TAG_SHORT_GENERAL);
    2261                 :          0 :         return jl_deserialize_value_any(s, tag, loc);
    2262                 :            :     }
    2263                 :            : }
    2264                 :            : 
    2265                 :            : // Add methods to external (non-worklist-owned) functions
    2266                 :          0 : static void jl_insert_methods(jl_array_t *list)
    2267                 :            : {
    2268                 :          0 :     size_t i, l = jl_array_len(list);
    2269         [ #  # ]:          0 :     for (i = 0; i < l; i += 2) {
    2270                 :          0 :         jl_method_t *meth = (jl_method_t*)jl_array_ptr_ref(list, i);
    2271         [ #  # ]:          0 :         assert(jl_is_method(meth));
    2272         [ #  # ]:          0 :         assert(!meth->is_for_opaque_closure);
    2273                 :          0 :         jl_tupletype_t *simpletype = (jl_tupletype_t*)jl_array_ptr_ref(list, i + 1);
    2274                 :          0 :         jl_methtable_t *mt = jl_method_get_table(meth);
    2275         [ #  # ]:          0 :         assert((jl_value_t*)mt != jl_nothing);
    2276                 :          0 :         jl_method_table_insert(mt, meth, simpletype);
    2277                 :            :     }
    2278                 :          0 : }
    2279                 :            : 
    2280                 :          0 : void remove_code_instance_from_validation(jl_code_instance_t *codeinst)
    2281                 :            : {
    2282                 :          0 :     ptrhash_remove(&new_code_instance_validate, codeinst);
    2283                 :          0 : }
    2284                 :            : 
    2285                 :          0 : static void jl_insert_method_instances(jl_array_t *list)
    2286                 :            : {
    2287                 :          0 :     size_t i, l = jl_array_len(list);
    2288                 :            :     // Validate the MethodInstances
    2289                 :          0 :     jl_array_t *valids = jl_alloc_array_1d(jl_array_uint8_type, l);
    2290                 :          0 :     memset(jl_array_data(valids), 1, l);
    2291                 :          0 :     size_t world = jl_atomic_load_acquire(&jl_world_counter);
    2292         [ #  # ]:          0 :     for (i = 0; i < l; i++) {
    2293                 :          0 :         jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
    2294         [ #  # ]:          0 :         assert(jl_is_method_instance(mi));
    2295         [ #  # ]:          0 :         if (jl_is_method(mi->def.method)) {
    2296                 :            :             // Is this still the method we'd be calling?
    2297                 :          0 :             jl_methtable_t *mt = jl_method_table_for(mi->specTypes);
    2298                 :          0 :             struct jl_typemap_assoc search = {(jl_value_t*)mi->specTypes, world, NULL, 0, ~(size_t)0};
    2299                 :          0 :             jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, &search, /*offs*/0, /*subtype*/1);
    2300         [ #  # ]:          0 :             if (entry) {
    2301                 :          0 :                 jl_value_t *mworld = entry->func.value;
    2302   [ #  #  #  #  :          0 :                 if (jl_is_method(mworld) && mi->def.method != (jl_method_t*)mworld && jl_type_morespecific(((jl_method_t*)mworld)->sig, mi->def.method->sig)) {
                   #  # ]
    2303                 :          0 :                     jl_array_uint8_set(valids, i, 0);
    2304                 :          0 :                     invalidate_backedges(&remove_code_instance_from_validation, mi, world, "jl_insert_method_instance");
    2305                 :            :                     // The codeinst of this mi haven't yet been removed
    2306                 :          0 :                     jl_code_instance_t *codeinst = mi->cache;
    2307         [ #  # ]:          0 :                     while (codeinst) {
    2308                 :          0 :                         remove_code_instance_from_validation(codeinst);
    2309                 :          0 :                         codeinst = codeinst->next;
    2310                 :            :                     }
    2311         [ #  # ]:          0 :                     if (_jl_debug_method_invalidation) {
    2312                 :          0 :                         jl_array_ptr_1d_push(_jl_debug_method_invalidation, mworld);
    2313                 :          0 :                         jl_array_ptr_1d_push(_jl_debug_method_invalidation, jl_cstr_to_string("jl_method_table_insert")); // GC disabled
    2314                 :            :                     }
    2315                 :            :                 }
    2316                 :            :             }
    2317                 :            :         }
    2318                 :            :     }
    2319                 :            :     // While it's tempting to just remove the invalidated MIs altogether,
    2320                 :            :     // this hurts the ability of SnoopCompile to diagnose problems.
    2321         [ #  # ]:          0 :     for (i = 0; i < l; i++) {
    2322                 :          0 :         jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
    2323                 :          0 :         jl_method_instance_t *milive = jl_specializations_get_or_insert(mi);
    2324                 :          0 :         ptrhash_put(&uniquing_table, mi, milive);  // store the association for the 2nd pass
    2325                 :            :     }
    2326                 :            :     // We may need to fix up the backedges for the ones that didn't "go live"
    2327         [ #  # ]:          0 :     for (i = 0; i < l; i++) {
    2328                 :          0 :         jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
    2329                 :          0 :         jl_method_instance_t *milive = (jl_method_instance_t*)ptrhash_get(&uniquing_table, mi);
    2330         [ #  # ]:          0 :         if (milive != mi) {
    2331                 :            :             // A previously-loaded module compiled this method, so the one we deserialized will be dropped.
    2332                 :            :             // But make sure the backedges are copied over.
    2333         [ #  # ]:          0 :             if (mi->backedges) {
    2334         [ #  # ]:          0 :                 if (!milive->backedges) {
    2335                 :            :                     // Copy all the backedges (after looking up the live ones)
    2336                 :          0 :                     size_t j, n = jl_array_len(mi->backedges);
    2337                 :          0 :                     milive->backedges = jl_alloc_vec_any(n);
    2338                 :          0 :                     jl_gc_wb(milive, milive->backedges);
    2339         [ #  # ]:          0 :                     for (j = 0; j < n; j++) {
    2340                 :          0 :                         jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, j);
    2341                 :          0 :                         jl_method_instance_t *belive = (jl_method_instance_t*)ptrhash_get(&uniquing_table, be);
    2342         [ #  # ]:          0 :                         if (belive == HT_NOTFOUND)
    2343                 :          0 :                             belive = be;
    2344                 :          0 :                         jl_array_ptr_set(milive->backedges, j, belive);
    2345                 :            :                     }
    2346                 :            :                 } else {
    2347                 :            :                     // Copy the missing backedges (this is an O(N^2) algorithm, but many methods have few MethodInstances)
    2348                 :          0 :                     size_t j, k, n = jl_array_len(mi->backedges), nlive = jl_array_len(milive->backedges);
    2349         [ #  # ]:          0 :                     for (j = 0; j < n; j++) {
    2350                 :          0 :                         jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, j);
    2351                 :          0 :                         jl_method_instance_t *belive = (jl_method_instance_t*)ptrhash_get(&uniquing_table, be);
    2352         [ #  # ]:          0 :                         if (belive == HT_NOTFOUND)
    2353                 :          0 :                             belive = be;
    2354                 :          0 :                         int found = 0;
    2355         [ #  # ]:          0 :                         for (k = 0; k < nlive; k++) {
    2356         [ #  # ]:          0 :                             if (belive == (jl_method_instance_t*)jl_array_ptr_ref(milive->backedges, k)) {
    2357                 :          0 :                                 found = 1;
    2358                 :          0 :                                 break;
    2359                 :            :                             }
    2360                 :            :                         }
    2361         [ #  # ]:          0 :                         if (!found)
    2362                 :          0 :                             jl_array_ptr_1d_push(milive->backedges, (jl_value_t*)belive);
    2363                 :            :                     }
    2364                 :            :                 }
    2365                 :            :             }
    2366                 :            :             // Additionally, if we have CodeInstance(s) and the running CodeInstance is world-limited, transfer it
    2367   [ #  #  #  # ]:          0 :             if (mi->cache && jl_array_uint8_ref(valids, i)) {
    2368   [ #  #  #  # ]:          0 :                 if (!milive->cache || milive->cache->max_world < ~(size_t)0) {
    2369                 :          0 :                     jl_code_instance_t *cilive = milive->cache, *ci;
    2370                 :          0 :                     milive->cache = mi->cache;
    2371                 :          0 :                     jl_gc_wb(milive, milive->cache);
    2372                 :          0 :                     ci = mi->cache;
    2373                 :          0 :                     ci->def = milive;
    2374         [ #  # ]:          0 :                     while (ci->next) {
    2375                 :          0 :                         ci = ci->next;
    2376                 :          0 :                         ci->def = milive;
    2377                 :            :                     }
    2378                 :          0 :                     ci->next = cilive;
    2379                 :          0 :                     jl_gc_wb(ci, ci->next);
    2380                 :            :                 }
    2381                 :            :             }
    2382                 :            :         }
    2383                 :            :     }
    2384                 :          0 : }
    2385                 :            : 
    2386                 :            : // verify that these edges intersect with the same methods as before
    2387                 :          0 : static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids)
    2388                 :            : {
    2389                 :          0 :     size_t i, l = jl_array_len(targets) / 2;
    2390                 :          0 :     jl_array_t *valids = jl_alloc_array_1d(jl_array_uint8_type, l);
    2391                 :          0 :     memset(jl_array_data(valids), 1, l);
    2392                 :          0 :     jl_value_t *loctag = NULL;
    2393                 :          0 :     JL_GC_PUSH1(&loctag);
    2394                 :          0 :     *pvalids = valids;
    2395         [ #  # ]:          0 :     for (i = 0; i < l; i++) {
    2396                 :          0 :         jl_value_t *callee = jl_array_ptr_ref(targets, i * 2);
    2397                 :          0 :         jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee;
    2398                 :            :         jl_value_t *sig;
    2399         [ #  # ]:          0 :         if (jl_is_method_instance(callee)) {
    2400                 :          0 :             sig = callee_mi->specTypes;
    2401                 :            :         }
    2402                 :            :         else {
    2403                 :          0 :             sig = callee;
    2404                 :            :         }
    2405                 :          0 :         jl_array_t *expected = (jl_array_t*)jl_array_ptr_ref(targets, i * 2 + 1);
    2406         [ #  # ]:          0 :         assert(jl_is_array(expected));
    2407                 :          0 :         int valid = 1;
    2408                 :          0 :         size_t min_valid = 0;
    2409                 :          0 :         size_t max_valid = ~(size_t)0;
    2410                 :          0 :         int ambig = 0;
    2411                 :            :         // TODO: possibly need to included ambiguities too (for the optimizer correctness)?
    2412                 :          0 :         jl_value_t *matches = jl_matching_methods((jl_tupletype_t*)sig, jl_nothing, -1, 0, jl_atomic_load_acquire(&jl_world_counter), &min_valid, &max_valid, &ambig);
    2413   [ #  #  #  # ]:          0 :         if (matches == jl_false || jl_array_len(matches) != jl_array_len(expected)) {
    2414                 :          0 :             valid = 0;
    2415                 :            :         }
    2416                 :            :         else {
    2417                 :          0 :             size_t j, k, l = jl_array_len(expected);
    2418         [ #  # ]:          0 :             for (k = 0; k < jl_array_len(matches); k++) {
    2419                 :          0 :                 jl_method_match_t *match = (jl_method_match_t*)jl_array_ptr_ref(matches, k);
    2420                 :          0 :                 jl_method_t *m = match->method;
    2421         [ #  # ]:          0 :                 for (j = 0; j < l; j++) {
    2422         [ #  # ]:          0 :                     if (m == (jl_method_t*)jl_array_ptr_ref(expected, j))
    2423                 :          0 :                         break;
    2424                 :            :                 }
    2425         [ #  # ]:          0 :                 if (j == l) {
    2426                 :            :                     // intersection has a new method or a method was
    2427                 :            :                     // deleted--this is now probably no good, just invalidate
    2428                 :            :                     // everything about it now
    2429                 :          0 :                     valid = 0;
    2430                 :          0 :                     break;
    2431                 :            :                 }
    2432                 :            :             }
    2433                 :            :         }
    2434                 :          0 :         jl_array_uint8_set(valids, i, valid);
    2435   [ #  #  #  # ]:          0 :         if (!valid && _jl_debug_method_invalidation) {
    2436                 :          0 :             jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)callee);
    2437                 :          0 :             loctag = jl_cstr_to_string("insert_backedges_callee");
    2438                 :          0 :             jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
    2439                 :            :         }
    2440                 :            :     }
    2441                 :          0 :     JL_GC_POP();
    2442                 :          0 : }
    2443                 :            : 
    2444                 :            : // Restore backedges to external targets
    2445                 :            : // `targets` is [callee1, matches1, ...], the global set of non-worklist callees of worklist-owned methods.
    2446                 :            : // `list` = [caller1, targets_indexes1, ...], the list of worklist-owned methods calling external methods.
    2447                 :          0 : static void jl_insert_backedges(jl_array_t *list, jl_array_t *targets)
    2448                 :            : {
    2449                 :            :     // map(enable, ((list[i] => targets[list[i + 1] .* 2]) for i in 1:2:length(list) if all(valids[list[i + 1]])))
    2450                 :          0 :     size_t i, l = jl_array_len(list);
    2451                 :          0 :     jl_array_t *valids = NULL;
    2452                 :          0 :     jl_value_t *loctag = NULL;
    2453                 :          0 :     JL_GC_PUSH2(&valids, &loctag);
    2454                 :          0 :     jl_verify_edges(targets, &valids);
    2455         [ #  # ]:          0 :     for (i = 0; i < l; i += 2) {
    2456                 :          0 :         jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
    2457   [ #  #  #  # ]:          0 :         assert(jl_is_method_instance(caller) && jl_is_method(caller->def.method));
    2458                 :          0 :         jl_array_t *idxs_array = (jl_array_t*)jl_array_ptr_ref(list, i + 1);
    2459         [ #  # ]:          0 :         assert(jl_isa((jl_value_t*)idxs_array, jl_array_int32_type));
    2460                 :          0 :         int32_t *idxs = (int32_t*)jl_array_data(idxs_array);
    2461                 :          0 :         int valid = 1;
    2462                 :            :         size_t j;
    2463   [ #  #  #  # ]:          0 :         for (j = 0; valid && j < jl_array_len(idxs_array); j++) {
    2464                 :          0 :             int32_t idx = idxs[j];
    2465                 :          0 :             valid = jl_array_uint8_ref(valids, idx);
    2466                 :            :         }
    2467         [ #  # ]:          0 :         if (valid) {
    2468                 :            :             // if this callee is still valid, add all the backedges
    2469         [ #  # ]:          0 :             for (j = 0; j < jl_array_len(idxs_array); j++) {
    2470                 :          0 :                 int32_t idx = idxs[j];
    2471                 :          0 :                 jl_value_t *callee = jl_array_ptr_ref(targets, idx * 2);
    2472         [ #  # ]:          0 :                 if (jl_is_method_instance(callee)) {
    2473                 :          0 :                     jl_method_instance_add_backedge((jl_method_instance_t*)callee, caller);
    2474                 :            :                 }
    2475                 :            :                 else {
    2476                 :          0 :                     jl_methtable_t *mt = jl_method_table_for(callee);
    2477                 :            :                     // FIXME: rarely, `callee` has an unexpected `Union` signature,
    2478                 :            :                     // see https://github.com/JuliaLang/julia/pull/43990#issuecomment-1030329344
    2479                 :            :                     // Fix the issue and turn this back into an `assert((jl_value_t*)mt != jl_nothing)`
    2480                 :            :                     // This workaround exposes us to (rare) 265-violations.
    2481         [ #  # ]:          0 :                     if ((jl_value_t*)mt != jl_nothing)
    2482                 :          0 :                         jl_method_table_add_backedge(mt, callee, (jl_value_t*)caller);
    2483                 :            :                 }
    2484                 :            :             }
    2485                 :            :             // then enable it
    2486                 :          0 :             jl_code_instance_t *codeinst = caller->cache;
    2487         [ #  # ]:          0 :             while (codeinst) {
    2488   [ #  #  #  # ]:          0 :                 if (ptrhash_get(&new_code_instance_validate, codeinst) != HT_NOTFOUND && codeinst->min_world > 0)
    2489                 :          0 :                     codeinst->max_world = ~(size_t)0;
    2490                 :          0 :                 ptrhash_remove(&new_code_instance_validate, codeinst);  // mark it as handled
    2491                 :          0 :                 codeinst = jl_atomic_load_relaxed(&codeinst->next);
    2492                 :            :             }
    2493                 :            :         }
    2494                 :            :         else {
    2495                 :          0 :             jl_code_instance_t *codeinst = caller->cache;
    2496         [ #  # ]:          0 :             while (codeinst) {
    2497                 :          0 :                 ptrhash_remove(&new_code_instance_validate, codeinst);  // should be left invalid
    2498                 :          0 :                 codeinst = jl_atomic_load_relaxed(&codeinst->next);
    2499                 :            :             }
    2500         [ #  # ]:          0 :             if (_jl_debug_method_invalidation) {
    2501                 :          0 :                 jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller);
    2502                 :          0 :                 loctag = jl_cstr_to_string("insert_backedges");
    2503                 :          0 :                 jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
    2504                 :            :             }
    2505                 :            :         }
    2506                 :            :     }
    2507                 :          0 :     JL_GC_POP();
    2508                 :          0 : }
    2509                 :            : 
    2510                 :          0 : static void validate_new_code_instances(void)
    2511                 :            : {
    2512                 :            :     size_t i;
    2513         [ #  # ]:          0 :     for (i = 0; i < new_code_instance_validate.size; i += 2) {
    2514         [ #  # ]:          0 :         if (new_code_instance_validate.table[i+1] != HT_NOTFOUND) {
    2515                 :          0 :             ((jl_code_instance_t*)new_code_instance_validate.table[i])->max_world = ~(size_t)0;
    2516                 :            :         }
    2517                 :            :     }
    2518                 :          0 : }
    2519                 :            : 
    2520                 :          0 : static jl_value_t *read_verify_mod_list(ios_t *s, jl_array_t *mod_list)
    2521                 :            : {
    2522         [ #  # ]:          0 :     if (!jl_main_module->build_id) {
    2523                 :          0 :         return jl_get_exceptionf(jl_errorexception_type,
    2524                 :            :                 "Main module uuid state is invalid for module deserialization.");
    2525                 :            :     }
    2526                 :          0 :     size_t i, l = jl_array_len(mod_list);
    2527                 :          0 :     for (i = 0; ; i++) {
    2528                 :          0 :         size_t len = read_int32(s);
    2529   [ #  #  #  # ]:          0 :         if (len == 0 && i == l)
    2530                 :          0 :             return NULL; // success
    2531   [ #  #  #  # ]:          0 :         if (len == 0 || i == l)
    2532                 :          0 :             return jl_get_exceptionf(jl_errorexception_type, "Wrong number of entries in module list.");
    2533                 :          0 :         char *name = (char*)alloca(len + 1);
    2534                 :          0 :         ios_readall(s, name, len);
    2535                 :          0 :         name[len] = '\0';
    2536                 :            :         jl_uuid_t uuid;
    2537                 :          0 :         uuid.hi = read_uint64(s);
    2538                 :          0 :         uuid.lo = read_uint64(s);
    2539                 :          0 :         uint64_t build_id = read_uint64(s);
    2540                 :          0 :         jl_sym_t *sym = _jl_symbol(name, len);
    2541                 :          0 :         jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_list, i);
    2542   [ #  #  #  #  :          0 :         if (!m || !jl_is_module(m) || m->uuid.hi != uuid.hi || m->uuid.lo != uuid.lo || m->name != sym || m->build_id != build_id) {
          #  #  #  #  #  
                #  #  # ]
    2543                 :          0 :             return jl_get_exceptionf(jl_errorexception_type,
    2544                 :            :                 "Invalid input in module list: expected %s.", name);
    2545                 :            :         }
    2546                 :            :     }
    2547                 :            : }
    2548                 :            : 
    2549                 :         24 : static int readstr_verify(ios_t *s, const char *str)
    2550                 :            : {
    2551                 :         24 :     size_t i, len = strlen(str);
    2552         [ +  + ]:        328 :     for (i = 0; i < len; ++i)
    2553         [ -  + ]:        304 :         if ((char)read_uint8(s) != str[i])
    2554                 :          0 :             return 0;
    2555                 :         24 :     return 1;
    2556                 :            : }
    2557                 :            : 
    2558                 :          4 : JL_DLLEXPORT int jl_read_verify_header(ios_t *s)
    2559                 :            : {
    2560                 :            :     uint16_t bom;
    2561                 :          4 :     return (readstr_verify(s, JI_MAGIC) &&
    2562   [ +  -  +  - ]:          8 :             read_uint16(s) == JI_FORMAT_VERSION &&
    2563         [ +  - ]:          8 :             ios_read(s, (char *) &bom, 2) == 2 && bom == BOM &&
    2564   [ +  -  +  - ]:          8 :             read_uint8(s) == sizeof(void*) &&
    2565   [ +  -  +  - ]:         12 :             readstr_verify(s, JL_BUILD_UNAME) && !read_uint8(s) &&
    2566   [ +  -  +  - ]:         12 :             readstr_verify(s, JL_BUILD_ARCH) && !read_uint8(s) &&
    2567   [ +  -  +  - ]:         12 :             readstr_verify(s, JULIA_VERSION_STRING) && !read_uint8(s) &&
    2568   [ +  -  +  - ]:         12 :             readstr_verify(s, jl_git_branch()) && !read_uint8(s) &&
    2569   [ +  -  +  - ]:         12 :             readstr_verify(s, jl_git_commit()) && !read_uint8(s));
    2570                 :            : }
    2571                 :            : 
    2572                 :          4 : static void jl_finalize_serializer(jl_serializer_state *s)
    2573                 :            : {
    2574                 :            :     size_t i, l;
    2575                 :            :     // save module initialization order
    2576         [ +  - ]:          4 :     if (jl_module_init_order != NULL) {
    2577                 :          4 :         l = jl_array_len(jl_module_init_order);
    2578         [ -  + ]:          4 :         for (i = 0; i < l; i++) {
    2579                 :            :             // verify that all these modules were saved
    2580         [ #  # ]:          0 :             assert(ptrhash_get(&backref_table, jl_array_ptr_ref(jl_module_init_order, i)) != HT_NOTFOUND);
    2581                 :            :         }
    2582                 :            :     }
    2583                 :          4 :     jl_serialize_value(s, jl_module_init_order);
    2584                 :            : 
    2585                 :            :     // record list of reinitialization functions
    2586                 :          4 :     l = reinit_list.len;
    2587         [ +  + ]:         14 :     for (i = 0; i < l; i += 2) {
    2588                 :         10 :         write_int32(s->s, (int)((uintptr_t) reinit_list.items[i]));
    2589                 :         10 :         write_int32(s->s, (int)((uintptr_t) reinit_list.items[i+1]));
    2590                 :            :     }
    2591                 :          4 :     write_int32(s->s, -1);
    2592                 :          4 : }
    2593                 :            : 
    2594                 :          0 : static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list)
    2595                 :            : {
    2596   [ #  #  #  # ]:          0 :     JL_TRY {
    2597   [ #  #  #  # ]:          0 :         switch (how) {
    2598                 :          0 :             case 1: { // rehash IdDict
    2599                 :          0 :                 jl_array_t **a = (jl_array_t**)v;
    2600                 :            :                 // Assume *a don't need a write barrier
    2601                 :          0 :                 *a = jl_idtable_rehash(*a, jl_array_len(*a));
    2602                 :          0 :                 jl_gc_wb(v, *a);
    2603                 :          0 :                 break;
    2604                 :            :             }
    2605                 :          0 :             case 2: { // reinsert module v into parent (const)
    2606                 :          0 :                 jl_module_t *mod = (jl_module_t*)v;
    2607         [ #  # ]:          0 :                 if (mod->parent == mod) // top level modules handled by loader
    2608                 :          0 :                     break;
    2609                 :          0 :                 jl_binding_t *b = jl_get_binding_wr(mod->parent, mod->name, 1); // this can throw
    2610                 :          0 :                 jl_declare_constant(b); // this can also throw
    2611         [ #  # ]:          0 :                 if (b->value != NULL) {
    2612         [ #  # ]:          0 :                     if (!jl_is_module(b->value)) {
    2613                 :          0 :                         jl_errorf("Invalid redefinition of constant %s.",
    2614                 :            :                                   jl_symbol_name(mod->name)); // this also throws
    2615                 :            :                     }
    2616   [ #  #  #  # ]:          0 :                     if (jl_generating_output() && jl_options.incremental) {
    2617                 :          0 :                         jl_errorf("Cannot replace module %s during incremental precompile.", jl_symbol_name(mod->name));
    2618                 :            :                     }
    2619                 :          0 :                     jl_printf(JL_STDERR, "WARNING: replacing module %s.\n", jl_symbol_name(mod->name));
    2620                 :            :                 }
    2621                 :          0 :                 b->value = v;
    2622                 :          0 :                 jl_gc_wb_binding(b, v);
    2623                 :          0 :                 break;
    2624                 :            :             }
    2625                 :          0 :             case 3: { // rehash MethodTable
    2626                 :          0 :                 jl_methtable_t *mt = (jl_methtable_t*)v;
    2627         [ #  # ]:          0 :                 if (tracee_list)
    2628                 :          0 :                     arraylist_push(tracee_list, mt);
    2629                 :          0 :                 break;
    2630                 :            :             }
    2631                 :          0 :             default:
    2632                 :          0 :                 assert(0 && "corrupt deserialization state");
    2633                 :            :                 abort();
    2634                 :            :         }
    2635                 :            :     }
    2636         [ #  # ]:          0 :     JL_CATCH {
    2637                 :          0 :         jl_printf((JL_STREAM*)STDERR_FILENO, "WARNING: error while reinitializing value ");
    2638                 :          0 :         jl_static_show((JL_STREAM*)STDERR_FILENO, v);
    2639                 :          0 :         jl_printf((JL_STREAM*)STDERR_FILENO, ":\n");
    2640                 :          0 :         jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
    2641                 :          0 :         jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
    2642                 :          0 :         jlbacktrace(); // written to STDERR_FILENO
    2643                 :            :     }
    2644                 :          0 : }
    2645                 :            : 
    2646                 :          0 : static jl_array_t *jl_finalize_deserializer(jl_serializer_state *s, arraylist_t *tracee_list)
    2647                 :            : {
    2648                 :          0 :     jl_array_t *init_order = (jl_array_t*)jl_deserialize_value(s, NULL);
    2649                 :            : 
    2650                 :            :     // run reinitialization functions
    2651                 :          0 :     int pos = read_int32(s->s);
    2652         [ #  # ]:          0 :     while (pos != -1) {
    2653                 :          0 :         jl_reinit_item((jl_value_t*)backref_list.items[pos], read_int32(s->s), tracee_list);
    2654                 :          0 :         pos = read_int32(s->s);
    2655                 :            :     }
    2656                 :          0 :     return init_order;
    2657                 :            : }
    2658                 :            : 
    2659                 :          0 : JL_DLLEXPORT void jl_init_restored_modules(jl_array_t *init_order)
    2660                 :            : {
    2661                 :          0 :     int i, l = jl_array_len(init_order);
    2662         [ #  # ]:          0 :     for (i = 0; i < l; i++) {
    2663                 :          0 :         jl_value_t *mod = jl_array_ptr_ref(init_order, i);
    2664   [ #  #  #  # ]:          0 :         if (!jl_generating_output() || jl_options.incremental) {
    2665                 :          0 :             jl_module_run_initializer((jl_module_t*)mod);
    2666                 :            :         }
    2667                 :            :         else {
    2668         [ #  # ]:          0 :             if (jl_module_init_order == NULL)
    2669                 :          0 :                 jl_module_init_order = jl_alloc_vec_any(0);
    2670                 :          0 :             jl_array_ptr_1d_push(jl_module_init_order, mod);
    2671                 :            :         }
    2672                 :            :     }
    2673                 :          0 : }
    2674                 :            : 
    2675                 :            : 
    2676                 :            : // --- entry points ---
    2677                 :            : 
    2678                 :            : // Register all newly-inferred MethodInstances
    2679                 :            : // This gets called as the final step of Base.include_package_for_output
    2680                 :          4 : JL_DLLEXPORT void jl_set_newly_inferred(jl_value_t* _newly_inferred)
    2681                 :            : {
    2682   [ +  -  -  + ]:          4 :     assert(_newly_inferred == NULL || jl_is_array(_newly_inferred));
    2683                 :          4 :     newly_inferred = (jl_array_t*) _newly_inferred;
    2684                 :          4 : }
    2685                 :            : 
    2686                 :            : // Serialize the modules in `worklist` to file `fname`
    2687                 :          4 : JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist)
    2688                 :            : {
    2689                 :            :     JL_TIMING(SAVE_MODULE);
    2690                 :            :     ios_t f;
    2691                 :          4 :     jl_array_t *mod_array = NULL, *udeps = NULL;
    2692         [ -  + ]:          4 :     if (ios_file(&f, fname, 1, 1, 1, 1) == NULL) {
    2693                 :          0 :         jl_printf(JL_STDERR, "Cannot open cache file \"%s\" for writing.\n", fname);
    2694                 :          0 :         return 1;
    2695                 :            :     }
    2696                 :          4 :     JL_GC_PUSH2(&mod_array, &udeps);
    2697                 :          4 :     mod_array = jl_get_loaded_modules();  // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
    2698         [ -  + ]:          4 :     assert(jl_precompile_toplevel_module == NULL);
    2699                 :          4 :     jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1);
    2700                 :            : 
    2701                 :          4 :     serializer_worklist = worklist;
    2702                 :          4 :     write_header(&f);
    2703                 :            :     // write description of contents (name, uuid, buildid)
    2704                 :          4 :     write_work_list(&f);
    2705                 :            :     // Determine unique (module, abspath, mtime) dependencies for the files defining modules in the worklist
    2706                 :            :     // (see Base._require_dependencies). These get stored in `udeps` and written to the ji-file header.
    2707                 :            :     // Also write Preferences.
    2708                 :          4 :     int64_t srctextpos = write_dependency_list(&f, &udeps);  // srctextpos: position of srctext entry in header index (update later)
    2709                 :            :     // write description of requirements for loading (modules that must be pre-loaded if initialization is to succeed)
    2710                 :            :     // this can return errors during deserialize,
    2711                 :            :     // best to keep it early (before any actual initialization)
    2712                 :          4 :     write_mod_list(&f, mod_array);
    2713                 :            : 
    2714                 :          4 :     arraylist_new(&reinit_list, 0);
    2715                 :          4 :     htable_new(&edges_map, 0);
    2716                 :          4 :     htable_new(&backref_table, 5000);
    2717         [ +  - ]:          4 :     htable_new(&external_mis, newly_inferred ? jl_array_len(newly_inferred) : 0);
    2718                 :          4 :     ptrhash_put(&backref_table, jl_main_module, (char*)HT_NOTFOUND + 1);
    2719                 :          4 :     backref_table_numel = 1;
    2720         [ +  - ]:          4 :     jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("IdDict")) : NULL;
    2721         [ +  - ]:          4 :     jl_idtable_typename = jl_base_module ? ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_idtable_type))->name : NULL;
    2722         [ +  - ]:          4 :     jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
    2723         [ +  - ]:          4 :     if (jl_bigint_type) {
    2724                 :          4 :         gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
    2725                 :          4 :                                                     jl_symbol("BITS_PER_LIMB"))) / 8;
    2726                 :            :     }
    2727                 :            : 
    2728                 :          4 :     int en = jl_gc_enable(0); // edges map is not gc-safe
    2729                 :          4 :     jl_array_t *extext_methods = jl_alloc_vec_any(0);  // [method1, simplesig1, ...], worklist-owned "extending external" methods added to functions owned by modules outside the worklist
    2730                 :          4 :     jl_array_t *ext_targets = jl_alloc_vec_any(0);     // [callee1, matches1, ...] non-worklist callees of worklist-owned methods
    2731                 :          4 :     jl_array_t *edges = jl_alloc_vec_any(0);           // [caller1, ext_targets_indexes1, ...] for worklist-owned methods calling external methods
    2732                 :            : 
    2733                 :          4 :     int n_ext_mis = queue_external_mis(newly_inferred);
    2734                 :            : 
    2735                 :            :     size_t i;
    2736                 :          4 :     size_t len = jl_array_len(mod_array);
    2737         [ +  + ]:        180 :     for (i = 0; i < len; i++) {
    2738                 :        176 :         jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_array, i);
    2739         [ -  + ]:        176 :         assert(jl_is_module(m));
    2740         [ +  + ]:        176 :         if (m->parent == m) // some toplevel modules (really just Base) aren't actually
    2741                 :        172 :             jl_collect_extext_methods_from_mod(extext_methods, m);
    2742                 :            :     }
    2743                 :          4 :     jl_collect_methtable_from_mod(extext_methods, jl_type_type_mt);
    2744                 :          4 :     jl_collect_missing_backedges_to_mod(jl_type_type_mt);
    2745                 :          4 :     jl_collect_methtable_from_mod(extext_methods, jl_nonfunction_mt);
    2746                 :          4 :     jl_collect_missing_backedges_to_mod(jl_nonfunction_mt);
    2747                 :            : 
    2748                 :            :     // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges_to_mod accumulate data in edges_map.
    2749                 :            :     // Process this to extract `edges` and `ext_targets`.
    2750                 :          4 :     jl_collect_backedges(edges, ext_targets);
    2751                 :            : 
    2752                 :          4 :     jl_serializer_state s = {
    2753                 :            :         &f,
    2754                 :          4 :         jl_current_task->ptls,
    2755                 :            :         mod_array
    2756                 :            :     };
    2757                 :          4 :     jl_serialize_value(&s, worklist);   // serialize module-owned items (those accessible from the bindings table)
    2758                 :          4 :     jl_serialize_value(&s, extext_methods);  // serialize new worklist-owned methods for external functions
    2759                 :          4 :     serialize_htable_keys(&s, &external_mis, n_ext_mis);  // serialize external MethodInstances
    2760                 :            : 
    2761                 :            :     // The next two allow us to restore backedges from external "unserialized" (stub-serialized) MethodInstances
    2762                 :            :     // to the ones we serialize here
    2763                 :          4 :     jl_serialize_value(&s, edges);
    2764                 :          4 :     jl_serialize_value(&s, ext_targets);
    2765                 :          4 :     jl_finalize_serializer(&s);
    2766                 :          4 :     serializer_worklist = NULL;
    2767                 :            : 
    2768                 :          4 :     jl_gc_enable(en);
    2769                 :          4 :     htable_reset(&edges_map, 0);
    2770                 :          4 :     htable_reset(&backref_table, 0);
    2771                 :          4 :     htable_reset(&external_mis, 0);
    2772                 :          4 :     arraylist_free(&reinit_list);
    2773                 :            : 
    2774                 :            :     // Write the source-text for the dependent files
    2775         [ +  - ]:          4 :     if (udeps) {
    2776                 :            :         // Go back and update the source-text position to point to the current position
    2777                 :          4 :         int64_t posfile = ios_pos(&f);
    2778                 :          4 :         ios_seek(&f, srctextpos);
    2779                 :          4 :         write_int64(&f, posfile);
    2780                 :          4 :         ios_seek_end(&f);
    2781                 :            :         // Each source-text file is written as
    2782                 :            :         //   int32: length of abspath
    2783                 :            :         //   char*: abspath
    2784                 :            :         //   uint64: length of src text
    2785                 :            :         //   char*: src text
    2786                 :            :         // At the end we write int32(0) as a terminal sentinel.
    2787                 :          4 :         len = jl_array_len(udeps);
    2788                 :            :         ios_t srctext;
    2789         [ +  + ]:          8 :         for (i = 0; i < len; i++) {
    2790                 :          4 :             jl_value_t *deptuple = jl_array_ptr_ref(udeps, i);
    2791                 :          4 :             jl_value_t *depmod = jl_fieldref(deptuple, 0);  // module
    2792                 :            :             // Dependencies declared with `include_dependency` are excluded
    2793                 :            :             // because these may not be Julia code (and could be huge)
    2794         [ +  - ]:          4 :             if (depmod != (jl_value_t*)jl_main_module) {
    2795                 :          4 :                 jl_value_t *dep = jl_fieldref(deptuple, 1);  // file abspath
    2796                 :          4 :                 const char *depstr = jl_string_data(dep);
    2797         [ -  + ]:          4 :                 if (!depstr[0])
    2798                 :          0 :                     continue;
    2799                 :          4 :                 ios_t *srctp = ios_file(&srctext, depstr, 1, 0, 0, 0);
    2800         [ -  + ]:          4 :                 if (!srctp) {
    2801                 :          0 :                     jl_printf(JL_STDERR, "WARNING: could not cache source text for \"%s\".\n",
    2802                 :            :                               jl_string_data(dep));
    2803                 :          0 :                     continue;
    2804                 :            :                 }
    2805                 :          4 :                 size_t slen = jl_string_len(dep);
    2806                 :          4 :                 write_int32(&f, slen);
    2807                 :          4 :                 ios_write(&f, depstr, slen);
    2808                 :          4 :                 posfile = ios_pos(&f);
    2809                 :          4 :                 write_uint64(&f, 0);   // placeholder for length of this file in bytes
    2810                 :          4 :                 uint64_t filelen = (uint64_t) ios_copyall(&f, &srctext);
    2811                 :          4 :                 ios_close(&srctext);
    2812                 :          4 :                 ios_seek(&f, posfile);
    2813                 :          4 :                 write_uint64(&f, filelen);
    2814                 :          4 :                 ios_seek_end(&f);
    2815                 :            :             }
    2816                 :            :         }
    2817                 :            :     }
    2818                 :          4 :     write_int32(&f, 0); // mark the end of the source text
    2819                 :          4 :     ios_close(&f);
    2820                 :          4 :     JL_GC_POP();
    2821                 :          4 :     jl_precompile_toplevel_module = NULL;
    2822                 :            : 
    2823                 :          4 :     return 0;
    2824                 :            : }
    2825                 :            : 
    2826                 :            : #ifndef JL_NDEBUG
    2827                 :            : // skip the performance optimizations of jl_types_equal and just use subtyping directly
    2828                 :            : // one of these types is invalid - that's why we're doing the recache type operation
    2829                 :          0 : static int jl_invalid_types_equal(jl_datatype_t *a, jl_datatype_t *b)
    2830                 :            : {
    2831   [ #  #  #  # ]:          0 :     return jl_subtype((jl_value_t*)a, (jl_value_t*)b) && jl_subtype((jl_value_t*)b, (jl_value_t*)a);
    2832                 :            : }
    2833                 :          0 : STATIC_INLINE jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT
    2834                 :            : {
    2835   [ #  #  #  #  :          0 :     assert(v && jl_typeof(v) && jl_typeof(jl_typeof(v)) == (jl_value_t*)jl_datatype_type);
                   #  # ]
    2836                 :          0 :     return v;
    2837                 :            : }
    2838                 :            : #endif
    2839                 :            : 
    2840                 :            : 
    2841                 :            : static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED;
    2842                 :            : 
    2843                 :          0 : static jl_value_t *recache_type(jl_value_t *p) JL_GC_DISABLED
    2844                 :            : {
    2845         [ #  # ]:          0 :     if (jl_is_datatype(p)) {
    2846                 :          0 :         jl_datatype_t *pdt = (jl_datatype_t*)p;
    2847         [ #  # ]:          0 :         if (ptrhash_get(&uniquing_table, p) != HT_NOTFOUND) {
    2848                 :          0 :             p = (jl_value_t*)recache_datatype(pdt);
    2849                 :            :         }
    2850                 :            :         else {
    2851                 :          0 :             jl_svec_t *tt = pdt->parameters;
    2852                 :            :             // ensure all type parameters are recached
    2853                 :          0 :             size_t i, l = jl_svec_len(tt);
    2854         [ #  # ]:          0 :             for (i = 0; i < l; i++)
    2855                 :          0 :                 jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
    2856                 :          0 :             ptrhash_put(&uniquing_table, p, p); // ensures this algorithm isn't too exponential
    2857                 :            :         }
    2858                 :            :     }
    2859         [ #  # ]:          0 :     else if (jl_is_typevar(p)) {
    2860                 :          0 :         jl_tvar_t *ptv = (jl_tvar_t*)p;
    2861                 :          0 :         ptv->lb = recache_type(ptv->lb);
    2862                 :          0 :         ptv->ub = recache_type(ptv->ub);
    2863                 :            :     }
    2864         [ #  # ]:          0 :     else if (jl_is_uniontype(p)) {
    2865                 :          0 :         jl_uniontype_t *pu = (jl_uniontype_t*)p;
    2866                 :          0 :         pu->a = recache_type(pu->a);
    2867                 :          0 :         pu->b = recache_type(pu->b);
    2868                 :            :     }
    2869         [ #  # ]:          0 :     else if (jl_is_unionall(p)) {
    2870                 :          0 :         jl_unionall_t *pa = (jl_unionall_t*)p;
    2871                 :          0 :         pa->var = (jl_tvar_t*)recache_type((jl_value_t*)pa->var);
    2872                 :          0 :         pa->body = recache_type(pa->body);
    2873                 :            :     }
    2874                 :            :     else {
    2875                 :          0 :         jl_datatype_t *pt = (jl_datatype_t*)jl_typeof(p);
    2876                 :          0 :         jl_datatype_t *cachep = recache_datatype(pt);
    2877         [ #  # ]:          0 :         if (cachep->instance)
    2878                 :          0 :             p = cachep->instance;
    2879         [ #  # ]:          0 :         else if (pt != cachep)
    2880                 :          0 :             jl_set_typeof(p, cachep);
    2881                 :            :     }
    2882                 :          0 :     return p;
    2883                 :            : }
    2884                 :            : 
    2885                 :            : // Extract pre-existing datatypes from cache, and insert new types into cache
    2886                 :            : // insertions also update uniquing_table
    2887                 :          0 : static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED
    2888                 :            : {
    2889                 :            :     jl_datatype_t *t; // the type after unique'ing
    2890         [ #  # ]:          0 :     assert(verify_type((jl_value_t*)dt));
    2891                 :          0 :     t = (jl_datatype_t*)ptrhash_get(&uniquing_table, dt);
    2892         [ #  # ]:          0 :     if (t == HT_NOTFOUND)
    2893                 :          0 :         return dt;
    2894         [ #  # ]:          0 :     if (t != NULL)
    2895                 :          0 :         return t;
    2896                 :            : 
    2897                 :          0 :     jl_svec_t *tt = dt->parameters;
    2898                 :            :     // recache all type parameters
    2899                 :          0 :     size_t i, l = jl_svec_len(tt);
    2900         [ #  # ]:          0 :     for (i = 0; i < l; i++)
    2901                 :          0 :         jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
    2902                 :            : 
    2903                 :            :     // then recache the type itself
    2904         [ #  # ]:          0 :     if (jl_svec_len(tt) == 0) { // jl_cache_type doesn't work if length(parameters) == 0
    2905                 :          0 :         t = dt;
    2906                 :            :     }
    2907                 :            :     else {
    2908                 :          0 :         t = jl_lookup_cache_type_(dt);
    2909         [ #  # ]:          0 :         if (t == NULL) {
    2910                 :          0 :             jl_cache_type_(dt);
    2911                 :          0 :             t = dt;
    2912                 :            :         }
    2913         [ #  # ]:          0 :         assert(t->hash == dt->hash);
    2914         [ #  # ]:          0 :         assert(jl_invalid_types_equal(t, dt));
    2915                 :            :     }
    2916                 :          0 :     ptrhash_put(&uniquing_table, dt, t);
    2917                 :          0 :     return t;
    2918                 :            : }
    2919                 :            : 
    2920                 :            : // Recache everything from flagref_list except methods and method instances
    2921                 :            : // Cleans out any handled items so that anything left in flagref_list still needs future processing
    2922                 :          0 : static void jl_recache_types(void) JL_GC_DISABLED
    2923                 :            : {
    2924                 :            :     size_t i;
    2925                 :            :     // first rewrite all the unique'd objects
    2926         [ #  # ]:          0 :     for (i = 0; i < flagref_list.len; i += 2) {
    2927                 :          0 :         jl_value_t **loc = (jl_value_t**)flagref_list.items[i + 0];
    2928                 :          0 :         int offs = (int)(intptr_t)flagref_list.items[i + 1];
    2929         [ #  # ]:          0 :         jl_value_t *o = loc ? *loc : (jl_value_t*)backref_list.items[offs];
    2930   [ #  #  #  # ]:          0 :         if (!jl_is_method(o) && !jl_is_method_instance(o)) {
    2931                 :            :             jl_datatype_t *dt;
    2932                 :            :             jl_value_t *v;
    2933         [ #  # ]:          0 :             if (jl_is_datatype(o)) {
    2934                 :          0 :                 dt = (jl_datatype_t*)o;
    2935                 :          0 :                 v = dt->instance;
    2936                 :            :             }
    2937                 :            :             else {
    2938                 :          0 :                 dt = (jl_datatype_t*)jl_typeof(o);
    2939                 :          0 :                 v = o;
    2940                 :            :             }
    2941                 :          0 :             jl_datatype_t *t = recache_datatype(dt); // get or create cached type (also updates uniquing_table)
    2942   [ #  #  #  # ]:          0 :             if ((jl_value_t*)dt == o && t != dt) {
    2943         [ #  # ]:          0 :                 assert(!type_in_worklist(dt));
    2944         [ #  # ]:          0 :                 if (loc)
    2945                 :          0 :                     *loc = (jl_value_t*)t;
    2946         [ #  # ]:          0 :                 if (offs > 0)
    2947                 :          0 :                     backref_list.items[offs] = t;
    2948                 :            :             }
    2949   [ #  #  #  # ]:          0 :             if (v == o && t->instance != v) {
    2950         [ #  # ]:          0 :                 assert(t->instance);
    2951         [ #  # ]:          0 :                 assert(loc);
    2952                 :          0 :                 *loc = t->instance;
    2953         [ #  # ]:          0 :                 if (offs > 0)
    2954                 :          0 :                     backref_list.items[offs] = t->instance;
    2955                 :            :             }
    2956                 :            :         }
    2957                 :            :     }
    2958                 :            :     // invalidate the old datatypes to help catch errors
    2959         [ #  # ]:          0 :     for (i = 0; i < uniquing_table.size; i += 2) {
    2960                 :          0 :         jl_datatype_t *o = (jl_datatype_t*)uniquing_table.table[i];      // deserialized ref
    2961                 :          0 :         jl_datatype_t *t = (jl_datatype_t*)uniquing_table.table[i + 1];  // the real type
    2962         [ #  # ]:          0 :         if (o != t) {
    2963   [ #  #  #  # ]:          0 :             assert(t != NULL && jl_is_datatype(o));
    2964         [ #  # ]:          0 :             if (t->instance != o->instance)
    2965                 :          0 :                 jl_set_typeof(o->instance, (void*)(intptr_t)0x20);
    2966                 :          0 :             jl_set_typeof(o, (void*)(intptr_t)0x10);
    2967                 :            :         }
    2968                 :            :     }
    2969                 :            :     // then do a cleanup pass to drop these from future iterations of flagref_list
    2970                 :          0 :     i = 0;
    2971         [ #  # ]:          0 :     while (i < flagref_list.len) {
    2972                 :          0 :         jl_value_t **loc = (jl_value_t**)flagref_list.items[i + 0];
    2973                 :          0 :         int offs = (int)(intptr_t)flagref_list.items[i + 1];
    2974         [ #  # ]:          0 :         jl_value_t *o = loc ? *loc : (jl_value_t*)backref_list.items[offs];
    2975   [ #  #  #  # ]:          0 :         if (jl_is_method(o) || jl_is_method_instance(o)) {
    2976                 :          0 :             i += 2;
    2977                 :            :         }
    2978                 :            :         else {
    2979                 :            :             // delete this item from the flagref list, so it won't be re-encountered later
    2980                 :          0 :             flagref_list.len -= 2;
    2981         [ #  # ]:          0 :             if (i >= flagref_list.len)
    2982                 :          0 :                 break;
    2983                 :          0 :             flagref_list.items[i + 0] = flagref_list.items[flagref_list.len + 0];  // move end-of-list here (executes a `reverse()`)
    2984                 :          0 :             flagref_list.items[i + 1] = flagref_list.items[flagref_list.len + 1];
    2985                 :            :         }
    2986                 :            :     }
    2987                 :          0 : }
    2988                 :            : 
    2989                 :            : // look up a method from a previously deserialized dependent module
    2990                 :          0 : static jl_method_t *jl_lookup_method(jl_methtable_t *mt, jl_datatype_t *sig, size_t world)
    2991                 :            : {
    2992         [ #  # ]:          0 :     if (world < jl_main_module->primary_world)
    2993                 :          0 :         world = jl_main_module->primary_world;
    2994                 :          0 :     struct jl_typemap_assoc search = {(jl_value_t*)sig, world, NULL, 0, ~(size_t)0};
    2995                 :          0 :     jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, &search, /*offs*/0, /*subtype*/0);
    2996                 :          0 :     return (jl_method_t*)entry->func.value;
    2997                 :            : }
    2998                 :            : 
    2999                 :          0 : static jl_method_t *jl_recache_method(jl_method_t *m)
    3000                 :            : {
    3001         [ #  # ]:          0 :     assert(!m->is_for_opaque_closure);
    3002         [ #  # ]:          0 :     assert(jl_is_method(m));
    3003                 :          0 :     jl_datatype_t *sig = (jl_datatype_t*)m->sig;
    3004                 :          0 :     jl_methtable_t *mt = jl_method_get_table(m);
    3005         [ #  # ]:          0 :     assert((jl_value_t*)mt != jl_nothing);
    3006                 :          0 :     jl_set_typeof(m, (void*)(intptr_t)0x30); // invalidate the old value to help catch errors
    3007                 :          0 :     return jl_lookup_method(mt, sig, m->module->primary_world);
    3008                 :            : }
    3009                 :            : 
    3010                 :            : static jl_value_t *jl_recache_other_(jl_value_t *o);
    3011                 :            : 
    3012                 :          0 : static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *mi)
    3013                 :            : {
    3014                 :          0 :     jl_method_t *m = mi->def.method;
    3015                 :          0 :     m = (jl_method_t*)jl_recache_other_((jl_value_t*)m);
    3016         [ #  # ]:          0 :     assert(jl_is_method(m));
    3017                 :          0 :     jl_datatype_t *argtypes = (jl_datatype_t*)mi->specTypes;
    3018                 :          0 :     jl_set_typeof(mi, (void*)(intptr_t)0x40); // invalidate the old value to help catch errors
    3019                 :          0 :     jl_svec_t *env = jl_emptysvec;
    3020                 :          0 :     jl_value_t *ti = jl_type_intersection_env((jl_value_t*)argtypes, (jl_value_t*)m->sig, &env);
    3021                 :            :     //assert(ti != jl_bottom_type); (void)ti;
    3022         [ #  # ]:          0 :     if (ti == jl_bottom_type)
    3023                 :          0 :         env = jl_emptysvec; // the intersection may fail now if the type system had made an incorrect subtype env in the past
    3024                 :          0 :     jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env);
    3025                 :          0 :     return _new;
    3026                 :            : }
    3027                 :            : 
    3028                 :          0 : static jl_value_t *jl_recache_other_(jl_value_t *o)
    3029                 :            : {
    3030                 :          0 :     jl_value_t *newo = (jl_value_t*)ptrhash_get(&uniquing_table, o);
    3031         [ #  # ]:          0 :     if (newo != HT_NOTFOUND)
    3032                 :          0 :         return newo;
    3033         [ #  # ]:          0 :     if (jl_is_method(o)) {
    3034                 :            :         // lookup the real Method based on the placeholder sig
    3035                 :          0 :         newo = (jl_value_t*)jl_recache_method((jl_method_t*)o);
    3036                 :          0 :         ptrhash_put(&uniquing_table, newo, newo);
    3037                 :            :     }
    3038         [ #  # ]:          0 :     else if (jl_is_method_instance(o)) {
    3039                 :            :         // lookup the real MethodInstance based on the placeholder specTypes
    3040                 :          0 :         newo = (jl_value_t*)jl_recache_method_instance((jl_method_instance_t*)o);
    3041                 :            :     }
    3042                 :            :     else {
    3043                 :          0 :         abort();
    3044                 :            :     }
    3045                 :          0 :     ptrhash_put(&uniquing_table, o, newo);
    3046                 :          0 :     return newo;
    3047                 :            : }
    3048                 :            : 
    3049                 :          0 : static void jl_recache_other(void)
    3050                 :            : {
    3051                 :          0 :     size_t i = 0;
    3052         [ #  # ]:          0 :     while (i < flagref_list.len) {
    3053                 :          0 :         jl_value_t **loc = (jl_value_t**)flagref_list.items[i + 0];
    3054                 :          0 :         int offs = (int)(intptr_t)flagref_list.items[i + 1];
    3055         [ #  # ]:          0 :         jl_value_t *o = loc ? *loc : (jl_value_t*)backref_list.items[offs];
    3056                 :          0 :         i += 2;
    3057                 :          0 :         jl_value_t *newo = jl_recache_other_(o);
    3058         [ #  # ]:          0 :         if (loc)
    3059                 :          0 :             *loc = newo;
    3060         [ #  # ]:          0 :         if (offs > 0)
    3061                 :          0 :             backref_list.items[offs] = newo;
    3062                 :            :     }
    3063                 :          0 :     flagref_list.len = 0;
    3064                 :          0 : }
    3065                 :            : 
    3066                 :            : // Wait to copy roots until recaching is done
    3067                 :            : // This is because recaching requires that all pointers to methods and methodinstances
    3068                 :            : // stay at their source location as recorded by flagref_list. Once recaching is complete,
    3069                 :            : // they can be safely copied over.
    3070                 :          0 : static void jl_copy_roots(void)
    3071                 :            : {
    3072                 :            :     size_t i, j, l;
    3073         [ #  # ]:          0 :     for (i = 0; i < queued_method_roots.size; i+=2) {
    3074                 :          0 :         jl_method_t *m = (jl_method_t*)queued_method_roots.table[i];
    3075                 :          0 :         m = (jl_method_t*)ptrhash_get(&uniquing_table, m);
    3076                 :          0 :         jl_svec_t *keyroots = (jl_svec_t*)queued_method_roots.table[i+1];
    3077         [ #  # ]:          0 :         if (keyroots != HT_NOTFOUND) {
    3078                 :          0 :             uint64_t key = (uint64_t)(uintptr_t)jl_svec_ref(keyroots, 0) | ((uint64_t)(uintptr_t)jl_svec_ref(keyroots, 1) << 32);
    3079                 :          0 :             jl_array_t *roots = (jl_array_t*)jl_svec_ref(keyroots, 2);
    3080         [ #  # ]:          0 :             assert(jl_is_array(roots));
    3081                 :          0 :             l = jl_array_len(roots);
    3082         [ #  # ]:          0 :             for (j = 0; j < l; j++) {
    3083                 :          0 :                 jl_value_t *r = jl_array_ptr_ref(roots, j);
    3084                 :          0 :                 jl_value_t *newr = (jl_value_t*)ptrhash_get(&uniquing_table, r);
    3085         [ #  # ]:          0 :                 if (newr != HT_NOTFOUND) {
    3086                 :          0 :                     jl_array_ptr_set(roots, j, newr);
    3087                 :            :                 }
    3088                 :            :             }
    3089                 :          0 :             jl_append_method_roots(m, key, roots);
    3090                 :            :         }
    3091                 :            :     }
    3092                 :          0 : }
    3093                 :            : 
    3094                 :          0 : static int trace_method(jl_typemap_entry_t *entry, void *closure)
    3095                 :            : {
    3096                 :          0 :     jl_call_tracer(jl_newmeth_tracer, (jl_value_t*)entry->func.method);
    3097                 :          0 :     return 1;
    3098                 :            : }
    3099                 :            : 
    3100                 :            : // Restore module(s) from a cache file f
    3101                 :          0 : static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array)
    3102                 :            : {
    3103                 :            :     JL_TIMING(LOAD_MODULE);
    3104                 :          0 :     jl_task_t *ct = jl_current_task;
    3105   [ #  #  #  # ]:          0 :     if (ios_eof(f) || !jl_read_verify_header(f)) {
    3106                 :          0 :         ios_close(f);
    3107                 :          0 :         return jl_get_exceptionf(jl_errorexception_type,
    3108                 :            :                 "Precompile file header verification checks failed.");
    3109                 :            :     }
    3110                 :            :     { // skip past the mod list
    3111                 :            :         size_t len;
    3112         [ #  # ]:          0 :         while ((len = read_int32(f)))
    3113                 :          0 :             ios_skip(f, len + 3 * sizeof(uint64_t));
    3114                 :            :     }
    3115                 :            :     { // skip past the dependency list
    3116                 :          0 :         size_t deplen = read_uint64(f);
    3117                 :          0 :         ios_skip(f, deplen);
    3118                 :            :     }
    3119                 :            : 
    3120         [ #  # ]:          0 :     jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
    3121         [ #  # ]:          0 :     if (jl_bigint_type) {
    3122                 :          0 :         gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
    3123                 :          0 :                                                     jl_symbol("BITS_PER_LIMB"))) / 8;
    3124                 :            :     }
    3125                 :            : 
    3126                 :            :     // verify that the system state is valid
    3127                 :          0 :     jl_value_t *verify_fail = read_verify_mod_list(f, mod_array);
    3128         [ #  # ]:          0 :     if (verify_fail) {
    3129                 :          0 :         ios_close(f);
    3130                 :          0 :         return verify_fail;
    3131                 :            :     }
    3132                 :            : 
    3133                 :            :     // prepare to deserialize
    3134                 :          0 :     int en = jl_gc_enable(0);
    3135                 :          0 :     jl_gc_enable_finalizers(ct, 0);
    3136                 :          0 :     jl_atomic_fetch_add(&jl_world_counter, 1); // reserve a world age for the deserialization
    3137                 :            : 
    3138                 :          0 :     arraylist_new(&backref_list, 4000);
    3139                 :          0 :     arraylist_push(&backref_list, jl_main_module);
    3140                 :          0 :     arraylist_new(&flagref_list, 0);
    3141                 :          0 :     htable_new(&queued_method_roots, 0);
    3142                 :          0 :     htable_new(&new_code_instance_validate, 0);
    3143                 :          0 :     arraylist_new(&ccallable_list, 0);
    3144                 :          0 :     htable_new(&uniquing_table, 0);
    3145                 :            : 
    3146                 :          0 :     jl_serializer_state s = {
    3147                 :            :         f,
    3148                 :          0 :         ct->ptls,
    3149                 :            :         mod_array
    3150                 :            :     };
    3151                 :          0 :     jl_array_t *restored = (jl_array_t*)jl_deserialize_value(&s, (jl_value_t**)&restored);
    3152                 :          0 :     serializer_worklist = restored;
    3153         [ #  # ]:          0 :     assert(jl_isa((jl_value_t*)restored, jl_array_any_type));
    3154                 :            : 
    3155                 :            :     // See explanation in jl_save_incremental for variables of the same names
    3156                 :          0 :     jl_value_t *extext_methods = jl_deserialize_value(&s, &extext_methods);
    3157                 :          0 :     int i, n_ext_mis = read_int32(s.s);
    3158                 :          0 :     jl_array_t *mi_list = jl_alloc_vec_any(n_ext_mis);   // reload MIs stored by serialize_htable_keys
    3159                 :          0 :     jl_value_t **midata = (jl_value_t**)jl_array_data(mi_list);
    3160         [ #  # ]:          0 :     for (i = 0; i < n_ext_mis; i++)
    3161                 :          0 :         midata[i] = jl_deserialize_value(&s, &(midata[i]));
    3162                 :          0 :     jl_value_t *edges = jl_deserialize_value(&s, &edges);
    3163                 :          0 :     jl_value_t *ext_targets = jl_deserialize_value(&s, &ext_targets);
    3164                 :            : 
    3165                 :          0 :     arraylist_t *tracee_list = NULL;
    3166         [ #  # ]:          0 :     if (jl_newmeth_tracer)  // debugging
    3167                 :          0 :         tracee_list = arraylist_new((arraylist_t*)malloc_s(sizeof(arraylist_t)), 0);
    3168                 :            : 
    3169                 :            :     // at this point, the AST is fully reconstructed, but still completely disconnected
    3170                 :            :     // now all of the interconnects will be created
    3171                 :          0 :     jl_recache_types(); // make all of the types identities correct
    3172                 :          0 :     jl_insert_methods((jl_array_t*)extext_methods); // hook up extension methods for external generic functions (needs to be after recache types)
    3173                 :          0 :     jl_recache_other(); // make all of the other objects identities correct (needs to be after insert methods)
    3174                 :          0 :     jl_copy_roots();    // copying new roots of external methods (must wait until recaching is complete)
    3175                 :            :     // At this point, the novel specializations in mi_list reference the real method, but they haven't been cached in its specializations
    3176                 :          0 :     jl_insert_method_instances(mi_list);   // insert novel specializations
    3177                 :          0 :     htable_free(&uniquing_table);
    3178                 :          0 :     jl_array_t *init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache)
    3179         [ #  # ]:          0 :     if (init_order == NULL)
    3180                 :          0 :         init_order = (jl_array_t*)jl_an_empty_vec_any;
    3181         [ #  # ]:          0 :     assert(jl_isa((jl_value_t*)init_order, jl_array_any_type));
    3182                 :            : 
    3183                 :          0 :     JL_GC_PUSH4(&init_order, &restored, &edges, &ext_targets);
    3184                 :          0 :     jl_gc_enable(en); // subtyping can allocate a lot, not valid before recache-other
    3185                 :            : 
    3186                 :          0 :     jl_insert_backedges((jl_array_t*)edges, (jl_array_t*)ext_targets); // restore external backedges (needs to be last)
    3187                 :            : 
    3188                 :            :     // check new CodeInstances and validate any that lack external backedges
    3189                 :          0 :     validate_new_code_instances();
    3190                 :            : 
    3191                 :          0 :     serializer_worklist = NULL;
    3192                 :          0 :     htable_free(&new_code_instance_validate);
    3193                 :          0 :     arraylist_free(&flagref_list);
    3194                 :          0 :     arraylist_free(&backref_list);
    3195                 :          0 :     htable_free(&queued_method_roots);
    3196                 :          0 :     ios_close(f);
    3197                 :            : 
    3198                 :          0 :     jl_gc_enable_finalizers(ct, 1); // make sure we don't run any Julia code concurrently before this point
    3199         [ #  # ]:          0 :     if (tracee_list) {
    3200                 :            :         jl_methtable_t *mt;
    3201         [ #  # ]:          0 :         while ((mt = (jl_methtable_t*)arraylist_pop(tracee_list)) != NULL) {
    3202                 :            :             JL_GC_PROMISE_ROOTED(mt);
    3203                 :          0 :             jl_typemap_visitor(mt->defs, trace_method, NULL);
    3204                 :            :         }
    3205                 :          0 :         arraylist_free(tracee_list);
    3206                 :          0 :         free(tracee_list);
    3207                 :            :     }
    3208         [ #  # ]:          0 :     for (int i = 0; i < ccallable_list.len; i++) {
    3209                 :          0 :         jl_svec_t *item = (jl_svec_t*)ccallable_list.items[i];
    3210                 :            :         JL_GC_PROMISE_ROOTED(item);
    3211                 :          0 :         int success = jl_compile_extern_c(NULL, NULL, NULL, jl_svecref(item, 0), jl_svecref(item, 1));
    3212         [ #  # ]:          0 :         if (!success)
    3213                 :          0 :             jl_safe_printf("@ccallable was already defined for this method name\n");
    3214                 :            :     }
    3215                 :          0 :     arraylist_free(&ccallable_list);
    3216                 :          0 :     jl_value_t *ret = (jl_value_t*)jl_svec(2, restored, init_order);
    3217                 :          0 :     JL_GC_POP();
    3218                 :            : 
    3219                 :          0 :     return (jl_value_t*)ret;
    3220                 :            : }
    3221                 :            : 
    3222                 :          0 : JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, size_t sz, jl_array_t *mod_array)
    3223                 :            : {
    3224                 :            :     ios_t f;
    3225                 :          0 :     ios_static_buffer(&f, (char*)buf, sz);
    3226                 :          0 :     return _jl_restore_incremental(&f, mod_array);
    3227                 :            : }
    3228                 :            : 
    3229                 :          0 : JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *mod_array)
    3230                 :            : {
    3231                 :            :     ios_t f;
    3232         [ #  # ]:          0 :     if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) {
    3233                 :          0 :         return jl_get_exceptionf(jl_errorexception_type,
    3234                 :            :             "Cache file \"%s\" not found.\n", fname);
    3235                 :            :     }
    3236                 :          0 :     return _jl_restore_incremental(&f, mod_array);
    3237                 :            : }
    3238                 :            : 
    3239                 :            : // --- init ---
    3240                 :            : 
    3241                 :         15 : void jl_init_serializer(void)
    3242                 :            : {
    3243                 :         15 :     jl_task_t *ct = jl_current_task;
    3244                 :         15 :     htable_new(&ser_tag, 0);
    3245                 :         15 :     htable_new(&common_symbol_tag, 0);
    3246                 :         15 :     htable_new(&backref_table, 0);
    3247                 :            : 
    3248                 :         15 :     void *vals[] = { jl_emptysvec, jl_emptytuple, jl_false, jl_true, jl_nothing, jl_any_type,
    3249                 :         15 :                      jl_call_sym, jl_invoke_sym, jl_invoke_modify_sym, jl_goto_ifnot_sym, jl_return_sym, jl_symbol("tuple"),
    3250                 :            :                      jl_an_empty_string, jl_an_empty_vec_any,
    3251                 :            : 
    3252                 :            :                      // empirical list of very common symbols
    3253                 :            :                      #include "common_symbols1.inc"
    3254                 :            : 
    3255                 :         15 :                      jl_box_int32(0), jl_box_int32(1), jl_box_int32(2),
    3256                 :         15 :                      jl_box_int32(3), jl_box_int32(4), jl_box_int32(5),
    3257                 :         15 :                      jl_box_int32(6), jl_box_int32(7), jl_box_int32(8),
    3258                 :         15 :                      jl_box_int32(9), jl_box_int32(10), jl_box_int32(11),
    3259                 :         15 :                      jl_box_int32(12), jl_box_int32(13), jl_box_int32(14),
    3260                 :         15 :                      jl_box_int32(15), jl_box_int32(16), jl_box_int32(17),
    3261                 :         15 :                      jl_box_int32(18), jl_box_int32(19), jl_box_int32(20),
    3262                 :            : 
    3263                 :         15 :                      jl_box_int64(0), jl_box_int64(1), jl_box_int64(2),
    3264                 :         15 :                      jl_box_int64(3), jl_box_int64(4), jl_box_int64(5),
    3265                 :         15 :                      jl_box_int64(6), jl_box_int64(7), jl_box_int64(8),
    3266                 :         15 :                      jl_box_int64(9), jl_box_int64(10), jl_box_int64(11),
    3267                 :         15 :                      jl_box_int64(12), jl_box_int64(13), jl_box_int64(14),
    3268                 :         15 :                      jl_box_int64(15), jl_box_int64(16), jl_box_int64(17),
    3269                 :         15 :                      jl_box_int64(18), jl_box_int64(19), jl_box_int64(20),
    3270                 :            : 
    3271                 :            :                      jl_bool_type, jl_linenumbernode_type, jl_pinode_type,
    3272                 :            :                      jl_upsilonnode_type, jl_type_type, jl_bottom_type, jl_ref_type,
    3273                 :            :                      jl_pointer_type, jl_abstractarray_type, jl_nothing_type,
    3274                 :            :                      jl_vararg_type,
    3275                 :            :                      jl_densearray_type, jl_function_type, jl_typename_type,
    3276                 :            :                      jl_builtin_type, jl_task_type, jl_uniontype_type,
    3277                 :            :                      jl_array_any_type, jl_intrinsic_type,
    3278                 :            :                      jl_abstractslot_type, jl_methtable_type, jl_typemap_level_type,
    3279                 :            :                      jl_voidpointer_type, jl_newvarnode_type, jl_abstractstring_type,
    3280                 :         15 :                      jl_array_symbol_type, jl_anytuple_type, jl_tparam0(jl_anytuple_type),
    3281                 :            :                      jl_emptytuple_type, jl_array_uint8_type, jl_code_info_type,
    3282                 :         15 :                      jl_typeofbottom_type, jl_typeofbottom_type->super,
    3283                 :            :                      jl_namedtuple_type, jl_array_int32_type,
    3284                 :            :                      jl_typedslot_type, jl_uint32_type, jl_uint64_type,
    3285                 :            :                      jl_type_type_mt, jl_nonfunction_mt,
    3286                 :            :                      jl_opaque_closure_type,
    3287                 :            : 
    3288                 :         15 :                      ct->ptls->root_task,
    3289                 :            : 
    3290                 :            :                      NULL };
    3291                 :            : 
    3292                 :            :     // more common symbols, less common than those above. will get 2-byte encodings.
    3293                 :         15 :     void *common_symbols[] = {
    3294                 :            :         #include "common_symbols2.inc"
    3295                 :            :         NULL
    3296                 :            :     };
    3297                 :            : 
    3298                 :         15 :     deser_tag[TAG_SYMBOL] = (jl_value_t*)jl_symbol_type;
    3299                 :         15 :     deser_tag[TAG_SSAVALUE] = (jl_value_t*)jl_ssavalue_type;
    3300                 :         15 :     deser_tag[TAG_DATATYPE] = (jl_value_t*)jl_datatype_type;
    3301                 :         15 :     deser_tag[TAG_SLOTNUMBER] = (jl_value_t*)jl_slotnumber_type;
    3302                 :         15 :     deser_tag[TAG_SVEC] = (jl_value_t*)jl_simplevector_type;
    3303                 :         15 :     deser_tag[TAG_ARRAY] = (jl_value_t*)jl_array_type;
    3304                 :         15 :     deser_tag[TAG_EXPR] = (jl_value_t*)jl_expr_type;
    3305                 :         15 :     deser_tag[TAG_PHINODE] = (jl_value_t*)jl_phinode_type;
    3306                 :         15 :     deser_tag[TAG_PHICNODE] = (jl_value_t*)jl_phicnode_type;
    3307                 :         15 :     deser_tag[TAG_STRING] = (jl_value_t*)jl_string_type;
    3308                 :         15 :     deser_tag[TAG_MODULE] = (jl_value_t*)jl_module_type;
    3309                 :         15 :     deser_tag[TAG_TVAR] = (jl_value_t*)jl_tvar_type;
    3310                 :         15 :     deser_tag[TAG_METHOD_INSTANCE] = (jl_value_t*)jl_method_instance_type;
    3311                 :         15 :     deser_tag[TAG_METHOD] = (jl_value_t*)jl_method_type;
    3312                 :         15 :     deser_tag[TAG_CODE_INSTANCE] = (jl_value_t*)jl_code_instance_type;
    3313                 :         15 :     deser_tag[TAG_GLOBALREF] = (jl_value_t*)jl_globalref_type;
    3314                 :         15 :     deser_tag[TAG_INT32] = (jl_value_t*)jl_int32_type;
    3315                 :         15 :     deser_tag[TAG_INT64] = (jl_value_t*)jl_int64_type;
    3316                 :         15 :     deser_tag[TAG_UINT8] = (jl_value_t*)jl_uint8_type;
    3317                 :         15 :     deser_tag[TAG_LINEINFO] = (jl_value_t*)jl_lineinfonode_type;
    3318                 :         15 :     deser_tag[TAG_UNIONALL] = (jl_value_t*)jl_unionall_type;
    3319                 :         15 :     deser_tag[TAG_GOTONODE] = (jl_value_t*)jl_gotonode_type;
    3320                 :         15 :     deser_tag[TAG_QUOTENODE] = (jl_value_t*)jl_quotenode_type;
    3321                 :         15 :     deser_tag[TAG_GOTOIFNOT] = (jl_value_t*)jl_gotoifnot_type;
    3322                 :         15 :     deser_tag[TAG_RETURNNODE] = (jl_value_t*)jl_returnnode_type;
    3323                 :         15 :     deser_tag[TAG_ARGUMENT] = (jl_value_t*)jl_argument_type;
    3324                 :            : 
    3325                 :         15 :     intptr_t i = 0;
    3326         [ +  + ]:       2970 :     while (vals[i] != NULL) {
    3327                 :       2955 :         deser_tag[LAST_TAG+1+i] = (jl_value_t*)vals[i];
    3328                 :       2955 :         i += 1;
    3329                 :            :     }
    3330         [ -  + ]:         15 :     assert(LAST_TAG+1+i < 256);
    3331                 :            : 
    3332         [ +  + ]:       3825 :     for (i = 2; i < 256; i++) {
    3333         [ +  + ]:       3810 :         if (deser_tag[i])
    3334                 :       3345 :             ptrhash_put(&ser_tag, deser_tag[i], (void*)i);
    3335                 :            :     }
    3336                 :            : 
    3337                 :         15 :     i = 2;
    3338         [ +  + ]:       3825 :     while (common_symbols[i-2] != NULL) {
    3339                 :       3810 :         ptrhash_put(&common_symbol_tag, common_symbols[i-2], (void*)i);
    3340                 :       3810 :         deser_symbols[i] = (jl_value_t*)common_symbols[i-2];
    3341                 :       3810 :         i += 1;
    3342                 :            :     }
    3343         [ -  + ]:         15 :     assert(i <= 256);
    3344                 :         15 : }
    3345                 :            : 
    3346                 :            : #ifdef __cplusplus
    3347                 :            : }
    3348                 :            : #endif

Generated by: LCOV version 1.14