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 : 11764 : static void write_uint64(ios_t *s, uint64_t i) JL_NOTSAFEPOINT
192 : : {
193 : 11764 : ios_write(s, (char*)&i, 8);
194 : 11764 : }
195 : :
196 : 167 : static void write_float64(ios_t *s, double x) JL_NOTSAFEPOINT
197 : : {
198 : 167 : write_uint64(s, *((uint64_t*)&x));
199 : 167 : }
200 : :
201 : 2011360000 : void *jl_lookup_ser_tag(jl_value_t *v)
202 : : {
203 : 2011360000 : return ptrhash_get(&ser_tag, v);
204 : : }
205 : :
206 : 144349000 : void *jl_lookup_common_symbol(jl_value_t *v)
207 : : {
208 : 144349000 : return ptrhash_get(&common_symbol_tag, v);
209 : : }
210 : :
211 : 846637000 : jl_value_t *jl_deser_tag(uint8_t tag)
212 : : {
213 : 846637000 : return deser_tag[tag];
214 : : }
215 : :
216 : 86027400 : jl_value_t *jl_deser_symbol(uint8_t tag)
217 : : {
218 : 86027400 : return deser_symbols[tag];
219 : : }
220 : :
221 : 3138 : uint64_t jl_worklist_key(jl_array_t *worklist)
222 : : {
223 [ - + ]: 3138 : assert(jl_is_array(worklist));
224 : 3138 : size_t len = jl_array_len(worklist);
225 [ + - ]: 3138 : if (len > 0) {
226 : 3138 : jl_module_t *topmod = (jl_module_t*)jl_array_ptr_ref(worklist, len-1);
227 [ - + ]: 3138 : assert(jl_is_module(topmod));
228 : 3138 : 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 : 2 : static void jl_serialize_cnull(jl_serializer_state *s, jl_value_t *t)
239 : : {
240 : 2 : backref_table_numel++;
241 : 2 : write_uint8(s->s, TAG_CNULL);
242 : 2 : jl_serialize_value(s, t);
243 : 2 : }
244 : :
245 : 7340180 : static int module_in_worklist(jl_module_t *mod) JL_NOTSAFEPOINT
246 : : {
247 : 7340180 : int i, l = jl_array_len(serializer_worklist);
248 [ + + ]: 16883000 : for (i = 0; i < l; i++) {
249 : 9553960 : jl_module_t *workmod = (jl_module_t*)jl_array_ptr_ref(serializer_worklist, i);
250 [ + - + + ]: 9553960 : if (jl_is_module(workmod) && jl_is_submodule(mod, workmod))
251 : 11107 : return 1;
252 : : }
253 : 7329080 : return 0;
254 : : }
255 : :
256 : 10456000 : static int method_instance_in_queue(jl_method_instance_t *mi)
257 : : {
258 : 10456000 : 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 : 238195 : static int type_in_worklist(jl_datatype_t *dt) JL_NOTSAFEPOINT
265 : : {
266 [ + + ]: 238195 : if (module_in_worklist(dt->name->module))
267 : 1927 : return 1;
268 : 236268 : int i, l = jl_svec_len(dt->parameters);
269 [ + + ]: 408458 : for (i = 0; i < l; i++) {
270 : 172966 : jl_value_t *p = jl_unwrap_unionall(jl_tparam(dt, i));
271 : : // TODO: what about Union and TypeVar??
272 [ + + + + ]: 172966 : if (type_in_worklist((jl_datatype_t*)(jl_is_datatype(p) ? p : jl_typeof(p))))
273 : 776 : return 1;
274 : : }
275 : 235492 : return 0;
276 : : }
277 : :
278 : : static int type_recursively_external(jl_datatype_t *dt);
279 : :
280 : 17141 : static int type_parameter_recursively_external(jl_value_t *p0) JL_NOTSAFEPOINT
281 : : {
282 [ + + ]: 17141 : if (!jl_is_concrete_type(p0))
283 : 1356 : return 0;
284 : 15785 : 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 [ + + ]: 15785 : if (module_in_worklist(p->name->module))
293 : 294 : return 0;
294 [ + + ]: 15491 : if (p->name->wrapper != (jl_value_t*)p0) {
295 [ + + ]: 3437 : if (!type_recursively_external(p))
296 : 1369 : return 0;
297 : : }
298 : 14122 : return 1;
299 : : }
300 : :
301 : : // returns true if all of the parameters are tag 6 or 7
302 : 9569 : static int type_recursively_external(jl_datatype_t *dt) JL_NOTSAFEPOINT
303 : : {
304 [ + + ]: 9569 : if (!dt->isconcretetype)
305 : 1178 : return 0;
306 [ + + ]: 8391 : if (jl_svec_len(dt->parameters) == 0)
307 : 112 : return 1;
308 : :
309 : 8279 : int i, l = jl_svec_len(dt->parameters);
310 [ + + ]: 22401 : for (i = 0; i < l; i++) {
311 [ + + ]: 17141 : if (!type_parameter_recursively_external(jl_tparam(dt, i)))
312 : 3019 : return 0;
313 : : }
314 : 5260 : 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 : 841 : static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited)
320 : : {
321 : 841 : 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 [ + + ]: 841 : if (*bp != HT_NOTFOUND)
326 : 375 : return (char*)*bp - (char*)HT_NOTFOUND - 1;
327 : 466 : *bp = (void*)((char*)HT_NOTFOUND + 1); // preliminarily mark as "not found"
328 : 466 : jl_module_t *mod = mi->def.module;
329 [ + - ]: 466 : if (jl_is_method(mod))
330 : 466 : mod = ((jl_method_t*)mod)->module;
331 [ - + ]: 466 : assert(jl_is_module(mod));
332 [ + + + + ]: 466 : if (mi->precompiled || module_in_worklist(mod)) {
333 : 16 : *bp = (void*)((char*)HT_NOTFOUND + 2); // found
334 : 16 : return 1;
335 : : }
336 [ + + ]: 450 : if (!mi->backedges) {
337 : 93 : return 0;
338 : : }
339 : 357 : size_t i, n = jl_array_len(mi->backedges);
340 [ + + ]: 656 : for (i = 0; i < n; i++) {
341 : 427 : jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, i);
342 [ + + ]: 427 : if (has_backedge_to_worklist(be, visited)) {
343 : 128 : bp = ptrhash_bp(visited, mi); // re-acquire since rehashing might change the location
344 : 128 : *bp = (void*)((char*)HT_NOTFOUND + 2); // found
345 : 128 : return 1;
346 : : }
347 : : }
348 : 229 : 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 : 81 : static size_t queue_external_mis(jl_array_t *list)
355 : : {
356 : 81 : size_t i, n = 0;
357 : : htable_t visited;
358 [ + - ]: 81 : if (list) {
359 [ - + ]: 81 : assert(jl_is_array(list));
360 : 81 : size_t n0 = jl_array_len(list);
361 : 81 : htable_new(&visited, n0);
362 [ + + ]: 696 : for (i = 0; i < n0; i++) {
363 : 615 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
364 [ - + ]: 615 : assert(jl_is_method_instance(mi));
365 [ + - ]: 615 : if (jl_is_method(mi->def.value)) {
366 : 615 : jl_method_t *m = mi->def.method;
367 [ + + ]: 615 : if (!module_in_worklist(m->module)) {
368 : 564 : jl_code_instance_t *ci = mi->cache;
369 : 564 : int relocatable = 0;
370 [ + + ]: 1129 : while (ci) {
371 : 565 : relocatable |= ci->relocatability;
372 : 565 : ci = ci->next;
373 : : }
374 [ + + + - ]: 564 : if (relocatable && ptrhash_get(&external_mis, mi) == HT_NOTFOUND) {
375 [ + + ]: 414 : if (has_backedge_to_worklist(mi, &visited)) {
376 : 125 : ptrhash_put(&external_mis, mi, mi);
377 : 125 : n++;
378 : : }
379 : : }
380 : : }
381 : : }
382 : : }
383 : 81 : htable_free(&visited);
384 : : }
385 : 81 : return n;
386 : : }
387 : :
388 : 24875 : static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_GC_DISABLED
389 : : {
390 : 24875 : int tag = 0;
391 : 24875 : int internal = module_in_worklist(dt->name->module);
392 [ + + + + ]: 24875 : if (!internal && jl_unwrap_unionall(dt->name->wrapper) == (jl_value_t*)dt) {
393 : 2090 : tag = 6; // external primary type
394 : : }
395 [ + + + + ]: 22785 : else if (jl_is_tuple_type(dt) ? !dt->isconcretetype : dt->hasfreetypevars) {
396 : 15320 : tag = 0; // normal struct
397 : : }
398 [ + + ]: 7465 : else if (internal) {
399 [ + + ]: 1333 : if (jl_unwrap_unionall(dt->name->wrapper) == (jl_value_t*)dt) // comes up often since functions create types
400 : 1287 : tag = 5; // internal, and not in the typename cache
401 : : else
402 : 46 : tag = 10; // anything else that's internal (just may need recaching)
403 : : }
404 [ + + ]: 6132 : else if (type_recursively_external(dt)) {
405 : 3304 : tag = 7; // external type that can be immediately recreated (with apply_type)
406 : : }
407 [ + + ]: 2828 : else if (type_in_worklist(dt)) {
408 : 503 : 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 : 2325 : uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, dt);
414 [ - + ]: 2325 : assert(*bp != (uintptr_t)HT_NOTFOUND);
415 : 2325 : *bp |= 1;
416 : 2325 : tag = 12;
417 : : }
418 : :
419 : 24875 : char *dtname = jl_symbol_name(dt->name->name);
420 : 24875 : size_t dtnl = strlen(dtname);
421 [ + + + + : 24875 : 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 [ - + ]: 38 : assert(tag == 6); // other struct types should never exist
424 : 38 : tag = 9;
425 [ + - + + ]: 38 : if (jl_type_type_mt->kwsorter != NULL && dt == (jl_datatype_t*)jl_typeof(jl_type_type_mt->kwsorter)) {
426 : 4 : dt = jl_datatype_type; // any representative member with this MethodTable
427 : : }
428 [ + - - + ]: 34 : 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 : 34 : jl_methtable_t *mt = dt->name->mt;
434 : 34 : size_t l = strlen(jl_symbol_name(mt->name));
435 : : char *prefixed;
436 : 34 : prefixed = (char*)malloc_s(l + 2);
437 : 34 : prefixed[0] = '#';
438 : 34 : strcpy(&prefixed[1], jl_symbol_name(mt->name));
439 : : // remove ##kw suffix
440 : 34 : prefixed[l-3] = 0;
441 : 34 : jl_sym_t *tname = jl_symbol(prefixed);
442 : 34 : free(prefixed);
443 : 34 : jl_value_t *primarydt = jl_get_global(mt->module, tname);
444 [ - + ]: 34 : if (!primarydt)
445 : 0 : primarydt = jl_get_global(mt->module, mt->name);
446 : 34 : primarydt = jl_unwrap_unionall(primarydt);
447 [ - + ]: 34 : assert(jl_is_datatype(primarydt));
448 [ + - - + ]: 34 : assert(primarydt == (jl_value_t*)jl_any_type || jl_typeof(((jl_datatype_t*)primarydt)->name->mt->kwsorter) == (jl_value_t*)dt);
449 : 34 : dt = (jl_datatype_t*)primarydt;
450 : : }
451 : : }
452 : :
453 : 24875 : write_uint8(s->s, TAG_DATATYPE);
454 : 24875 : write_uint8(s->s, tag);
455 [ + + + + ]: 24875 : if (tag == 6 || tag == 7) {
456 : : // for tag==6, copy its typevars in case there are references to them elsewhere
457 : 5356 : jl_serialize_value(s, dt->name);
458 : 5356 : jl_serialize_value(s, dt->parameters);
459 : 5356 : return;
460 : : }
461 [ + + ]: 19519 : if (tag == 9) {
462 : 38 : jl_serialize_value(s, dt);
463 : 38 : return;
464 : : }
465 : :
466 : 19481 : write_int32(s->s, dt->size);
467 : 19481 : int has_instance = (dt->instance != NULL);
468 : 19481 : int has_layout = (dt->layout != NULL);
469 : 19481 : write_uint8(s->s, has_layout | (has_instance << 1));
470 : 19481 : 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 : 19481 : write_int32(s->s, dt->hash);
478 : :
479 [ + + ]: 19481 : if (has_layout) {
480 : 3717 : uint8_t layout = 0;
481 [ + + ]: 3717 : if (dt->layout == ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type))->layout) {
482 : 122 : layout = 1;
483 : : }
484 [ - + ]: 3595 : else if (dt->layout == jl_nothing_type->layout) {
485 : 0 : layout = 2;
486 : : }
487 [ + + ]: 3595 : else if (dt->layout == ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->layout) {
488 : 58 : layout = 3;
489 : : }
490 : 3717 : write_uint8(s->s, layout);
491 [ + + ]: 3717 : if (layout == 0) {
492 : 3537 : uint32_t nf = dt->layout->nfields;
493 : 3537 : uint32_t np = dt->layout->npointers;
494 : 3537 : size_t fieldsize = jl_fielddesc_size(dt->layout->fielddesc_type);
495 : 3537 : ios_write(s->s, (const char*)dt->layout, sizeof(*dt->layout));
496 : 3537 : size_t fldsize = nf * fieldsize;
497 [ + + ]: 3537 : if (dt->layout->first_ptr != -1)
498 : 1415 : fldsize += np << dt->layout->fielddesc_type;
499 : 3537 : ios_write(s->s, (const char*)(dt->layout + 1), fldsize);
500 : : }
501 : : }
502 : :
503 [ + + ]: 19481 : if (has_instance)
504 : 1511 : jl_serialize_value(s, dt->instance);
505 : 19481 : jl_serialize_value(s, dt->name);
506 : 19481 : jl_serialize_value(s, dt->parameters);
507 : 19481 : jl_serialize_value(s, dt->super);
508 : 19481 : jl_serialize_value(s, dt->types);
509 : : }
510 : :
511 : 217 : static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m)
512 : : {
513 : 217 : write_uint8(s->s, TAG_MODULE);
514 : 217 : jl_serialize_value(s, m->name);
515 : : size_t i;
516 [ + + ]: 217 : if (!module_in_worklist(m)) {
517 [ + + ]: 125 : if (m == m->parent) {
518 : : // top-level module
519 : 66 : write_int8(s->s, 2);
520 : 66 : int j = 0;
521 [ + - ]: 2076 : for (i = 0; i < jl_array_len(s->loaded_modules_array); i++) {
522 : 2076 : jl_module_t *mi = (jl_module_t*)jl_array_ptr_ref(s->loaded_modules_array, i);
523 [ + + ]: 2076 : if (!module_in_worklist(mi)) {
524 [ + + ]: 2042 : if (m == mi) {
525 : 66 : write_int32(s->s, j);
526 : 66 : return;
527 : : }
528 : 1976 : j++;
529 : : }
530 : : }
531 : 0 : assert(0 && "top level module not found in modules array");
532 : : }
533 : : else {
534 : 59 : write_int8(s->s, 1);
535 : 59 : jl_serialize_value(s, m->parent);
536 : : }
537 : 59 : return;
538 : : }
539 : 92 : write_int8(s->s, 0);
540 : 92 : jl_serialize_value(s, m->parent);
541 : 92 : void **table = m->bindings.table;
542 [ + + ]: 11580 : for (i = 0; i < m->bindings.size; i += 2) {
543 [ + + ]: 11488 : if (table[i+1] != HT_NOTFOUND) {
544 : 4208 : jl_serialize_value(s, (jl_value_t*)table[i]);
545 : 4208 : jl_binding_t *b = (jl_binding_t*)table[i+1];
546 : 4208 : jl_serialize_value(s, b->name);
547 : 4208 : jl_value_t *e = jl_atomic_load_relaxed(&b->value);
548 [ + + + + : 4208 : 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 : 1 : jl_serialize_cnull(s, jl_typeof(e));
551 : : else
552 : 4207 : jl_serialize_value(s, e);
553 : 4208 : jl_serialize_value(s, jl_atomic_load_relaxed(&b->globalref));
554 : 4208 : jl_serialize_value(s, b->owner);
555 : 4208 : jl_serialize_value(s, jl_atomic_load_relaxed(&b->ty));
556 : 4208 : write_int8(s->s, (b->deprecated<<3) | (b->constp<<2) | (b->exportp<<1) | (b->imported));
557 : : }
558 : : }
559 : 92 : jl_serialize_value(s, NULL);
560 : 92 : write_int32(s->s, m->usings.len);
561 [ + + ]: 332 : for(i=0; i < m->usings.len; i++) {
562 : 240 : jl_serialize_value(s, (jl_value_t*)m->usings.items[i]);
563 : : }
564 : 92 : write_uint8(s->s, m->istopmod);
565 : 92 : write_uint64(s->s, m->uuid.hi);
566 : 92 : write_uint64(s->s, m->uuid.lo);
567 : 92 : write_uint64(s->s, m->build_id);
568 : 92 : write_int32(s->s, m->counter);
569 : 92 : write_int32(s->s, m->nospecialize);
570 : 92 : write_uint8(s->s, m->optlevel);
571 : 92 : write_uint8(s->s, m->compile);
572 : 92 : write_uint8(s->s, m->infer);
573 : 92 : write_uint8(s->s, m->max_methods);
574 : : }
575 : :
576 : 395715 : static int jl_serialize_generic(jl_serializer_state *s, jl_value_t *v) JL_GC_DISABLED
577 : : {
578 [ + + ]: 395715 : if (v == NULL) {
579 : 36757 : write_uint8(s->s, TAG_NULL);
580 : 36757 : return 1;
581 : : }
582 : :
583 : 358958 : void *tag = ptrhash_get(&ser_tag, v);
584 [ + + ]: 358958 : if (tag != HT_NOTFOUND) {
585 : 110267 : uint8_t t8 = (intptr_t)tag;
586 [ + + ]: 110267 : if (t8 <= LAST_TAG)
587 : 9124 : write_uint8(s->s, 0);
588 : 110267 : write_uint8(s->s, t8);
589 : 110267 : return 1;
590 : : }
591 : :
592 [ + + ]: 248691 : if (jl_is_symbol(v)) {
593 : 36365 : void *idx = ptrhash_get(&common_symbol_tag, v);
594 [ + + ]: 36365 : if (idx != HT_NOTFOUND) {
595 : 1581 : write_uint8(s->s, TAG_COMMONSYM);
596 : 1581 : write_uint8(s->s, (uint8_t)(size_t)idx);
597 : 1581 : return 1;
598 : : }
599 : : }
600 [ + + ]: 212326 : else if (v == (jl_value_t*)jl_core_module) {
601 : 1468 : write_uint8(s->s, TAG_CORE);
602 : 1468 : return 1;
603 : : }
604 [ + + ]: 210858 : else if (v == (jl_value_t*)jl_base_module) {
605 : 4765 : write_uint8(s->s, TAG_BASE);
606 : 4765 : return 1;
607 : : }
608 : :
609 [ + + - + ]: 240877 : 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 [ + - ]: 240877 : else if (!jl_is_uint8(v)) {
614 : 240877 : void **bp = ptrhash_bp(&backref_table, v);
615 [ + + ]: 240877 : if (*bp != HT_NOTFOUND) {
616 : 129459 : uintptr_t pos = (char*)*bp - (char*)HT_NOTFOUND - 1;
617 [ + + ]: 129459 : if (pos < 65536) {
618 : 107922 : write_uint8(s->s, TAG_SHORT_BACKREF);
619 : 107922 : write_uint16(s->s, pos);
620 : : }
621 : : else {
622 : 21537 : write_uint8(s->s, TAG_BACKREF);
623 : 21537 : write_int32(s->s, pos);
624 : : }
625 : 129459 : return 1;
626 : : }
627 : 111418 : intptr_t pos = backref_table_numel++;
628 [ + + ]: 111418 : if (((jl_datatype_t*)(jl_typeof(v)))->name == jl_idtable_typename) {
629 : : // will need to rehash this, later (after types are fully constructed)
630 : 100 : arraylist_push(&reinit_list, (void*)pos);
631 : 100 : arraylist_push(&reinit_list, (void*)1);
632 : : }
633 [ + + ]: 111418 : if (jl_is_module(v)) {
634 : 217 : jl_module_t *m = (jl_module_t*)v;
635 [ + + - + ]: 217 : 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 [ + + ]: 111418 : if (jl_is_mtable(v)) {
643 : 1311 : arraylist_push(&reinit_list, (void*)pos);
644 : 1311 : arraylist_push(&reinit_list, (void*)3);
645 : : }
646 : 111418 : pos <<= 1;
647 : 111418 : ptrhash_put(&backref_table, v, (char*)HT_NOTFOUND + pos + 1);
648 : : }
649 : :
650 : 111418 : return 0;
651 : : }
652 : :
653 : 384 : 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 [ + + ]: 384 : if (internal > 2) {
656 [ + + - + ]: 251 : while (codeinst && !codeinst->relocatability)
657 : 0 : codeinst = codeinst->next;
658 : : }
659 [ + + ]: 384 : if (jl_serialize_generic(s, (jl_value_t*)codeinst)) {
660 : 194 : return;
661 : : }
662 [ - + ]: 190 : assert(codeinst != NULL); // handle by jl_serialize_generic, but this makes clang-sa happy
663 : :
664 : 190 : int validate = 0;
665 [ + + ]: 190 : if (codeinst->max_world == ~(size_t)0)
666 : 189 : validate = 1; // can check on deserialize if this cache entry is still valid
667 : 190 : int flags = validate << 0;
668 [ + + ]: 190 : if (codeinst->invoke == jl_fptr_const_return)
669 : 7 : flags |= 1 << 2;
670 [ + + ]: 190 : if (codeinst->precompile)
671 : 42 : 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 [ + + - + ]: 190 : int write_ret_type = validate || codeinst->min_world == 0;
677 [ + + + + ]: 190 : if (write_ret_type && codeinst->rettype_const &&
678 [ - + ]: 23 : 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 : 190 : write_uint8(s->s, TAG_CODE_INSTANCE);
689 : 190 : write_uint8(s->s, flags);
690 : 190 : write_uint32(s->s, codeinst->ipo_purity_bits);
691 : 190 : write_uint32(s->s, codeinst->purity_bits);
692 : 190 : jl_serialize_value(s, (jl_value_t*)codeinst->def);
693 [ + + ]: 190 : if (write_ret_type) {
694 : 189 : jl_serialize_value(s, codeinst->inferred);
695 : 189 : jl_serialize_value(s, codeinst->rettype_const);
696 : 189 : jl_serialize_value(s, codeinst->rettype);
697 : 189 : jl_serialize_value(s, codeinst->argescapes);
698 : : }
699 : : else {
700 : : // skip storing useless data
701 : 1 : jl_serialize_value(s, NULL);
702 : 1 : jl_serialize_value(s, NULL);
703 : 1 : jl_serialize_value(s, jl_any_type);
704 : 1 : jl_serialize_value(s, jl_nothing);
705 : : }
706 : 190 : write_uint8(s->s, codeinst->relocatability);
707 : 190 : 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 : 395331 : static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED
717 : : {
718 [ + + ]: 395331 : if (jl_serialize_generic(s, v)) {
719 : 284103 : return;
720 : : }
721 : :
722 : : size_t i;
723 [ + + ]: 111228 : if (jl_is_svec(v)) {
724 : 21960 : size_t l = jl_svec_len(v);
725 [ + - ]: 21960 : if (l <= 255) {
726 : 21960 : write_uint8(s->s, TAG_SVEC);
727 : 21960 : 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 [ + + ]: 78599 : for (i = 0; i < l; i++) {
734 : 56639 : jl_serialize_value(s, jl_svecref(v, i));
735 : : }
736 : : }
737 [ + + ]: 89268 : else if (jl_is_symbol(v)) {
738 : 7058 : size_t l = strlen(jl_symbol_name((jl_sym_t*)v));
739 [ + - ]: 7058 : if (l <= 255) {
740 : 7058 : write_uint8(s->s, TAG_SYMBOL);
741 : 7058 : 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 : 7058 : ios_write(s->s, jl_symbol_name((jl_sym_t*)v), l);
748 : : }
749 [ + + ]: 82210 : else if (jl_is_array(v)) {
750 : 16339 : jl_array_t *ar = (jl_array_t*)v;
751 : 16339 : jl_value_t *et = jl_tparam0(jl_typeof(ar));
752 : 16339 : int isunion = jl_is_uniontype(et);
753 [ + - + - ]: 16339 : if (ar->flags.ndims == 1 && ar->elsize <= 0x1f) {
754 : 16339 : write_uint8(s->s, TAG_ARRAY1D);
755 : 16339 : 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 [ + + ]: 32678 : for (i = 0; i < ar->flags.ndims; i++)
763 : 16339 : jl_serialize_value(s, jl_box_long(jl_array_dim(ar,i)));
764 : 16339 : jl_serialize_value(s, jl_typeof(ar));
765 : 16339 : size_t l = jl_array_len(ar);
766 [ + + ]: 16339 : if (ar->flags.ptrarray) {
767 [ + + ]: 55080 : for (i = 0; i < l; i++) {
768 : 44749 : jl_value_t *e = jl_array_ptr_ref(v, i);
769 [ + + + + : 44749 : 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 : 1 : jl_serialize_cnull(s, jl_typeof(e));
772 : : else
773 : 44748 : jl_serialize_value(s, e);
774 : : }
775 : : }
776 [ + + ]: 6008 : else if (ar->flags.hasptr) {
777 : 1 : const char *data = (const char*)jl_array_data(ar);
778 : 1 : uint16_t elsz = ar->elsize;
779 : 1 : size_t j, np = ((jl_datatype_t*)et)->layout->npointers;
780 [ + + ]: 6 : for (i = 0; i < l; i++) {
781 : 5 : const char *start = data;
782 [ + + ]: 10 : for (j = 0; j < np; j++) {
783 : 5 : uint32_t ptr = jl_ptr_offset((jl_datatype_t*)et, j);
784 : 5 : const jl_value_t *const *fld = &((const jl_value_t *const *)data)[ptr];
785 [ - + ]: 5 : if ((const char*)fld != start)
786 : 0 : ios_write(s->s, start, (const char*)fld - start);
787 : : JL_GC_PROMISE_ROOTED(*fld);
788 : 5 : jl_serialize_value(s, *fld);
789 : 5 : start = (const char*)&fld[1];
790 : : }
791 : 5 : data += elsz;
792 [ + - ]: 5 : if (data != start)
793 : 5 : ios_write(s->s, start, data - start);
794 : : }
795 : : }
796 [ + + ]: 6007 : else if (jl_is_cpointer_type(et)) {
797 : : // reset Ptr elements to C_NULL
798 : 1 : const void **data = (const void**)jl_array_data(ar);
799 [ + + ]: 4 : for (i = 0; i < l; i++) {
800 : 3 : const void *e = data[i];
801 [ + + ]: 3 : if (e != (void*)-1)
802 : 2 : e = NULL;
803 : 3 : ios_write(s->s, (const char*)&e, sizeof(e));
804 : : }
805 : : }
806 : : else {
807 : 6006 : ios_write(s->s, (char*)jl_array_data(ar), l * ar->elsize);
808 [ + - + + ]: 6006 : if (jl_array_isbitsunion(ar))
809 : 1 : ios_write(s->s, jl_array_typetagdata(ar), l);
810 : : }
811 : : }
812 [ + + ]: 65871 : else if (jl_is_datatype(v)) {
813 : 24875 : jl_serialize_datatype(s, (jl_datatype_t*)v);
814 : : }
815 [ + + ]: 40996 : else if (jl_is_unionall(v)) {
816 : 4775 : write_uint8(s->s, TAG_UNIONALL);
817 : 4775 : jl_datatype_t *d = (jl_datatype_t*)jl_unwrap_unionall(v);
818 [ + + + + : 4985 : if (jl_is_datatype(d) && d->name->wrapper == v &&
+ + ]
819 : 210 : !module_in_worklist(d->name->module)) {
820 : 143 : write_uint8(s->s, 1);
821 : 143 : jl_serialize_value(s, d->name->module);
822 : 143 : jl_serialize_value(s, d->name->name);
823 : : }
824 : : else {
825 : 4632 : write_uint8(s->s, 0);
826 : 4632 : jl_serialize_value(s, ((jl_unionall_t*)v)->var);
827 : 4632 : jl_serialize_value(s, ((jl_unionall_t*)v)->body);
828 : : }
829 : : }
830 [ + + ]: 36221 : else if (jl_is_typevar(v)) {
831 : 3399 : write_uint8(s->s, TAG_TVAR);
832 : 3399 : jl_serialize_value(s, ((jl_tvar_t*)v)->name);
833 : 3399 : jl_serialize_value(s, ((jl_tvar_t*)v)->lb);
834 : 3399 : jl_serialize_value(s, ((jl_tvar_t*)v)->ub);
835 : : }
836 [ + + ]: 32822 : else if (jl_is_method(v)) {
837 : 5899 : write_uint8(s->s, TAG_METHOD);
838 : 5899 : jl_method_t *m = (jl_method_t*)v;
839 : 5899 : uint64_t key = 0;
840 : 5899 : int serialization_mode = 0, nwithkey = 0;
841 [ + + + + ]: 5899 : if (m->is_for_opaque_closure || module_in_worklist(m->module))
842 : 2761 : serialization_mode |= METHOD_INTERNAL;
843 [ + + ]: 5899 : if (!(serialization_mode & METHOD_INTERNAL)) {
844 : 3138 : key = jl_worklist_key(serializer_worklist);
845 : 3138 : nwithkey = nroots_with_key(m, key);
846 [ + + ]: 3138 : if (nwithkey > 0)
847 : 81 : serialization_mode |= METHOD_HAS_NEW_ROOTS;
848 : : }
849 [ + + ]: 5899 : if (!(serialization_mode & METHOD_INTERNAL)) {
850 : : // flag this in the backref table as special
851 : 3138 : uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v);
852 [ - + ]: 3138 : assert(*bp != (uintptr_t)HT_NOTFOUND);
853 : 3138 : *bp |= 1;
854 : : }
855 : 5899 : jl_serialize_value(s, (jl_value_t*)m->sig);
856 : 5899 : jl_serialize_value(s, (jl_value_t*)m->module);
857 [ + + ]: 5899 : if (m->external_mt != NULL) {
858 [ - + ]: 2 : assert(jl_typeis(m->external_mt, jl_methtable_type));
859 : 2 : jl_methtable_t *mt = (jl_methtable_t*)m->external_mt;
860 [ + + ]: 2 : if (!module_in_worklist(mt->module)) {
861 : 1 : serialization_mode |= METHOD_EXTERNAL_MT;
862 : : }
863 : : }
864 : 5899 : write_uint8(s->s, serialization_mode);
865 [ + + ]: 5899 : if (serialization_mode & METHOD_EXTERNAL_MT) {
866 : : // We reference this method table by module and binding
867 : 1 : jl_methtable_t *mt = (jl_methtable_t*)m->external_mt;
868 : 1 : jl_serialize_value(s, mt->module);
869 : 1 : jl_serialize_value(s, mt->name);
870 : : }
871 : : else {
872 : 5898 : jl_serialize_value(s, (jl_value_t*)m->external_mt);
873 : : }
874 [ + + ]: 5899 : if (!(serialization_mode & METHOD_INTERNAL)) {
875 [ + + ]: 3138 : if (serialization_mode & METHOD_HAS_NEW_ROOTS) {
876 : : // Serialize the roots that belong to key
877 : 81 : write_uint64(s->s, key);
878 : 81 : write_int32(s->s, nwithkey);
879 : 81 : rle_iter_state rootiter = rle_iter_init(0);
880 : 81 : uint64_t *rletable = NULL;
881 : 81 : size_t nblocks2 = 0, nroots = jl_array_len(m->roots);
882 [ + - ]: 81 : if (m->root_blocks) {
883 : 81 : rletable = (uint64_t*)jl_array_data(m->root_blocks);
884 : 81 : nblocks2 = jl_array_len(m->root_blocks);
885 : : }
886 : : // this visits every item, if it becomes a bottlneck we could hop blocks
887 [ + + ]: 16031 : while (rle_iter_increment(&rootiter, nroots, rletable, nblocks2))
888 [ + + ]: 15950 : if (rootiter.key == key)
889 : 377 : jl_serialize_value(s, jl_array_ptr_ref(m->roots, rootiter.i));
890 : : }
891 : 3138 : return;
892 : : }
893 : 2761 : jl_serialize_value(s, m->specializations);
894 : 2761 : jl_serialize_value(s, jl_atomic_load_relaxed(&m->speckeyset));
895 : 2761 : jl_serialize_value(s, (jl_value_t*)m->name);
896 : 2761 : jl_serialize_value(s, (jl_value_t*)m->file);
897 : 2761 : write_int32(s->s, m->line);
898 : 2761 : write_int32(s->s, m->called);
899 : 2761 : write_int32(s->s, m->nargs);
900 : 2761 : write_int32(s->s, m->nospecialize);
901 : 2761 : write_int32(s->s, m->nkw);
902 : 2761 : write_int8(s->s, m->isva);
903 : 2761 : write_int8(s->s, m->pure);
904 : 2761 : write_int8(s->s, m->is_for_opaque_closure);
905 : 2761 : write_int8(s->s, m->constprop);
906 : 2761 : write_uint8(s->s, m->purity.bits);
907 : 2761 : jl_serialize_value(s, (jl_value_t*)m->slot_syms);
908 : 2761 : jl_serialize_value(s, (jl_value_t*)m->roots);
909 : 2761 : jl_serialize_value(s, (jl_value_t*)m->root_blocks);
910 : 2761 : write_int32(s->s, m->nroots_sysimg);
911 : 2761 : jl_serialize_value(s, (jl_value_t*)m->ccallable);
912 : 2761 : jl_serialize_value(s, (jl_value_t*)m->source);
913 : 2761 : jl_serialize_value(s, (jl_value_t*)m->unspecialized);
914 : 2761 : jl_serialize_value(s, (jl_value_t*)m->generator);
915 : 2761 : jl_serialize_value(s, (jl_value_t*)m->invokes);
916 : 2761 : jl_serialize_value(s, (jl_value_t*)m->recursion_relation);
917 : : }
918 [ + + ]: 26923 : else if (jl_is_method_instance(v)) {
919 : 6588 : jl_method_instance_t *mi = (jl_method_instance_t*)v;
920 [ + - - + ]: 6588 : 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 : 6588 : write_uint8(s->s, TAG_METHOD_INSTANCE);
924 : 6588 : int internal = 0;
925 [ - + ]: 6588 : if (!jl_is_method(mi->def.method))
926 : 0 : internal = 1;
927 [ + + ]: 6588 : else if (module_in_worklist(mi->def.method->module))
928 : 69 : internal = 2;
929 [ + + ]: 6519 : else if (ptrhash_get(&external_mis, (void*)mi) != HT_NOTFOUND)
930 : 125 : internal = 3;
931 : 6588 : write_uint8(s->s, internal);
932 [ + + ]: 6588 : if (!internal) {
933 : : // also flag this in the backref table as special
934 : 6394 : uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v);
935 [ - + ]: 6394 : assert(*bp != (uintptr_t)HT_NOTFOUND);
936 : 6394 : *bp |= 1;
937 : : }
938 [ - + ]: 6588 : if (internal == 1)
939 : 0 : jl_serialize_value(s, (jl_value_t*)mi->uninferred);
940 : 6588 : jl_serialize_value(s, (jl_value_t*)mi->specTypes);
941 : 6588 : jl_serialize_value(s, mi->def.value);
942 [ + + ]: 6588 : if (!internal)
943 : 6394 : return;
944 : 194 : jl_serialize_value(s, (jl_value_t*)mi->sparam_vals);
945 : 194 : jl_array_t *backedges = mi->backedges;
946 [ + + ]: 194 : if (backedges) {
947 : : // filter backedges to only contain pointers
948 : : // to items that we will actually store (internal >= 2)
949 : 147 : size_t ins, i, l = jl_array_len(backedges);
950 : 147 : jl_method_instance_t **b_edges = (jl_method_instance_t**)jl_array_data(backedges);
951 [ + + ]: 358 : for (ins = i = 0; i < l; i++) {
952 : 211 : jl_method_instance_t *backedge = b_edges[i];
953 [ + + + + ]: 211 : if (module_in_worklist(backedge->def.method->module) || method_instance_in_queue(backedge)) {
954 : 183 : b_edges[ins++] = backedge;
955 : : }
956 : : }
957 [ + + ]: 147 : if (ins != l)
958 : 12 : jl_array_del_end(backedges, l - ins);
959 [ + + ]: 147 : if (ins == 0)
960 : 4 : backedges = NULL;
961 : : }
962 : 194 : jl_serialize_value(s, (jl_value_t*)backedges);
963 : 194 : jl_serialize_value(s, (jl_value_t*)NULL); //callbacks
964 : 194 : jl_serialize_code_instance(s, mi->cache, 1, internal);
965 : : }
966 [ - + ]: 20335 : else if (jl_is_code_instance(v)) {
967 : 0 : jl_serialize_code_instance(s, (jl_code_instance_t*)v, 0, 2);
968 : : }
969 [ + + ]: 20335 : else if (jl_typeis(v, jl_module_type)) {
970 : 217 : jl_serialize_module(s, (jl_module_t*)v);
971 : : }
972 [ - + ]: 20118 : else if (jl_typeis(v, jl_task_type)) {
973 : 0 : jl_error("Task cannot be serialized");
974 : : }
975 [ - + ]: 20118 : else if (jl_typeis(v, jl_opaque_closure_type)) {
976 : 0 : jl_error("Live opaque closures cannot be serialized");
977 : : }
978 [ + + ]: 20118 : else if (jl_typeis(v, jl_string_type)) {
979 : 3483 : write_uint8(s->s, TAG_STRING);
980 : 3483 : write_int32(s->s, jl_string_len(v));
981 : 3483 : ios_write(s->s, jl_string_data(v), jl_string_len(v));
982 : : }
983 [ + + ]: 16635 : else if (jl_typeis(v, jl_int64_type)) {
984 : 1602 : void *data = jl_data_ptr(v);
985 [ + - + + ]: 1602 : if (*(int64_t*)data >= INT16_MIN && *(int64_t*)data <= INT16_MAX) {
986 : 1597 : write_uint8(s->s, TAG_SHORTER_INT64);
987 : 1597 : write_uint16(s->s, (uint16_t)*(int64_t*)data);
988 : : }
989 [ + - - + ]: 5 : 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 : 5 : write_uint8(s->s, TAG_INT64);
995 : 5 : write_int64(s->s, *(int64_t*)data);
996 : : }
997 : : }
998 [ - + ]: 15033 : 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 [ - + ]: 15033 : 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 [ + + + + ]: 15033 : else if (jl_is_cpointer(v) && jl_unbox_voidpointer(v) == NULL) {
1014 : 17 : write_uint8(s->s, TAG_CNULL);
1015 : 17 : jl_serialize_value(s, jl_typeof(v));
1016 : 17 : return;
1017 : : }
1018 [ + - + + ]: 15018 : else if (jl_bigint_type && jl_typeis(v, jl_bigint_type)) {
1019 : 2 : write_uint8(s->s, TAG_SHORT_GENERAL);
1020 : 2 : write_uint8(s->s, jl_datatype_size(jl_bigint_type));
1021 : 2 : jl_serialize_value(s, jl_bigint_type);
1022 : 2 : jl_value_t *sizefield = jl_get_nth_field(v, 1);
1023 : 2 : jl_serialize_value(s, sizefield);
1024 : 2 : void *data = jl_unbox_voidpointer(jl_get_nth_field(v, 2));
1025 : 2 : int32_t sz = jl_unbox_int32(sizefield);
1026 [ + - ]: 2 : size_t nb = (sz == 0 ? 1 : (sz < 0 ? -sz : sz)) * gmp_limb_size;
1027 : 2 : ios_write(s->s, (char*)data, nb);
1028 : : }
1029 : : else {
1030 : 15014 : jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v);
1031 [ + + ]: 15014 : if (v == t->instance) {
1032 [ + + ]: 1519 : 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 : 95 : uintptr_t *bp = (uintptr_t*)ptrhash_bp(&backref_table, v);
1036 [ - + ]: 95 : assert(*bp != (uintptr_t)HT_NOTFOUND);
1037 : 95 : *bp |= 1;
1038 : : }
1039 : 1519 : write_uint8(s->s, TAG_SINGLETON);
1040 : 1519 : jl_serialize_value(s, t);
1041 : 1519 : return;
1042 : : }
1043 [ - + ]: 13495 : assert(!t->instance && "detected singleton construction corruption");
1044 : :
1045 [ + + ]: 13495 : if (t == jl_typename_type) {
1046 : 3991 : void *bttag = ptrhash_get(&ser_tag, ((jl_typename_t*)t)->wrapper);
1047 [ - + ]: 3991 : 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 [ + - ]: 13495 : if (t->size <= 255) {
1054 : 13495 : write_uint8(s->s, TAG_SHORT_GENERAL);
1055 : 13495 : 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 : 13495 : jl_serialize_value(s, t);
1062 [ + + ]: 13495 : if (t == jl_typename_type) {
1063 : 3991 : jl_typename_t *tn = (jl_typename_t*)v;
1064 : 3991 : int internal = module_in_worklist(tn->module);
1065 : 3991 : write_uint8(s->s, internal);
1066 : 3991 : jl_serialize_value(s, tn->module);
1067 : 3991 : jl_serialize_value(s, tn->name);
1068 [ + + ]: 3991 : if (internal) {
1069 : 1354 : jl_serialize_value(s, tn->names);
1070 : 1354 : jl_serialize_value(s, tn->wrapper);
1071 : 1354 : jl_serialize_value(s, tn->mt);
1072 : 1354 : ios_write(s->s, (char*)&tn->hash, sizeof(tn->hash));
1073 : 1354 : write_uint8(s->s, tn->abstract | (tn->mutabl << 1) | (tn->mayinlinealloc << 2));
1074 : 1354 : write_uint8(s->s, tn->max_methods);
1075 [ + + ]: 1354 : if (!tn->abstract)
1076 : 1349 : write_uint16(s->s, tn->n_uninitialized);
1077 [ - + ]: 1354 : size_t nb = tn->atomicfields ? (jl_svec_len(tn->names) + 31) / 32 * sizeof(uint32_t) : 0;
1078 : 1354 : write_int32(s->s, nb);
1079 [ - + ]: 1354 : if (nb)
1080 : 0 : ios_write(s->s, (char*)tn->atomicfields, nb);
1081 [ - + ]: 1354 : nb = tn->constfields ? (jl_svec_len(tn->names) + 31) / 32 * sizeof(uint32_t) : 0;
1082 : 1354 : write_int32(s->s, nb);
1083 [ - + ]: 1354 : if (nb)
1084 : 0 : ios_write(s->s, (char*)tn->constfields, nb);
1085 : : }
1086 : 3991 : return;
1087 : : }
1088 : :
1089 [ - + ]: 9504 : if (jl_is_foreign_type(t)) {
1090 : 0 : jl_error("Cannot serialize instances of foreign datatypes");
1091 : : }
1092 : :
1093 : 9504 : char *data = (char*)jl_data_ptr(v);
1094 : 9504 : size_t i, j, np = t->layout->npointers;
1095 : 9504 : uint32_t nf = t->layout->nfields;
1096 : 9504 : char *last = data;
1097 [ + - ]: 55846 : for (i = 0, j = 0; i < nf+1; i++) {
1098 [ + + ]: 55846 : char *ptr = data + (i < nf ? jl_field_offset(t, i) : jl_datatype_size(t));
1099 [ + + ]: 55846 : if (j < np) {
1100 : 43725 : char *prevptr = (char*)&((jl_value_t**)data)[jl_ptr_offset(t, j)];
1101 [ + + ]: 63484 : while (ptr > prevptr) {
1102 : : // previous field contained pointers; write them and their interleaved data
1103 [ + + ]: 29095 : if (prevptr > last)
1104 : 3315 : ios_write(s->s, last, prevptr - last);
1105 : 29095 : jl_value_t *e = *(jl_value_t**)prevptr;
1106 : : JL_GC_PROMISE_ROOTED(e);
1107 [ + + + + : 29095 : 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 : 29095 : jl_serialize_value(s, e);
1113 : 29095 : last = prevptr + sizeof(jl_value_t*);
1114 : 29095 : j++;
1115 [ + + ]: 29095 : if (j < np)
1116 : 19759 : prevptr = (char*)&((jl_value_t**)data)[jl_ptr_offset(t, j)];
1117 : : else
1118 : 9336 : break;
1119 : : }
1120 : : }
1121 [ + + ]: 55846 : if (i == nf)
1122 : 9504 : break;
1123 [ + + + + : 46342 : if (t->name->mutabl && jl_is_cpointer_type(jl_field_type(t, i)) && *(void**)ptr != (void*)-1) {
+ - ]
1124 [ + - ]: 5 : if (ptr > last)
1125 : 5 : ios_write(s->s, last, ptr - last);
1126 : 5 : char *n = NULL;
1127 : 5 : ios_write(s->s, (char*)&n, sizeof(n));
1128 : 5 : last = ptr + sizeof(n);
1129 : : }
1130 : : }
1131 : 9504 : char *ptr = data + jl_datatype_size(t);
1132 [ + + ]: 9504 : if (ptr > last)
1133 : 3660 : 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 : 81 : static void serialize_htable_keys(jl_serializer_state *s, htable_t *ht, int nitems)
1139 : : {
1140 : 81 : write_int32(s->s, nitems);
1141 : 81 : void **table = ht->table;
1142 : 81 : size_t i, n = 0, sz = ht->size;
1143 : : (void)n;
1144 [ + + ]: 2577 : for (i = 0; i < sz; i += 2) {
1145 [ + + ]: 2496 : if (table[i+1] != HT_NOTFOUND) {
1146 : 125 : jl_serialize_value(s, (jl_value_t*)table[i]);
1147 : 125 : n += 1;
1148 : : }
1149 : : }
1150 [ - + ]: 81 : assert(n == nitems);
1151 : 81 : }
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 : 901737 : static void jl_collect_missing_backedges_to_mod(jl_methtable_t *mt)
1160 : : {
1161 : 901737 : jl_array_t *backedges = mt->backedges;
1162 [ + + ]: 901737 : if (backedges) {
1163 : 28906 : size_t i, l = jl_array_len(backedges);
1164 [ + + ]: 244694 : for (i = 1; i < l; i += 2) {
1165 : 215788 : jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i);
1166 : 215788 : jl_value_t *missing_callee = jl_array_ptr_ref(backedges, i - 1); // signature of abstract callee
1167 : 215788 : jl_array_t **edges = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller);
1168 [ + + ]: 215788 : if (*edges == HT_NOTFOUND)
1169 : 20009 : *edges = jl_alloc_vec_any(0);
1170 : 215788 : jl_array_ptr_1d_push(*edges, missing_callee);
1171 : : }
1172 : : }
1173 : 901737 : }
1174 : :
1175 : : // from MethodInstances
1176 : 5918550 : static void collect_backedges(jl_method_instance_t *callee) JL_GC_DISABLED
1177 : : {
1178 : 5918550 : jl_array_t *backedges = callee->backedges;
1179 [ + + ]: 5918550 : if (backedges) {
1180 : 5310520 : size_t i, l = jl_array_len(backedges);
1181 [ + + ]: 24668100 : for (i = 0; i < l; i++) {
1182 : 19357600 : jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i);
1183 : 19357600 : jl_array_t **edges = (jl_array_t**)ptrhash_bp(&edges_map, caller);
1184 [ + + ]: 19357600 : if (*edges == HT_NOTFOUND)
1185 : 4518930 : *edges = jl_alloc_vec_any(0);
1186 : 19357600 : jl_array_ptr_1d_push(*edges, (jl_value_t*)callee);
1187 : : }
1188 : : }
1189 : 5918550 : }
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 : 2489530 : static int jl_collect_methcache_from_mod(jl_typemap_entry_t *ml, void *closure) JL_GC_DISABLED
1198 : : {
1199 : 2489530 : jl_array_t *s = (jl_array_t*)closure;
1200 : 2489530 : jl_method_t *m = ml->func.method;
1201 [ + + ]: 2489530 : if (module_in_worklist(m->module)) {
1202 : 856 : jl_array_ptr_1d_push(s, (jl_value_t*)m);
1203 : 856 : jl_array_ptr_1d_push(s, (jl_value_t*)ml->simplesig);
1204 : : }
1205 : : else {
1206 : 2488670 : jl_svec_t *specializations = m->specializations;
1207 : 2488670 : size_t i, l = jl_svec_len(specializations);
1208 [ + + ]: 14263900 : for (i = 0; i < l; i++) {
1209 : 11775200 : jl_method_instance_t *callee = (jl_method_instance_t*)jl_svecref(specializations, i);
1210 [ + + + + ]: 11775200 : if ((jl_value_t*)callee != jl_nothing && !method_instance_in_queue(callee))
1211 : 5918550 : collect_backedges(callee);
1212 : : }
1213 : : }
1214 : 2489530 : return 1;
1215 : : }
1216 : :
1217 : 901738 : static void jl_collect_methtable_from_mod(jl_array_t *s, jl_methtable_t *mt) JL_GC_DISABLED
1218 : : {
1219 : 901738 : jl_typemap_visitor(mt->defs, jl_collect_methcache_from_mod, (void*)s);
1220 : 901738 : }
1221 : :
1222 : : // Collect methods of external functions defined by modules in the worklist
1223 : : // "extext" = "extending external"
1224 : : // Also collect relevant backedges
1225 : 10415 : static void jl_collect_extext_methods_from_mod(jl_array_t *s, jl_module_t *m) JL_GC_DISABLED
1226 : : {
1227 [ + + ]: 10415 : if (module_in_worklist(m))
1228 : 81 : return;
1229 : : size_t i;
1230 : 10334 : void **table = m->bindings.table;
1231 [ + + ]: 7912080 : for (i = 1; i < m->bindings.size; i += 2) {
1232 [ + + ]: 7901740 : if (table[i] != HT_NOTFOUND) {
1233 : 2765520 : jl_binding_t *b = (jl_binding_t*)table[i];
1234 [ + + + + : 2765520 : if (b->owner == m && b->value && b->constp) {
+ + ]
1235 : 2013080 : jl_value_t *bv = jl_unwrap_unionall(b->value);
1236 [ + + ]: 2013080 : if (jl_is_datatype(bv)) {
1237 : 1012810 : jl_typename_t *tn = ((jl_datatype_t*)bv)->name;
1238 [ + + + + : 1012810 : if (tn->module == m && tn->name == b->name && tn->wrapper == b->value) {
+ - ]
1239 : 991865 : jl_methtable_t *mt = tn->mt;
1240 [ + + ]: 991865 : if (mt != NULL &&
1241 [ + - ]: 991622 : (jl_value_t*)mt != jl_nothing &&
1242 [ + + + + ]: 991622 : (mt != jl_type_type_mt && mt != jl_nonfunction_mt)) {
1243 : 901575 : jl_collect_methtable_from_mod(s, mt);
1244 : 901575 : jl_collect_missing_backedges_to_mod(mt);
1245 : : }
1246 : : }
1247 : : }
1248 [ + + ]: 1000280 : else if (jl_is_module(b->value)) {
1249 : 19994 : jl_module_t *child = (jl_module_t*)b->value;
1250 [ + + + + : 19994 : if (child != m && child->parent == m && child->name == b->name) {
+ - ]
1251 : : // this is the original/primary binding for the submodule
1252 : 6895 : jl_collect_extext_methods_from_mod(s, (jl_module_t*)b->value);
1253 : : }
1254 : : }
1255 [ + + ]: 980281 : else if (jl_is_mtable(b->value)) {
1256 : 1 : jl_methtable_t *mt = (jl_methtable_t*)b->value;
1257 [ + - + - ]: 1 : 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 : 1 : 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 : 15151 : static void jl_collect_backedges_to(jl_method_instance_t *caller, htable_t *all_callees) JL_GC_DISABLED
1272 : : {
1273 : 15151 : jl_array_t **pcallees = (jl_array_t**)ptrhash_bp(&edges_map, (void*)caller),
1274 : 15151 : *callees = *pcallees;
1275 [ + + ]: 15151 : if (callees != HT_NOTFOUND) {
1276 : 4278 : *pcallees = (jl_array_t*) HT_NOTFOUND;
1277 : 4278 : size_t i, l = jl_array_len(callees);
1278 [ + + ]: 18995 : for (i = 0; i < l; i++) {
1279 : 14717 : jl_value_t *c = jl_array_ptr_ref(callees, i);
1280 : 14717 : ptrhash_put(all_callees, c, c);
1281 [ + + ]: 14717 : if (jl_is_method_instance(c)) {
1282 : 14676 : jl_collect_backedges_to((jl_method_instance_t*)c, all_callees);
1283 : : }
1284 : : }
1285 : : }
1286 : 15151 : }
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 : 81 : 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 : 81 : htable_new(&all_targets, 0);
1295 : 81 : htable_new(&all_callees, 0);
1296 : : size_t i;
1297 : 81 : void **table = edges_map.table; // edges is caller => callees
1298 [ + + ]: 5308500 : for (i = 0; i < edges_map.size; i += 2) {
1299 : 5308420 : jl_method_instance_t *caller = (jl_method_instance_t*)table[i];
1300 : 5308420 : jl_array_t *callees = (jl_array_t*)table[i + 1];
1301 [ + + + + : 5308420 : if (callees != HT_NOTFOUND && (module_in_worklist(caller->def.method->module) || method_instance_in_queue(caller))) {
+ + ]
1302 : 116 : size_t i, l = jl_array_len(callees);
1303 [ + + ]: 595 : for (i = 0; i < l; i++) {
1304 : 479 : jl_value_t *c = jl_array_ptr_ref(callees, i);
1305 : 479 : ptrhash_put(&all_callees, c, c);
1306 [ + + ]: 479 : if (jl_is_method_instance(c)) {
1307 : 475 : jl_collect_backedges_to((jl_method_instance_t*)c, &all_callees);
1308 : : }
1309 : : }
1310 : 116 : callees = jl_alloc_array_1d(jl_array_int32_type, 0);
1311 : 116 : void **pc = all_callees.table;
1312 : : size_t j;
1313 : 116 : int valid = 1;
1314 [ + - + + ]: 22580 : for (j = 0; valid && j < all_callees.size; j += 2) {
1315 [ + + ]: 22464 : if (pc[j + 1] != HT_NOTFOUND) {
1316 : 6966 : jl_value_t *callee = (jl_value_t*)pc[j];
1317 : 6966 : void *target = ptrhash_get(&all_targets, (void*)callee);
1318 [ + + ]: 6966 : if (target == HT_NOTFOUND) {
1319 : 6431 : jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee;
1320 : : jl_value_t *sig;
1321 [ + + ]: 6431 : if (jl_is_method_instance(callee)) {
1322 : 6392 : sig = callee_mi->specTypes;
1323 : : }
1324 : : else {
1325 : 39 : sig = callee;
1326 : : }
1327 : 6431 : size_t min_valid = 0;
1328 : 6431 : size_t max_valid = ~(size_t)0;
1329 : 6431 : int ambig = 0;
1330 : 6431 : 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 [ - + ]: 6431 : if (matches == jl_false) {
1332 : 0 : valid = 0;
1333 : 0 : break;
1334 : : }
1335 : : size_t k;
1336 [ + + ]: 12954 : for (k = 0; k < jl_array_len(matches); k++) {
1337 : 6523 : jl_method_match_t *match = (jl_method_match_t *)jl_array_ptr_ref(matches, k);
1338 : 6523 : jl_array_ptr_set(matches, k, match->method);
1339 : : }
1340 : 6431 : jl_array_ptr_1d_push(t, callee);
1341 : 6431 : jl_array_ptr_1d_push(t, matches);
1342 : 6431 : target = (char*)HT_NOTFOUND + jl_array_len(t) / 2;
1343 : 6431 : ptrhash_put(&all_targets, (void*)callee, target);
1344 : : }
1345 : 6966 : jl_array_grow_end(callees, 1);
1346 : 6966 : ((int32_t*)jl_array_data(callees))[jl_array_len(callees) - 1] = (char*)target - (char*)HT_NOTFOUND - 1;
1347 : : }
1348 : : }
1349 : 116 : htable_reset(&all_callees, 100);
1350 [ + - ]: 116 : if (valid) {
1351 : 116 : jl_array_ptr_1d_push(s, (jl_value_t*)caller);
1352 : 116 : jl_array_ptr_1d_push(s, (jl_value_t*)callees);
1353 : : }
1354 : : }
1355 : : }
1356 : 81 : htable_free(&all_targets);
1357 : 81 : htable_free(&all_callees);
1358 : 81 : }
1359 : :
1360 : : // serialize information about all loaded modules
1361 : 81 : static void write_mod_list(ios_t *s, jl_array_t *a)
1362 : : {
1363 : : size_t i;
1364 : 81 : size_t len = jl_array_len(a);
1365 [ + + ]: 3682 : for (i = 0; i < len; i++) {
1366 : 3601 : jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(a, i);
1367 [ - + ]: 3601 : assert(jl_is_module(m));
1368 [ + + ]: 3601 : if (!module_in_worklist(m)) {
1369 : 3520 : const char *modname = jl_symbol_name(m->name);
1370 : 3520 : size_t l = strlen(modname);
1371 : 3520 : write_int32(s, l);
1372 : 3520 : ios_write(s, modname, l);
1373 : 3520 : write_uint64(s, m->uuid.hi);
1374 : 3520 : write_uint64(s, m->uuid.lo);
1375 : 3520 : write_uint64(s, m->build_id);
1376 : : }
1377 : : }
1378 : 81 : write_int32(s, 0);
1379 : 81 : }
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 : 81 : static void write_header(ios_t *s)
1386 : : {
1387 : 81 : ios_write(s, JI_MAGIC, strlen(JI_MAGIC));
1388 : 81 : write_uint16(s, JI_FORMAT_VERSION);
1389 : 81 : ios_write(s, (char *) &BOM, 2);
1390 : 81 : write_uint8(s, sizeof(void*));
1391 : 81 : ios_write(s, JL_BUILD_UNAME, strlen(JL_BUILD_UNAME)+1);
1392 : 81 : ios_write(s, JL_BUILD_ARCH, strlen(JL_BUILD_ARCH)+1);
1393 : 81 : ios_write(s, JULIA_VERSION_STRING, strlen(JULIA_VERSION_STRING)+1);
1394 : 81 : const char *branch = jl_git_branch(), *commit = jl_git_commit();
1395 : 81 : ios_write(s, branch, strlen(branch)+1);
1396 : 81 : ios_write(s, commit, strlen(commit)+1);
1397 : 81 : }
1398 : :
1399 : : // serialize information about the result of deserializing this file
1400 : 81 : static void write_work_list(ios_t *s)
1401 : : {
1402 : 81 : int i, l = jl_array_len(serializer_worklist);
1403 [ + + ]: 173 : for (i = 0; i < l; i++) {
1404 : 92 : jl_module_t *workmod = (jl_module_t*)jl_array_ptr_ref(serializer_worklist, i);
1405 [ + - + + ]: 92 : if (workmod->parent == jl_main_module || workmod->parent == workmod) {
1406 : 81 : size_t l = strlen(jl_symbol_name(workmod->name));
1407 : 81 : write_int32(s, l);
1408 : 81 : ios_write(s, jl_symbol_name(workmod->name), l);
1409 : 81 : write_uint64(s, workmod->uuid.hi);
1410 : 81 : write_uint64(s, workmod->uuid.lo);
1411 : 81 : write_uint64(s, workmod->build_id);
1412 : : }
1413 : : }
1414 : 81 : write_int32(s, 0);
1415 : 81 : }
1416 : :
1417 : 95 : static void write_module_path(ios_t *s, jl_module_t *depmod) JL_NOTSAFEPOINT
1418 : : {
1419 [ + - + + ]: 95 : if (depmod->parent == jl_main_module || depmod->parent == depmod)
1420 : 84 : return;
1421 : 11 : const char *mname = jl_symbol_name(depmod->name);
1422 : 11 : size_t slen = strlen(mname);
1423 : 11 : write_module_path(s, depmod->parent);
1424 : 11 : write_int32(s, slen);
1425 : 11 : 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 : 81 : static int64_t write_dependency_list(ios_t *s, jl_array_t **udepsp)
1433 : : {
1434 : 81 : int64_t initial_pos = 0;
1435 : 81 : int64_t pos = 0;
1436 : : static jl_array_t *deps = NULL;
1437 [ + - ]: 81 : if (!deps)
1438 : 81 : 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 [ + - ]: 81 : if (!unique_func)
1444 : 81 : unique_func = jl_get_global(jl_base_module, jl_symbol("unique"));
1445 : 81 : jl_value_t *uniqargs[2] = {unique_func, (jl_value_t*)deps};
1446 : 81 : jl_task_t *ct = jl_current_task;
1447 : 81 : size_t last_age = ct->world_age;
1448 : 81 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
1449 [ + - + - ]: 81 : jl_array_t *udeps = (*udepsp = deps && unique_func ? (jl_array_t*)jl_apply(uniqargs, 2) : NULL);
1450 : 81 : 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 : 81 : initial_pos = ios_pos(s);
1455 : 81 : write_uint64(s, 0);
1456 [ + - ]: 81 : if (udeps) {
1457 : 81 : size_t i, l = jl_array_len(udeps);
1458 [ + + ]: 248 : for (i = 0; i < l; i++) {
1459 : 167 : jl_value_t *deptuple = jl_array_ptr_ref(udeps, i);
1460 : 167 : jl_value_t *dep = jl_fieldref(deptuple, 1); // file abspath
1461 : 167 : size_t slen = jl_string_len(dep);
1462 : 167 : write_int32(s, slen);
1463 : 167 : ios_write(s, jl_string_data(dep), slen);
1464 : 167 : write_float64(s, jl_unbox_float64(jl_fieldref(deptuple, 2))); // mtime
1465 : 167 : jl_module_t *depmod = (jl_module_t*)jl_fieldref(deptuple, 0); // evaluating module
1466 : 167 : jl_module_t *depmod_top = depmod;
1467 [ + + + + ]: 259 : while (depmod_top->parent != jl_main_module && depmod_top->parent != depmod_top)
1468 : 92 : depmod_top = depmod_top->parent;
1469 : 167 : unsigned provides = 0;
1470 : 167 : size_t j, lj = jl_array_len(serializer_worklist);
1471 [ + + ]: 395 : for (j = 0; j < lj; j++) {
1472 : 312 : jl_module_t *workmod = (jl_module_t*)jl_array_ptr_ref(serializer_worklist, j);
1473 [ + - + + ]: 312 : if (workmod->parent == jl_main_module || workmod->parent == workmod) {
1474 : 167 : ++provides;
1475 [ + + ]: 167 : if (workmod == depmod_top) {
1476 : 84 : write_int32(s, provides);
1477 : 84 : write_module_path(s, depmod);
1478 : 84 : break;
1479 : : }
1480 : : }
1481 : : }
1482 : 167 : write_int32(s, 0);
1483 : : }
1484 : 81 : write_int32(s, 0); // terminator, for ease of reading
1485 : :
1486 : : // Calculate Preferences hash for current package.
1487 : 81 : jl_value_t *prefs_hash = NULL;
1488 : 81 : jl_value_t *prefs_list = NULL;
1489 : 81 : JL_GC_PUSH1(&prefs_list);
1490 [ + - ]: 81 : if (jl_base_module) {
1491 : : // Toplevel module is the module we're currently compiling, use it to get our preferences hash
1492 : 81 : jl_value_t * toplevel = (jl_value_t*)jl_get_global(jl_base_module, jl_symbol("__toplevel__"));
1493 : 81 : jl_value_t * prefs_hash_func = jl_get_global(jl_base_module, jl_symbol("get_preferences_hash"));
1494 : 81 : jl_value_t * get_compiletime_prefs_func = jl_get_global(jl_base_module, jl_symbol("get_compiletime_preferences"));
1495 : :
1496 [ + - + - : 81 : if (toplevel && prefs_hash_func && get_compiletime_prefs_func) {
+ - ]
1497 : : // Temporary invoke in newest world age
1498 : 81 : size_t last_age = ct->world_age;
1499 : 81 : ct->world_age = jl_atomic_load_acquire(&jl_world_counter);
1500 : :
1501 : : // call get_compiletime_prefs(__toplevel__)
1502 : 81 : jl_value_t *args[3] = {get_compiletime_prefs_func, (jl_value_t*)toplevel, NULL};
1503 : 81 : prefs_list = (jl_value_t*)jl_apply(args, 2);
1504 : :
1505 : : // Call get_preferences_hash(__toplevel__, prefs_list)
1506 : 81 : args[0] = prefs_hash_func;
1507 : 81 : args[2] = prefs_list;
1508 : 81 : prefs_hash = (jl_value_t*)jl_apply(args, 3);
1509 : :
1510 : : // Reset world age to normal
1511 : 81 : 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 [ + - + - ]: 162 : if (prefs_hash != NULL && prefs_list != NULL) {
1517 : 81 : size_t i, l = jl_array_len(prefs_list);
1518 [ - + ]: 81 : 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 : 81 : write_int32(s, 0); // terminator
1525 : 81 : 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 : 81 : JL_GC_POP(); // for prefs_list
1536 : :
1537 : : // write a dummy file position to indicate the beginning of the source-text
1538 : 81 : pos = ios_pos(s);
1539 : 81 : ios_seek(s, initial_pos);
1540 : 81 : write_uint64(s, pos - initial_pos);
1541 : 81 : ios_seek(s, pos);
1542 : 81 : write_int64(s, 0);
1543 : : }
1544 : 81 : 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 : 181887 : static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_value_t **loc) JL_GC_DISABLED
1552 : : {
1553 [ - + ]: 181887 : assert(pos == backref_list.len - 1 && "nothing should have been deserialized since assigning pos");
1554 : 181887 : int tag = read_uint8(s->s);
1555 [ + + + + ]: 181887 : if (tag == 6 || tag == 7) {
1556 : 31759 : jl_typename_t *name = (jl_typename_t*)jl_deserialize_value(s, NULL);
1557 : 31759 : jl_value_t *dtv = name->wrapper;
1558 : 31759 : jl_svec_t *parameters = (jl_svec_t*)jl_deserialize_value(s, NULL);
1559 : 31759 : dtv = jl_apply_type(dtv, jl_svec_data(parameters), jl_svec_len(parameters));
1560 : 31759 : backref_list.items[pos] = dtv;
1561 : 31759 : return dtv;
1562 : : }
1563 [ + + ]: 150128 : if (tag == 9) {
1564 : 289 : jl_datatype_t *primarydt = (jl_datatype_t*)jl_deserialize_value(s, NULL);
1565 : 289 : jl_value_t *dtv = jl_typeof(jl_get_kwsorter((jl_value_t*)primarydt));
1566 : 289 : backref_list.items[pos] = dtv;
1567 : 289 : return dtv;
1568 : : }
1569 [ + + + + : 149839 : if (!(tag == 0 || tag == 5 || tag == 10 || tag == 11 || tag == 12)) {
+ + + + -
+ ]
1570 : 0 : assert(0 && "corrupt deserialization state");
1571 : : abort();
1572 : : }
1573 : 149839 : jl_datatype_t *dt = jl_new_uninitialized_datatype();
1574 : 149839 : backref_list.items[pos] = dt;
1575 [ + - + + ]: 149839 : if (loc != NULL && loc != HT_NOTFOUND)
1576 : 144683 : *loc = (jl_value_t*)dt;
1577 : 149839 : size_t size = read_int32(s->s);
1578 : 149839 : uint8_t flags = read_uint8(s->s);
1579 : 149839 : uint8_t memflags = read_uint8(s->s);
1580 : 149839 : dt->size = size;
1581 : 149839 : int has_layout = flags & 1;
1582 : 149839 : int has_instance = (flags >> 1) & 1;
1583 : 149839 : dt->hasfreetypevars = memflags & 1;
1584 : 149839 : dt->isconcretetype = (memflags >> 1) & 1;
1585 : 149839 : dt->isdispatchtuple = (memflags >> 2) & 1;
1586 : 149839 : dt->isbitstype = (memflags >> 3) & 1;
1587 : 149839 : dt->zeroinit = (memflags >> 4) & 1;
1588 : 149839 : dt->has_concrete_subtype = (memflags >> 5) & 1;
1589 : 149839 : dt->cached_by_hash = (memflags >> 6) & 1;
1590 : 149839 : dt->hash = read_int32(s->s);
1591 : :
1592 [ + + ]: 149839 : if (has_layout) {
1593 : 28525 : uint8_t layout = read_uint8(s->s);
1594 [ + + ]: 28525 : if (layout == 1) {
1595 : 1039 : dt->layout = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_array_type))->layout;
1596 : : }
1597 [ - + ]: 27486 : else if (layout == 2) {
1598 : 0 : dt->layout = jl_nothing_type->layout;
1599 : : }
1600 [ + + ]: 27486 : else if (layout == 3) {
1601 : 161 : dt->layout = ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_pointer_type))->layout;
1602 : : }
1603 : : else {
1604 [ - + ]: 27325 : assert(layout == 0);
1605 : : jl_datatype_layout_t buffer;
1606 : 27325 : ios_readall(s->s, (char*)&buffer, sizeof(buffer));
1607 : 27325 : uint32_t nf = buffer.nfields;
1608 : 27325 : uint32_t np = buffer.npointers;
1609 : 27325 : uint8_t fielddesc_type = buffer.fielddesc_type;
1610 [ + + ]: 27325 : size_t fielddesc_size = nf > 0 ? jl_fielddesc_size(fielddesc_type) : 0;
1611 : 27325 : size_t fldsize = nf * fielddesc_size;
1612 [ + + ]: 27325 : if (buffer.first_ptr != -1)
1613 : 12639 : fldsize += np << fielddesc_type;
1614 : 27325 : 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 : 27325 : *layout = buffer;
1618 : 27325 : ios_readall(s->s, (char*)(layout + 1), fldsize);
1619 : 27325 : dt->layout = layout;
1620 : : }
1621 : : }
1622 : :
1623 [ + + + + : 149839 : if (tag == 10 || tag == 11 || tag == 12) {
+ + ]
1624 [ - + ]: 17221 : assert(pos > 0);
1625 [ + + ]: 17221 : arraylist_push(&flagref_list, loc == HT_NOTFOUND ? NULL : loc);
1626 : 17221 : arraylist_push(&flagref_list, (void*)(uintptr_t)pos);
1627 : 17221 : ptrhash_put(&uniquing_table, dt, NULL);
1628 : : }
1629 : :
1630 [ + + ]: 149839 : if (has_instance) {
1631 [ - + ]: 10775 : assert(dt->isconcretetype && "there shouldn't be an instance on an abstract type");
1632 : 10775 : dt->instance = jl_deserialize_value(s, &dt->instance);
1633 : 10775 : jl_gc_wb(dt, dt->instance);
1634 : : }
1635 : 149839 : dt->name = (jl_typename_t*)jl_deserialize_value(s, (jl_value_t**)&dt->name);
1636 : 149839 : jl_gc_wb(dt, dt->name);
1637 : 149839 : dt->parameters = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&dt->parameters);
1638 : 149839 : jl_gc_wb(dt, dt->parameters);
1639 : 149839 : dt->super = (jl_datatype_t*)jl_deserialize_value(s, (jl_value_t**)&dt->super);
1640 : 149839 : jl_gc_wb(dt, dt->super);
1641 : 149839 : dt->types = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&dt->types);
1642 [ + + ]: 149839 : if (dt->types) jl_gc_wb(dt, dt->types);
1643 : :
1644 : 149839 : return (jl_value_t*)dt;
1645 : : }
1646 : :
1647 : 164381 : 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 [ + - ]: 164381 : if (tag == TAG_SVEC)
1651 : 164381 : len = read_uint8(s->s);
1652 : : else
1653 : 0 : len = read_int32(s->s);
1654 : 164381 : jl_svec_t *sv = jl_alloc_svec(len);
1655 [ + + ]: 164381 : if (loc != NULL)
1656 : 142861 : *loc = (jl_value_t*)sv;
1657 : 164381 : arraylist_push(&backref_list, (jl_value_t*)sv);
1658 : 164381 : jl_value_t **data = jl_svec_data(sv);
1659 [ + + ]: 601113 : for (i = 0; i < len; i++) {
1660 : 436732 : data[i] = jl_deserialize_value(s, &data[i]);
1661 : : }
1662 : 164381 : return (jl_value_t*)sv;
1663 : : }
1664 : :
1665 : 46726 : static jl_value_t *jl_deserialize_value_symbol(jl_serializer_state *s, uint8_t tag) JL_GC_DISABLED
1666 : : {
1667 : : size_t len;
1668 [ + - ]: 46726 : if (tag == TAG_SYMBOL)
1669 : 46726 : len = read_uint8(s->s);
1670 : : else
1671 : 0 : len = read_int32(s->s);
1672 [ - + ]: 46726 : char *name = (char*)(len >= 256 ? malloc_s(len + 1) : alloca(len + 1));
1673 : 46726 : ios_readall(s->s, name, len);
1674 : 46726 : name[len] = '\0';
1675 : 46726 : jl_value_t *sym = (jl_value_t*)jl_symbol(name);
1676 [ - + ]: 46726 : if (len >= 256)
1677 : 0 : free(name);
1678 : 46726 : arraylist_push(&backref_list, sym);
1679 : 46726 : return sym;
1680 : : }
1681 : :
1682 : 123347 : 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 [ + - ]: 123347 : if (tag == TAG_ARRAY1D) {
1687 : 123347 : ndims = 1;
1688 : 123347 : elsize = read_uint8(s->s);
1689 : 123347 : isptr = (elsize >> 7) & 1;
1690 : 123347 : hasptr = (elsize >> 6) & 1;
1691 : 123347 : isunion = (elsize >> 5) & 1;
1692 : 123347 : 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 : 123347 : uintptr_t pos = backref_list.len;
1703 : 123347 : arraylist_push(&backref_list, NULL);
1704 : 123347 : size_t *dims = (size_t*)alloca(ndims * sizeof(size_t));
1705 [ + + ]: 246694 : for (i = 0; i < ndims; i++) {
1706 : 123347 : dims[i] = jl_unbox_long(jl_deserialize_value(s, NULL));
1707 : : }
1708 : 123347 : jl_array_t *a = jl_new_array_for_deserialization(
1709 : : (jl_value_t*)NULL, ndims, dims, !isptr, hasptr, isunion, elsize);
1710 : 123347 : backref_list.items[pos] = a;
1711 : 123347 : jl_value_t *aty = jl_deserialize_value(s, &jl_astaggedvalue(a)->type);
1712 : 123347 : jl_set_typeof(a, aty);
1713 [ + + ]: 123347 : if (a->flags.ptrarray) {
1714 : 73634 : jl_value_t **data = (jl_value_t**)jl_array_data(a);
1715 : 73634 : size_t i, numel = jl_array_len(a);
1716 [ + + ]: 418772 : for (i = 0; i < numel; i++) {
1717 : 345138 : 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 [ - + ]: 73634 : assert(jl_astaggedvalue(a)->bits.gc == GC_CLEAN); // gc is disabled
1722 : : }
1723 [ + + ]: 49713 : else if (a->flags.hasptr) {
1724 : 2 : size_t i, numel = jl_array_len(a);
1725 : 2 : char *data = (char*)jl_array_data(a);
1726 : 2 : uint16_t elsz = a->elsize;
1727 : 2 : jl_datatype_t *et = (jl_datatype_t*)jl_tparam0(jl_typeof(a));
1728 : 2 : size_t j, np = et->layout->npointers;
1729 [ + + ]: 12 : for (i = 0; i < numel; i++) {
1730 : 10 : char *start = data;
1731 [ + + ]: 20 : for (j = 0; j < np; j++) {
1732 : 10 : uint32_t ptr = jl_ptr_offset(et, j);
1733 : 10 : jl_value_t **fld = &((jl_value_t**)data)[ptr];
1734 [ - + ]: 10 : if ((char*)fld != start)
1735 : 0 : ios_readall(s->s, start, (const char*)fld - start);
1736 : 10 : *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 : 10 : start = (char*)&fld[1];
1740 : : }
1741 : 10 : data += elsz;
1742 [ + - ]: 10 : if (data != start)
1743 : 10 : ios_readall(s->s, start, data - start);
1744 : : }
1745 [ - + ]: 2 : assert(jl_astaggedvalue(a)->bits.gc == GC_CLEAN); // gc is disabled
1746 : : }
1747 : : else {
1748 [ + - + + ]: 49711 : size_t extra = jl_array_isbitsunion(a) ? jl_array_len(a) : 0;
1749 : 49711 : size_t tot = jl_array_len(a) * a->elsize + extra;
1750 : 49711 : ios_readall(s->s, (char*)jl_array_data(a), tot);
1751 : : }
1752 : 123347 : return (jl_value_t*)a;
1753 : : }
1754 : :
1755 : 40720 : 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 : 40720 : (jl_method_t*)jl_gc_alloc(s->ptls, sizeof(jl_method_t),
1759 : : jl_method_type);
1760 : 40720 : memset(m, 0, sizeof(jl_method_t));
1761 : 40720 : uintptr_t pos = backref_list.len;
1762 : 40720 : arraylist_push(&backref_list, m);
1763 : 40720 : m->sig = (jl_value_t*)jl_deserialize_value(s, (jl_value_t**)&m->sig);
1764 : 40720 : jl_gc_wb(m, m->sig);
1765 : 40720 : m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module);
1766 : 40720 : jl_gc_wb(m, m->module);
1767 : 40720 : int serialization_mode = read_uint8(s->s);
1768 [ + + ]: 40720 : if (serialization_mode & METHOD_EXTERNAL_MT) {
1769 : 1 : jl_module_t *mt_mod = (jl_module_t*)jl_deserialize_value(s, NULL);
1770 : 1 : jl_sym_t *mt_name = (jl_sym_t*)jl_deserialize_value(s, NULL);
1771 : 1 : m->external_mt = jl_get_global(mt_mod, mt_name);
1772 : 1 : jl_gc_wb(m, m->external_mt);
1773 [ - + ]: 1 : assert(jl_typeis(m->external_mt, jl_methtable_type));
1774 : : }
1775 : : else {
1776 : 40719 : m->external_mt = jl_deserialize_value(s, &m->external_mt);
1777 : 40719 : jl_gc_wb(m, m->external_mt);
1778 : : }
1779 [ + + ]: 40720 : if (!(serialization_mode & METHOD_INTERNAL)) {
1780 [ + - + - ]: 16890 : assert(loc != NULL && loc != HT_NOTFOUND);
1781 : 16890 : arraylist_push(&flagref_list, loc);
1782 : 16890 : arraylist_push(&flagref_list, (void*)pos);
1783 [ + + ]: 16890 : if (serialization_mode & METHOD_HAS_NEW_ROOTS) {
1784 : 217 : uint64_t key = read_uint64(s->s);
1785 : 217 : int i, nnew = read_int32(s->s);
1786 : 217 : jl_array_t *newroots = jl_alloc_vec_any(nnew);
1787 : 217 : jl_value_t **data = (jl_value_t**)jl_array_data(newroots);
1788 [ + + ]: 1584 : for (i = 0; i < nnew; i++)
1789 : 1367 : 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 [ - + ]: 217 : 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 : 217 : jl_svec_t *qmrval = jl_alloc_svec_uninit(3); // GC is disabled
1796 : 217 : jl_svec_data(qmrval)[0] = (jl_value_t*)(uintptr_t)(key & ((((uint64_t)1) << 32) - 1)); // lo bits
1797 : 217 : jl_svec_data(qmrval)[1] = (jl_value_t*)(uintptr_t)((key >> 32) & ((((uint64_t)1) << 32) - 1)); // hi bits
1798 : 217 : jl_svec_data(qmrval)[2] = (jl_value_t*)newroots;
1799 : 217 : ptrhash_put(&queued_method_roots, m, qmrval);
1800 : : }
1801 : 16890 : return (jl_value_t*)m;
1802 : : }
1803 : 23830 : m->specializations = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->specializations);
1804 : 23830 : jl_gc_wb(m, m->specializations);
1805 : 23830 : jl_array_t *speckeyset = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->speckeyset);
1806 : 23830 : jl_atomic_store_relaxed(&m->speckeyset, speckeyset);
1807 : 23830 : jl_gc_wb(m, speckeyset);
1808 : 23830 : m->name = (jl_sym_t*)jl_deserialize_value(s, NULL);
1809 : 23830 : jl_gc_wb(m, m->name);
1810 : 23830 : m->file = (jl_sym_t*)jl_deserialize_value(s, NULL);
1811 : 23830 : m->line = read_int32(s->s);
1812 : 23830 : m->primary_world = jl_atomic_load_acquire(&jl_world_counter);
1813 : 23830 : m->deleted_world = ~(size_t)0;
1814 : 23830 : m->called = read_int32(s->s);
1815 : 23830 : m->nargs = read_int32(s->s);
1816 : 23830 : m->nospecialize = read_int32(s->s);
1817 : 23830 : m->nkw = read_int32(s->s);
1818 : 23830 : m->isva = read_int8(s->s);
1819 : 23830 : m->pure = read_int8(s->s);
1820 : 23830 : m->is_for_opaque_closure = read_int8(s->s);
1821 : 23830 : m->constprop = read_int8(s->s);
1822 : 23830 : m->purity.bits = read_uint8(s->s);
1823 : 23830 : m->slot_syms = jl_deserialize_value(s, (jl_value_t**)&m->slot_syms);
1824 : 23830 : jl_gc_wb(m, m->slot_syms);
1825 : 23830 : m->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->roots);
1826 [ + - ]: 23830 : if (m->roots)
1827 : 23830 : jl_gc_wb(m, m->roots);
1828 : 23830 : m->root_blocks = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->root_blocks);
1829 [ + - ]: 23830 : if (m->root_blocks)
1830 : 23830 : jl_gc_wb(m, m->root_blocks);
1831 : 23830 : m->nroots_sysimg = read_int32(s->s);
1832 : 23830 : m->ccallable = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->ccallable);
1833 [ + + ]: 23830 : if (m->ccallable) {
1834 : 2 : jl_gc_wb(m, m->ccallable);
1835 : 2 : arraylist_push(&ccallable_list, m->ccallable);
1836 : : }
1837 : 23830 : m->source = jl_deserialize_value(s, &m->source);
1838 [ + - ]: 23830 : if (m->source)
1839 : 23830 : jl_gc_wb(m, m->source);
1840 : 23830 : m->unspecialized = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&m->unspecialized);
1841 [ + + ]: 23830 : if (m->unspecialized)
1842 : 44 : jl_gc_wb(m, m->unspecialized);
1843 : 23830 : m->generator = jl_deserialize_value(s, (jl_value_t**)&m->generator);
1844 [ - + ]: 23830 : if (m->generator)
1845 : 0 : jl_gc_wb(m, m->generator);
1846 : 23830 : m->invokes = jl_deserialize_value(s, (jl_value_t**)&m->invokes);
1847 : 23830 : jl_gc_wb(m, m->invokes);
1848 : 23830 : m->recursion_relation = jl_deserialize_value(s, (jl_value_t**)&m->recursion_relation);
1849 [ - + ]: 23830 : if (m->recursion_relation)
1850 : 0 : jl_gc_wb(m, m->recursion_relation);
1851 : 23830 : JL_MUTEX_INIT(&m->writelock);
1852 : 23830 : return (jl_value_t*)m;
1853 : : }
1854 : :
1855 : 44470 : 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 : 44470 : (jl_method_instance_t*)jl_gc_alloc(s->ptls, sizeof(jl_method_instance_t),
1859 : : jl_method_instance_type);
1860 : 44470 : memset(mi, 0, sizeof(jl_method_instance_t));
1861 : 44470 : uintptr_t pos = backref_list.len;
1862 : 44470 : arraylist_push(&backref_list, mi);
1863 : 44470 : int internal = read_uint8(s->s);
1864 [ - + ]: 44470 : if (internal == 1) {
1865 : 0 : mi->uninferred = jl_deserialize_value(s, &mi->uninferred);
1866 : 0 : jl_gc_wb(mi, mi->uninferred);
1867 : : }
1868 : 44470 : mi->specTypes = (jl_value_t*)jl_deserialize_value(s, (jl_value_t**)&mi->specTypes);
1869 : 44470 : jl_gc_wb(mi, mi->specTypes);
1870 : 44470 : mi->def.value = jl_deserialize_value(s, &mi->def.value);
1871 : 44470 : jl_gc_wb(mi, mi->def.value);
1872 : :
1873 [ + + ]: 44470 : if (!internal) {
1874 [ + - + - ]: 43927 : assert(loc != NULL && loc != HT_NOTFOUND);
1875 : 43927 : arraylist_push(&flagref_list, loc);
1876 : 43927 : arraylist_push(&flagref_list, (void*)pos);
1877 : 43927 : return (jl_value_t*)mi;
1878 : : }
1879 : :
1880 : 543 : mi->sparam_vals = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&mi->sparam_vals);
1881 : 543 : jl_gc_wb(mi, mi->sparam_vals);
1882 : 543 : mi->backedges = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&mi->backedges);
1883 [ + + ]: 543 : if (mi->backedges)
1884 : 268 : jl_gc_wb(mi, mi->backedges);
1885 : 543 : mi->callbacks = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&mi->callbacks);
1886 [ - + ]: 543 : if (mi->callbacks)
1887 : 0 : jl_gc_wb(mi, mi->callbacks);
1888 : 543 : mi->cache = (jl_code_instance_t*)jl_deserialize_value(s, (jl_value_t**)&mi->cache);
1889 [ + + ]: 543 : if (mi->cache)
1890 : 497 : jl_gc_wb(mi, mi->cache);
1891 : 543 : return (jl_value_t*)mi;
1892 : : }
1893 : :
1894 : 498 : 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 : 498 : (jl_code_instance_t*)jl_gc_alloc(s->ptls, sizeof(jl_code_instance_t), jl_code_instance_type);
1898 : 498 : memset(codeinst, 0, sizeof(jl_code_instance_t));
1899 : 498 : arraylist_push(&backref_list, codeinst);
1900 : 498 : int flags = read_uint8(s->s);
1901 : 498 : int validate = (flags >> 0) & 3;
1902 : 498 : int constret = (flags >> 2) & 1;
1903 : 498 : codeinst->ipo_purity_bits = read_uint32(s->s);
1904 : 498 : codeinst->purity_bits = read_uint32(s->s);
1905 : 498 : codeinst->def = (jl_method_instance_t*)jl_deserialize_value(s, (jl_value_t**)&codeinst->def);
1906 : 498 : jl_gc_wb(codeinst, codeinst->def);
1907 : 498 : codeinst->inferred = jl_deserialize_value(s, &codeinst->inferred);
1908 : 498 : jl_gc_wb(codeinst, codeinst->inferred);
1909 : 498 : codeinst->rettype_const = jl_deserialize_value(s, &codeinst->rettype_const);
1910 [ + + ]: 498 : if (codeinst->rettype_const)
1911 : 65 : jl_gc_wb(codeinst, codeinst->rettype_const);
1912 : 498 : codeinst->rettype = jl_deserialize_value(s, &codeinst->rettype);
1913 : 498 : jl_gc_wb(codeinst, codeinst->rettype);
1914 : 498 : codeinst->argescapes = jl_deserialize_value(s, &codeinst->argescapes);
1915 : 498 : jl_gc_wb(codeinst, codeinst->argescapes);
1916 [ + + ]: 498 : if (constret)
1917 : 10 : codeinst->invoke = jl_fptr_const_return;
1918 [ + + ]: 498 : if ((flags >> 3) & 1)
1919 : 183 : codeinst->precompile = 1;
1920 : 498 : codeinst->relocatability = read_uint8(s->s);
1921 [ - + ]: 498 : assert(codeinst->relocatability <= 1);
1922 : 498 : codeinst->next = (jl_code_instance_t*)jl_deserialize_value(s, (jl_value_t**)&codeinst->next);
1923 : 498 : jl_gc_wb(codeinst, codeinst->next);
1924 [ + + ]: 498 : if (validate) {
1925 : 497 : codeinst->min_world = jl_atomic_load_acquire(&jl_world_counter);
1926 : 497 : ptrhash_put(&new_code_instance_validate, codeinst, (void*)(~(uintptr_t)HT_NOTFOUND)); // "HT_FOUND"
1927 : : }
1928 : 498 : return (jl_value_t*)codeinst;
1929 : : }
1930 : :
1931 : 647 : static jl_value_t *jl_deserialize_value_module(jl_serializer_state *s) JL_GC_DISABLED
1932 : : {
1933 : 647 : uintptr_t pos = backref_list.len;
1934 : 647 : arraylist_push(&backref_list, NULL);
1935 : 647 : jl_sym_t *mname = (jl_sym_t*)jl_deserialize_value(s, NULL);
1936 : 647 : int ref_only = read_uint8(s->s);
1937 [ + + ]: 647 : if (ref_only) {
1938 : : jl_value_t *m_ref;
1939 [ + + ]: 454 : if (ref_only == 1)
1940 : 298 : m_ref = jl_get_global((jl_module_t*)jl_deserialize_value(s, NULL), mname);
1941 : : else
1942 : 156 : m_ref = jl_array_ptr_ref(s->loaded_modules_array, read_int32(s->s));
1943 : 454 : backref_list.items[pos] = m_ref;
1944 : 454 : return m_ref;
1945 : : }
1946 : 193 : jl_module_t *m = jl_new_module(mname);
1947 : 193 : backref_list.items[pos] = m;
1948 : 193 : m->parent = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->parent);
1949 : 193 : jl_gc_wb(m, m->parent);
1950 : :
1951 : 32629 : while (1) {
1952 : 32822 : jl_sym_t *asname = (jl_sym_t*)jl_deserialize_value(s, NULL);
1953 [ + + ]: 32822 : if (asname == NULL)
1954 : 193 : break;
1955 : 32629 : jl_binding_t *b = jl_get_binding_wr(m, asname, 1);
1956 : 32629 : b->name = (jl_sym_t*)jl_deserialize_value(s, (jl_value_t**)&b->name);
1957 : 32629 : jl_value_t *bvalue = jl_deserialize_value(s, (jl_value_t**)&b->value);
1958 : 32629 : *(jl_value_t**)&b->value = bvalue;
1959 [ + + ]: 32629 : if (bvalue != NULL) jl_gc_wb(m, bvalue);
1960 : 32629 : jl_value_t *bglobalref = jl_deserialize_value(s, (jl_value_t**)&b->globalref);
1961 : 32629 : *(jl_value_t**)&b->globalref = bglobalref;
1962 [ + + ]: 32629 : if (bglobalref != NULL) jl_gc_wb(m, bglobalref);
1963 : 32629 : b->owner = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&b->owner);
1964 [ + - ]: 32629 : if (b->owner != NULL) jl_gc_wb(m, b->owner);
1965 : 32629 : jl_value_t *bty = jl_deserialize_value(s, (jl_value_t**)&b->ty);
1966 : 32629 : *(jl_value_t**)&b->ty = bty;
1967 : 32629 : int8_t flags = read_int8(s->s);
1968 : 32629 : b->deprecated = (flags>>3) & 1;
1969 : 32629 : b->constp = (flags>>2) & 1;
1970 : 32629 : b->exportp = (flags>>1) & 1;
1971 : 32629 : b->imported = (flags) & 1;
1972 : : }
1973 : 193 : size_t i = m->usings.len;
1974 : 193 : size_t ni = read_int32(s->s);
1975 : 193 : arraylist_grow(&m->usings, ni);
1976 : 193 : ni += i;
1977 [ + + ]: 769 : while (i < ni) {
1978 : 576 : m->usings.items[i] = jl_deserialize_value(s, (jl_value_t**)&m->usings.items[i]);
1979 : 576 : i++;
1980 : : }
1981 : 193 : m->istopmod = read_uint8(s->s);
1982 : 193 : m->uuid.hi = read_uint64(s->s);
1983 : 193 : m->uuid.lo = read_uint64(s->s);
1984 : 193 : m->build_id = read_uint64(s->s);
1985 : 193 : m->counter = read_int32(s->s);
1986 : 193 : m->nospecialize = read_int32(s->s);
1987 : 193 : m->optlevel = read_int8(s->s);
1988 : 193 : m->compile = read_int8(s->s);
1989 : 193 : m->infer = read_int8(s->s);
1990 : 193 : m->max_methods = read_int8(s->s);
1991 : 193 : m->primary_world = jl_atomic_load_acquire(&jl_world_counter);
1992 : 193 : return (jl_value_t*)m;
1993 : : }
1994 : :
1995 : 10792 : static jl_value_t *jl_deserialize_value_singleton(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
1996 : : {
1997 : 10792 : jl_value_t *v = (jl_value_t*)jl_gc_alloc(s->ptls, 0, NULL);
1998 : 10792 : uintptr_t pos = backref_list.len;
1999 : 10792 : 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 [ - + ]: 10792 : 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 [ + - ]: 10792 : if (loc != NULL) {
2007 : 10792 : arraylist_push(&flagref_list, loc);
2008 : 10792 : arraylist_push(&flagref_list, (void*)pos);
2009 : : }
2010 : 10792 : 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 : 10792 : jl_set_typeof(v, dt);
2012 [ + + ]: 10792 : if (dt->instance == NULL)
2013 : 5619 : return v;
2014 : 5173 : return dt->instance;
2015 : : }
2016 : :
2017 : 76930 : static void jl_deserialize_struct(jl_serializer_state *s, jl_value_t *v) JL_GC_DISABLED
2018 : : {
2019 : 76930 : jl_datatype_t *dt = (jl_datatype_t*)jl_typeof(v);
2020 : 76930 : char *data = (char*)jl_data_ptr(v);
2021 : 76930 : size_t i, np = dt->layout->npointers;
2022 : 76930 : char *start = data;
2023 [ + + ]: 306655 : for (i = 0; i < np; i++) {
2024 : 229725 : uint32_t ptr = jl_ptr_offset(dt, i);
2025 : 229725 : jl_value_t **fld = &((jl_value_t**)data)[ptr];
2026 [ + + ]: 229725 : if ((char*)fld != start)
2027 : 25989 : ios_readall(s->s, start, (const char*)fld - start);
2028 : 229725 : *fld = jl_deserialize_value(s, fld);
2029 : : //if (*fld)// a is new (gc is disabled)
2030 : : // jl_gc_wb(a, *fld);
2031 : 229725 : start = (char*)&fld[1];
2032 : : }
2033 : 76930 : data += jl_datatype_size(dt);
2034 [ + + ]: 76930 : if (data != start)
2035 : 28279 : ios_readall(s->s, start, data - start);
2036 [ + + ]: 76930 : if (dt == jl_typemap_entry_type) {
2037 : 15062 : jl_typemap_entry_t *entry = (jl_typemap_entry_t*)v;
2038 [ + - ]: 15062 : if (entry->max_world == ~(size_t)0) {
2039 [ + - ]: 15062 : if (entry->min_world > 1) {
2040 : : // update world validity to reflect current state of the counter
2041 : 15062 : 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 : 76930 : }
2051 : :
2052 : 99741 : static jl_value_t *jl_deserialize_value_any(jl_serializer_state *s, uint8_t tag, jl_value_t **loc) JL_GC_DISABLED
2053 : : {
2054 [ + - ]: 99741 : int32_t sz = (tag == TAG_SHORT_GENERAL ? read_uint8(s->s) : read_int32(s->s));
2055 : 99741 : jl_value_t *v = jl_gc_alloc(s->ptls, sz, NULL);
2056 : 99741 : jl_set_typeof(v, (void*)(intptr_t)0x50);
2057 : 99741 : uintptr_t pos = backref_list.len;
2058 : 99741 : arraylist_push(&backref_list, v);
2059 : 99741 : jl_datatype_t *dt = (jl_datatype_t*)jl_deserialize_value(s, &jl_astaggedvalue(v)->type);
2060 [ - + - - ]: 99741 : assert(sz != 0 || loc);
2061 [ + + ]: 99741 : if (dt == jl_typename_type) {
2062 : 22807 : int internal = read_uint8(s->s);
2063 : : jl_typename_t *tn;
2064 [ + + ]: 22807 : if (internal) {
2065 : 10744 : tn = (jl_typename_t*)jl_gc_alloc(
2066 : : s->ptls, sizeof(jl_typename_t), jl_typename_type);
2067 : 10744 : memset(tn, 0, sizeof(jl_typename_t));
2068 : 10744 : tn->cache = jl_emptysvec; // the cache is refilled later (tag 5)
2069 : 10744 : tn->linearcache = jl_emptysvec; // the cache is refilled later (tag 5)
2070 : 10744 : backref_list.items[pos] = tn;
2071 : : }
2072 : 22807 : jl_module_t *m = (jl_module_t*)jl_deserialize_value(s, NULL);
2073 : 22807 : jl_sym_t *sym = (jl_sym_t*)jl_deserialize_value(s, NULL);
2074 [ + + ]: 22807 : if (internal) {
2075 : 10744 : tn->module = m;
2076 : 10744 : tn->name = sym;
2077 : 10744 : tn->names = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&tn->names);
2078 : 10744 : jl_gc_wb(tn, tn->names);
2079 : 10744 : tn->wrapper = jl_deserialize_value(s, &tn->wrapper);
2080 : 10744 : jl_gc_wb(tn, tn->wrapper);
2081 : 10744 : tn->Typeofwrapper = NULL;
2082 : 10744 : tn->mt = (jl_methtable_t*)jl_deserialize_value(s, (jl_value_t**)&tn->mt);
2083 : 10744 : jl_gc_wb(tn, tn->mt);
2084 : 10744 : ios_read(s->s, (char*)&tn->hash, sizeof(tn->hash));
2085 : 10744 : int8_t flags = read_int8(s->s);
2086 : 10744 : tn->abstract = flags & 1;
2087 : 10744 : tn->mutabl = (flags>>1) & 1;
2088 : 10744 : tn->mayinlinealloc = (flags>>2) & 1;
2089 : 10744 : tn->max_methods = read_uint8(s->s);
2090 [ + + ]: 10744 : if (tn->abstract)
2091 : 27 : tn->n_uninitialized = 0;
2092 : : else
2093 : 10717 : tn->n_uninitialized = read_uint16(s->s);
2094 : 10744 : size_t nfields = read_int32(s->s);
2095 [ - + ]: 10744 : if (nfields) {
2096 : 0 : tn->atomicfields = (uint32_t*)malloc(nfields);
2097 : 0 : ios_read(s->s, (char*)tn->atomicfields, nfields);
2098 : : }
2099 : 10744 : nfields = read_int32(s->s);
2100 [ - + ]: 10744 : 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 : 12063 : jl_datatype_t *dt = (jl_datatype_t*)jl_unwrap_unionall(jl_get_global(m, sym));
2107 [ - + ]: 12063 : assert(jl_is_datatype(dt));
2108 : 12063 : tn = dt->name;
2109 : 12063 : backref_list.items[pos] = tn;
2110 : : }
2111 : 22807 : return (jl_value_t*)tn;
2112 : : }
2113 : 76934 : jl_set_typeof(v, dt);
2114 [ + + ]: 76934 : if ((jl_value_t*)dt == jl_bigint_type) {
2115 : 4 : jl_value_t *sizefield = jl_deserialize_value(s, NULL);
2116 : 4 : int32_t sz = jl_unbox_int32(sizefield);
2117 [ + - ]: 4 : int32_t nw = (sz == 0 ? 1 : (sz < 0 ? -sz : sz));
2118 : 4 : size_t nb = nw * gmp_limb_size;
2119 : 4 : void *buf = jl_gc_counted_malloc(nb);
2120 [ - + ]: 4 : if (buf == NULL)
2121 : 0 : jl_throw(jl_memory_exception);
2122 : 4 : ios_readall(s->s, (char*)buf, nb);
2123 : 4 : jl_set_nth_field(v, 0, jl_box_int32(nw));
2124 : 4 : jl_set_nth_field(v, 1, sizefield);
2125 : 4 : jl_set_nth_field(v, 2, jl_box_voidpointer(buf));
2126 : : }
2127 : : else {
2128 : 76930 : jl_deserialize_struct(s, v);
2129 : : }
2130 : 76934 : return v;
2131 : : }
2132 : :
2133 : 3011220 : static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc) JL_GC_DISABLED
2134 : : {
2135 [ - + ]: 3011220 : assert(!ios_eof(s->s));
2136 : : jl_value_t *v;
2137 : : size_t n;
2138 : : uintptr_t pos;
2139 : 3011220 : uint8_t tag = read_uint8(s->s);
2140 [ + + ]: 3011220 : if (tag > LAST_TAG)
2141 : 764920 : return deser_tag[tag];
2142 [ + + + + : 2246300 : switch (tag) {
+ + + + +
+ + + + +
- + - - -
+ + + + -
+ + + ]
2143 : 290554 : case TAG_NULL: return NULL;
2144 : 67531 : case 0:
2145 : 67531 : tag = read_uint8(s->s);
2146 : 67531 : return deser_tag[tag];
2147 : 1026080 : case TAG_BACKREF: JL_FALLTHROUGH; case TAG_SHORT_BACKREF: ;
2148 [ + + ]: 1026080 : uintptr_t offs = (tag == TAG_BACKREF) ? read_int32(s->s) : read_uint16(s->s);
2149 : 1026080 : int isflagref = 0;
2150 : 1026080 : isflagref = !!(offs & 1);
2151 : 1026080 : offs >>= 1;
2152 : : // assert(offs >= 0); // offs is unsigned so this is always true
2153 [ - + ]: 1026080 : assert(offs < backref_list.len);
2154 : 1026080 : jl_value_t *bp = (jl_value_t*)backref_list.items[offs];
2155 [ - + ]: 1026080 : assert(bp);
2156 [ + + + + ]: 1026080 : if (isflagref && loc != HT_NOTFOUND) {
2157 [ + - ]: 128370 : 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 : 128370 : arraylist_push(&flagref_list, loc);
2161 : 128370 : arraylist_push(&flagref_list, (void*)(uintptr_t)-1);
2162 : : }
2163 : : }
2164 : 1026080 : return (jl_value_t*)bp;
2165 : 164381 : case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC:
2166 : 164381 : return jl_deserialize_value_svec(s, tag, loc);
2167 : 9211 : case TAG_COMMONSYM:
2168 : 9211 : return deser_symbols[read_uint8(s->s)];
2169 : 46726 : case TAG_SYMBOL: JL_FALLTHROUGH; case TAG_LONG_SYMBOL:
2170 : 46726 : return jl_deserialize_value_symbol(s, tag);
2171 : 123347 : case TAG_ARRAY: JL_FALLTHROUGH; case TAG_ARRAY1D:
2172 : 123347 : return jl_deserialize_value_array(s, tag);
2173 : 40953 : case TAG_UNIONALL:
2174 : 40953 : pos = backref_list.len;
2175 : 40953 : arraylist_push(&backref_list, NULL);
2176 [ + + ]: 40953 : if (read_uint8(s->s)) {
2177 : 952 : jl_module_t *m = (jl_module_t*)jl_deserialize_value(s, NULL);
2178 : 952 : jl_sym_t *sym = (jl_sym_t*)jl_deserialize_value(s, NULL);
2179 : 952 : jl_value_t *v = jl_get_global(m, sym);
2180 [ - + ]: 952 : assert(jl_is_unionall(v));
2181 : 952 : backref_list.items[pos] = v;
2182 : 952 : return v;
2183 : : }
2184 : 40001 : v = jl_gc_alloc(s->ptls, sizeof(jl_unionall_t), jl_unionall_type);
2185 : 40001 : backref_list.items[pos] = v;
2186 : 40001 : ((jl_unionall_t*)v)->var = (jl_tvar_t*)jl_deserialize_value(s, (jl_value_t**)&((jl_unionall_t*)v)->var);
2187 : 40001 : jl_gc_wb(v, ((jl_unionall_t*)v)->var);
2188 : 40001 : ((jl_unionall_t*)v)->body = jl_deserialize_value(s, &((jl_unionall_t*)v)->body);
2189 : 40001 : jl_gc_wb(v, ((jl_unionall_t*)v)->body);
2190 : 40001 : return v;
2191 : 27568 : case TAG_TVAR:
2192 : 27568 : v = jl_gc_alloc(s->ptls, sizeof(jl_tvar_t), jl_tvar_type);
2193 : 27568 : jl_tvar_t *tv = (jl_tvar_t*)v;
2194 : 27568 : arraylist_push(&backref_list, tv);
2195 : 27568 : tv->name = (jl_sym_t*)jl_deserialize_value(s, NULL);
2196 : 27568 : jl_gc_wb(tv, tv->name);
2197 : 27568 : tv->lb = jl_deserialize_value(s, &tv->lb);
2198 : 27568 : jl_gc_wb(tv, tv->lb);
2199 : 27568 : tv->ub = jl_deserialize_value(s, &tv->ub);
2200 : 27568 : jl_gc_wb(tv, tv->ub);
2201 : 27568 : return (jl_value_t*)tv;
2202 : 40720 : case TAG_METHOD:
2203 : 40720 : return jl_deserialize_value_method(s, loc);
2204 : 44470 : case TAG_METHOD_INSTANCE:
2205 : 44470 : return jl_deserialize_value_method_instance(s, loc);
2206 : 498 : case TAG_CODE_INSTANCE:
2207 : 498 : return jl_deserialize_value_code_instance(s, loc);
2208 : 647 : case TAG_MODULE:
2209 : 647 : return jl_deserialize_value_module(s);
2210 : 10575 : case TAG_SHORTER_INT64:
2211 : 10575 : v = jl_box_int64((int16_t)read_uint16(s->s));
2212 : 10575 : arraylist_push(&backref_list, v);
2213 : 10575 : 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 : 19 : case TAG_INT64:
2219 : 19 : v = jl_box_int64((int64_t)read_uint64(s->s));
2220 : 19 : arraylist_push(&backref_list, v);
2221 : 19 : 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 : 10792 : case TAG_SINGLETON:
2233 : 10792 : return jl_deserialize_value_singleton(s, loc);
2234 : 4623 : case TAG_CORE:
2235 : 4623 : return (jl_value_t*)jl_core_module;
2236 : 26095 : case TAG_BASE:
2237 : 26095 : return (jl_value_t*)jl_base_module;
2238 : 38 : case TAG_CNULL:
2239 : 38 : v = jl_gc_alloc(s->ptls, sizeof(void*), NULL);
2240 : 38 : jl_set_typeof(v, (void*)(intptr_t)0x50);
2241 : 38 : *(void**)v = NULL;
2242 : 38 : uintptr_t pos = backref_list.len;
2243 : 38 : arraylist_push(&backref_list, v);
2244 : 38 : jl_set_typeof(v, jl_deserialize_value(s, &jl_astaggedvalue(v)->type));
2245 : 38 : 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 : 29842 : case TAG_STRING:
2250 : 29842 : n = read_int32(s->s);
2251 : 29842 : v = jl_alloc_string(n);
2252 : 29842 : arraylist_push(&backref_list, v);
2253 : 29842 : ios_readall(s->s, jl_string_data(v), n);
2254 : 29842 : return v;
2255 : 181887 : case TAG_DATATYPE:
2256 : 181887 : pos = backref_list.len;
2257 : 181887 : arraylist_push(&backref_list, NULL);
2258 : 181887 : return jl_deserialize_datatype(s, pos, loc);
2259 : 99741 : default:
2260 [ + - - + ]: 99741 : assert(tag == TAG_GENERAL || tag == TAG_SHORT_GENERAL);
2261 : 99741 : return jl_deserialize_value_any(s, tag, loc);
2262 : : }
2263 : : }
2264 : :
2265 : : // Add methods to external (non-worklist-owned) functions
2266 : 130 : static void jl_insert_methods(jl_array_t *list)
2267 : : {
2268 : 130 : size_t i, l = jl_array_len(list);
2269 [ + + ]: 9158 : for (i = 0; i < l; i += 2) {
2270 : 9028 : jl_method_t *meth = (jl_method_t*)jl_array_ptr_ref(list, i);
2271 [ - + ]: 9028 : assert(jl_is_method(meth));
2272 [ - + ]: 9028 : assert(!meth->is_for_opaque_closure);
2273 : 9028 : jl_tupletype_t *simpletype = (jl_tupletype_t*)jl_array_ptr_ref(list, i + 1);
2274 : 9028 : jl_methtable_t *mt = jl_method_get_table(meth);
2275 [ - + ]: 9028 : assert((jl_value_t*)mt != jl_nothing);
2276 : 9028 : jl_method_table_insert(mt, meth, simpletype);
2277 : : }
2278 : 130 : }
2279 : :
2280 : 2 : void remove_code_instance_from_validation(jl_code_instance_t *codeinst)
2281 : : {
2282 : 2 : ptrhash_remove(&new_code_instance_validate, codeinst);
2283 : 2 : }
2284 : :
2285 : 130 : static void jl_insert_method_instances(jl_array_t *list)
2286 : : {
2287 : 130 : size_t i, l = jl_array_len(list);
2288 : : // Validate the MethodInstances
2289 : 130 : jl_array_t *valids = jl_alloc_array_1d(jl_array_uint8_type, l);
2290 : 130 : memset(jl_array_data(valids), 1, l);
2291 : 130 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
2292 [ + + ]: 331 : for (i = 0; i < l; i++) {
2293 : 201 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
2294 [ - + ]: 201 : assert(jl_is_method_instance(mi));
2295 [ + - ]: 201 : if (jl_is_method(mi->def.method)) {
2296 : : // Is this still the method we'd be calling?
2297 : 201 : jl_methtable_t *mt = jl_method_table_for(mi->specTypes);
2298 : 201 : struct jl_typemap_assoc search = {(jl_value_t*)mi->specTypes, world, NULL, 0, ~(size_t)0};
2299 : 201 : jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, &search, /*offs*/0, /*subtype*/1);
2300 [ + - ]: 201 : if (entry) {
2301 : 201 : jl_value_t *mworld = entry->func.value;
2302 [ + - + + : 201 : 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 : 1 : jl_array_uint8_set(valids, i, 0);
2304 : 1 : 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 : 1 : jl_code_instance_t *codeinst = mi->cache;
2307 [ + + ]: 2 : while (codeinst) {
2308 : 1 : remove_code_instance_from_validation(codeinst);
2309 : 1 : codeinst = codeinst->next;
2310 : : }
2311 [ - + ]: 1 : 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 [ + + ]: 331 : for (i = 0; i < l; i++) {
2322 : 201 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
2323 : 201 : jl_method_instance_t *milive = jl_specializations_get_or_insert(mi);
2324 : 201 : 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 [ + + ]: 331 : for (i = 0; i < l; i++) {
2328 : 201 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
2329 : 201 : jl_method_instance_t *milive = (jl_method_instance_t*)ptrhash_get(&uniquing_table, mi);
2330 [ + + ]: 201 : 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 [ + - ]: 13 : if (mi->backedges) {
2334 [ + + ]: 13 : if (!milive->backedges) {
2335 : : // Copy all the backedges (after looking up the live ones)
2336 : 1 : size_t j, n = jl_array_len(mi->backedges);
2337 : 1 : milive->backedges = jl_alloc_vec_any(n);
2338 : 1 : jl_gc_wb(milive, milive->backedges);
2339 [ + + ]: 2 : for (j = 0; j < n; j++) {
2340 : 1 : jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, j);
2341 : 1 : jl_method_instance_t *belive = (jl_method_instance_t*)ptrhash_get(&uniquing_table, be);
2342 [ - + ]: 1 : if (belive == HT_NOTFOUND)
2343 : 0 : belive = be;
2344 : 1 : 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 : 12 : size_t j, k, n = jl_array_len(mi->backedges), nlive = jl_array_len(milive->backedges);
2349 [ + + ]: 25 : for (j = 0; j < n; j++) {
2350 : 13 : jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, j);
2351 : 13 : jl_method_instance_t *belive = (jl_method_instance_t*)ptrhash_get(&uniquing_table, be);
2352 [ + + ]: 13 : if (belive == HT_NOTFOUND)
2353 : 9 : belive = be;
2354 : 13 : int found = 0;
2355 [ + + ]: 243 : for (k = 0; k < nlive; k++) {
2356 [ + + ]: 234 : if (belive == (jl_method_instance_t*)jl_array_ptr_ref(milive->backedges, k)) {
2357 : 4 : found = 1;
2358 : 4 : break;
2359 : : }
2360 : : }
2361 [ + + ]: 13 : if (!found)
2362 : 9 : 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 [ + - + - ]: 13 : if (mi->cache && jl_array_uint8_ref(valids, i)) {
2368 [ + - + + ]: 13 : if (!milive->cache || milive->cache->max_world < ~(size_t)0) {
2369 : 1 : jl_code_instance_t *cilive = milive->cache, *ci;
2370 : 1 : milive->cache = mi->cache;
2371 : 1 : jl_gc_wb(milive, milive->cache);
2372 : 1 : ci = mi->cache;
2373 : 1 : ci->def = milive;
2374 [ + + ]: 2 : while (ci->next) {
2375 : 1 : ci = ci->next;
2376 : 1 : ci->def = milive;
2377 : : }
2378 : 1 : ci->next = cilive;
2379 : 1 : jl_gc_wb(ci, ci->next);
2380 : : }
2381 : : }
2382 : : }
2383 : : }
2384 : 130 : }
2385 : :
2386 : : // verify that these edges intersect with the same methods as before
2387 : 130 : static void jl_verify_edges(jl_array_t *targets, jl_array_t **pvalids)
2388 : : {
2389 : 130 : size_t i, l = jl_array_len(targets) / 2;
2390 : 130 : jl_array_t *valids = jl_alloc_array_1d(jl_array_uint8_type, l);
2391 : 130 : memset(jl_array_data(valids), 1, l);
2392 : 130 : jl_value_t *loctag = NULL;
2393 : 130 : JL_GC_PUSH1(&loctag);
2394 : 130 : *pvalids = valids;
2395 [ + + ]: 44370 : for (i = 0; i < l; i++) {
2396 : 44240 : jl_value_t *callee = jl_array_ptr_ref(targets, i * 2);
2397 : 44240 : jl_method_instance_t *callee_mi = (jl_method_instance_t*)callee;
2398 : : jl_value_t *sig;
2399 [ + + ]: 44240 : if (jl_is_method_instance(callee)) {
2400 : 43914 : sig = callee_mi->specTypes;
2401 : : }
2402 : : else {
2403 : 326 : sig = callee;
2404 : : }
2405 : 44240 : jl_array_t *expected = (jl_array_t*)jl_array_ptr_ref(targets, i * 2 + 1);
2406 [ - + ]: 44240 : assert(jl_is_array(expected));
2407 : 44240 : int valid = 1;
2408 : 44240 : size_t min_valid = 0;
2409 : 44240 : size_t max_valid = ~(size_t)0;
2410 : 44240 : int ambig = 0;
2411 : : // TODO: possibly need to included ambiguities too (for the optimizer correctness)?
2412 : 44240 : 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 [ + - + + ]: 44240 : if (matches == jl_false || jl_array_len(matches) != jl_array_len(expected)) {
2414 : 12 : valid = 0;
2415 : : }
2416 : : else {
2417 : 44228 : size_t j, k, l = jl_array_len(expected);
2418 [ + + ]: 89109 : for (k = 0; k < jl_array_len(matches); k++) {
2419 : 44887 : jl_method_match_t *match = (jl_method_match_t*)jl_array_ptr_ref(matches, k);
2420 : 44887 : jl_method_t *m = match->method;
2421 [ + + ]: 47969 : for (j = 0; j < l; j++) {
2422 [ + + ]: 47963 : if (m == (jl_method_t*)jl_array_ptr_ref(expected, j))
2423 : 44881 : break;
2424 : : }
2425 [ + + ]: 44887 : 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 : 6 : valid = 0;
2430 : 6 : break;
2431 : : }
2432 : : }
2433 : : }
2434 : 44240 : jl_array_uint8_set(valids, i, valid);
2435 [ + + - + ]: 44240 : 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 : 130 : JL_GC_POP();
2442 : 130 : }
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 : 130 : 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 : 130 : size_t i, l = jl_array_len(list);
2451 : 130 : jl_array_t *valids = NULL;
2452 : 130 : jl_value_t *loctag = NULL;
2453 : 130 : JL_GC_PUSH2(&valids, &loctag);
2454 : 130 : jl_verify_edges(targets, &valids);
2455 [ + + ]: 440 : for (i = 0; i < l; i += 2) {
2456 : 310 : jl_method_instance_t *caller = (jl_method_instance_t*)jl_array_ptr_ref(list, i);
2457 [ + - + - ]: 310 : assert(jl_is_method_instance(caller) && jl_is_method(caller->def.method));
2458 : 310 : jl_array_t *idxs_array = (jl_array_t*)jl_array_ptr_ref(list, i + 1);
2459 [ - + ]: 310 : assert(jl_isa((jl_value_t*)idxs_array, jl_array_int32_type));
2460 : 310 : int32_t *idxs = (int32_t*)jl_array_data(idxs_array);
2461 : 310 : int valid = 1;
2462 : : size_t j;
2463 [ + + + + ]: 31396 : for (j = 0; valid && j < jl_array_len(idxs_array); j++) {
2464 : 31086 : int32_t idx = idxs[j];
2465 : 31086 : valid = jl_array_uint8_ref(valids, idx);
2466 : : }
2467 [ + + ]: 310 : if (valid) {
2468 : : // if this callee is still valid, add all the backedges
2469 [ + + ]: 21108 : for (j = 0; j < jl_array_len(idxs_array); j++) {
2470 : 20808 : int32_t idx = idxs[j];
2471 : 20808 : jl_value_t *callee = jl_array_ptr_ref(targets, idx * 2);
2472 [ + + ]: 20808 : if (jl_is_method_instance(callee)) {
2473 : 20671 : jl_method_instance_add_backedge((jl_method_instance_t*)callee, caller);
2474 : : }
2475 : : else {
2476 : 137 : 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 [ + - ]: 137 : if ((jl_value_t*)mt != jl_nothing)
2482 : 137 : jl_method_table_add_backedge(mt, callee, (jl_value_t*)caller);
2483 : : }
2484 : : }
2485 : : // then enable it
2486 : 300 : jl_code_instance_t *codeinst = caller->cache;
2487 [ + + ]: 602 : while (codeinst) {
2488 [ + + + - ]: 302 : if (ptrhash_get(&new_code_instance_validate, codeinst) != HT_NOTFOUND && codeinst->min_world > 0)
2489 : 298 : codeinst->max_world = ~(size_t)0;
2490 : 302 : ptrhash_remove(&new_code_instance_validate, codeinst); // mark it as handled
2491 : 302 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
2492 : : }
2493 : : }
2494 : : else {
2495 : 10 : jl_code_instance_t *codeinst = caller->cache;
2496 [ + + ]: 20 : while (codeinst) {
2497 : 10 : ptrhash_remove(&new_code_instance_validate, codeinst); // should be left invalid
2498 : 10 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
2499 : : }
2500 [ - + ]: 10 : 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 : 130 : JL_GC_POP();
2508 : 130 : }
2509 : :
2510 : 130 : static void validate_new_code_instances(void)
2511 : : {
2512 : : size_t i;
2513 [ + + ]: 2658 : for (i = 0; i < new_code_instance_validate.size; i += 2) {
2514 [ + + ]: 2528 : if (new_code_instance_validate.table[i+1] != HT_NOTFOUND) {
2515 : 187 : ((jl_code_instance_t*)new_code_instance_validate.table[i])->max_world = ~(size_t)0;
2516 : : }
2517 : : }
2518 : 130 : }
2519 : :
2520 : 130 : static jl_value_t *read_verify_mod_list(ios_t *s, jl_array_t *mod_list)
2521 : : {
2522 [ - + ]: 130 : 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 : 130 : size_t i, l = jl_array_len(mod_list);
2527 : 5772 : for (i = 0; ; i++) {
2528 : 5772 : size_t len = read_int32(s);
2529 [ + + + - ]: 5772 : if (len == 0 && i == l)
2530 : 130 : return NULL; // success
2531 [ + - - + ]: 5642 : if (len == 0 || i == l)
2532 : 0 : return jl_get_exceptionf(jl_errorexception_type, "Wrong number of entries in module list.");
2533 : 5642 : char *name = (char*)alloca(len + 1);
2534 : 5642 : ios_readall(s, name, len);
2535 : 5642 : name[len] = '\0';
2536 : : jl_uuid_t uuid;
2537 : 5642 : uuid.hi = read_uint64(s);
2538 : 5642 : uuid.lo = read_uint64(s);
2539 : 5642 : uint64_t build_id = read_uint64(s);
2540 : 5642 : jl_sym_t *sym = _jl_symbol(name, len);
2541 : 5642 : jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_list, i);
2542 [ + - + - : 5642 : 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 : 2370 : static int readstr_verify(ios_t *s, const char *str)
2550 : : {
2551 : 2370 : size_t i, len = strlen(str);
2552 [ + + ]: 30914 : for (i = 0; i < len; ++i)
2553 [ + + ]: 28583 : if ((char)read_uint8(s) != str[i])
2554 : 39 : return 0;
2555 : 2331 : return 1;
2556 : : }
2557 : :
2558 : 398 : JL_DLLEXPORT int jl_read_verify_header(ios_t *s)
2559 : : {
2560 : : uint16_t bom;
2561 : 398 : return (readstr_verify(s, JI_MAGIC) &&
2562 [ + - + - ]: 796 : read_uint16(s) == JI_FORMAT_VERSION &&
2563 [ + - ]: 796 : ios_read(s, (char *) &bom, 2) == 2 && bom == BOM &&
2564 [ + - + - ]: 796 : read_uint8(s) == sizeof(void*) &&
2565 [ + - + - ]: 1194 : readstr_verify(s, JL_BUILD_UNAME) && !read_uint8(s) &&
2566 [ + - + - ]: 1194 : readstr_verify(s, JL_BUILD_ARCH) && !read_uint8(s) &&
2567 [ + - + + ]: 1194 : readstr_verify(s, JULIA_VERSION_STRING) && !read_uint8(s) &&
2568 [ + - + + ]: 1158 : readstr_verify(s, jl_git_branch()) && !read_uint8(s) &&
2569 [ + - + - ]: 1176 : readstr_verify(s, jl_git_commit()) && !read_uint8(s));
2570 : : }
2571 : :
2572 : 81 : static void jl_finalize_serializer(jl_serializer_state *s)
2573 : : {
2574 : : size_t i, l;
2575 : : // save module initialization order
2576 [ + - ]: 81 : if (jl_module_init_order != NULL) {
2577 : 81 : l = jl_array_len(jl_module_init_order);
2578 [ + + ]: 99 : for (i = 0; i < l; i++) {
2579 : : // verify that all these modules were saved
2580 [ - + ]: 18 : assert(ptrhash_get(&backref_table, jl_array_ptr_ref(jl_module_init_order, i)) != HT_NOTFOUND);
2581 : : }
2582 : : }
2583 : 81 : jl_serialize_value(s, jl_module_init_order);
2584 : :
2585 : : // record list of reinitialization functions
2586 : 81 : l = reinit_list.len;
2587 [ + + ]: 1492 : for (i = 0; i < l; i += 2) {
2588 : 1411 : write_int32(s->s, (int)((uintptr_t) reinit_list.items[i]));
2589 : 1411 : write_int32(s->s, (int)((uintptr_t) reinit_list.items[i+1]));
2590 : : }
2591 : 81 : write_int32(s->s, -1);
2592 : 81 : }
2593 : :
2594 : 11283 : static void jl_reinit_item(jl_value_t *v, int how, arraylist_t *tracee_list)
2595 : : {
2596 [ + - + + ]: 22566 : JL_TRY {
2597 [ + - + - ]: 11283 : switch (how) {
2598 : 855 : case 1: { // rehash IdDict
2599 : 855 : jl_array_t **a = (jl_array_t**)v;
2600 : : // Assume *a don't need a write barrier
2601 : 855 : *a = jl_idtable_rehash(*a, jl_array_len(*a));
2602 : 855 : jl_gc_wb(v, *a);
2603 : 855 : 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 : 10428 : case 3: { // rehash MethodTable
2626 : 10428 : jl_methtable_t *mt = (jl_methtable_t*)v;
2627 [ - + ]: 10428 : if (tracee_list)
2628 : 0 : arraylist_push(tracee_list, mt);
2629 : 10428 : 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 : 11283 : }
2645 : :
2646 : 130 : static jl_array_t *jl_finalize_deserializer(jl_serializer_state *s, arraylist_t *tracee_list)
2647 : : {
2648 : 130 : jl_array_t *init_order = (jl_array_t*)jl_deserialize_value(s, NULL);
2649 : :
2650 : : // run reinitialization functions
2651 : 130 : int pos = read_int32(s->s);
2652 [ + + ]: 11413 : while (pos != -1) {
2653 : 11283 : jl_reinit_item((jl_value_t*)backref_list.items[pos], read_int32(s->s), tracee_list);
2654 : 11283 : pos = read_int32(s->s);
2655 : : }
2656 : 130 : return init_order;
2657 : : }
2658 : :
2659 : 33 : JL_DLLEXPORT void jl_init_restored_modules(jl_array_t *init_order)
2660 : : {
2661 : 33 : int i, l = jl_array_len(init_order);
2662 [ + + ]: 66 : for (i = 0; i < l; i++) {
2663 : 33 : jl_value_t *mod = jl_array_ptr_ref(init_order, i);
2664 [ + + + - ]: 33 : if (!jl_generating_output() || jl_options.incremental) {
2665 : 33 : 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 : 33 : }
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 : 81 : JL_DLLEXPORT void jl_set_newly_inferred(jl_value_t* _newly_inferred)
2681 : : {
2682 [ + - - + ]: 81 : assert(_newly_inferred == NULL || jl_is_array(_newly_inferred));
2683 : 81 : newly_inferred = (jl_array_t*) _newly_inferred;
2684 : 81 : }
2685 : :
2686 : : // Serialize the modules in `worklist` to file `fname`
2687 : 81 : JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist)
2688 : : {
2689 : : JL_TIMING(SAVE_MODULE);
2690 : : ios_t f;
2691 : 81 : jl_array_t *mod_array = NULL, *udeps = NULL;
2692 [ - + ]: 81 : 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 : 81 : JL_GC_PUSH2(&mod_array, &udeps);
2697 : 81 : mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
2698 [ - + ]: 81 : assert(jl_precompile_toplevel_module == NULL);
2699 : 81 : jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1);
2700 : :
2701 : 81 : serializer_worklist = worklist;
2702 : 81 : write_header(&f);
2703 : : // write description of contents (name, uuid, buildid)
2704 : 81 : 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 : 81 : 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 : 81 : write_mod_list(&f, mod_array);
2713 : :
2714 : 81 : arraylist_new(&reinit_list, 0);
2715 : 81 : htable_new(&edges_map, 0);
2716 : 81 : htable_new(&backref_table, 5000);
2717 [ + - ]: 81 : htable_new(&external_mis, newly_inferred ? jl_array_len(newly_inferred) : 0);
2718 : 81 : ptrhash_put(&backref_table, jl_main_module, (char*)HT_NOTFOUND + 1);
2719 : 81 : backref_table_numel = 1;
2720 [ + - ]: 81 : jl_idtable_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("IdDict")) : NULL;
2721 [ + - ]: 81 : jl_idtable_typename = jl_base_module ? ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_idtable_type))->name : NULL;
2722 [ + - ]: 81 : jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
2723 [ + - ]: 81 : if (jl_bigint_type) {
2724 : 81 : gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
2725 : 81 : jl_symbol("BITS_PER_LIMB"))) / 8;
2726 : : }
2727 : :
2728 : 81 : int en = jl_gc_enable(0); // edges map is not gc-safe
2729 : 81 : 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 : 81 : jl_array_t *ext_targets = jl_alloc_vec_any(0); // [callee1, matches1, ...] non-worklist callees of worklist-owned methods
2731 : 81 : jl_array_t *edges = jl_alloc_vec_any(0); // [caller1, ext_targets_indexes1, ...] for worklist-owned methods calling external methods
2732 : :
2733 : 81 : int n_ext_mis = queue_external_mis(newly_inferred);
2734 : :
2735 : : size_t i;
2736 : 81 : size_t len = jl_array_len(mod_array);
2737 [ + + ]: 3682 : for (i = 0; i < len; i++) {
2738 : 3601 : jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_array, i);
2739 [ - + ]: 3601 : assert(jl_is_module(m));
2740 [ + + ]: 3601 : if (m->parent == m) // some toplevel modules (really just Base) aren't actually
2741 : 3520 : jl_collect_extext_methods_from_mod(extext_methods, m);
2742 : : }
2743 : 81 : jl_collect_methtable_from_mod(extext_methods, jl_type_type_mt);
2744 : 81 : jl_collect_missing_backedges_to_mod(jl_type_type_mt);
2745 : 81 : jl_collect_methtable_from_mod(extext_methods, jl_nonfunction_mt);
2746 : 81 : 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 : 81 : jl_collect_backedges(edges, ext_targets);
2751 : :
2752 : 81 : jl_serializer_state s = {
2753 : : &f,
2754 : 81 : jl_current_task->ptls,
2755 : : mod_array
2756 : : };
2757 : 81 : jl_serialize_value(&s, worklist); // serialize module-owned items (those accessible from the bindings table)
2758 : 81 : jl_serialize_value(&s, extext_methods); // serialize new worklist-owned methods for external functions
2759 : 81 : 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 : 81 : jl_serialize_value(&s, edges);
2764 : 81 : jl_serialize_value(&s, ext_targets);
2765 : 81 : jl_finalize_serializer(&s);
2766 : 81 : serializer_worklist = NULL;
2767 : :
2768 : 81 : jl_gc_enable(en);
2769 : 81 : htable_reset(&edges_map, 0);
2770 : 81 : htable_reset(&backref_table, 0);
2771 : 81 : htable_reset(&external_mis, 0);
2772 : 81 : arraylist_free(&reinit_list);
2773 : :
2774 : : // Write the source-text for the dependent files
2775 [ + - ]: 81 : if (udeps) {
2776 : : // Go back and update the source-text position to point to the current position
2777 : 81 : int64_t posfile = ios_pos(&f);
2778 : 81 : ios_seek(&f, srctextpos);
2779 : 81 : write_int64(&f, posfile);
2780 : 81 : 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 : 81 : len = jl_array_len(udeps);
2788 : : ios_t srctext;
2789 [ + + ]: 248 : for (i = 0; i < len; i++) {
2790 : 167 : jl_value_t *deptuple = jl_array_ptr_ref(udeps, i);
2791 : 167 : 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 [ + + ]: 167 : if (depmod != (jl_value_t*)jl_main_module) {
2795 : 165 : jl_value_t *dep = jl_fieldref(deptuple, 1); // file abspath
2796 : 165 : const char *depstr = jl_string_data(dep);
2797 [ + + ]: 165 : if (!depstr[0])
2798 : 68 : continue;
2799 : 97 : ios_t *srctp = ios_file(&srctext, depstr, 1, 0, 0, 0);
2800 [ - + ]: 97 : 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 : 97 : size_t slen = jl_string_len(dep);
2806 : 97 : write_int32(&f, slen);
2807 : 97 : ios_write(&f, depstr, slen);
2808 : 97 : posfile = ios_pos(&f);
2809 : 97 : write_uint64(&f, 0); // placeholder for length of this file in bytes
2810 : 97 : uint64_t filelen = (uint64_t) ios_copyall(&f, &srctext);
2811 : 97 : ios_close(&srctext);
2812 : 97 : ios_seek(&f, posfile);
2813 : 97 : write_uint64(&f, filelen);
2814 : 97 : ios_seek_end(&f);
2815 : : }
2816 : : }
2817 : : }
2818 : 81 : write_int32(&f, 0); // mark the end of the source text
2819 : 81 : ios_close(&f);
2820 : 81 : JL_GC_POP();
2821 : 81 : jl_precompile_toplevel_module = NULL;
2822 : :
2823 : 81 : 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 : 17221 : static int jl_invalid_types_equal(jl_datatype_t *a, jl_datatype_t *b)
2830 : : {
2831 [ + - + - ]: 17221 : return jl_subtype((jl_value_t*)a, (jl_value_t*)b) && jl_subtype((jl_value_t*)b, (jl_value_t*)a);
2832 : : }
2833 : 126771 : STATIC_INLINE jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT
2834 : : {
2835 [ + - + - : 126771 : assert(v && jl_typeof(v) && jl_typeof(jl_typeof(v)) == (jl_value_t*)jl_datatype_type);
+ - ]
2836 : 126771 : return v;
2837 : : }
2838 : : #endif
2839 : :
2840 : :
2841 : : static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED;
2842 : :
2843 : 53708 : static jl_value_t *recache_type(jl_value_t *p) JL_GC_DISABLED
2844 : : {
2845 [ + + ]: 53708 : if (jl_is_datatype(p)) {
2846 : 44427 : jl_datatype_t *pdt = (jl_datatype_t*)p;
2847 [ + + ]: 44427 : if (ptrhash_get(&uniquing_table, p) != HT_NOTFOUND) {
2848 : 37693 : p = (jl_value_t*)recache_datatype(pdt);
2849 : : }
2850 : : else {
2851 : 6734 : jl_svec_t *tt = pdt->parameters;
2852 : : // ensure all type parameters are recached
2853 : 6734 : size_t i, l = jl_svec_len(tt);
2854 [ + + ]: 10318 : for (i = 0; i < l; i++)
2855 : 3584 : jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
2856 : 6734 : ptrhash_put(&uniquing_table, p, p); // ensures this algorithm isn't too exponential
2857 : : }
2858 : : }
2859 [ + + ]: 9281 : else if (jl_is_typevar(p)) {
2860 : 2502 : jl_tvar_t *ptv = (jl_tvar_t*)p;
2861 : 2502 : ptv->lb = recache_type(ptv->lb);
2862 : 2502 : ptv->ub = recache_type(ptv->ub);
2863 : : }
2864 [ + + ]: 6779 : else if (jl_is_uniontype(p)) {
2865 : 394 : jl_uniontype_t *pu = (jl_uniontype_t*)p;
2866 : 394 : pu->a = recache_type(pu->a);
2867 : 394 : pu->b = recache_type(pu->b);
2868 : : }
2869 [ + + ]: 6385 : else if (jl_is_unionall(p)) {
2870 : 1268 : jl_unionall_t *pa = (jl_unionall_t*)p;
2871 : 1268 : pa->var = (jl_tvar_t*)recache_type((jl_value_t*)pa->var);
2872 : 1268 : pa->body = recache_type(pa->body);
2873 : : }
2874 : : else {
2875 : 5117 : jl_datatype_t *pt = (jl_datatype_t*)jl_typeof(p);
2876 : 5117 : jl_datatype_t *cachep = recache_datatype(pt);
2877 [ + + ]: 5117 : if (cachep->instance)
2878 : 2555 : p = cachep->instance;
2879 [ - + ]: 2562 : else if (pt != cachep)
2880 : 0 : jl_set_typeof(p, cachep);
2881 : : }
2882 : 53708 : return p;
2883 : : }
2884 : :
2885 : : // Extract pre-existing datatypes from cache, and insert new types into cache
2886 : : // insertions also update uniquing_table
2887 : 126771 : 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 [ - + ]: 126771 : assert(verify_type((jl_value_t*)dt));
2891 : 126771 : t = (jl_datatype_t*)ptrhash_get(&uniquing_table, dt);
2892 [ + + ]: 126771 : if (t == HT_NOTFOUND)
2893 : 22216 : return dt;
2894 [ + + ]: 104555 : if (t != NULL)
2895 : 87334 : return t;
2896 : :
2897 : 17221 : jl_svec_t *tt = dt->parameters;
2898 : : // recache all type parameters
2899 : 17221 : size_t i, l = jl_svec_len(tt);
2900 [ + + ]: 59017 : for (i = 0; i < l; i++)
2901 : 41796 : jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
2902 : :
2903 : : // then recache the type itself
2904 [ - + ]: 17221 : if (jl_svec_len(tt) == 0) { // jl_cache_type doesn't work if length(parameters) == 0
2905 : 0 : t = dt;
2906 : : }
2907 : : else {
2908 : 17221 : t = jl_lookup_cache_type_(dt);
2909 [ + + ]: 17221 : if (t == NULL) {
2910 : 2310 : jl_cache_type_(dt);
2911 : 2310 : t = dt;
2912 : : }
2913 [ - + ]: 17221 : assert(t->hash == dt->hash);
2914 [ - + ]: 17221 : assert(jl_invalid_types_equal(t, dt));
2915 : : }
2916 : 17221 : ptrhash_put(&uniquing_table, dt, t);
2917 : 17221 : 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 : 130 : static void jl_recache_types(void) JL_GC_DISABLED
2923 : : {
2924 : : size_t i;
2925 : : // first rewrite all the unique'd objects
2926 [ + + ]: 217330 : for (i = 0; i < flagref_list.len; i += 2) {
2927 : 217200 : jl_value_t **loc = (jl_value_t**)flagref_list.items[i + 0];
2928 : 217200 : int offs = (int)(intptr_t)flagref_list.items[i + 1];
2929 [ + + ]: 217200 : jl_value_t *o = loc ? *loc : (jl_value_t*)backref_list.items[offs];
2930 [ + + + + ]: 217200 : if (!jl_is_method(o) && !jl_is_method_instance(o)) {
2931 : : jl_datatype_t *dt;
2932 : : jl_value_t *v;
2933 [ + + ]: 83961 : if (jl_is_datatype(o)) {
2934 : 73151 : dt = (jl_datatype_t*)o;
2935 : 73151 : v = dt->instance;
2936 : : }
2937 : : else {
2938 : 10810 : dt = (jl_datatype_t*)jl_typeof(o);
2939 : 10810 : v = o;
2940 : : }
2941 : 83961 : jl_datatype_t *t = recache_datatype(dt); // get or create cached type (also updates uniquing_table)
2942 [ + + + + ]: 83961 : if ((jl_value_t*)dt == o && t != dt) {
2943 [ - + ]: 60882 : assert(!type_in_worklist(dt));
2944 [ + - ]: 60882 : if (loc)
2945 : 60882 : *loc = (jl_value_t*)t;
2946 [ + + ]: 60882 : if (offs > 0)
2947 : 14185 : backref_list.items[offs] = t;
2948 : : }
2949 [ + + + + ]: 83961 : if (v == o && t->instance != v) {
2950 [ - + ]: 402 : assert(t->instance);
2951 [ - + ]: 402 : assert(loc);
2952 : 402 : *loc = t->instance;
2953 [ + + ]: 402 : if (offs > 0)
2954 : 385 : backref_list.items[offs] = t->instance;
2955 : : }
2956 : : }
2957 : : }
2958 : : // invalidate the old datatypes to help catch errors
2959 [ + + ]: 55634 : for (i = 0; i < uniquing_table.size; i += 2) {
2960 : 55504 : jl_datatype_t *o = (jl_datatype_t*)uniquing_table.table[i]; // deserialized ref
2961 : 55504 : jl_datatype_t *t = (jl_datatype_t*)uniquing_table.table[i + 1]; // the real type
2962 [ + + ]: 55504 : if (o != t) {
2963 [ + - + - ]: 14911 : assert(t != NULL && jl_is_datatype(o));
2964 [ - + ]: 14911 : if (t->instance != o->instance)
2965 : 0 : jl_set_typeof(o->instance, (void*)(intptr_t)0x20);
2966 : 14911 : 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 : 130 : i = 0;
2971 [ + + ]: 217211 : while (i < flagref_list.len) {
2972 : 217200 : jl_value_t **loc = (jl_value_t**)flagref_list.items[i + 0];
2973 : 217200 : int offs = (int)(intptr_t)flagref_list.items[i + 1];
2974 [ + + ]: 217200 : jl_value_t *o = loc ? *loc : (jl_value_t*)backref_list.items[offs];
2975 [ + + + + ]: 217200 : if (jl_is_method(o) || jl_is_method_instance(o)) {
2976 : 133239 : i += 2;
2977 : : }
2978 : : else {
2979 : : // delete this item from the flagref list, so it won't be re-encountered later
2980 : 83961 : flagref_list.len -= 2;
2981 [ + + ]: 83961 : if (i >= flagref_list.len)
2982 : 119 : break;
2983 : 83842 : flagref_list.items[i + 0] = flagref_list.items[flagref_list.len + 0]; // move end-of-list here (executes a `reverse()`)
2984 : 83842 : flagref_list.items[i + 1] = flagref_list.items[flagref_list.len + 1];
2985 : : }
2986 : : }
2987 : 130 : }
2988 : :
2989 : : // look up a method from a previously deserialized dependent module
2990 : 16890 : static jl_method_t *jl_lookup_method(jl_methtable_t *mt, jl_datatype_t *sig, size_t world)
2991 : : {
2992 [ - + ]: 16890 : if (world < jl_main_module->primary_world)
2993 : 0 : world = jl_main_module->primary_world;
2994 : 16890 : struct jl_typemap_assoc search = {(jl_value_t*)sig, world, NULL, 0, ~(size_t)0};
2995 : 16890 : jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, &search, /*offs*/0, /*subtype*/0);
2996 : 16890 : return (jl_method_t*)entry->func.value;
2997 : : }
2998 : :
2999 : 16890 : static jl_method_t *jl_recache_method(jl_method_t *m)
3000 : : {
3001 [ - + ]: 16890 : assert(!m->is_for_opaque_closure);
3002 [ - + ]: 16890 : assert(jl_is_method(m));
3003 : 16890 : jl_datatype_t *sig = (jl_datatype_t*)m->sig;
3004 : 16890 : jl_methtable_t *mt = jl_method_get_table(m);
3005 [ - + ]: 16890 : assert((jl_value_t*)mt != jl_nothing);
3006 : 16890 : jl_set_typeof(m, (void*)(intptr_t)0x30); // invalidate the old value to help catch errors
3007 : 16890 : 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 : 43927 : static jl_method_instance_t *jl_recache_method_instance(jl_method_instance_t *mi)
3013 : : {
3014 : 43927 : jl_method_t *m = mi->def.method;
3015 : 43927 : m = (jl_method_t*)jl_recache_other_((jl_value_t*)m);
3016 [ - + ]: 43927 : assert(jl_is_method(m));
3017 : 43927 : jl_datatype_t *argtypes = (jl_datatype_t*)mi->specTypes;
3018 : 43927 : jl_set_typeof(mi, (void*)(intptr_t)0x40); // invalidate the old value to help catch errors
3019 : 43927 : jl_svec_t *env = jl_emptysvec;
3020 : 43927 : 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 [ - + ]: 43927 : 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 : 43927 : jl_method_instance_t *_new = jl_specializations_get_linfo(m, (jl_value_t*)argtypes, env);
3025 : 43927 : return _new;
3026 : : }
3027 : :
3028 : 177166 : static jl_value_t *jl_recache_other_(jl_value_t *o)
3029 : : {
3030 : 177166 : jl_value_t *newo = (jl_value_t*)ptrhash_get(&uniquing_table, o);
3031 [ + + ]: 177166 : if (newo != HT_NOTFOUND)
3032 : 116349 : return newo;
3033 [ + + ]: 60817 : if (jl_is_method(o)) {
3034 : : // lookup the real Method based on the placeholder sig
3035 : 16890 : newo = (jl_value_t*)jl_recache_method((jl_method_t*)o);
3036 : 16890 : ptrhash_put(&uniquing_table, newo, newo);
3037 : : }
3038 [ + - ]: 43927 : else if (jl_is_method_instance(o)) {
3039 : : // lookup the real MethodInstance based on the placeholder specTypes
3040 : 43927 : newo = (jl_value_t*)jl_recache_method_instance((jl_method_instance_t*)o);
3041 : : }
3042 : : else {
3043 : 0 : abort();
3044 : : }
3045 : 60817 : ptrhash_put(&uniquing_table, o, newo);
3046 : 60817 : return newo;
3047 : : }
3048 : :
3049 : 130 : static void jl_recache_other(void)
3050 : : {
3051 : 130 : size_t i = 0;
3052 [ + + ]: 133369 : while (i < flagref_list.len) {
3053 : 133239 : jl_value_t **loc = (jl_value_t**)flagref_list.items[i + 0];
3054 : 133239 : int offs = (int)(intptr_t)flagref_list.items[i + 1];
3055 [ + - ]: 133239 : jl_value_t *o = loc ? *loc : (jl_value_t*)backref_list.items[offs];
3056 : 133239 : i += 2;
3057 : 133239 : jl_value_t *newo = jl_recache_other_(o);
3058 [ + - ]: 133239 : if (loc)
3059 : 133239 : *loc = newo;
3060 [ + + ]: 133239 : if (offs > 0)
3061 : 60817 : backref_list.items[offs] = newo;
3062 : : }
3063 : 130 : flagref_list.len = 0;
3064 : 130 : }
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 : 130 : static void jl_copy_roots(void)
3071 : : {
3072 : : size_t i, j, l;
3073 [ + + ]: 2258 : for (i = 0; i < queued_method_roots.size; i+=2) {
3074 : 2128 : jl_method_t *m = (jl_method_t*)queued_method_roots.table[i];
3075 : 2128 : m = (jl_method_t*)ptrhash_get(&uniquing_table, m);
3076 : 2128 : jl_svec_t *keyroots = (jl_svec_t*)queued_method_roots.table[i+1];
3077 [ + + ]: 2128 : if (keyroots != HT_NOTFOUND) {
3078 : 217 : uint64_t key = (uint64_t)(uintptr_t)jl_svec_ref(keyroots, 0) | ((uint64_t)(uintptr_t)jl_svec_ref(keyroots, 1) << 32);
3079 : 217 : jl_array_t *roots = (jl_array_t*)jl_svec_ref(keyroots, 2);
3080 [ - + ]: 217 : assert(jl_is_array(roots));
3081 : 217 : l = jl_array_len(roots);
3082 [ + + ]: 1584 : for (j = 0; j < l; j++) {
3083 : 1367 : jl_value_t *r = jl_array_ptr_ref(roots, j);
3084 : 1367 : jl_value_t *newr = (jl_value_t*)ptrhash_get(&uniquing_table, r);
3085 [ + + ]: 1367 : if (newr != HT_NOTFOUND) {
3086 : 145 : jl_array_ptr_set(roots, j, newr);
3087 : : }
3088 : : }
3089 : 217 : jl_append_method_roots(m, key, roots);
3090 : : }
3091 : : }
3092 : 130 : }
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 : 130 : static jl_value_t *_jl_restore_incremental(ios_t *f, jl_array_t *mod_array)
3102 : : {
3103 : : JL_TIMING(LOAD_MODULE);
3104 : 130 : jl_task_t *ct = jl_current_task;
3105 [ + - - + ]: 130 : 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 [ + + ]: 260 : while ((len = read_int32(f)))
3113 : 130 : ios_skip(f, len + 3 * sizeof(uint64_t));
3114 : : }
3115 : : { // skip past the dependency list
3116 : 130 : size_t deplen = read_uint64(f);
3117 : 130 : ios_skip(f, deplen);
3118 : : }
3119 : :
3120 [ + - ]: 130 : jl_bigint_type = jl_base_module ? jl_get_global(jl_base_module, jl_symbol("BigInt")) : NULL;
3121 [ + - ]: 130 : if (jl_bigint_type) {
3122 : 130 : gmp_limb_size = jl_unbox_long(jl_get_global((jl_module_t*)jl_get_global(jl_base_module, jl_symbol("GMP")),
3123 : 130 : jl_symbol("BITS_PER_LIMB"))) / 8;
3124 : : }
3125 : :
3126 : : // verify that the system state is valid
3127 : 130 : jl_value_t *verify_fail = read_verify_mod_list(f, mod_array);
3128 [ - + ]: 130 : if (verify_fail) {
3129 : 0 : ios_close(f);
3130 : 0 : return verify_fail;
3131 : : }
3132 : :
3133 : : // prepare to deserialize
3134 : 130 : int en = jl_gc_enable(0);
3135 : 130 : jl_gc_enable_finalizers(ct, 0);
3136 : 130 : jl_atomic_fetch_add(&jl_world_counter, 1); // reserve a world age for the deserialization
3137 : :
3138 : 130 : arraylist_new(&backref_list, 4000);
3139 : 130 : arraylist_push(&backref_list, jl_main_module);
3140 : 130 : arraylist_new(&flagref_list, 0);
3141 : 130 : htable_new(&queued_method_roots, 0);
3142 : 130 : htable_new(&new_code_instance_validate, 0);
3143 : 130 : arraylist_new(&ccallable_list, 0);
3144 : 130 : htable_new(&uniquing_table, 0);
3145 : :
3146 : 130 : jl_serializer_state s = {
3147 : : f,
3148 : 130 : ct->ptls,
3149 : : mod_array
3150 : : };
3151 : 130 : jl_array_t *restored = (jl_array_t*)jl_deserialize_value(&s, (jl_value_t**)&restored);
3152 : 130 : serializer_worklist = restored;
3153 [ - + ]: 130 : 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 : 130 : jl_value_t *extext_methods = jl_deserialize_value(&s, &extext_methods);
3157 : 130 : int i, n_ext_mis = read_int32(s.s);
3158 : 130 : jl_array_t *mi_list = jl_alloc_vec_any(n_ext_mis); // reload MIs stored by serialize_htable_keys
3159 : 130 : jl_value_t **midata = (jl_value_t**)jl_array_data(mi_list);
3160 [ + + ]: 331 : for (i = 0; i < n_ext_mis; i++)
3161 : 201 : midata[i] = jl_deserialize_value(&s, &(midata[i]));
3162 : 130 : jl_value_t *edges = jl_deserialize_value(&s, &edges);
3163 : 130 : jl_value_t *ext_targets = jl_deserialize_value(&s, &ext_targets);
3164 : :
3165 : 130 : arraylist_t *tracee_list = NULL;
3166 [ - + ]: 130 : 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 : 130 : jl_recache_types(); // make all of the types identities correct
3172 : 130 : jl_insert_methods((jl_array_t*)extext_methods); // hook up extension methods for external generic functions (needs to be after recache types)
3173 : 130 : jl_recache_other(); // make all of the other objects identities correct (needs to be after insert methods)
3174 : 130 : 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 : 130 : jl_insert_method_instances(mi_list); // insert novel specializations
3177 : 130 : htable_free(&uniquing_table);
3178 : 130 : jl_array_t *init_order = jl_finalize_deserializer(&s, tracee_list); // done with f and s (needs to be after recache)
3179 [ - + ]: 130 : if (init_order == NULL)
3180 : 0 : init_order = (jl_array_t*)jl_an_empty_vec_any;
3181 [ - + ]: 130 : assert(jl_isa((jl_value_t*)init_order, jl_array_any_type));
3182 : :
3183 : 130 : JL_GC_PUSH4(&init_order, &restored, &edges, &ext_targets);
3184 : 130 : jl_gc_enable(en); // subtyping can allocate a lot, not valid before recache-other
3185 : :
3186 : 130 : 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 : 130 : validate_new_code_instances();
3190 : :
3191 : 130 : serializer_worklist = NULL;
3192 : 130 : htable_free(&new_code_instance_validate);
3193 : 130 : arraylist_free(&flagref_list);
3194 : 130 : arraylist_free(&backref_list);
3195 : 130 : htable_free(&queued_method_roots);
3196 : 130 : ios_close(f);
3197 : :
3198 : 130 : jl_gc_enable_finalizers(ct, 1); // make sure we don't run any Julia code concurrently before this point
3199 [ - + ]: 130 : 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 [ + + ]: 132 : for (int i = 0; i < ccallable_list.len; i++) {
3209 : 2 : jl_svec_t *item = (jl_svec_t*)ccallable_list.items[i];
3210 : : JL_GC_PROMISE_ROOTED(item);
3211 : 2 : int success = jl_compile_extern_c(NULL, NULL, NULL, jl_svecref(item, 0), jl_svecref(item, 1));
3212 [ + + ]: 2 : if (!success)
3213 : 1 : jl_safe_printf("@ccallable was already defined for this method name\n");
3214 : : }
3215 : 130 : arraylist_free(&ccallable_list);
3216 : 130 : jl_value_t *ret = (jl_value_t*)jl_svec(2, restored, init_order);
3217 : 130 : JL_GC_POP();
3218 : :
3219 : 130 : 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 : 130 : JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *mod_array)
3230 : : {
3231 : : ios_t f;
3232 [ - + ]: 130 : 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 : 130 : return _jl_restore_incremental(&f, mod_array);
3237 : : }
3238 : :
3239 : : // --- init ---
3240 : :
3241 : 566 : void jl_init_serializer(void)
3242 : : {
3243 : 566 : jl_task_t *ct = jl_current_task;
3244 : 566 : htable_new(&ser_tag, 0);
3245 : 566 : htable_new(&common_symbol_tag, 0);
3246 : 566 : htable_new(&backref_table, 0);
3247 : :
3248 : 566 : void *vals[] = { jl_emptysvec, jl_emptytuple, jl_false, jl_true, jl_nothing, jl_any_type,
3249 : 566 : 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 : 566 : jl_box_int32(0), jl_box_int32(1), jl_box_int32(2),
3256 : 566 : jl_box_int32(3), jl_box_int32(4), jl_box_int32(5),
3257 : 566 : jl_box_int32(6), jl_box_int32(7), jl_box_int32(8),
3258 : 566 : jl_box_int32(9), jl_box_int32(10), jl_box_int32(11),
3259 : 566 : jl_box_int32(12), jl_box_int32(13), jl_box_int32(14),
3260 : 566 : jl_box_int32(15), jl_box_int32(16), jl_box_int32(17),
3261 : 566 : jl_box_int32(18), jl_box_int32(19), jl_box_int32(20),
3262 : :
3263 : 566 : jl_box_int64(0), jl_box_int64(1), jl_box_int64(2),
3264 : 566 : jl_box_int64(3), jl_box_int64(4), jl_box_int64(5),
3265 : 566 : jl_box_int64(6), jl_box_int64(7), jl_box_int64(8),
3266 : 566 : jl_box_int64(9), jl_box_int64(10), jl_box_int64(11),
3267 : 566 : jl_box_int64(12), jl_box_int64(13), jl_box_int64(14),
3268 : 566 : jl_box_int64(15), jl_box_int64(16), jl_box_int64(17),
3269 : 566 : 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 : 566 : 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 : 566 : 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 : 566 : ct->ptls->root_task,
3289 : :
3290 : : NULL };
3291 : :
3292 : : // more common symbols, less common than those above. will get 2-byte encodings.
3293 : 566 : void *common_symbols[] = {
3294 : : #include "common_symbols2.inc"
3295 : : NULL
3296 : : };
3297 : :
3298 : 566 : deser_tag[TAG_SYMBOL] = (jl_value_t*)jl_symbol_type;
3299 : 566 : deser_tag[TAG_SSAVALUE] = (jl_value_t*)jl_ssavalue_type;
3300 : 566 : deser_tag[TAG_DATATYPE] = (jl_value_t*)jl_datatype_type;
3301 : 566 : deser_tag[TAG_SLOTNUMBER] = (jl_value_t*)jl_slotnumber_type;
3302 : 566 : deser_tag[TAG_SVEC] = (jl_value_t*)jl_simplevector_type;
3303 : 566 : deser_tag[TAG_ARRAY] = (jl_value_t*)jl_array_type;
3304 : 566 : deser_tag[TAG_EXPR] = (jl_value_t*)jl_expr_type;
3305 : 566 : deser_tag[TAG_PHINODE] = (jl_value_t*)jl_phinode_type;
3306 : 566 : deser_tag[TAG_PHICNODE] = (jl_value_t*)jl_phicnode_type;
3307 : 566 : deser_tag[TAG_STRING] = (jl_value_t*)jl_string_type;
3308 : 566 : deser_tag[TAG_MODULE] = (jl_value_t*)jl_module_type;
3309 : 566 : deser_tag[TAG_TVAR] = (jl_value_t*)jl_tvar_type;
3310 : 566 : deser_tag[TAG_METHOD_INSTANCE] = (jl_value_t*)jl_method_instance_type;
3311 : 566 : deser_tag[TAG_METHOD] = (jl_value_t*)jl_method_type;
3312 : 566 : deser_tag[TAG_CODE_INSTANCE] = (jl_value_t*)jl_code_instance_type;
3313 : 566 : deser_tag[TAG_GLOBALREF] = (jl_value_t*)jl_globalref_type;
3314 : 566 : deser_tag[TAG_INT32] = (jl_value_t*)jl_int32_type;
3315 : 566 : deser_tag[TAG_INT64] = (jl_value_t*)jl_int64_type;
3316 : 566 : deser_tag[TAG_UINT8] = (jl_value_t*)jl_uint8_type;
3317 : 566 : deser_tag[TAG_LINEINFO] = (jl_value_t*)jl_lineinfonode_type;
3318 : 566 : deser_tag[TAG_UNIONALL] = (jl_value_t*)jl_unionall_type;
3319 : 566 : deser_tag[TAG_GOTONODE] = (jl_value_t*)jl_gotonode_type;
3320 : 566 : deser_tag[TAG_QUOTENODE] = (jl_value_t*)jl_quotenode_type;
3321 : 566 : deser_tag[TAG_GOTOIFNOT] = (jl_value_t*)jl_gotoifnot_type;
3322 : 566 : deser_tag[TAG_RETURNNODE] = (jl_value_t*)jl_returnnode_type;
3323 : 566 : deser_tag[TAG_ARGUMENT] = (jl_value_t*)jl_argument_type;
3324 : :
3325 : 566 : intptr_t i = 0;
3326 [ + + ]: 112068 : while (vals[i] != NULL) {
3327 : 111502 : deser_tag[LAST_TAG+1+i] = (jl_value_t*)vals[i];
3328 : 111502 : i += 1;
3329 : : }
3330 [ - + ]: 566 : assert(LAST_TAG+1+i < 256);
3331 : :
3332 [ + + ]: 144330 : for (i = 2; i < 256; i++) {
3333 [ + + ]: 143764 : if (deser_tag[i])
3334 : 126218 : ptrhash_put(&ser_tag, deser_tag[i], (void*)i);
3335 : : }
3336 : :
3337 : 566 : i = 2;
3338 [ + + ]: 144330 : while (common_symbols[i-2] != NULL) {
3339 : 143764 : ptrhash_put(&common_symbol_tag, common_symbols[i-2], (void*)i);
3340 : 143764 : deser_symbols[i] = (jl_value_t*)common_symbols[i-2];
3341 : 143764 : i += 1;
3342 : : }
3343 [ - + ]: 566 : assert(i <= 256);
3344 : 566 : }
3345 : :
3346 : : #ifdef __cplusplus
3347 : : }
3348 : : #endif
|