Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : /*
4 : : Generic Functions
5 : : . method table and lookup
6 : : . GF constructor
7 : : . dispatch
8 : : . static parameter inference
9 : : . method specialization and caching, invoking type inference
10 : : */
11 : : #include <stdlib.h>
12 : : #include <string.h>
13 : : #include "julia.h"
14 : : #include "julia_internal.h"
15 : : #ifndef _OS_WINDOWS_
16 : : #include <unistd.h>
17 : : #endif
18 : : #include "julia_assert.h"
19 : :
20 : : // The compilation signature is not used to cache the method if the number of overlapping methods is greater than this
21 : : #define MAX_UNSPECIALIZED_CONFLICTS 32
22 : :
23 : : #ifdef __cplusplus
24 : : extern "C" {
25 : : #endif
26 : :
27 : : JL_DLLEXPORT _Atomic(size_t) jl_world_counter = 1; // uses atomic acquire/release
28 : 1143380 : JL_DLLEXPORT size_t jl_get_world_counter(void) JL_NOTSAFEPOINT
29 : : {
30 : 1143380 : return jl_atomic_load_acquire(&jl_world_counter);
31 : : }
32 : :
33 : 121 : JL_DLLEXPORT size_t jl_get_tls_world_age(void) JL_NOTSAFEPOINT
34 : : {
35 : 121 : return jl_current_task->world_age;
36 : : }
37 : :
38 : : /// ----- Handling for Julia callbacks ----- ///
39 : :
40 : 0 : JL_DLLEXPORT int8_t jl_is_in_pure_context(void)
41 : : {
42 : 0 : jl_task_t *ct = jl_current_task;
43 : 0 : return ct->ptls->in_pure_callback;
44 : : }
45 : :
46 : : tracer_cb jl_newmeth_tracer = NULL;
47 : 0 : JL_DLLEXPORT void jl_register_newmeth_tracer(void (*callback)(jl_method_t *tracee))
48 : : {
49 : 0 : jl_newmeth_tracer = (tracer_cb)callback;
50 : 0 : }
51 : :
52 : 0 : void jl_call_tracer(tracer_cb callback, jl_value_t *tracee)
53 : : {
54 : 0 : jl_task_t *ct = jl_current_task;
55 : 0 : int last_in = ct->ptls->in_pure_callback;
56 [ # # # # ]: 0 : JL_TRY {
57 : 0 : ct->ptls->in_pure_callback = 1;
58 : 0 : callback(tracee);
59 : 0 : ct->ptls->in_pure_callback = last_in;
60 : : }
61 [ # # ]: 0 : JL_CATCH {
62 : 0 : ct->ptls->in_pure_callback = last_in;
63 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "WARNING: tracer callback function threw an error:\n");
64 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
65 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
66 : 0 : jlbacktrace(); // written to STDERR_FILENO
67 : : }
68 : 0 : }
69 : :
70 : : /// ----- Definitions for various internal TypeMaps ----- ///
71 : :
72 : 141334000 : static int8_t jl_cachearg_offset(jl_methtable_t *mt)
73 : : {
74 : 141334000 : return mt->offs;
75 : : }
76 : :
77 : : /// ----- Insertion logic for special entries ----- ///
78 : :
79 : :
80 : 378628 : static uint_t speccache_hash(size_t idx, jl_svec_t *data)
81 : : {
82 : 378628 : jl_method_instance_t *ml = (jl_method_instance_t*)jl_svecref(data, idx);
83 : 378628 : jl_value_t *sig = ml->specTypes;
84 [ - + ]: 378628 : if (jl_is_unionall(sig))
85 : 0 : sig = jl_unwrap_unionall(sig);
86 : 378628 : return ((jl_datatype_t*)sig)->hash;
87 : : }
88 : :
89 : 4697160 : static int speccache_eq(size_t idx, const void *ty, jl_svec_t *data, uint_t hv)
90 : : {
91 : 4697160 : jl_method_instance_t *ml = (jl_method_instance_t*)jl_svecref(data, idx);
92 : 4697160 : jl_value_t *sig = ml->specTypes;
93 [ + + ]: 4697160 : if (ty == sig)
94 : 2694000 : return 1;
95 [ - + ]: 2003150 : uint_t h2 = ((jl_datatype_t*)(jl_is_unionall(sig) ? jl_unwrap_unionall(sig) : sig))->hash;
96 [ + + ]: 2003150 : if (h2 != hv)
97 : 1633060 : return 0;
98 : 370091 : return jl_types_equal(sig, (jl_value_t*)ty);
99 : : }
100 : :
101 : : // get or create the MethodInstance for a specialization
102 : 3619360 : static jl_method_instance_t *jl_specializations_get_linfo_(jl_method_t *m JL_PROPAGATES_ROOT, jl_value_t *type, jl_svec_t *sparams, jl_method_instance_t *mi_insert)
103 : : {
104 [ - + - - ]: 3619360 : if (m->sig == (jl_value_t*)jl_anytuple_type && jl_atomic_load_relaxed(&m->unspecialized) != NULL)
105 : 0 : return jl_atomic_load_relaxed(&m->unspecialized); // handle builtin methods
106 [ + + ]: 3619360 : jl_value_t *ut = jl_is_unionall(type) ? jl_unwrap_unionall(type) : type;
107 [ - + ]: 3619360 : JL_TYPECHK(specializations, datatype, ut);
108 : 3619360 : uint_t hv = ((jl_datatype_t*)ut)->hash;
109 : 3845910 : for (int locked = 0; ; locked++) {
110 : 3845910 : jl_array_t *speckeyset = jl_atomic_load_acquire(&m->speckeyset);
111 : 3845910 : jl_svec_t *specializations = jl_atomic_load_relaxed(&m->specializations);
112 : 3845910 : size_t i = -1, cl = jl_svec_len(specializations);
113 [ + + ]: 3845910 : if (hv) {
114 : 3431550 : ssize_t idx = jl_smallintset_lookup(speckeyset, speccache_eq, type, specializations, hv);
115 [ + + ]: 3431550 : if (idx != -1) {
116 : 3063650 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, idx);
117 [ - + ]: 3063650 : if (locked)
118 : 0 : JL_UNLOCK(&m->writelock);
119 : 3619360 : return mi;
120 : : }
121 : : }
122 : : else {
123 : 414360 : _Atomic(jl_method_instance_t*) *data = (_Atomic(jl_method_instance_t*)*)jl_svec_data(specializations);
124 : 414360 : JL_GC_PUSH1(&specializations); // clang-sa doesn't realize this loop uses specializations
125 [ + + ]: 16924800 : for (i = cl; i > 0; i--) {
126 : 16919200 : jl_method_instance_t *mi = jl_atomic_load_relaxed(&data[i - 1]);
127 [ + + ]: 16919200 : if ((jl_value_t*)mi == jl_nothing)
128 : 82756 : break;
129 [ + + ]: 16836400 : if (jl_types_equal(mi->specTypes, type)) {
130 [ - + ]: 326016 : if (locked)
131 : 0 : JL_UNLOCK(&m->writelock);
132 : 326016 : JL_GC_POP();
133 : 326016 : return mi;
134 : : }
135 : : }
136 : 88344 : JL_GC_POP();
137 : : }
138 [ + + ]: 456238 : if (!sparams) // can't insert without knowing this
139 : 3148 : return NULL;
140 [ + + ]: 453090 : if (!locked) {
141 : 226545 : JL_LOCK(&m->writelock);
142 : : }
143 : : else {
144 [ + + ]: 226545 : if (hv) {
145 : 182755 : _Atomic(jl_method_instance_t*) *data = (_Atomic(jl_method_instance_t*)*)jl_svec_data(specializations);
146 [ + + ]: 20064800 : for (i = 0; i < cl; i++) {
147 : 20039300 : jl_method_instance_t *mi = jl_atomic_load_relaxed(&data[i]);
148 [ + + ]: 20039300 : if ((jl_value_t*)mi == jl_nothing)
149 : 157306 : break;
150 [ - + ]: 19882000 : assert(!jl_types_equal(mi->specTypes, type));
151 : : }
152 : : }
153 [ + - ]: 226545 : jl_method_instance_t *mi = mi_insert ? mi_insert : jl_get_specialized(m, type, sparams);
154 : 226545 : JL_GC_PUSH1(&mi);
155 [ + + + + : 226545 : if (hv ? (i + 1 >= cl || jl_svecref(specializations, i + 1) != jl_nothing) : (i <= 1 || jl_svecref(specializations, i - 2) != jl_nothing)) {
+ + + + +
+ + + ]
156 [ + + ]: 39987 : size_t ncl = cl < 8 ? 8 : (cl*3)>>1;
157 : 39987 : jl_svec_t *nc = jl_alloc_svec_uninit(ncl);
158 [ + + ]: 39987 : if (i > 0)
159 : 11847 : memcpy((char*)jl_svec_data(nc), jl_svec_data(specializations), sizeof(void*) * i);
160 [ + + ]: 465799 : for (int j = 0; j < ncl - cl; j++)
161 : 425812 : jl_svecset(nc, j+i, jl_nothing);
162 [ + + ]: 39987 : if (i < cl)
163 : 11716 : memcpy((char*)jl_svec_data(nc) + sizeof(void*) * (i + ncl - cl),
164 : 11716 : (char*)jl_svec_data(specializations) + sizeof(void*) * i,
165 : 11716 : sizeof(void*) * (cl - i));
166 : 39987 : jl_atomic_store_release(&m->specializations, nc);
167 : 39987 : jl_gc_wb(m, nc);
168 : 39987 : specializations = nc;
169 [ + + ]: 39987 : if (!hv)
170 : 4962 : i += ncl - cl;
171 : : }
172 [ + + ]: 226545 : if (!hv)
173 : 43790 : i -= 1;
174 [ - + ]: 226545 : assert(jl_svecref(specializations, i) == jl_nothing);
175 : 226545 : jl_svecset(specializations, i, mi); // jl_atomic_store_release?
176 [ + + ]: 226545 : if (hv) {
177 : : // TODO: fuse lookup and insert steps?
178 : 182755 : jl_smallintset_insert(&m->speckeyset, (jl_value_t*)m, speccache_hash, i, specializations);
179 : : }
180 : 226545 : JL_UNLOCK(&m->writelock);
181 : 226545 : JL_GC_POP();
182 : 226545 : return mi;
183 : : }
184 : : }
185 : : }
186 : :
187 : 3619360 : JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(jl_method_t *m JL_PROPAGATES_ROOT, jl_value_t *type, jl_svec_t *sparams)
188 : : {
189 : 3619360 : return jl_specializations_get_linfo_(m, type, sparams, NULL);
190 : : }
191 : :
192 : 0 : jl_method_instance_t *jl_specializations_get_or_insert(jl_method_instance_t *mi)
193 : : {
194 : 0 : jl_method_t *m = mi->def.method;
195 : 0 : jl_value_t *type = mi->specTypes;
196 : 0 : jl_svec_t *sparams = mi->sparam_vals;
197 : 0 : return jl_specializations_get_linfo_(m, type, sparams, mi);
198 : : }
199 : :
200 : 1149180 : JL_DLLEXPORT jl_value_t *jl_specializations_lookup(jl_method_t *m, jl_value_t *type)
201 : : {
202 : 1149180 : jl_value_t *mi = (jl_value_t*)jl_specializations_get_linfo(m, type, NULL);
203 [ + + ]: 1149180 : if (mi == NULL)
204 : 3148 : return jl_nothing;
205 : 1146030 : return mi;
206 : : }
207 : :
208 : 0 : JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_value_t *type, size_t world)
209 : : {
210 : 0 : struct jl_typemap_assoc search = {type, world, NULL, 0, ~(size_t)0};
211 : 0 : jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(&mt->defs), &search, /*offs*/0, /*subtype*/0);
212 [ # # ]: 0 : if (!sf)
213 : 0 : return jl_nothing;
214 : 0 : return sf->func.value;
215 : : }
216 : :
217 : : // ----- MethodInstance specialization instantiation ----- //
218 : :
219 : : JL_DLLEXPORT jl_code_instance_t* jl_new_codeinst(
220 : : jl_method_instance_t *mi, jl_value_t *rettype,
221 : : jl_value_t *inferred_const, jl_value_t *inferred,
222 : : int32_t const_flags, size_t min_world, size_t max_world,
223 : : uint32_t ipo_effects, uint32_t effects, jl_value_t *argescapes,
224 : : uint8_t relocatability);
225 : : JL_DLLEXPORT void jl_mi_cache_insert(jl_method_instance_t *mi JL_ROOTING_ARGUMENT,
226 : : jl_code_instance_t *ci JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED);
227 : :
228 : 47 : jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED
229 : : {
230 : 47 : jl_sym_t *sname = jl_symbol(name);
231 [ + + ]: 47 : if (dt == NULL) {
232 : 44 : jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type);
233 : 44 : jl_set_const(jl_core_module, sname, f);
234 : 44 : dt = (jl_datatype_t*)jl_typeof(f);
235 : : }
236 : :
237 : 47 : jl_method_t *m = jl_new_method_uninit(jl_core_module);
238 : 47 : m->name = sname;
239 : 47 : m->module = jl_core_module;
240 : 47 : m->isva = 1;
241 : 47 : m->nargs = 2;
242 : 47 : m->sig = (jl_value_t*)jl_anytuple_type;
243 : 47 : m->slot_syms = jl_an_empty_string;
244 : 47 : m->nospecialize = 0;
245 : 47 : m->nospecialize = ~m->nospecialize;
246 : :
247 : 47 : jl_methtable_t *mt = dt->name->mt;
248 : 47 : jl_typemap_entry_t *newentry = NULL;
249 : 47 : JL_GC_PUSH2(&m, &newentry);
250 : :
251 : 47 : newentry = jl_typemap_alloc(jl_anytuple_type, NULL, jl_emptysvec,
252 : : (jl_value_t*)m, 1, ~(size_t)0);
253 : 47 : jl_typemap_insert(&mt->defs, (jl_value_t*)mt, newentry, 0);
254 : :
255 : 47 : jl_method_instance_t *mi = jl_get_specialized(m, (jl_value_t*)jl_anytuple_type, jl_emptysvec);
256 : 47 : jl_atomic_store_relaxed(&m->unspecialized, mi);
257 : 47 : jl_gc_wb(m, mi);
258 : :
259 : 47 : jl_code_instance_t *codeinst = jl_new_codeinst(mi,
260 : : (jl_value_t*)jl_any_type, jl_nothing, jl_nothing,
261 : : 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0);
262 : 47 : jl_mi_cache_insert(mi, codeinst);
263 : 47 : jl_atomic_store_relaxed(&codeinst->specptr.fptr1, fptr);
264 : 47 : jl_atomic_store_relaxed(&codeinst->invoke, jl_fptr_args);
265 : :
266 : 47 : newentry = jl_typemap_alloc(jl_anytuple_type, NULL, jl_emptysvec,
267 : : (jl_value_t*)mi, 1, ~(size_t)0);
268 : 47 : jl_typemap_insert(&mt->cache, (jl_value_t*)mt, newentry, 0);
269 : :
270 : 47 : mt->frozen = 1;
271 : 47 : JL_GC_POP();
272 : 47 : return dt;
273 : : }
274 : :
275 : : // run type inference on lambda "mi" for given argument types.
276 : : // returns the inferred source, and may cache the result in mi
277 : : // if successful, also updates the mi argument to describe the validity of this src
278 : : // if inference doesn't occur (or can't finish), returns NULL instead
279 : 77833700 : jl_code_info_t *jl_type_infer(jl_method_instance_t *mi, size_t world, int force)
280 : : {
281 : : JL_TIMING(INFERENCE);
282 [ + + ]: 77833700 : if (jl_typeinf_func == NULL)
283 : 77797600 : return NULL;
284 [ + + - + ]: 36098 : if (jl_is_method(mi->def.method) && jl_atomic_load_relaxed(&mi->def.method->unspecialized) == mi)
285 : 0 : return NULL; // avoid inferring the unspecialized method
286 : : static int in_inference;
287 [ + + ]: 36098 : if (in_inference > 2)
288 : 23459 : return NULL;
289 : :
290 : 12639 : jl_code_info_t *src = NULL;
291 : : #ifdef ENABLE_INFERENCE
292 [ + + + - ]: 12639 : if (mi->inInference && !force)
293 : 3254 : return NULL;
294 : :
295 : : jl_value_t **fargs;
296 : 9385 : JL_GC_PUSHARGS(fargs, 3);
297 : 9385 : fargs[0] = (jl_value_t*)jl_typeinf_func;
298 : 9385 : fargs[1] = (jl_value_t*)mi;
299 : 9385 : fargs[2] = jl_box_ulong(world);
300 : : #ifdef TRACE_INFERENCE
301 : : if (mi->specTypes != (jl_value_t*)jl_emptytuple_type) {
302 : : jl_printf(JL_STDERR,"inference on ");
303 : : jl_static_show_func_sig(JL_STDERR, (jl_value_t*)mi->specTypes);
304 : : jl_printf(JL_STDERR, "\n");
305 : : }
306 : : #endif
307 : 9385 : jl_task_t *ct = jl_current_task;
308 : 9385 : int last_errno = errno;
309 : : #ifdef _OS_WINDOWS_
310 : : DWORD last_error = GetLastError();
311 : : #endif
312 : 9385 : size_t last_age = ct->world_age;
313 : 9385 : ct->world_age = jl_typeinf_world;
314 : 9385 : mi->inInference = 1;
315 : 9385 : in_inference++;
316 [ + - + + ]: 18770 : JL_TRY {
317 : 9385 : src = (jl_code_info_t*)jl_apply(fargs, 3);
318 : : }
319 [ # # ]: 0 : JL_CATCH {
320 : 0 : jl_value_t *e = jl_current_exception();
321 [ # # ]: 0 : if (e == jl_stackovf_exception) {
322 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "Internal error: stack overflow in type inference of ");
323 : 0 : jl_static_show_func_sig((JL_STREAM*)STDERR_FILENO, (jl_value_t*)mi->specTypes);
324 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, ".\n");
325 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "This might be caused by recursion over very long tuples or argument lists.\n");
326 : : }
327 : : else {
328 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "Internal error: encountered unexpected error in runtime:\n");
329 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO, e);
330 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
331 : 0 : jlbacktrace(); // written to STDERR_FILENO
332 : : }
333 : 0 : src = NULL;
334 : : }
335 : 9385 : ct->world_age = last_age;
336 : 9385 : in_inference--;
337 : 9385 : mi->inInference = 0;
338 : : #ifdef _OS_WINDOWS_
339 : : SetLastError(last_error);
340 : : #endif
341 : 9385 : errno = last_errno;
342 : :
343 [ + - - + ]: 9385 : if (src && !jl_is_code_info(src)) {
344 : 0 : src = NULL;
345 : : }
346 : 9385 : JL_GC_POP();
347 : : #endif
348 : 9385 : return src;
349 : : }
350 : :
351 : 120 : JL_DLLEXPORT jl_value_t *jl_call_in_typeinf_world(jl_value_t **args, int nargs)
352 : : {
353 : 120 : jl_task_t *ct = jl_current_task;
354 : 120 : size_t last_age = ct->world_age;
355 : 120 : ct->world_age = jl_typeinf_world;
356 : 120 : jl_value_t *ret = jl_apply(args, nargs);
357 : 120 : ct->world_age = last_age;
358 : 120 : return ret;
359 : : }
360 : :
361 : 81475600 : JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT
362 : : {
363 : 81475600 : jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache);
364 [ + + ]: 81499800 : while (codeinst) {
365 [ + + + + ]: 3173100 : if (codeinst->min_world <= min_world && max_world <= codeinst->max_world) {
366 : 3153120 : jl_value_t *code = codeinst->inferred;
367 [ + + + + : 3153120 : if (code && (code == jl_nothing || jl_ir_flag_inferred((jl_array_t*)code)))
+ - ]
368 : 3148900 : return (jl_value_t*)codeinst;
369 : : }
370 : 24204 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
371 : : }
372 : 78326700 : return (jl_value_t*)jl_nothing;
373 : : }
374 : :
375 : :
376 : 77853900 : JL_DLLEXPORT jl_code_instance_t *jl_get_method_inferred(
377 : : jl_method_instance_t *mi JL_PROPAGATES_ROOT, jl_value_t *rettype,
378 : : size_t min_world, size_t max_world)
379 : : {
380 : 77853900 : jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache);
381 [ + + ]: 77853900 : while (codeinst) {
382 [ + + ]: 77852000 : if (codeinst->min_world == min_world &&
383 [ + + + - ]: 155704000 : codeinst->max_world == max_world &&
384 : 77852000 : jl_egal(codeinst->rettype, rettype)) {
385 : 77852000 : return codeinst;
386 : : }
387 : 15 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
388 : : }
389 : 1918 : codeinst = jl_new_codeinst(
390 : : mi, rettype, NULL, NULL,
391 : : 0, min_world, max_world, 0, 0, jl_nothing, 0);
392 : 1918 : jl_mi_cache_insert(mi, codeinst);
393 : 1918 : return codeinst;
394 : : }
395 : :
396 : 231770 : JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst(
397 : : jl_method_instance_t *mi, jl_value_t *rettype,
398 : : jl_value_t *inferred_const, jl_value_t *inferred,
399 : : int32_t const_flags, size_t min_world, size_t max_world,
400 : : uint32_t ipo_effects, uint32_t effects, jl_value_t *argescapes,
401 : : uint8_t relocatability
402 : : /*, jl_array_t *edges, int absolute_max*/)
403 : : {
404 : 231770 : jl_task_t *ct = jl_current_task;
405 [ - + ]: 231770 : assert(min_world <= max_world && "attempting to set invalid world constraints");
406 : 231770 : jl_code_instance_t *codeinst = (jl_code_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_instance_t),
407 : : jl_code_instance_type);
408 : 231770 : codeinst->def = mi;
409 : 231770 : codeinst->min_world = min_world;
410 : 231770 : codeinst->max_world = max_world;
411 : 231770 : codeinst->rettype = rettype;
412 : 231770 : codeinst->inferred = inferred;
413 : : //codeinst->edges = NULL;
414 [ + + ]: 231770 : if ((const_flags & 2) == 0)
415 : 176040 : inferred_const = NULL;
416 : 231770 : codeinst->rettype_const = inferred_const;
417 : 231770 : jl_atomic_store_relaxed(&codeinst->invoke, NULL);
418 : 231770 : jl_atomic_store_relaxed(&codeinst->specptr.fptr, NULL);
419 [ + + ]: 231770 : if ((const_flags & 1) != 0) {
420 [ - + ]: 29167 : assert(const_flags & 2);
421 : 29167 : jl_atomic_store_relaxed(&codeinst->invoke, jl_fptr_const_return);
422 : : }
423 : 231770 : codeinst->isspecsig = 0;
424 : 231770 : jl_atomic_store_relaxed(&codeinst->precompile, 0);
425 : 231770 : jl_atomic_store_relaxed(&codeinst->next, NULL);
426 : 231770 : codeinst->ipo_purity_bits = ipo_effects;
427 : 231770 : codeinst->purity_bits = effects;
428 : 231770 : codeinst->argescapes = argescapes;
429 : 231770 : codeinst->relocatability = relocatability;
430 : 231770 : return codeinst;
431 : : }
432 : :
433 : 231770 : JL_DLLEXPORT void jl_mi_cache_insert(jl_method_instance_t *mi JL_ROOTING_ARGUMENT,
434 : : jl_code_instance_t *ci JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED)
435 : : {
436 : 231770 : JL_GC_PUSH1(&ci);
437 [ + + ]: 231770 : if (jl_is_method(mi->def.method))
438 : 231671 : JL_LOCK(&mi->def.method->writelock);
439 : 231770 : jl_code_instance_t *oldci = jl_atomic_load_relaxed(&mi->cache);
440 : 231770 : jl_atomic_store_relaxed(&ci->next, oldci);
441 : 231770 : jl_gc_wb(ci, oldci); // likely older, but just being careful
442 : 231770 : jl_atomic_store_release(&mi->cache, ci);
443 : 231770 : jl_gc_wb(mi, ci);
444 [ + + ]: 231770 : if (jl_is_method(mi->def.method))
445 : 231671 : JL_UNLOCK(&mi->def.method->writelock);
446 : 231770 : JL_GC_POP();
447 : 231770 : return;
448 : : }
449 : :
450 : 5130 : static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure)
451 : : {
452 : 5130 : jl_svec_t *specializations = jl_atomic_load_relaxed(&def->func.method->specializations);
453 : 5130 : size_t i, l = jl_svec_len(specializations);
454 : 5130 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
455 [ + + ]: 24776 : for (i = 0; i < l; i++) {
456 : 19646 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
457 [ + + ]: 19646 : if ((jl_value_t*)mi != jl_nothing) {
458 [ - + ]: 7225 : assert(jl_is_method_instance(mi));
459 [ + + ]: 7225 : if (jl_rettype_inferred(mi, world, world) == jl_nothing)
460 : 846 : jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)mi);
461 : : }
462 : : }
463 : 5130 : return 1;
464 : : }
465 : :
466 : 1052 : static int foreach_mtable_in_module(
467 : : jl_module_t *m,
468 : : int (*visit)(jl_methtable_t *mt, void *env),
469 : : void *env)
470 : : {
471 : : size_t i;
472 : 1052 : void **table = m->bindings.table;
473 [ + + ]: 703596 : for (i = 1; i < m->bindings.size; i += 2) {
474 [ + + ]: 702544 : if (table[i] != HT_NOTFOUND) {
475 : 277816 : jl_binding_t *b = (jl_binding_t*)table[i];
476 : : JL_GC_PROMISE_ROOTED(b);
477 [ + + + + ]: 277816 : if (b->owner == m && b->constp) {
478 : 211243 : jl_value_t *v = jl_atomic_load_relaxed(&b->value);
479 [ + - ]: 211243 : if (v) {
480 : 211243 : jl_value_t *uw = jl_unwrap_unionall(v);
481 [ + + ]: 211243 : if (jl_is_datatype(uw)) {
482 : 106757 : jl_typename_t *tn = ((jl_datatype_t*)uw)->name;
483 [ + + + + : 106757 : if (tn->module == m && tn->name == b->name && tn->wrapper == v) {
+ - ]
484 : : // this is the original/primary binding for the type (name/wrapper)
485 : 104558 : jl_methtable_t *mt = tn->mt;
486 [ + + + - : 104558 : if (mt != NULL && (jl_value_t*)mt != jl_nothing && mt != jl_type_type_mt && mt != jl_nonfunction_mt) {
+ + + + ]
487 [ - + ]: 94677 : if (!visit(mt, env))
488 : 0 : return 0;
489 : : }
490 : : }
491 : : }
492 [ + + ]: 104486 : else if (jl_is_module(v)) {
493 : 2052 : jl_module_t *child = (jl_module_t*)v;
494 [ + + + + : 2052 : if (child != m && child->parent == m && child->name == b->name) {
+ - ]
495 : : // this is the original/primary binding for the submodule
496 [ - + ]: 710 : if (!foreach_mtable_in_module(child, visit, env))
497 : 0 : return 0;
498 : : }
499 : : }
500 : : }
501 : : }
502 : : }
503 : : }
504 : 1052 : return 1;
505 : : }
506 : :
507 : 11 : int jl_foreach_reachable_mtable(int (*visit)(jl_methtable_t *mt, void *env), void *env)
508 : : {
509 [ - + ]: 11 : if (!visit(jl_type_type_mt, env))
510 : 0 : return 0;
511 [ - + ]: 11 : if (!visit(jl_nonfunction_mt, env))
512 : 0 : return 0;
513 : 11 : jl_array_t *mod_array = jl_get_loaded_modules();
514 [ + + ]: 11 : if (mod_array) {
515 : 8 : JL_GC_PUSH1(&mod_array);
516 : : int i;
517 [ + + ]: 352 : for (i = 0; i < jl_array_len(mod_array); i++) {
518 : 344 : jl_module_t *m = (jl_module_t*)jl_array_ptr_ref(mod_array, i);
519 [ - + ]: 344 : assert(jl_is_module(m));
520 [ + + ]: 344 : if (m->parent == m) // some toplevel modules (really just Base) aren't actually
521 [ - + ]: 336 : if (!foreach_mtable_in_module(m, visit, env)) {
522 : 0 : JL_GC_POP();
523 : 0 : return 0;
524 : : }
525 : : }
526 : 8 : JL_GC_POP();
527 : : }
528 : : else {
529 [ - + ]: 3 : if (!foreach_mtable_in_module(jl_main_module, visit, env))
530 : 0 : return 0;
531 [ - + ]: 3 : if (!foreach_mtable_in_module(jl_core_module, visit, env))
532 : 0 : return 0;
533 : : }
534 : 11 : return 1;
535 : : }
536 : :
537 : 1943 : static int reset_mt_caches(jl_methtable_t *mt, void *env)
538 : : {
539 : : // removes all method caches
540 : : // this might not be entirely safe (GC or MT), thus we only do it very early in bootstrapping
541 [ + + ]: 1943 : if (!mt->frozen) { // make sure not to reset builtin functions
542 : 1896 : jl_atomic_store_release(&mt->leafcache, (jl_array_t*)jl_an_empty_vec_any);
543 : 1896 : jl_atomic_store_release(&mt->cache, jl_nothing);
544 : : }
545 : 1943 : jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), get_method_unspec_list, env);
546 : 1943 : return 1;
547 : : }
548 : :
549 : :
550 : : jl_function_t *jl_typeinf_func = NULL;
551 : : JL_DLLEXPORT size_t jl_typeinf_world = 1;
552 : :
553 : 1 : JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f)
554 : : {
555 [ + - + - ]: 1 : size_t newfunc = jl_typeinf_world == 1 && jl_typeinf_func == NULL;
556 : 1 : jl_typeinf_func = (jl_function_t*)f;
557 : 1 : jl_typeinf_world = jl_get_tls_world_age();
558 : 1 : int world = jl_atomic_fetch_add(&jl_world_counter, 1) + 1; // make type-inference the only thing in this world
559 [ + - ]: 1 : if (newfunc) {
560 : : // give type inference a chance to see all of these
561 : : // TODO: also reinfer if max_world != ~(size_t)0
562 : 1 : jl_array_t *unspec = jl_alloc_vec_any(0);
563 : 1 : JL_GC_PUSH1(&unspec);
564 : 1 : jl_foreach_reachable_mtable(reset_mt_caches, (void*)unspec);
565 : : size_t i, l;
566 [ + + ]: 847 : for (i = 0, l = jl_array_len(unspec); i < l; i++) {
567 : 846 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(unspec, i);
568 [ + + ]: 846 : if (jl_rettype_inferred(mi, world, world) == jl_nothing)
569 : 602 : jl_type_infer(mi, world, 1);
570 : : }
571 : 1 : JL_GC_POP();
572 : : }
573 : 1 : }
574 : :
575 : 444018 : static int very_general_type(jl_value_t *t)
576 : : {
577 [ + + + + ]: 444018 : return (t == (jl_value_t*)jl_any_type || jl_types_equal(t, (jl_value_t*)jl_type_type));
578 : : }
579 : :
580 : 8871740 : jl_value_t *jl_nth_slot_type(jl_value_t *sig, size_t i) JL_NOTSAFEPOINT
581 : : {
582 : 8871740 : sig = jl_unwrap_unionall(sig);
583 : 8871740 : size_t len = jl_nparams(sig);
584 [ - + ]: 8871740 : if (len == 0)
585 : 0 : return NULL;
586 [ + + ]: 8871740 : if (i < len-1)
587 : 5990260 : return jl_tparam(sig, i);
588 [ + + ]: 2881480 : if (jl_is_vararg(jl_tparam(sig, len-1)))
589 : 234144 : return jl_unwrap_vararg(jl_tparam(sig, len-1));
590 [ + - ]: 2647340 : if (i == len-1)
591 : 2647340 : return jl_tparam(sig, i);
592 : 0 : return NULL;
593 : : }
594 : :
595 : : // if concrete_match returns false, the sig may specify `Type{T::DataType}`, while the `tt` contained DataType
596 : : // in this case, subtyping is wrong, and this may not actually match at runtime
597 : : // since it may instead match any kind of `Type{T::Type}`
598 : : //static int concrete_match(jl_tupletype_t *tt, jl_value_t *sig)
599 : : //{
600 : : // size_t i, np;
601 : : // for (i = 0, np = jl_nparams(tt); i < np; i++) {
602 : : // jl_value_t *elt = jl_tparam(tt, i);
603 : : // jl_value_t *decl_i = jl_nth_slot_type((jl_value_t*)sig, i);
604 : : // if (jl_is_kind(elt)) {
605 : : // // check whether this match may be exact at runtime
606 : : // if (!jl_subtype(elt, decl_i))
607 : : // return 0;
608 : : // }
609 : : // }
610 : : // return 1;
611 : : //}
612 : :
613 : : static jl_value_t *ml_matches(jl_methtable_t *mt,
614 : : jl_tupletype_t *type, int lim, int include_ambiguous,
615 : : int intersections, size_t world, int cache_result,
616 : : size_t *min_valid, size_t *max_valid, int *ambig);
617 : :
618 : : // get the compilation signature specialization for this method
619 : 2066260 : static void jl_compilation_sig(
620 : : jl_tupletype_t *const tt, // the original tupletype of the call : this is expected to be a relative simple type (no Varags, Union, UnionAll, etc.)
621 : : jl_svec_t *sparams,
622 : : jl_method_t *definition,
623 : : intptr_t nspec,
624 : : // output:
625 : : jl_svec_t **const newparams JL_REQUIRE_ROOTED_SLOT)
626 : : {
627 [ + + ]: 2066260 : if (definition->generator) {
628 : : // staged functions aren't optimized
629 : : // so assume the caller was intelligent about calling us
630 : 5954 : return;
631 : : }
632 [ - + - - ]: 2060310 : if (definition->sig == (jl_value_t*)jl_anytuple_type && jl_atomic_load_relaxed(&definition->unspecialized)) {
633 : 0 : *newparams = jl_anytuple_type->parameters; // handle builtin methods
634 : 0 : return;
635 : : }
636 : :
637 : 2060310 : jl_value_t *decl = definition->sig;
638 [ - + ]: 2060310 : assert(jl_is_tuple_type(tt));
639 : 2060310 : size_t i, np = jl_nparams(tt);
640 : 2060310 : size_t nargs = definition->nargs; // == jl_nparams(jl_unwrap_unionall(decl));
641 [ + + ]: 8272650 : for (i = 0; i < np; i++) {
642 : 6212340 : jl_value_t *elt = jl_tparam(tt, i);
643 : 6212340 : jl_value_t *decl_i = jl_nth_slot_type(decl, i);
644 : 6212340 : size_t i_arg = (i < nargs - 1 ? i : nargs - 1);
645 : :
646 [ + + ]: 6212340 : if (jl_is_kind(decl_i)) {
647 : : // if we can prove the match was against the kind (not a Type)
648 : : // we want to put that in the cache instead
649 [ + + ]: 1909 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
650 : 1909 : elt = decl_i;
651 : 1909 : jl_svecset(*newparams, i, elt);
652 : : }
653 [ + + ]: 6210440 : else if (jl_is_type_type(elt)) {
654 : : // if the declared type was not Any or Union{Type, ...},
655 : : // then the match must been with the kind (e.g. UnionAll or DataType)
656 : : // and the result of matching the type signature
657 : : // needs to be restricted to the concrete type 'kind'
658 : 387223 : jl_value_t *kind = jl_typeof(jl_tparam0(elt));
659 [ + + + + ]: 387223 : if (jl_subtype(kind, decl_i) && !jl_subtype((jl_value_t*)jl_type_type, decl_i)) {
660 : : // if we can prove the match was against the kind (not a Type)
661 : : // it's simpler (and thus better) to put that cache instead
662 [ + + ]: 1568 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
663 : 1568 : elt = kind;
664 : 1568 : jl_svecset(*newparams, i, elt);
665 : : }
666 : : }
667 [ + + ]: 5823210 : else if (jl_is_kind(elt)) {
668 : : // not triggered for isdispatchtuple(tt), this attempts to handle
669 : : // some cases of adapting a random signature into a compilation signature
670 : : // if we get a kind, where we don't expect to accept one, widen it to something more expected (Type{T})
671 [ + + + - ]: 9597 : if (!(jl_subtype(elt, decl_i) && !jl_subtype((jl_value_t*)jl_type_type, decl_i))) {
672 [ + + ]: 9597 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
673 : 9597 : elt = (jl_value_t*)jl_type_type;
674 : 9597 : jl_svecset(*newparams, i, elt);
675 : : }
676 : : }
677 : :
678 : :
679 [ + + ]: 6212340 : if (jl_is_kind(elt)) {
680 : : // kind slots always need guard entries (checking for subtypes of Type)
681 : 3477 : continue;
682 : : }
683 : :
684 [ + + + - ]: 6208870 : if (i_arg > 0 && i_arg <= sizeof(definition->nospecialize) * 8 &&
685 [ + + ]: 4148580 : (definition->nospecialize & (1 << (i_arg - 1)))) {
686 [ + + + - ]: 259097 : if (!jl_has_free_typevars(decl_i) && !jl_is_kind(decl_i)) {
687 [ + + ]: 259073 : if (decl_i != elt) {
688 [ + + ]: 190193 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
689 : 190193 : jl_svecset(*newparams, i, (jl_value_t*)decl_i);
690 : : }
691 : 259073 : continue;
692 : : }
693 : : }
694 : :
695 [ + + ]: 5949790 : if (jl_is_vararg(elt)) {
696 : 1959 : continue;
697 : : }
698 : :
699 [ + + ]: 5947840 : if (jl_types_equal(elt, (jl_value_t*)jl_type_type)) { // elt == Type{T} where T
700 : : // not triggered for isdispatchtuple(tt), this attempts to handle
701 : : // some cases of adapting a random signature into a compilation signature
702 : : }
703 [ + + + + ]: 5936290 : else if (!jl_is_datatype(elt) && jl_subtype(elt, (jl_value_t*)jl_type_type)) { // elt <: Type{T}
704 : : // not triggered for isdispatchtuple(tt), this attempts to handle
705 : : // some cases of adapting a random signature into a compilation signature
706 [ + + ]: 6852 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
707 : 6852 : jl_svecset(*newparams, i, jl_type_type);
708 : : }
709 [ + + ]: 5929440 : else if (jl_is_type_type(elt)) { // elt isa Type{T}
710 [ + + ]: 375803 : if (very_general_type(decl_i)) {
711 : : /*
712 : : Here's a fairly simple heuristic: if this argument slot's
713 : : declared type is general (Type or Any),
714 : : then don't specialize for every Type that got passed.
715 : :
716 : : Since every type x has its own type Type{x}, this would be
717 : : excessive specialization for an Any slot.
718 : :
719 : : This may require guard entries due to other potential matches.
720 : : In particular, TypeConstructors are problematic because they can
721 : : be alternate representations of any type. Extensionally, TC == TC.body,
722 : : but typeof(TC) != typeof(TC.body). This creates an ambiguity:
723 : : Type{TC} is type-equal to Type{TC.body}, yet a slot
724 : : x::TypeConstructor matches the first but not the second, while
725 : : also matching all other TypeConstructors. This means neither
726 : : Type{TC} nor TypeConstructor is more specific.
727 : :
728 : : But don't apply this heuristic if the argument is called (issue #36783).
729 : : */
730 [ + - + + : 21270 : int iscalled = i_arg > 0 && i_arg <= 8 && (definition->called & (1 << (i_arg - 1)));
+ + ]
731 [ + + ]: 21270 : if (!iscalled) {
732 [ + + ]: 21201 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
733 : 21201 : jl_svecset(*newparams, i, jl_type_type);
734 : : }
735 : : }
736 [ + + + - ]: 354692 : else if (jl_is_type_type(jl_tparam0(elt)) &&
737 : : // try to give up on specializing type parameters for Type{Type{Type{...}}}
738 [ - + ]: 318 : (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_free_typevars(decl_i))) {
739 : : /*
740 : : actual argument was Type{...}, we computed its type as
741 : : Type{Type{...}}. we like to avoid unbounded nesting here, so
742 : : compile (and hopefully cache) the signature as Type{T},
743 : : unless something more specific like Type{Type{Int32}} was
744 : : actually declared. this can be determined using a type
745 : : intersection.
746 : : */
747 [ # # ]: 0 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
748 [ # # # # ]: 0 : if (i < nargs || !definition->isva) {
749 : 0 : jl_value_t *di = jl_type_intersection(decl_i, (jl_value_t*)jl_type_type);
750 [ # # ]: 0 : assert(di != (jl_value_t*)jl_bottom_type);
751 : : // issue #11355: DataType has a UID and so would take precedence in the cache
752 [ # # ]: 0 : if (jl_is_kind(di))
753 : 0 : jl_svecset(*newparams, i, (jl_value_t*)jl_type_type);
754 : : else
755 : 0 : jl_svecset(*newparams, i, di);
756 : : // TODO: recompute static parameter values, so in extreme cases we
757 : : // can give `T=Type` instead of `T=Type{Type{Type{...`. /* make editors happy:}}} */
758 : : }
759 : : else {
760 : 0 : jl_svecset(*newparams, i, (jl_value_t*)jl_type_type);
761 : : }
762 : : }
763 : : }
764 : :
765 [ + + + + : 9791540 : int notcalled_func = (i_arg > 0 && i_arg <= 8 && !(definition->called & (1 << (i_arg - 1))) &&
+ + + + ]
766 : 3843700 : jl_subtype(elt, (jl_value_t*)jl_function_type));
767 [ + + + + ]: 5947840 : if (notcalled_func && (decl_i == (jl_value_t*)jl_any_type ||
768 [ + + ]: 78028 : decl_i == (jl_value_t*)jl_function_type ||
769 [ + + ]: 70706 : (jl_is_uniontype(decl_i) && // Base.Callable
770 [ + + ]: 1448 : ((((jl_uniontype_t*)decl_i)->a == (jl_value_t*)jl_function_type &&
771 [ - + ]: 36 : ((jl_uniontype_t*)decl_i)->b == (jl_value_t*)jl_type_type) ||
772 [ + + ]: 1412 : (((jl_uniontype_t*)decl_i)->b == (jl_value_t*)jl_function_type &&
773 [ - + ]: 1300 : ((jl_uniontype_t*)decl_i)->a == (jl_value_t*)jl_type_type))))) {
774 : : // and attempt to despecialize types marked Function, Callable, or Any
775 : : // when called with a subtype of Function but is not called
776 [ + + ]: 45290 : if (!*newparams) *newparams = jl_svec_copy(tt->parameters);
777 : 45290 : jl_svecset(*newparams, i, (jl_value_t*)jl_function_type);
778 : : }
779 : : }
780 : :
781 : : // for varargs methods, only specialize up to max_args.
782 : : // in general, here we want to find the biggest type that's not a
783 : : // supertype of any other method signatures. so far we are conservative
784 : : // and the types we find should be bigger.
785 [ + + + + ]: 2060310 : if (jl_nparams(tt) >= nspec && jl_va_tuple_kind((jl_datatype_t*)decl) == JL_VARARG_UNBOUND) {
786 : 24485 : jl_svec_t *limited = jl_alloc_svec(nspec);
787 : 24485 : JL_GC_PUSH1(&limited);
788 [ + + ]: 24485 : if (!*newparams) *newparams = tt->parameters;
789 : : size_t i;
790 [ + + ]: 117598 : for (i = 0; i < nspec - 1; i++) {
791 : 93113 : jl_svecset(limited, i, jl_svecref(*newparams, i));
792 : : }
793 : 24485 : jl_value_t *lasttype = jl_svecref(*newparams, i - 1);
794 : : // if all subsequent arguments are subtypes of lasttype, specialize
795 : : // on that instead of decl. for example, if decl is
796 : : // (Any...)
797 : : // and type is
798 : : // (Symbol, Symbol, Symbol)
799 : : // then specialize as (Symbol...), but if type is
800 : : // (Symbol, Int32, Expr)
801 : : // then specialize as (Any...)
802 : 24485 : size_t j = i;
803 : 24485 : int all_are_subtypes = 1;
804 [ + + ]: 65877 : for (; j < jl_svec_len(*newparams); j++) {
805 : 54741 : jl_value_t *paramj = jl_svecref(*newparams, j);
806 [ + + ]: 54741 : if (jl_is_vararg(paramj))
807 : 632 : paramj = jl_unwrap_vararg(paramj);
808 [ + + ]: 54741 : if (!jl_subtype(paramj, lasttype)) {
809 : 13349 : all_are_subtypes = 0;
810 : 13349 : break;
811 : : }
812 : : }
813 [ + + ]: 24485 : if (all_are_subtypes) {
814 : : // avoid Vararg{Type{Type{...}}}
815 [ - + - - ]: 11136 : if (jl_is_type_type(lasttype) && jl_is_type_type(jl_tparam0(lasttype)))
816 : 0 : lasttype = (jl_value_t*)jl_type_type;
817 : 11136 : jl_svecset(limited, i, jl_wrap_vararg(lasttype, (jl_value_t*)NULL));
818 : : }
819 : : else {
820 : 13349 : jl_value_t *unw = jl_unwrap_unionall(decl);
821 : 13349 : jl_value_t *lastdeclt = jl_tparam(unw, jl_nparams(unw) - 1);
822 [ - + ]: 13349 : assert(jl_is_vararg(lastdeclt));
823 : 13349 : int nsp = jl_svec_len(sparams);
824 [ + + + + ]: 13349 : if (nsp > 0 && jl_has_free_typevars(lastdeclt)) {
825 [ - + ]: 38 : assert(jl_subtype_env_size(decl) == nsp);
826 : 38 : lastdeclt = jl_instantiate_type_in_env(lastdeclt, (jl_unionall_t*)decl, jl_svec_data(sparams));
827 : : // TODO: rewrap_unionall(lastdeclt, sparams) if any sparams isa TypeVar???
828 : : // TODO: if we made any replacements above, sparams may now be incorrect
829 : : }
830 : 13349 : jl_svecset(limited, i, lastdeclt);
831 : : }
832 : 24485 : *newparams = limited;
833 : : // now there is a problem: the widened signature is more
834 : : // general than just the given arguments, so it might conflict
835 : : // with another definition that doesn't have cache instances yet.
836 : : // to fix this, we insert guard cache entries for all intersections
837 : : // of this signature and definitions. those guard entries will
838 : : // supersede this one in conflicted cases, alerting us that there
839 : : // should actually be a cache miss.
840 : : // TODO: the above analysis assumes that there will never
841 : : // be a call attempted that should throw a no-method error
842 : 24485 : JL_GC_POP();
843 : : }
844 : : }
845 : :
846 : : // compute whether this type signature is a possible return value from jl_compilation_sig given a concrete-type for `tt`
847 : 336645 : JL_DLLEXPORT int jl_isa_compileable_sig(
848 : : jl_tupletype_t *type,
849 : : jl_method_t *definition)
850 : : {
851 : 336645 : jl_value_t *decl = definition->sig;
852 : :
853 [ + + + + ]: 336645 : if (!jl_is_datatype(type) || jl_has_free_typevars((jl_value_t*)type))
854 : 1089 : return 0;
855 [ - + - - ]: 335556 : if (definition->sig == (jl_value_t*)jl_anytuple_type && jl_atomic_load_relaxed(&definition->unspecialized))
856 : 0 : return jl_egal((jl_value_t*)type, definition->sig); // handle builtin methods
857 : :
858 : 335556 : size_t i, np = jl_nparams(type);
859 : 335556 : size_t nargs = definition->nargs; // == jl_nparams(jl_unwrap_unionall(decl));
860 [ - + ]: 335556 : if (np == 0)
861 : 0 : return nargs == 0;
862 : :
863 [ + + ]: 335556 : if (definition->generator) {
864 : : // staged functions aren't optimized
865 : : // so assume the caller was intelligent about calling us
866 [ + + + - : 1844 : return (definition->isva ? np >= nargs - 1 : np == nargs) && type->isdispatchtuple;
+ - + + ]
867 : : }
868 : :
869 : : // for varargs methods, only specialize up to max_args (>= nargs + 1).
870 : : // in general, here we want to find the biggest type that's not a
871 : : // supertype of any other method signatures. so far we are conservative
872 : : // and the types we find should be bigger.
873 [ + + ]: 333712 : if (definition->isva) {
874 : 31973 : unsigned nspec_min = nargs + 1; // min number of non-vararg values before vararg
875 : 31973 : unsigned nspec_max = INT32_MAX; // max number of non-vararg values before vararg
876 : 31973 : jl_methtable_t *mt = jl_method_table_for(decl);
877 [ + - ]: 31973 : if ((jl_value_t*)mt != jl_nothing) {
878 : : // try to refine estimate of min and max
879 [ + + + + ]: 31973 : if (mt != jl_type_type_mt && mt != jl_nonfunction_mt)
880 : 29982 : nspec_min = mt->max_args + 2;
881 : : else
882 : 1991 : nspec_max = nspec_min;
883 : : }
884 : 31973 : int isbound = (jl_va_tuple_kind((jl_datatype_t*)decl) == JL_VARARG_UNBOUND);
885 [ + + ]: 31973 : if (jl_is_vararg(jl_tparam(type, np - 1))) {
886 [ + - + + : 11118 : if (!isbound || np < nspec_min || np > nspec_max)
- + ]
887 : 1479 : return 0;
888 : : }
889 : : else {
890 [ + - + + : 20855 : if (np < nargs - 1 || (isbound && np >= nspec_max))
+ + ]
891 : 54 : return 0;
892 : : }
893 : : }
894 [ + - - + ]: 301739 : else if (np != nargs || jl_is_vararg(jl_tparam(type, np - 1))) {
895 : 0 : return 0;
896 : : }
897 : :
898 [ + + ]: 1175720 : for (i = 0; i < np; i++) {
899 : 1013480 : jl_value_t *elt = jl_tparam(type, i);
900 : 1013480 : jl_value_t *decl_i = jl_nth_slot_type((jl_value_t*)decl, i);
901 : 1013480 : size_t i_arg = (i < nargs - 1 ? i : nargs - 1);
902 : :
903 [ + + ]: 1013480 : if (jl_is_vararg(elt)) {
904 : 6247 : elt = jl_unwrap_vararg(elt);
905 [ + + ]: 6247 : if (jl_has_free_typevars(decl_i)) {
906 : : // TODO: in this case, answer semi-conservatively that these varargs are always compilable
907 : : // we don't have the ability to get sparams, so deciding if elt
908 : : // is a potential result of jl_instantiate_type_in_env for decl_i
909 : : // for any sparams that is consistent with the rest of the arguments
910 : : // seems like it would be extremely difficult
911 : : // and hopefully the upstream code probably gave us something reasonable
912 : 222 : continue;
913 : : }
914 [ + + ]: 6025 : else if (jl_egal(elt, decl_i)) {
915 : 5263 : continue;
916 : : }
917 [ - + - - ]: 762 : else if (jl_is_type_type(elt) && jl_is_type_type(jl_tparam0(elt))) {
918 : 0 : return 0;
919 : : }
920 : : // else, it needs to meet the usual rules
921 : : }
922 : :
923 [ + + + - ]: 1008000 : if (i_arg > 0 && i_arg <= sizeof(definition->nospecialize) * 8 &&
924 [ + + ]: 675817 : (definition->nospecialize & (1 << (i_arg - 1)))) {
925 [ + + + + ]: 130717 : if (!jl_has_free_typevars(decl_i) && !jl_is_kind(decl_i)) {
926 [ + + ]: 130398 : if (jl_egal(elt, decl_i))
927 : 125725 : continue;
928 : 4673 : return 0;
929 : : }
930 : : }
931 : :
932 [ + + ]: 877598 : if (jl_is_kind(elt)) {
933 : : // kind slots always get guard entries (checking for subtypes of Type)
934 [ + + + + ]: 2248 : if (jl_subtype(elt, decl_i) && !jl_subtype((jl_value_t*)jl_type_type, decl_i))
935 : 1975 : continue;
936 : : // TODO: other code paths that could reach here
937 : 273 : return 0;
938 : : }
939 [ + + ]: 875350 : else if (jl_is_kind(decl_i)) {
940 : 62 : return 0;
941 : : }
942 : :
943 [ + + ]: 875288 : if (jl_is_type_type(jl_unwrap_unionall(elt))) {
944 [ + + + + : 68319 : int iscalled = i_arg > 0 && i_arg <= 8 && (definition->called & (1 << (i_arg - 1)));
+ + ]
945 [ + + ]: 68319 : if (jl_types_equal(elt, (jl_value_t*)jl_type_type)) {
946 [ + + + + ]: 20374 : if (!iscalled && very_general_type(decl_i))
947 : 14074 : continue;
948 [ - + - - ]: 6300 : if (i >= nargs && definition->isva)
949 : 0 : continue;
950 : 6300 : return 0;
951 : : }
952 [ + + + + ]: 47945 : if (!iscalled && very_general_type(decl_i))
953 : 934 : return 0;
954 [ + + ]: 47011 : if (!jl_is_datatype(elt))
955 : 2540 : return 0;
956 : :
957 : : // if the declared type was not Any or Union{Type, ...},
958 : : // then the match must been with kind, such as UnionAll or DataType,
959 : : // and the result of matching the type signature
960 : : // needs to be corrected to the concrete type 'kind' (and not to Type)
961 : 44471 : jl_value_t *kind = jl_typeof(jl_tparam0(elt));
962 [ - + ]: 44471 : if (kind == jl_bottom_type)
963 : 0 : return 0; // Type{Union{}} gets normalized to typeof(Union{})
964 [ + + + + ]: 44471 : if (jl_subtype(kind, decl_i) && !jl_subtype((jl_value_t*)jl_type_type, decl_i))
965 : 35 : return 0; // gets turned into a kind
966 : :
967 [ + + + - ]: 44445 : else if (jl_is_type_type(jl_tparam0(elt)) &&
968 : : // give up on specializing static parameters for Type{Type{Type{...}}}
969 [ - + ]: 18 : (jl_is_type_type(jl_tparam0(jl_tparam0(elt))) || !jl_has_free_typevars(decl_i))) {
970 : : /*
971 : : actual argument was Type{...}, we computed its type as
972 : : Type{Type{...}}. we must avoid unbounded nesting here, so
973 : : cache the signature as Type{T}, unless something more
974 : : specific like Type{Type{Int32}} was actually declared.
975 : : this can be determined using a type intersection.
976 : : */
977 [ # # # # ]: 0 : if (i < nargs || !definition->isva) {
978 : 0 : jl_value_t *di = jl_type_intersection(decl_i, (jl_value_t*)jl_type_type);
979 : 0 : JL_GC_PUSH1(&di);
980 [ # # ]: 0 : assert(di != (jl_value_t*)jl_bottom_type);
981 [ # # ]: 0 : if (jl_is_kind(di)) {
982 : 0 : JL_GC_POP();
983 : 0 : return 0;
984 : : }
985 [ # # ]: 0 : else if (!jl_types_equal(di, elt)) {
986 : 0 : JL_GC_POP();
987 : 0 : return 0;
988 : : }
989 : 0 : JL_GC_POP();
990 : : }
991 : : else {
992 : 0 : return 0;
993 : : }
994 : : }
995 : 44436 : continue;
996 : : }
997 : :
998 [ + + + + : 1302650 : int notcalled_func = (i_arg > 0 && i_arg <= 8 && !(definition->called & (1 << (i_arg - 1))) &&
+ + + + ]
999 : 495682 : jl_subtype(elt, (jl_value_t*)jl_function_type));
1000 [ + + + + ]: 806969 : if (notcalled_func && (decl_i == (jl_value_t*)jl_any_type ||
1001 [ + + ]: 34037 : decl_i == (jl_value_t*)jl_function_type ||
1002 [ + + ]: 30076 : (jl_is_uniontype(decl_i) && // Base.Callable
1003 [ + + ]: 334 : ((((jl_uniontype_t*)decl_i)->a == (jl_value_t*)jl_function_type &&
1004 [ - + ]: 30 : ((jl_uniontype_t*)decl_i)->b == (jl_value_t*)jl_type_type) ||
1005 [ + - ]: 304 : (((jl_uniontype_t*)decl_i)->b == (jl_value_t*)jl_function_type &&
1006 [ - + ]: 304 : ((jl_uniontype_t*)decl_i)->a == (jl_value_t*)jl_type_type))))) {
1007 : : // and attempt to despecialize types marked Function, Callable, or Any
1008 : : // when called with a subtype of Function but is not called
1009 [ + + ]: 27229 : if (elt == (jl_value_t*)jl_function_type)
1010 : 25098 : continue;
1011 : 2131 : return 0;
1012 : : }
1013 : :
1014 [ + + ]: 779740 : if (!jl_is_concrete_type(elt))
1015 : 152987 : return 0;
1016 : : }
1017 : 162244 : return 1;
1018 : : }
1019 : :
1020 : :
1021 : 62995200 : static int concretesig_equal(jl_value_t *tt, jl_value_t *simplesig) JL_NOTSAFEPOINT
1022 : : {
1023 : 62995200 : jl_value_t **types = jl_svec_data(((jl_datatype_t*)tt)->parameters);
1024 : 62995200 : jl_value_t **sigs = jl_svec_data(((jl_datatype_t*)simplesig)->parameters);
1025 : 62995200 : size_t i, lensig = jl_nparams(simplesig);
1026 [ - + ]: 62995200 : assert(lensig == jl_nparams(tt));
1027 [ + - + - ]: 62995200 : assert(lensig > 0 && !jl_is_vararg(jl_tparam(simplesig, lensig - 1)));
1028 [ + + ]: 245754000 : for (i = 0; i < lensig; i++) {
1029 : 182759000 : jl_value_t *decl = sigs[i];
1030 : 182759000 : jl_value_t *a = types[i];
1031 [ + + + - ]: 182759000 : if (a != decl && decl != (jl_value_t*)jl_any_type) {
1032 [ + - - + ]: 64509200 : if (!(jl_is_type_type(a) && jl_typeof(jl_tparam0(a)) == decl))
1033 : 0 : return 0;
1034 : : }
1035 : : }
1036 : 62995200 : return 1;
1037 : : }
1038 : :
1039 : 74592300 : static inline jl_typemap_entry_t *lookup_leafcache(jl_array_t *leafcache JL_PROPAGATES_ROOT, jl_value_t *tt, size_t world) JL_NOTSAFEPOINT
1040 : : {
1041 : 74592300 : jl_typemap_entry_t *entry = (jl_typemap_entry_t*)jl_eqtable_get(leafcache, (jl_value_t*)tt, NULL);
1042 [ + + ]: 74592300 : if (entry) {
1043 : : do {
1044 [ + + + + ]: 70275000 : if (entry->min_world <= world && world <= entry->max_world) {
1045 [ + + + - ]: 70273600 : if (entry->simplesig == (void*)jl_nothing || concretesig_equal(tt, (jl_value_t*)entry->simplesig))
1046 : 70273600 : return entry;
1047 : : }
1048 : 1438 : entry = jl_atomic_load_relaxed(&entry->next);
1049 [ + + ]: 1438 : } while ((jl_value_t*)entry != jl_nothing);
1050 : : }
1051 : 4318660 : return NULL;
1052 : : }
1053 : :
1054 : 156317 : static jl_method_instance_t *cache_method(
1055 : : jl_methtable_t *mt, _Atomic(jl_typemap_t*) *cache, jl_value_t *parent JL_PROPAGATES_ROOT,
1056 : : jl_tupletype_t *tt, // the original tupletype of the signature
1057 : : jl_method_t *definition,
1058 : : size_t world, size_t min_valid, size_t max_valid,
1059 : : jl_svec_t *sparams)
1060 : : {
1061 : : // caller must hold the mt->writelock
1062 : : // short-circuit (now that we hold the lock) if this entry is already present
1063 [ + + ]: 156317 : int8_t offs = mt ? jl_cachearg_offset(mt) : 1;
1064 : : { // scope block
1065 [ + + ]: 156317 : if (mt) {
1066 : 156305 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
1067 : 156305 : jl_typemap_entry_t *entry = lookup_leafcache(leafcache, (jl_value_t*)tt, world);
1068 [ + + ]: 156305 : if (entry)
1069 : 12967 : return entry->func.linfo;
1070 : : }
1071 : 146385 : struct jl_typemap_assoc search = {(jl_value_t*)tt, world, NULL, 0, ~(size_t)0};
1072 : 146385 : jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(cache), &search, offs, /*subtype*/1);
1073 [ + + + - ]: 146385 : if (entry && entry->func.value)
1074 : 3035 : return entry->func.linfo;
1075 : : }
1076 : :
1077 : 143350 : jl_value_t *temp = NULL;
1078 : 143350 : jl_value_t *temp2 = NULL;
1079 : 143350 : jl_value_t *temp3 = NULL;
1080 : 143350 : jl_method_instance_t *newmeth = NULL;
1081 : 143350 : jl_svec_t *newparams = NULL;
1082 : 143350 : JL_GC_PUSH5(&temp, &temp2, &temp3, &newmeth, &newparams);
1083 : :
1084 : 143350 : int cache_with_orig = 1;
1085 : 143350 : jl_tupletype_t *compilationsig = tt;
1086 [ + + + + : 143350 : intptr_t nspec = (mt == NULL || mt == jl_type_type_mt || mt == jl_nonfunction_mt ? definition->nargs + 1 : mt->max_args + 2);
+ + ]
1087 : 143350 : jl_compilation_sig(tt, sparams, definition, nspec, &newparams);
1088 [ + + ]: 143350 : if (newparams) {
1089 : 11538 : compilationsig = jl_apply_tuple_type(newparams);
1090 : 11538 : temp2 = (jl_value_t*)compilationsig;
1091 : : // In most cases `!jl_isa_compileable_sig(tt, definition))`,
1092 : : // although for some cases, (notably Varargs)
1093 : : // we might choose a replacement type that's preferable but not strictly better
1094 : 11538 : cache_with_orig = !jl_subtype((jl_value_t*)compilationsig, definition->sig);
1095 : : }
1096 : : // TODO: maybe assert(jl_isa_compileable_sig(compilationsig, definition));
1097 : 143350 : newmeth = jl_specializations_get_linfo(definition, (jl_value_t*)compilationsig, sparams);
1098 : :
1099 : 143350 : jl_tupletype_t *cachett = tt;
1100 : 143350 : jl_svec_t* guardsigs = jl_emptysvec;
1101 [ + + + - ]: 143350 : if (!cache_with_orig && mt) {
1102 : : // now examine what will happen if we chose to use this sig in the cache
1103 : 11538 : size_t min_valid2 = 1;
1104 : 11538 : size_t max_valid2 = ~(size_t)0;
1105 : 11538 : temp = ml_matches(mt, compilationsig, MAX_UNSPECIALIZED_CONFLICTS, 1, 1, world, 0, &min_valid2, &max_valid2, NULL);
1106 : 11538 : int guards = 0;
1107 [ + + ]: 11538 : if (temp == jl_false) {
1108 : 534 : cache_with_orig = 1;
1109 : : }
1110 : : else {
1111 : 11004 : int unmatched_tvars = 0;
1112 : 11004 : size_t i, l = jl_array_len(temp);
1113 [ + + ]: 22372 : for (i = 0; i < l; i++) {
1114 : 12050 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(temp, i);
1115 : 12050 : jl_svec_t *env = matc->sparams;
1116 : : int k, l;
1117 [ + + ]: 14046 : for (k = 0, l = jl_svec_len(env); k < l; k++) {
1118 : 2678 : jl_value_t *env_k = jl_svecref(env, k);
1119 [ + + - + ]: 2678 : if (jl_is_typevar(env_k) || jl_is_vararg(env_k)) {
1120 : 682 : unmatched_tvars = 1;
1121 : 682 : break;
1122 : : }
1123 : : }
1124 [ + + - + ]: 12050 : if (unmatched_tvars || guards > MAX_UNSPECIALIZED_CONFLICTS) {
1125 : : // if distinguishing a guard entry from the generalized signature
1126 : : // would require matching type vars then bail out, since the
1127 : : // method cache matching algorithm cannot do that.
1128 : : //
1129 : : // also bail if this requires too many guard entries
1130 : 682 : cache_with_orig = 1;
1131 : 682 : break;
1132 : : }
1133 [ + + ]: 11368 : if (matc->method != definition) {
1134 : 1046 : guards++;
1135 : : }
1136 : : }
1137 : : }
1138 [ + + + + ]: 11538 : if (!cache_with_orig && guards > 0) {
1139 : : // use guard entries as placeholders to prevent this cached method
1140 : : // from matching when another more specific definition also exists
1141 : : size_t i, l;
1142 : 561 : guardsigs = jl_alloc_svec(guards);
1143 : 561 : temp3 = (jl_value_t*)guardsigs;
1144 : 561 : guards = 0;
1145 [ + + ]: 2056 : for (i = 0, l = jl_array_len(temp); i < l; i++) {
1146 : 1495 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(temp, i);
1147 : 1495 : jl_method_t *other = matc->method;
1148 [ + + ]: 1495 : if (other != definition) {
1149 : 934 : jl_svecset(guardsigs, guards, matc->spec_types);
1150 : 934 : guards++;
1151 : : // alternative approach: insert sentinel entry
1152 : : //jl_typemap_insert(cache, parent, (jl_tupletype_t*)matc->spec_types,
1153 : : // NULL, jl_emptysvec, /*guard*/NULL, jl_cachearg_offset(mt), other->min_world, other->max_world);
1154 : : }
1155 : : }
1156 : : }
1157 [ + + ]: 11538 : if (!cache_with_orig) {
1158 : : // determined above that there's no ambiguity in also using compilationsig as the cacheablesig
1159 : 10322 : min_valid = min_valid2;
1160 : 10322 : max_valid = max_valid2;
1161 : 10322 : cachett = compilationsig;
1162 : : }
1163 : : }
1164 : :
1165 : : // now scan `cachett` and ensure that `Type{T}` in the cache will be matched exactly by `typeof(T)`
1166 : : // and also reduce the complexity of rejecting this entry in the cache
1167 : : // by replacing non-simple types with jl_any_type to build a new `type`
1168 : : // (for example, if the signature contains jl_function_type)
1169 : : // TODO: this is also related to how we should handle partial matches
1170 : : // (which currently might miss detection of a MethodError)
1171 : 143350 : jl_tupletype_t *simplett = NULL;
1172 : 143350 : size_t i, np = jl_nparams(cachett);
1173 : 143350 : newparams = NULL;
1174 [ + + ]: 588842 : for (i = 0; i < np; i++) {
1175 : 445492 : jl_value_t *elt = jl_svecref(cachett->parameters, i);
1176 [ + + ]: 445492 : if (jl_is_vararg(elt)) {
1177 : : }
1178 [ + + ]: 443830 : else if (jl_is_type_type(elt)) {
1179 : : // TODO: if (!jl_is_singleton(elt)) ...
1180 : 43995 : jl_value_t *kind = jl_typeof(jl_tparam0(elt));
1181 [ + + ]: 43995 : if (!newparams) newparams = jl_svec_copy(cachett->parameters);
1182 : 43995 : jl_svecset(newparams, i, kind);
1183 : : }
1184 [ + + ]: 399835 : else if (!jl_is_concrete_type(elt)) { // for example, jl_function_type or jl_tuple_type
1185 [ + + ]: 10898 : if (!newparams) newparams = jl_svec_copy(cachett->parameters);
1186 : 10898 : jl_svecset(newparams, i, jl_any_type);
1187 : : }
1188 : : }
1189 [ + + ]: 143350 : if (newparams) {
1190 : 46983 : simplett = jl_apply_tuple_type(newparams);
1191 : 46983 : temp2 = (jl_value_t*)simplett;
1192 : : }
1193 : :
1194 : : // short-circuit if an existing entry is already present
1195 : : // that satisfies our requirements
1196 [ + + ]: 143350 : if (cachett != tt) {
1197 : 10322 : struct jl_typemap_assoc search = {(jl_value_t*)cachett, world, NULL, 0, ~(size_t)0};
1198 : 10322 : jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(cache), &search, offs, /*subtype*/1);
1199 [ - + - - : 10322 : if (entry && jl_egal((jl_value_t*)entry->simplesig, simplett ? (jl_value_t*)simplett : jl_nothing) &&
- - - - ]
1200 : 0 : jl_egal((jl_value_t*)guardsigs, (jl_value_t*)entry->guardsigs)) {
1201 : 0 : JL_GC_POP();
1202 : 0 : return entry->func.linfo;
1203 : : }
1204 : : }
1205 : :
1206 : 143350 : jl_typemap_entry_t *newentry = jl_typemap_alloc(cachett, simplett, guardsigs, (jl_value_t*)newmeth, min_valid, max_valid);
1207 : 143350 : temp = (jl_value_t*)newentry;
1208 [ + + + + : 267109 : if (mt && cachett == tt && jl_svec_len(guardsigs) == 0 && tt->hash && !tt->hasfreetypevars) {
+ - + + +
- ]
1209 : : // we check `tt->hash` exists, since otherwise the NamedTuple
1210 : : // constructor and `structdiff` method pollutes this lookup with a lot
1211 : : // of garbage in the linear table search
1212 [ + + ]: 123759 : if (jl_lookup_cache_type_(tt) == NULL) {
1213 : : // if this type isn't normally in the cache, force it in there now
1214 : : // anyways so that we can depend on it as a token (especially since
1215 : : // we just cached it in memory as this method signature anyways)
1216 : 27422 : JL_LOCK(&typecache_lock);
1217 [ + - ]: 27422 : if (jl_lookup_cache_type_(tt) == NULL)
1218 : 27422 : jl_cache_type_(tt);
1219 : 27422 : JL_UNLOCK(&typecache_lock); // Might GC
1220 : : }
1221 : 123759 : jl_array_t *oldcache = jl_atomic_load_relaxed(&mt->leafcache);
1222 : 123759 : jl_typemap_entry_t *old = (jl_typemap_entry_t*)jl_eqtable_get(oldcache, (jl_value_t*)tt, jl_nothing);
1223 : 123759 : jl_atomic_store_relaxed(&newentry->next, old);
1224 : 123759 : jl_gc_wb(newentry, old);
1225 : 123759 : jl_array_t *newcache = (jl_array_t*)jl_eqtable_put(jl_atomic_load_relaxed(&mt->leafcache), (jl_value_t*)tt, (jl_value_t*)newentry, NULL);
1226 [ + + ]: 123759 : if (newcache != oldcache) {
1227 : 15414 : jl_atomic_store_release(&mt->leafcache, newcache);
1228 : 15414 : jl_gc_wb(mt, newcache);
1229 : : }
1230 : : }
1231 : : else {
1232 : 19591 : jl_typemap_insert(cache, parent, newentry, offs);
1233 : : }
1234 : :
1235 : 143350 : JL_GC_POP();
1236 : 143350 : return newmeth;
1237 : : }
1238 : :
1239 : : static jl_method_match_t *_gf_invoke_lookup(jl_value_t *types JL_PROPAGATES_ROOT, jl_value_t *mt, size_t world, size_t *min_valid, size_t *max_valid);
1240 : :
1241 : 10407 : static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_datatype_t *tt, size_t world)
1242 : : {
1243 : : // caller must hold the mt->writelock
1244 [ + + - + ]: 10407 : assert(tt->isdispatchtuple || tt->hasfreetypevars);
1245 [ + + ]: 10407 : if (tt->isdispatchtuple) {
1246 : 10399 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
1247 : 10399 : jl_typemap_entry_t *entry = lookup_leafcache(leafcache, (jl_value_t*)tt, world);
1248 [ - + ]: 10399 : if (entry)
1249 : 0 : return entry->func.linfo;
1250 : : }
1251 : :
1252 : 10407 : struct jl_typemap_assoc search = {(jl_value_t*)tt, world, NULL, 0, ~(size_t)0};
1253 : 10407 : jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(&mt->cache), &search, jl_cachearg_offset(mt), /*subtype*/1);
1254 [ + + ]: 10407 : if (entry)
1255 : 84 : return entry->func.linfo;
1256 : :
1257 : 10323 : size_t min_valid = 0;
1258 : 10323 : size_t max_valid = ~(size_t)0;
1259 : 10323 : jl_method_match_t *matc = _gf_invoke_lookup((jl_value_t*)tt, jl_nothing, world, &min_valid, &max_valid);
1260 : 10323 : jl_method_instance_t *nf = NULL;
1261 [ + + ]: 10323 : if (matc) {
1262 : 9633 : JL_GC_PUSH1(&matc);
1263 : 9633 : jl_method_t *m = matc->method;
1264 : 9633 : jl_svec_t *env = matc->sparams;
1265 : 9633 : nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, tt, m, world, min_valid, max_valid, env);
1266 : 9633 : JL_GC_POP();
1267 : : }
1268 : 10323 : return nf;
1269 : : }
1270 : :
1271 : :
1272 : : struct matches_env {
1273 : : struct typemap_intersection_env match;
1274 : : jl_typemap_entry_t *newentry;
1275 : : jl_value_t *shadowed;
1276 : : };
1277 : 91347 : static int get_intersect_visitor(jl_typemap_entry_t *oldentry, struct typemap_intersection_env *closure0)
1278 : : {
1279 : 91347 : struct matches_env *closure = container_of(closure0, struct matches_env, match);
1280 [ + + ]: 91347 : if (oldentry == closure->newentry)
1281 : 56209 : return 1;
1282 [ + + - + ]: 35138 : if (oldentry->max_world < ~(size_t)0 || oldentry->min_world == closure->newentry->min_world)
1283 : : // skip if no world has both active
1284 : : // also be careful not to try to scan something from the current dump-reload though
1285 : 6 : return 1;
1286 : 35132 : jl_method_t *oldmethod = oldentry->func.method;
1287 [ + + ]: 35132 : if (closure->shadowed == NULL)
1288 : 17127 : closure->shadowed = (jl_value_t*)jl_alloc_vec_any(0);
1289 : 35132 : jl_array_ptr_1d_push((jl_array_t*)closure->shadowed, (jl_value_t*)oldmethod);
1290 : 35132 : return 1;
1291 : : }
1292 : :
1293 : 56209 : static jl_value_t *get_intersect_matches(jl_typemap_t *defs, jl_typemap_entry_t *newentry)
1294 : : {
1295 : 56209 : jl_tupletype_t *type = newentry->sig;
1296 : 56209 : jl_tupletype_t *ttypes = (jl_tupletype_t*)jl_unwrap_unionall((jl_value_t*)type);
1297 : 56209 : size_t l = jl_nparams(ttypes);
1298 : 56209 : jl_value_t *va = NULL;
1299 [ + - ]: 56209 : if (l > 0) {
1300 : 56209 : va = jl_tparam(ttypes, l - 1);
1301 [ + + ]: 56209 : if (jl_is_vararg(va))
1302 : 2683 : va = jl_unwrap_vararg(va);
1303 : : else
1304 : 53526 : va = NULL;
1305 : : }
1306 : 56209 : struct matches_env env = {{get_intersect_visitor, (jl_value_t*)type, va,
1307 : : /* .ti = */ NULL, /* .env = */ jl_emptysvec, /* .issubty = */ 0},
1308 : : /* .newentry = */ newentry, /* .shadowed */ NULL};
1309 : 56209 : JL_GC_PUSH3(&env.match.env, &env.match.ti, &env.shadowed);
1310 : 56209 : jl_typemap_intersection_visitor(defs, 0, &env.match);
1311 : 56209 : JL_GC_POP();
1312 : 56209 : return env.shadowed;
1313 : : }
1314 : :
1315 : 0 : void print_func_loc(JL_STREAM *s, jl_method_t *m)
1316 : : {
1317 : 0 : long lno = m->line;
1318 [ # # ]: 0 : if (lno > 0) {
1319 : 0 : char *fname = jl_symbol_name((jl_sym_t*)m->file);
1320 : 0 : jl_printf(s, " at %s:%ld", fname, lno);
1321 : : }
1322 : 0 : }
1323 : :
1324 : 0 : static int is_anonfn_typename(char *name)
1325 : : {
1326 [ # # # # ]: 0 : if (name[0] != '#' || name[1] == '#')
1327 : 0 : return 0;
1328 : 0 : char *other = strrchr(name, '#');
1329 [ # # # # : 0 : return other > &name[1] && other[1] > '0' && other[1] <= '9';
# # ]
1330 : : }
1331 : :
1332 : 0 : static void method_overwrite(jl_typemap_entry_t *newentry, jl_method_t *oldvalue)
1333 : : {
1334 : : // method overwritten
1335 : 0 : jl_method_t *method = (jl_method_t*)newentry->func.method;
1336 : 0 : jl_module_t *newmod = method->module;
1337 : 0 : jl_module_t *oldmod = oldvalue->module;
1338 : 0 : jl_datatype_t *dt = jl_first_argument_datatype(oldvalue->sig);
1339 [ # # # # ]: 0 : int anon = dt && is_anonfn_typename(jl_symbol_name(dt->name->name));
1340 [ # # ]: 0 : if ((jl_options.warn_overwrite == JL_OPTIONS_WARN_OVERWRITE_ON) ||
1341 [ # # # # : 0 : (jl_options.incremental && jl_generating_output()) || anon) {
# # ]
1342 : 0 : JL_STREAM *s = JL_STDERR;
1343 : 0 : jl_printf(s, "WARNING: Method definition ");
1344 : 0 : jl_static_show_func_sig(s, (jl_value_t*)newentry->sig);
1345 : 0 : jl_printf(s, " in module %s", jl_symbol_name(oldmod->name));
1346 : 0 : print_func_loc(s, oldvalue);
1347 : 0 : jl_printf(s, " overwritten");
1348 [ # # ]: 0 : if (oldmod != newmod)
1349 : 0 : jl_printf(s, " in module %s", jl_symbol_name(newmod->name));
1350 [ # # # # : 0 : if (method->line > 0 && method->line == oldvalue->line && method->file == oldvalue->file)
# # ]
1351 [ # # ]: 0 : jl_printf(s, anon ? " on the same line" : " on the same line (check for duplicate calls to `include`)");
1352 : : else
1353 : 0 : print_func_loc(s, method);
1354 : 0 : jl_printf(s, ".\n");
1355 : 0 : jl_uv_flush(s);
1356 : : }
1357 [ # # # # ]: 0 : if (jl_options.incremental && jl_generating_output())
1358 : 0 : jl_printf(JL_STDERR, " ** incremental compilation may be fatally broken for this module **\n\n");
1359 : 0 : }
1360 : :
1361 : 56209 : static void update_max_args(jl_methtable_t *mt, jl_value_t *type)
1362 : : {
1363 [ + + + + ]: 56209 : if (mt == jl_type_type_mt || mt == jl_nonfunction_mt)
1364 : 5969 : return;
1365 : 50240 : type = jl_unwrap_unionall(type);
1366 [ - + ]: 50240 : assert(jl_is_datatype(type));
1367 : 50240 : size_t na = jl_nparams(type);
1368 [ + + ]: 50240 : if (jl_va_tuple_kind((jl_datatype_t*)type) == JL_VARARG_UNBOUND)
1369 : 2430 : na--;
1370 [ + + ]: 50240 : if (na > mt->max_args)
1371 : 23060 : mt->max_args = na;
1372 : : }
1373 : :
1374 : : jl_array_t *_jl_debug_method_invalidation JL_GLOBALLY_ROOTED = NULL;
1375 : 0 : JL_DLLEXPORT jl_value_t *jl_debug_method_invalidation(int state)
1376 : : {
1377 : : /* After calling with `state = 1`, caller is responsible for
1378 : : holding a reference to the returned array until this is called
1379 : : again with `state = 0`. */
1380 [ # # ]: 0 : if (state) {
1381 [ # # ]: 0 : if (_jl_debug_method_invalidation)
1382 : 0 : return (jl_value_t*) _jl_debug_method_invalidation;
1383 : 0 : _jl_debug_method_invalidation = jl_alloc_array_1d(jl_array_any_type, 0);
1384 : 0 : return (jl_value_t*) _jl_debug_method_invalidation;
1385 : : }
1386 : 0 : _jl_debug_method_invalidation = NULL;
1387 : 0 : return jl_nothing;
1388 : : }
1389 : :
1390 : : // call external callbacks registered with this method_instance
1391 : 898 : static void invalidate_external(jl_method_instance_t *mi, size_t max_world) {
1392 : 898 : jl_array_t *callbacks = mi->callbacks;
1393 [ - + ]: 898 : if (callbacks) {
1394 : : // AbstractInterpreter allows for MethodInstances to be present in non-local caches
1395 : : // inform those caches about the invalidation.
1396 [ # # # # ]: 0 : JL_TRY {
1397 : 0 : size_t i, l = jl_array_len(callbacks);
1398 : : jl_value_t **args;
1399 : 0 : JL_GC_PUSHARGS(args, 3);
1400 : : // these arguments are constant per call
1401 : 0 : args[1] = (jl_value_t*)mi;
1402 : 0 : args[2] = jl_box_uint32(max_world);
1403 : :
1404 : 0 : jl_task_t *ct = jl_current_task;
1405 : 0 : size_t last_age = ct->world_age;
1406 : 0 : ct->world_age = jl_get_world_counter();
1407 : :
1408 : 0 : jl_value_t **cbs = (jl_value_t**)jl_array_ptr_data(callbacks);
1409 [ # # ]: 0 : for (i = 0; i < l; i++) {
1410 : 0 : args[0] = cbs[i];
1411 : 0 : jl_apply(args, 3);
1412 : : }
1413 : 0 : ct->world_age = last_age;
1414 : 0 : JL_GC_POP();
1415 : : }
1416 [ # # ]: 0 : JL_CATCH {
1417 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "error in invalidation callback: ");
1418 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception());
1419 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "\n");
1420 : 0 : jlbacktrace(); // written to STDERR_FILENO
1421 : : }
1422 : : }
1423 : 898 : }
1424 : :
1425 : 5836 : static void do_nothing_with_codeinst(jl_code_instance_t *ci) {}
1426 : :
1427 : : // recursively invalidate cached methods that had an edge to a replaced method
1428 : 3610 : static void invalidate_method_instance(void (*f)(jl_code_instance_t*), jl_method_instance_t *replaced, size_t max_world, int depth)
1429 : : {
1430 [ - + ]: 3610 : if (_jl_debug_method_invalidation) {
1431 : 0 : jl_value_t *boxeddepth = NULL;
1432 : 0 : JL_GC_PUSH1(&boxeddepth);
1433 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)replaced);
1434 : 0 : boxeddepth = jl_box_int32(depth);
1435 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, boxeddepth);
1436 : 0 : JL_GC_POP();
1437 : : }
1438 [ - + ]: 3610 : if (!jl_is_method(replaced->def.method))
1439 : 0 : return; // shouldn't happen, but better to be safe
1440 : 3610 : JL_LOCK(&replaced->def.method->writelock);
1441 : 3610 : jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&replaced->cache);
1442 [ + + ]: 9446 : while (codeinst) {
1443 [ + + ]: 5836 : if (codeinst->max_world == ~(size_t)0) {
1444 [ - + ]: 2160 : assert(codeinst->min_world - 1 <= max_world && "attempting to set illogical world constraints (probable race condition)");
1445 : 2160 : codeinst->max_world = max_world;
1446 : : }
1447 [ - + ]: 5836 : assert(codeinst->max_world <= max_world);
1448 : 5836 : (*f)(codeinst);
1449 : 5836 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
1450 : : }
1451 : : // recurse to all backedges to update their valid range also
1452 : 3610 : jl_array_t *backedges = replaced->backedges;
1453 [ + + ]: 3610 : if (backedges) {
1454 : 1788 : replaced->backedges = NULL;
1455 : 1788 : size_t i, l = jl_array_len(backedges);
1456 [ + + ]: 5212 : for (i = 0; i < l; i++) {
1457 : 3424 : jl_method_instance_t *replaced = (jl_method_instance_t*)jl_array_ptr_ref(backedges, i);
1458 : 3424 : invalidate_method_instance(f, replaced, max_world, depth + 1);
1459 : : }
1460 : : }
1461 : 3610 : JL_UNLOCK(&replaced->def.method->writelock);
1462 : : }
1463 : :
1464 : : // invalidate cached methods that overlap this definition
1465 : 50 : void invalidate_backedges(void (*f)(jl_code_instance_t*), jl_method_instance_t *replaced_mi, size_t max_world, const char *why)
1466 : : {
1467 : 50 : JL_LOCK(&replaced_mi->def.method->writelock);
1468 : 50 : jl_array_t *backedges = replaced_mi->backedges;
1469 [ + + ]: 50 : if (backedges) {
1470 : : // invalidate callers (if any)
1471 : 48 : replaced_mi->backedges = NULL;
1472 : 48 : size_t i, l = jl_array_len(backedges);
1473 : 48 : jl_method_instance_t **replaced = (jl_method_instance_t**)jl_array_ptr_data(backedges);
1474 [ + + ]: 146 : for (i = 0; i < l; i++) {
1475 : 98 : invalidate_method_instance(f, replaced[i], max_world, 1);
1476 : : }
1477 : : }
1478 : 50 : JL_UNLOCK(&replaced_mi->def.method->writelock);
1479 [ + - - + ]: 50 : if (why && _jl_debug_method_invalidation) {
1480 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)replaced_mi);
1481 : 0 : jl_value_t *loctag = jl_cstr_to_string(why);
1482 : 0 : JL_GC_PUSH1(&loctag);
1483 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1484 : 0 : JL_GC_POP();
1485 : : }
1486 : 50 : }
1487 : :
1488 : : // add a backedge from callee to caller
1489 : 3376760 : JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_method_instance_t *caller)
1490 : : {
1491 : 3376760 : JL_LOCK(&callee->def.method->writelock);
1492 [ + + ]: 3376760 : if (!callee->backedges) {
1493 : : // lazy-init the backedges array
1494 : 207307 : callee->backedges = jl_alloc_vec_any(1);
1495 : 207307 : jl_gc_wb(callee, callee->backedges);
1496 : 207307 : jl_array_ptr_set(callee->backedges, 0, caller);
1497 : : }
1498 : : else {
1499 : 3169460 : size_t i, l = jl_array_len(callee->backedges);
1500 [ + + ]: 739254000 : for (i = 0; i < l; i++) {
1501 [ + + ]: 738698000 : if (jl_array_ptr_ref(callee->backedges, i) == (jl_value_t*)caller)
1502 : 2613480 : break;
1503 : : }
1504 [ + + ]: 3169460 : if (i == l) {
1505 : 555976 : jl_array_ptr_1d_push(callee->backedges, (jl_value_t*)caller);
1506 : : }
1507 : : }
1508 : 3376760 : JL_UNLOCK(&callee->def.method->writelock);
1509 : 3376760 : }
1510 : :
1511 : : // add a backedge from a non-existent signature to caller
1512 : 9725 : JL_DLLEXPORT void jl_method_table_add_backedge(jl_methtable_t *mt, jl_value_t *typ, jl_value_t *caller)
1513 : : {
1514 : 9725 : JL_LOCK(&mt->writelock);
1515 [ + + ]: 9725 : if (!mt->backedges) {
1516 : : // lazy-init the backedges array
1517 : 1182 : mt->backedges = jl_alloc_vec_any(2);
1518 : 1182 : jl_gc_wb(mt, mt->backedges);
1519 : 1182 : jl_array_ptr_set(mt->backedges, 0, typ);
1520 : 1182 : jl_array_ptr_set(mt->backedges, 1, caller);
1521 : : }
1522 : : else {
1523 : 8543 : size_t i, l = jl_array_len(mt->backedges);
1524 [ + + ]: 1896860 : for (i = 1; i < l; i += 2) {
1525 [ + + ]: 1889160 : if (jl_types_equal(jl_array_ptr_ref(mt->backedges, i - 1), typ)) {
1526 [ + + ]: 30872 : if (jl_array_ptr_ref(mt->backedges, i) == caller) {
1527 : 838 : JL_UNLOCK(&mt->writelock);
1528 : 838 : return;
1529 : : }
1530 : : // reuse the already cached instance of this type
1531 : 30034 : typ = jl_array_ptr_ref(mt->backedges, i - 1);
1532 : : }
1533 : : }
1534 : 7705 : jl_array_ptr_1d_push(mt->backedges, typ);
1535 : 7705 : jl_array_ptr_1d_push(mt->backedges, caller);
1536 : : }
1537 : 8887 : JL_UNLOCK(&mt->writelock);
1538 : : }
1539 : :
1540 : : struct invalidate_mt_env {
1541 : : jl_typemap_entry_t *newentry;
1542 : : jl_array_t *shadowed;
1543 : : size_t max_world;
1544 : : int invalidated;
1545 : : };
1546 : 65260 : static int invalidate_mt_cache(jl_typemap_entry_t *oldentry, void *closure0)
1547 : : {
1548 : 65260 : struct invalidate_mt_env *env = (struct invalidate_mt_env*)closure0;
1549 : : JL_GC_PROMISE_ROOTED(env->newentry);
1550 [ + + ]: 65260 : if (oldentry->max_world == ~(size_t)0) {
1551 : 58848 : jl_method_instance_t *mi = oldentry->func.linfo;
1552 : 58848 : int intersects = 0;
1553 : 58848 : jl_method_instance_t **d = (jl_method_instance_t**)jl_array_ptr_data(env->shadowed);
1554 : 58848 : size_t i, n = jl_array_len(env->shadowed);
1555 [ + + ]: 121252 : for (i = 0; i < n; i++) {
1556 [ + + ]: 62670 : if (mi == d[i]) {
1557 : 266 : intersects = 1;
1558 : 266 : break;
1559 : : }
1560 : : }
1561 [ + + ]: 58848 : if (intersects) {
1562 [ - + ]: 266 : if (_jl_debug_method_invalidation) {
1563 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi);
1564 : 0 : jl_value_t *loctag = jl_cstr_to_string("invalidate_mt_cache");
1565 : 0 : JL_GC_PUSH1(&loctag);
1566 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1567 : 0 : JL_GC_POP();
1568 : : }
1569 : 266 : oldentry->max_world = env->max_world;
1570 : 266 : env->invalidated = 1;
1571 : : }
1572 : : }
1573 : 65260 : return 1;
1574 : : }
1575 : 0 : static int disable_mt_cache(jl_typemap_entry_t *oldentry, void *closure0)
1576 : : {
1577 : 0 : struct invalidate_mt_env *env = (struct invalidate_mt_env*)closure0;
1578 [ # # ]: 0 : if (oldentry->max_world < ~(size_t)0)
1579 : 0 : return 1;
1580 : 0 : jl_method_t *m = oldentry->func.linfo->def.method;
1581 [ # # ]: 0 : if (m == env->newentry->func.method)
1582 : 0 : oldentry->max_world = env->max_world;
1583 : 0 : return 1;
1584 : : }
1585 : :
1586 : 10 : static int typemap_search(jl_typemap_entry_t *entry, void *closure)
1587 : : {
1588 [ + + ]: 10 : if ((void*)(entry->func.method) == *(jl_method_t**)closure) {
1589 : 6 : *(jl_typemap_entry_t**)closure = entry;
1590 : 6 : return 0;
1591 : : }
1592 : 4 : return 1;
1593 : : }
1594 : :
1595 : : static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT;
1596 : :
1597 : : #ifndef __clang_gcanalyzer__
1598 : 6 : static jl_typemap_entry_t *do_typemap_search(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_method_t *method) JL_NOTSAFEPOINT {
1599 : 6 : jl_value_t *closure = (jl_value_t*)(method);
1600 [ - + ]: 6 : if (jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), typemap_search, &closure))
1601 : 0 : jl_error("method not in method table");
1602 : 6 : return (jl_typemap_entry_t *)closure;
1603 : : }
1604 : : #endif
1605 : :
1606 : 6 : static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *methodentry, jl_method_t *method, size_t max_world)
1607 : : {
1608 [ - + ]: 6 : assert(!method->is_for_opaque_closure);
1609 : 6 : method->deleted_world = methodentry->max_world = max_world;
1610 : : // drop this method from mt->cache
1611 : : struct invalidate_mt_env mt_cache_env;
1612 : 6 : mt_cache_env.max_world = max_world;
1613 : 6 : mt_cache_env.newentry = methodentry;
1614 : 6 : mt_cache_env.shadowed = NULL;
1615 : 6 : mt_cache_env.invalidated = 0;
1616 : 6 : jl_typemap_visitor(jl_atomic_load_relaxed(&mt->cache), disable_mt_cache, (void*)&mt_cache_env);
1617 : 6 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
1618 : 6 : size_t i, l = jl_array_len(leafcache);
1619 [ + + ]: 102 : for (i = 1; i < l; i += 2) {
1620 : 96 : jl_typemap_entry_t *oldentry = (jl_typemap_entry_t*)jl_array_ptr_ref(leafcache, i);
1621 [ + + ]: 96 : if (oldentry) {
1622 [ + + ]: 32 : while ((jl_value_t*)oldentry != jl_nothing) {
1623 [ + + ]: 20 : if (oldentry->max_world == ~(size_t)0)
1624 : 8 : oldentry->max_world = mt_cache_env.max_world;
1625 : 20 : oldentry = jl_atomic_load_relaxed(&oldentry->next);
1626 : : }
1627 : : }
1628 : : }
1629 : : // Invalidate the backedges
1630 : 6 : int invalidated = 0;
1631 : 6 : jl_svec_t *specializations = jl_atomic_load_relaxed(&methodentry->func.method->specializations);
1632 : 6 : l = jl_svec_len(specializations);
1633 [ + + ]: 54 : for (i = 0; i < l; i++) {
1634 : 48 : jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
1635 [ + + ]: 48 : if ((jl_value_t*)mi != jl_nothing) {
1636 : 6 : invalidated = 1;
1637 : 6 : invalidate_external(mi, methodentry->max_world);
1638 : 6 : invalidate_backedges(&do_nothing_with_codeinst, mi, methodentry->max_world, "jl_method_table_disable");
1639 : : }
1640 : : }
1641 [ + - - + ]: 6 : if (invalidated && _jl_debug_method_invalidation) {
1642 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method);
1643 : 0 : jl_value_t *loctag = jl_cstr_to_string("jl_method_table_disable");
1644 : 0 : JL_GC_PUSH1(&loctag);
1645 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1646 : 0 : JL_GC_POP();
1647 : : }
1648 : 6 : }
1649 : :
1650 : 6 : JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *method)
1651 : : {
1652 [ - + - - ]: 6 : if (jl_options.incremental && jl_generating_output())
1653 : 0 : jl_printf(JL_STDERR, "WARNING: method deletion during Module precompile may lead to undefined behavior"
1654 : : "\n ** incremental compilation may be fatally broken for this module **\n\n");
1655 : 6 : jl_typemap_entry_t *methodentry = do_typemap_search(mt, method);
1656 : 6 : JL_LOCK(&mt->writelock);
1657 : : // Narrow the world age on the method to make it uncallable
1658 : 6 : size_t world = jl_atomic_fetch_add(&jl_world_counter, 1);
1659 : 6 : jl_method_table_invalidate(mt, methodentry, method, world);
1660 : 6 : JL_UNLOCK(&mt->writelock);
1661 : 6 : }
1662 : :
1663 : 10549200 : static int jl_type_intersection2(jl_value_t *t1, jl_value_t *t2, jl_value_t **isect, jl_value_t **isect2)
1664 : : {
1665 : 10549200 : *isect2 = NULL;
1666 : 10549200 : int is_subty = 0;
1667 : 10549200 : *isect = jl_type_intersection_env_s(t1, t2, NULL, &is_subty);
1668 [ + + ]: 10549200 : if (*isect == jl_bottom_type)
1669 : 10083400 : return 0;
1670 [ + + ]: 465780 : if (is_subty)
1671 : 438289 : return 1;
1672 : : // TODO: sometimes type intersection returns types with free variables
1673 [ + - - + ]: 27491 : if (jl_has_free_typevars(t1) || jl_has_free_typevars(t2))
1674 : 0 : return 1;
1675 : : // determine if type-intersection can be convinced to give a better, non-bad answer
1676 : : // if the intersection was imprecise, see if we can do better by switching the types
1677 : 27491 : *isect2 = jl_type_intersection(t2, t1);
1678 [ - + ]: 27491 : if (*isect2 == jl_bottom_type) {
1679 : 0 : *isect = jl_bottom_type;
1680 : 0 : *isect2 = NULL;
1681 : 0 : return 0;
1682 : : }
1683 [ + + ]: 27491 : if (jl_types_egal(*isect2, *isect)) {
1684 : 22989 : *isect2 = NULL;
1685 : : }
1686 : 27491 : return 1;
1687 : : }
1688 : :
1689 : 56209 : JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype)
1690 : : {
1691 : : JL_TIMING(ADD_METHOD);
1692 [ - + ]: 56209 : assert(jl_is_method(method));
1693 [ - + ]: 56209 : assert(jl_is_mtable(mt));
1694 : 56209 : jl_value_t *type = method->sig;
1695 : 56209 : jl_value_t *oldvalue = NULL;
1696 : 56209 : jl_array_t *oldmi = NULL;
1697 [ + - ]: 56209 : if (method->primary_world == 1)
1698 : 56209 : method->primary_world = jl_atomic_fetch_add(&jl_world_counter, 1) + 1;
1699 : 56209 : size_t max_world = method->primary_world - 1;
1700 : 56209 : jl_value_t *loctag = NULL; // debug info for invalidation
1701 : 56209 : jl_value_t *isect = NULL;
1702 : 56209 : jl_value_t *isect2 = NULL;
1703 : 56209 : jl_value_t *isect3 = NULL;
1704 : 56209 : jl_typemap_entry_t *newentry = NULL;
1705 : 56209 : JL_GC_PUSH7(&oldvalue, &oldmi, &newentry, &loctag, &isect, &isect2, &isect3);
1706 : 56209 : JL_LOCK(&mt->writelock);
1707 : : // first find if we have an existing entry to delete
1708 : 56209 : struct jl_typemap_assoc search = {(jl_value_t*)type, method->primary_world, NULL, 0, ~(size_t)0};
1709 : 56209 : jl_typemap_entry_t *oldentry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(&mt->defs), &search, /*offs*/0, /*subtype*/0);
1710 : : // then add our new entry
1711 : 56209 : newentry = jl_typemap_alloc((jl_tupletype_t*)type, simpletype, jl_emptysvec,
1712 : : (jl_value_t*)method, method->primary_world, method->deleted_world);
1713 : 56209 : jl_typemap_insert(&mt->defs, (jl_value_t*)mt, newentry, 0);
1714 [ - + ]: 56209 : if (oldentry) {
1715 : 0 : jl_method_t *m = oldentry->func.method;
1716 : 0 : method_overwrite(newentry, m);
1717 : 0 : jl_method_table_invalidate(mt, oldentry, m, max_world);
1718 : : }
1719 : : else {
1720 : 56209 : oldvalue = get_intersect_matches(jl_atomic_load_relaxed(&mt->defs), newentry);
1721 : :
1722 : 56209 : int invalidated = 0;
1723 : : jl_method_t **d;
1724 : : size_t j, n;
1725 [ + + ]: 56209 : if (oldvalue == NULL) {
1726 : 39082 : d = NULL;
1727 : 39082 : n = 0;
1728 : : }
1729 : : else {
1730 [ - + ]: 17127 : assert(jl_is_array(oldvalue));
1731 : 17127 : d = (jl_method_t**)jl_array_ptr_data(oldvalue);
1732 : 17127 : n = jl_array_len(oldvalue);
1733 : : }
1734 [ + + ]: 56209 : if (mt->backedges) {
1735 : 6486 : jl_value_t **backedges = jl_array_ptr_data(mt->backedges);
1736 : 6486 : size_t i, na = jl_array_len(mt->backedges);
1737 : 6486 : size_t ins = 0;
1738 [ + + ]: 549568 : for (i = 1; i < na; i += 2) {
1739 : 543082 : jl_value_t *backedgetyp = backedges[i - 1];
1740 : 543082 : int missing = 0;
1741 [ + + ]: 543082 : if (jl_type_intersection2(backedgetyp, (jl_value_t*)type, &isect, &isect2)) {
1742 : : // See if the intersection was actually already fully
1743 : : // covered, but that the new method is ambiguous.
1744 : : // -> no previous method: now there is one, need to update the missing edge
1745 : : // -> one+ previously matching method(s):
1746 : : // -> more specific then all of them: need to update the missing edge
1747 : : // -> some may have been ambiguous: now there is a replacement
1748 : : // -> some may have been called: now there is a replacement (also will be detected in the loop later)
1749 : : // -> less specific or ambiguous with any one of them: can ignore the missing edge (not missing)
1750 : : // -> some may have been ambiguous: still are
1751 : : // -> some may have been called: they may be partly replaced (will be detected in the loop later)
1752 : 90 : missing = 1;
1753 : : size_t j;
1754 [ + + ]: 492 : for (j = 0; j < n; j++) {
1755 : 404 : jl_method_t *m = d[j];
1756 [ + + - + : 404 : if (jl_subtype(isect, m->sig) || (isect2 && jl_subtype(isect2, m->sig))) {
- - ]
1757 : : // We now know that there actually was a previous
1758 : : // method for this part of the type intersection.
1759 [ + + ]: 16 : if (!jl_type_morespecific(type, m->sig)) {
1760 : 2 : missing = 0;
1761 : 2 : break;
1762 : : }
1763 : : }
1764 : : }
1765 : : }
1766 [ + + ]: 543082 : if (missing) {
1767 : 88 : jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i];
1768 : 88 : invalidate_external(backedge, max_world);
1769 : 88 : invalidate_method_instance(&do_nothing_with_codeinst, backedge, max_world, 0);
1770 : 88 : invalidated = 1;
1771 [ - + ]: 88 : if (_jl_debug_method_invalidation)
1772 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)backedgetyp);
1773 : : }
1774 : : else {
1775 : 542994 : backedges[ins++] = backedges[i - 1];
1776 : 542994 : backedges[ins++] = backedges[i - 0];
1777 : : }
1778 : : }
1779 [ + + ]: 6486 : if (ins == 0)
1780 : 22 : mt->backedges = NULL;
1781 : : else
1782 : 6464 : jl_array_del_end(mt->backedges, na - ins);
1783 : : }
1784 [ + + ]: 56209 : if (oldvalue) {
1785 : 17127 : oldmi = jl_alloc_vec_any(0);
1786 : : enum morespec_options {
1787 : : morespec_unknown,
1788 : : morespec_isnot,
1789 : : morespec_is
1790 : : };
1791 : 17127 : char *morespec = (char*)alloca(n);
1792 : 17127 : memset(morespec, morespec_unknown, n);
1793 [ + + ]: 52259 : for (j = 0; j < n; j++) {
1794 : 35132 : jl_method_t *m = d[j];
1795 [ - + ]: 35132 : if (morespec[j] == (char)morespec_is)
1796 : 0 : continue;
1797 : 35132 : jl_svec_t *specializations = jl_atomic_load_relaxed(&m->specializations);
1798 : 35132 : _Atomic(jl_method_instance_t*) *data = (_Atomic(jl_method_instance_t*)*)jl_svec_data(specializations);
1799 : 35132 : size_t i, l = jl_svec_len(specializations);
1800 : 35132 : enum morespec_options ambig = morespec_unknown;
1801 [ + + ]: 135213 : for (i = 0; i < l; i++) {
1802 : 100262 : jl_method_instance_t *mi = jl_atomic_load_relaxed(&data[i]);
1803 [ + + ]: 100262 : if ((jl_value_t*)mi == jl_nothing)
1804 : 30191 : continue;
1805 : 70071 : isect3 = jl_type_intersection(m->sig, (jl_value_t*)mi->specTypes);
1806 [ + + ]: 70071 : if (jl_type_intersection2(type, isect3, &isect, &isect2)) {
1807 [ + + ]: 1053 : if (morespec[j] == (char)morespec_unknown)
1808 [ + + ]: 911 : morespec[j] = (char)(jl_type_morespecific(m->sig, type) ? morespec_is : morespec_isnot);
1809 [ + + ]: 1053 : if (morespec[j] == (char)morespec_is)
1810 : : // not actually shadowing--the existing method is still better
1811 : 181 : break;
1812 [ + + ]: 872 : if (ambig == morespec_unknown)
1813 [ + + ]: 736 : ambig = jl_type_morespecific(type, m->sig) ? morespec_is : morespec_isnot;
1814 : : // replacing a method--see if this really was the selected method previously
1815 : : // over the intersection
1816 [ + + ]: 872 : if (ambig == morespec_isnot) {
1817 : : size_t k;
1818 [ + + ]: 139 : for (k = 0; k < n; k++) {
1819 : 129 : jl_method_t *m2 = d[k];
1820 [ + + + + : 129 : if (m == m2 || !(jl_subtype(isect, m2->sig) || (isect && jl_subtype(isect, m2->sig))))
+ - + - ]
1821 : 44 : continue;
1822 [ + + ]: 85 : if (morespec[k] == (char)morespec_unknown)
1823 [ + + ]: 45 : morespec[k] = (char)(jl_type_morespecific(m2->sig, type) ? morespec_is : morespec_isnot);
1824 [ + + ]: 85 : if (morespec[k] == (char)morespec_is)
1825 : : // not actually shadowing this--m2 will still be better
1826 : 30 : break;
1827 : : // since m2 was also a previous match over isect,
1828 : : // see if m was also previously dominant over all m2
1829 [ + + ]: 55 : if (!jl_type_morespecific(m->sig, m2->sig))
1830 : 38 : break;
1831 : : }
1832 [ + + ]: 78 : if (k != n)
1833 : 68 : continue;
1834 : : }
1835 : 804 : jl_array_ptr_1d_push(oldmi, (jl_value_t*)mi);
1836 : 804 : invalidate_external(mi, max_world);
1837 [ + + ]: 804 : if (mi->backedges) {
1838 : 44 : invalidated = 1;
1839 : 44 : invalidate_backedges(&do_nothing_with_codeinst, mi, max_world, "jl_method_table_insert");
1840 : : }
1841 : : }
1842 : : }
1843 : : }
1844 [ + + ]: 17127 : if (jl_array_len(oldmi)) {
1845 : : // search mt->cache and leafcache and drop anything that might overlap with the new method
1846 : : // TODO: keep track of just the `mi` for which shadowing was true (to avoid recomputing that here)
1847 : : struct invalidate_mt_env mt_cache_env;
1848 : 690 : mt_cache_env.max_world = max_world;
1849 : 690 : mt_cache_env.shadowed = oldmi;
1850 : 690 : mt_cache_env.newentry = newentry;
1851 : 690 : mt_cache_env.invalidated = 0;
1852 : :
1853 : 690 : jl_typemap_visitor(jl_atomic_load_relaxed(&mt->cache), invalidate_mt_cache, (void*)&mt_cache_env);
1854 : 690 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
1855 : 690 : size_t i, l = jl_array_len(leafcache);
1856 [ + + ]: 118994 : for (i = 1; i < l; i += 2) {
1857 : 118304 : jl_value_t *entry = jl_array_ptr_ref(leafcache, i);
1858 [ + + ]: 118304 : if (entry) {
1859 [ + + ]: 105028 : while (entry != jl_nothing) {
1860 : 53060 : invalidate_mt_cache((jl_typemap_entry_t*)entry, (void*)&mt_cache_env);
1861 : 53060 : entry = (jl_value_t*)jl_atomic_load_relaxed(&((jl_typemap_entry_t*)entry)->next);
1862 : : }
1863 : : }
1864 : : }
1865 : : }
1866 : : }
1867 [ + + - + ]: 56209 : if (invalidated && _jl_debug_method_invalidation) {
1868 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)method);
1869 : 0 : loctag = jl_cstr_to_string("jl_method_table_insert");
1870 : 0 : jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag);
1871 : : }
1872 : 56209 : update_max_args(mt, type);
1873 : : }
1874 : 56209 : JL_UNLOCK(&mt->writelock);
1875 : 56209 : JL_GC_POP();
1876 : 56209 : }
1877 : :
1878 : 662 : static void JL_NORETURN jl_method_error_bare(jl_function_t *f, jl_value_t *args, size_t world)
1879 : : {
1880 [ + - ]: 662 : if (jl_methoderror_type) {
1881 : 662 : jl_value_t *e = jl_new_struct_uninit(jl_methoderror_type);
1882 : : struct jl_method_error {
1883 : : jl_value_t *f;
1884 : : jl_value_t *args;
1885 : : size_t world;
1886 : 662 : } *pe = (struct jl_method_error*)e,
1887 : 662 : ee = {f, args, world};
1888 : 662 : *pe = ee;
1889 : 662 : jl_throw(e);
1890 : : }
1891 : : else {
1892 : 0 : jl_printf((JL_STREAM*)STDERR_FILENO, "A method error occurred before the base MethodError type was defined. Aborting...\n");
1893 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO,(jl_value_t*)f); jl_printf((JL_STREAM*)STDERR_FILENO," world %u\n", (unsigned)world);
1894 : 0 : jl_static_show((JL_STREAM*)STDERR_FILENO,args); jl_printf((JL_STREAM*)STDERR_FILENO,"\n");
1895 : 0 : jl_ptls_t ptls = jl_current_task->ptls;
1896 : 0 : ptls->bt_size = rec_backtrace(ptls->bt_data, JL_MAX_BT_SIZE, 0);
1897 : 0 : jl_critical_error(0, NULL, jl_current_task);
1898 : 0 : abort();
1899 : : }
1900 : : // not reached
1901 : : }
1902 : :
1903 : 662 : void JL_NORETURN jl_method_error(jl_function_t *f, jl_value_t **args, size_t na, size_t world)
1904 : : {
1905 : 662 : jl_value_t *argtup = jl_f_tuple(NULL, args, na - 1);
1906 : 662 : JL_GC_PUSH1(&argtup);
1907 : 662 : jl_method_error_bare(f, argtup, world);
1908 : : // not reached
1909 : : }
1910 : :
1911 : 23749100 : jl_tupletype_t *arg_type_tuple(jl_value_t *arg1, jl_value_t **args, size_t nargs)
1912 : : {
1913 : 23749100 : return jl_inst_arg_tuple_type(arg1, args, nargs, 1);
1914 : : }
1915 : :
1916 : 57455400 : static jl_tupletype_t *lookup_arg_type_tuple(jl_value_t *arg1 JL_PROPAGATES_ROOT, jl_value_t **args, size_t nargs)
1917 : : {
1918 : 57455400 : return jl_lookup_arg_tuple_type(arg1, args, nargs, 1);
1919 : : }
1920 : :
1921 : 29898 : jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t world)
1922 : : {
1923 [ - + ]: 29898 : assert(nargs > 0 && "expected caller to handle this case");
1924 : 29898 : jl_methtable_t *mt = jl_gf_mtable(args[0]);
1925 : 29898 : jl_typemap_t *cache = jl_atomic_load_relaxed(&mt->cache); // XXX: gc root for this?
1926 : 29898 : jl_typemap_entry_t *entry = jl_typemap_assoc_exact(cache, args[0], &args[1], nargs, jl_cachearg_offset(mt), world);
1927 [ + + ]: 29898 : if (entry)
1928 : 19966 : return entry->func.linfo;
1929 : 9932 : jl_tupletype_t *tt = arg_type_tuple(args[0], &args[1], nargs);
1930 : 9932 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
1931 : 9932 : entry = lookup_leafcache(leafcache, (jl_value_t*)tt, world);
1932 [ + + ]: 9932 : if (entry)
1933 : 9535 : return entry->func.linfo;
1934 : 397 : JL_GC_PUSH1(&tt);
1935 : 397 : JL_LOCK(&mt->writelock);
1936 : 397 : jl_method_instance_t *sf = jl_mt_assoc_by_type(mt, tt, world);
1937 : 397 : JL_UNLOCK(&mt->writelock);
1938 : 397 : JL_GC_POP();
1939 : 397 : return sf;
1940 : : }
1941 : :
1942 : : // return a Vector{Any} of svecs, each describing a method match:
1943 : : // Any[svec(tt, spvals, m, full), ...]
1944 : : // tt is the intersection of the type argument and the method signature,
1945 : : // spvals is any matched static parameter values, m is the Method,
1946 : : // full is a boolean indicating if that method fully covers the input
1947 : : //
1948 : : // lim is the max # of methods to return. if there are more, returns jl_false.
1949 : : // Negative values stand for no limit.
1950 : : // Unless lim == -1, remove matches that are unambiguously covered by earler ones
1951 : 1803100 : JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous,
1952 : : size_t world, size_t *min_valid, size_t *max_valid, int *ambig)
1953 : : {
1954 : : JL_TIMING(METHOD_MATCH);
1955 [ + + ]: 1803100 : if (ambig != NULL)
1956 : 1798590 : *ambig = 0;
1957 : 1803100 : jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)types);
1958 [ + - - + ]: 1803100 : if (jl_is_tuple_type(unw) && jl_tparam0(unw) == jl_bottom_type)
1959 : 0 : return (jl_value_t*)jl_an_empty_vec_any;
1960 [ + - ]: 1803100 : if (mt == jl_nothing)
1961 : 1803100 : mt = (jl_value_t*)jl_method_table_for(unw);
1962 [ - + ]: 1803100 : if (mt == jl_nothing)
1963 : 0 : mt = NULL;
1964 : 1803100 : return ml_matches((jl_methtable_t*)mt, types, lim, include_ambiguous, 1, world, 1, min_valid, max_valid, ambig);
1965 : : }
1966 : :
1967 : 77847500 : jl_method_instance_t *jl_get_unspecialized_from_mi(jl_method_instance_t *method JL_PROPAGATES_ROOT)
1968 : : {
1969 : 77847500 : jl_method_t *def = method->def.method;
1970 : 77847500 : jl_method_instance_t *mi = jl_get_unspecialized(def);
1971 [ + + ]: 77847500 : if (mi == NULL) {
1972 : 39 : return method;
1973 : : }
1974 : 77847500 : return mi;
1975 : : }
1976 : :
1977 : 77847500 : jl_method_instance_t *jl_get_unspecialized(jl_method_t *def JL_PROPAGATES_ROOT)
1978 : : {
1979 : : // one unspecialized version of a function can be shared among all cached specializations
1980 [ + + - + ]: 77847500 : if (!jl_is_method(def) || def->source == NULL) {
1981 : : // generated functions might instead randomly just never get inferred, sorry
1982 : 39 : return NULL;
1983 : : }
1984 : 77847500 : jl_method_instance_t *unspec = jl_atomic_load_relaxed(&def->unspecialized);
1985 [ + + ]: 77847500 : if (unspec == NULL) {
1986 : 1866 : JL_LOCK(&def->writelock);
1987 : 1866 : unspec = jl_atomic_load_relaxed(&def->unspecialized);
1988 [ + - ]: 1866 : if (unspec == NULL) {
1989 : 1866 : unspec = jl_get_specialized(def, def->sig, jl_emptysvec);
1990 : 1866 : jl_atomic_store_release(&def->unspecialized, unspec);
1991 : 1866 : jl_gc_wb(def, unspec);
1992 : : }
1993 : 1866 : JL_UNLOCK(&def->writelock);
1994 : : }
1995 : 77847500 : return unspec;
1996 : : }
1997 : :
1998 : :
1999 : 155725000 : jl_code_instance_t *jl_method_compiled(jl_method_instance_t *mi, size_t world)
2000 : : {
2001 : 155725000 : jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache);
2002 [ + + ]: 155775000 : while (codeinst) {
2003 [ + + + + ]: 50887 : if (codeinst->min_world <= world && world <= codeinst->max_world) {
2004 [ + + ]: 49891 : if (jl_atomic_load_relaxed(&codeinst->invoke) != NULL)
2005 : 771 : return codeinst;
2006 : : }
2007 : 50116 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
2008 : : }
2009 : 155724000 : return NULL;
2010 : : }
2011 : :
2012 : : jl_mutex_t precomp_statement_out_lock;
2013 : :
2014 : 15071 : static void record_precompile_statement(jl_method_instance_t *mi)
2015 : : {
2016 : : static ios_t f_precompile;
2017 : : static JL_STREAM* s_precompile = NULL;
2018 : 15071 : jl_method_t *def = mi->def.method;
2019 [ + + ]: 15071 : if (jl_options.trace_compile == NULL)
2020 : 9917 : return;
2021 [ + + ]: 5154 : if (!jl_is_method(def))
2022 : 4 : return;
2023 : :
2024 [ - + ]: 5150 : if (jl_n_threads > 1)
2025 : 0 : JL_LOCK(&precomp_statement_out_lock);
2026 [ + + ]: 5150 : if (s_precompile == NULL) {
2027 : 6 : const char *t = jl_options.trace_compile;
2028 [ - + ]: 6 : if (!strncmp(t, "stderr", 6)) {
2029 : 0 : s_precompile = JL_STDERR;
2030 : : }
2031 : : else {
2032 [ - + ]: 6 : if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
2033 : 0 : jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
2034 : 6 : s_precompile = (JL_STREAM*) &f_precompile;
2035 : : }
2036 : : }
2037 [ + - ]: 5150 : if (!jl_has_free_typevars(mi->specTypes)) {
2038 : 5150 : jl_printf(s_precompile, "precompile(");
2039 : 5150 : jl_static_show(s_precompile, mi->specTypes);
2040 : 5150 : jl_printf(s_precompile, ")\n");
2041 [ + - ]: 5150 : if (s_precompile != JL_STDERR)
2042 : 5150 : ios_flush(&f_precompile);
2043 : : }
2044 [ - + ]: 5150 : if (jl_n_threads > 1)
2045 : 0 : JL_UNLOCK(&precomp_statement_out_lock);
2046 : : }
2047 : :
2048 : 77862600 : jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t world)
2049 : : {
2050 : 77862600 : jl_code_instance_t *codeinst = jl_method_compiled(mi, world);
2051 [ + + ]: 77862600 : if (codeinst)
2052 : 14 : return codeinst;
2053 : 77862600 : int compile_option = jl_options.compile_enabled;
2054 : 77862600 : jl_method_t *def = mi->def.method;
2055 : : // disabling compilation per-module can override global setting
2056 [ + + ]: 77862600 : if (jl_is_method(def)) {
2057 : 77862500 : int mod_setting = jl_get_module_compile(((jl_method_t*)def)->module);
2058 [ + - + + ]: 77862500 : if (mod_setting == JL_OPTIONS_COMPILE_OFF ||
2059 : : mod_setting == JL_OPTIONS_COMPILE_MIN)
2060 : 72 : compile_option = ((jl_method_t*)def)->module->compile;
2061 : : }
2062 : :
2063 : : // if compilation is disabled or source is unavailable, try calling unspecialized version
2064 [ + - + + ]: 77862600 : if (compile_option == JL_OPTIONS_COMPILE_OFF ||
2065 : 77862500 : compile_option == JL_OPTIONS_COMPILE_MIN ||
2066 [ - + ]: 77862500 : def->source == jl_nothing) {
2067 : : // copy fptr from the template method definition
2068 [ + - ]: 72 : if (jl_is_method(def)) {
2069 : 72 : jl_method_instance_t *unspecmi = jl_atomic_load_relaxed(&def->unspecialized);
2070 [ - + ]: 72 : if (unspecmi) {
2071 : 0 : jl_code_instance_t *unspec = jl_atomic_load_relaxed(&unspecmi->cache);
2072 [ # # # # ]: 0 : if (unspec && jl_atomic_load_acquire(&unspec->invoke)) {
2073 : 0 : jl_code_instance_t *codeinst = jl_new_codeinst(mi,
2074 : : (jl_value_t*)jl_any_type, NULL, NULL,
2075 : : 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0);
2076 : 0 : codeinst->isspecsig = 0;
2077 : 0 : codeinst->specptr = unspec->specptr;
2078 : 0 : codeinst->rettype_const = unspec->rettype_const;
2079 : 0 : jl_atomic_store_relaxed(&codeinst->invoke, jl_atomic_load_relaxed(&unspec->invoke));
2080 : 0 : jl_mi_cache_insert(mi, codeinst);
2081 : 0 : record_precompile_statement(mi);
2082 : 0 : return codeinst;
2083 : : }
2084 : : }
2085 : : }
2086 : : }
2087 : : // if that didn't work and compilation is off, try running in the interpreter
2088 [ + - + + ]: 77862600 : if (compile_option == JL_OPTIONS_COMPILE_OFF ||
2089 : : compile_option == JL_OPTIONS_COMPILE_MIN) {
2090 : 72 : jl_code_info_t *src = jl_code_for_interpreter(mi);
2091 [ + - ]: 72 : if (!jl_code_requires_compiler(src)) {
2092 : 72 : jl_code_instance_t *codeinst = jl_new_codeinst(mi,
2093 : : (jl_value_t*)jl_any_type, NULL, NULL,
2094 : : 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0);
2095 : 72 : jl_atomic_store_relaxed(&codeinst->invoke, jl_fptr_interpret_call);
2096 : 72 : jl_mi_cache_insert(mi, codeinst);
2097 : 72 : record_precompile_statement(mi);
2098 : 72 : return codeinst;
2099 : : }
2100 [ # # ]: 0 : if (compile_option == JL_OPTIONS_COMPILE_OFF) {
2101 : 0 : jl_printf(JL_STDERR, "code missing for ");
2102 : 0 : jl_static_show(JL_STDERR, (jl_value_t*)mi);
2103 : 0 : jl_printf(JL_STDERR, " : sysimg may not have been built with --compile=all\n");
2104 : : }
2105 : : }
2106 : :
2107 : 77862500 : codeinst = jl_generate_fptr(mi, world);
2108 [ + + ]: 77862500 : if (!codeinst) {
2109 : 77847500 : jl_method_instance_t *unspec = jl_get_unspecialized_from_mi(mi);
2110 : 77847500 : jl_code_instance_t *ucache = jl_get_method_inferred(unspec, (jl_value_t*)jl_any_type, 1, ~(size_t)0);
2111 : : // ask codegen to make the fptr for unspec
2112 [ + + ]: 77847500 : if (jl_atomic_load_acquire(&ucache->invoke) == NULL) {
2113 [ - + - - ]: 1961 : if (def->source == jl_nothing && (ucache->def->uninferred == jl_nothing ||
2114 [ # # ]: 0 : ucache->def->uninferred == NULL)) {
2115 : 0 : jl_printf(JL_STDERR, "source not available for ");
2116 : 0 : jl_static_show(JL_STDERR, (jl_value_t*)mi);
2117 : 0 : jl_printf(JL_STDERR, "\n");
2118 : 0 : jl_error("source missing for method that needs to be compiled");
2119 : : }
2120 : 1961 : jl_generate_fptr_for_unspecialized(ucache);
2121 : : }
2122 [ - + ]: 77847500 : assert(jl_atomic_load_relaxed(&ucache->invoke) != NULL);
2123 [ + + ]: 77847500 : if (jl_atomic_load_relaxed(&ucache->invoke) != jl_fptr_sparam &&
2124 [ + - ]: 77846000 : jl_atomic_load_relaxed(&ucache->invoke) != jl_fptr_interpret_call) {
2125 : : // only these care about the exact specTypes, otherwise we can use it directly
2126 : 77846000 : return ucache;
2127 : : }
2128 : 1469 : codeinst = jl_new_codeinst(mi, (jl_value_t*)jl_any_type, NULL, NULL,
2129 : : 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0);
2130 : 1469 : codeinst->isspecsig = 0;
2131 : 1469 : codeinst->specptr = ucache->specptr;
2132 : 1469 : codeinst->rettype_const = ucache->rettype_const;
2133 : 1469 : jl_atomic_store_relaxed(&codeinst->invoke, jl_atomic_load_relaxed(&ucache->invoke));
2134 : 1469 : jl_mi_cache_insert(mi, codeinst);
2135 : : }
2136 : : else {
2137 : 14999 : record_precompile_statement(mi);
2138 : : }
2139 : 16468 : jl_atomic_store_relaxed(&codeinst->precompile, 1);
2140 : 16468 : return codeinst;
2141 : : }
2142 : :
2143 : :
2144 : 11574700 : jl_value_t *jl_fptr_const_return(jl_value_t *f, jl_value_t **args, uint32_t nargs, jl_code_instance_t *m)
2145 : : {
2146 : 11574700 : return m->rettype_const;
2147 : : }
2148 : :
2149 : 126178000 : jl_value_t *jl_fptr_args(jl_value_t *f, jl_value_t **args, uint32_t nargs, jl_code_instance_t *m)
2150 : : {
2151 : 0 : while (1) {
2152 : 126178000 : jl_fptr_args_t invoke = jl_atomic_load_relaxed(&m->specptr.fptr1);
2153 [ + - ]: 126178000 : if (invoke)
2154 : 126178000 : return invoke(f, args, nargs);
2155 : : }
2156 : : }
2157 : :
2158 : 114943000 : jl_value_t *jl_fptr_sparam(jl_value_t *f, jl_value_t **args, uint32_t nargs, jl_code_instance_t *m)
2159 : : {
2160 : 114943000 : jl_svec_t *sparams = m->def->sparam_vals;
2161 [ - + ]: 114943000 : assert(sparams != jl_emptysvec);
2162 : 0 : while (1) {
2163 : 114943000 : jl_fptr_sparam_t invoke = jl_atomic_load_relaxed(&m->specptr.fptr3);
2164 [ + - ]: 114943000 : if (invoke)
2165 : 114943000 : return invoke(f, args, nargs, sparams);
2166 : : }
2167 : : }
2168 : :
2169 : : JL_DLLEXPORT jl_callptr_t jl_fptr_args_addr = &jl_fptr_args;
2170 : :
2171 : : JL_DLLEXPORT jl_callptr_t jl_fptr_const_return_addr = &jl_fptr_const_return;
2172 : :
2173 : : JL_DLLEXPORT jl_callptr_t jl_fptr_sparam_addr = &jl_fptr_sparam;
2174 : :
2175 : : // Return the index of the invoke api, if known
2176 : 872584 : JL_DLLEXPORT int32_t jl_invoke_api(jl_code_instance_t *codeinst)
2177 : : {
2178 : 872584 : jl_callptr_t f = jl_atomic_load_relaxed(&codeinst->invoke);
2179 [ + + ]: 872584 : if (f == NULL)
2180 : 492813 : return 0;
2181 [ + + ]: 379771 : if (f == &jl_fptr_args)
2182 : 720 : return 1;
2183 [ + + ]: 379051 : if (f == &jl_fptr_const_return)
2184 : 70728 : return 2;
2185 [ - + ]: 308323 : if (f == &jl_fptr_sparam)
2186 : 0 : return 3;
2187 [ - + ]: 308323 : if (f == &jl_fptr_interpret_call)
2188 : 0 : return 4;
2189 : 308323 : return -1;
2190 : : }
2191 : :
2192 : 1922910 : JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_methtable_t *mt, jl_tupletype_t *ti, jl_svec_t *env, jl_method_t *m)
2193 : : {
2194 : 1922910 : jl_tupletype_t *tt = NULL;
2195 : 1922910 : jl_svec_t *newparams = NULL;
2196 : 1922910 : JL_GC_PUSH2(&tt, &newparams);
2197 [ + + + + ]: 1922910 : intptr_t nspec = (mt == jl_type_type_mt || mt == jl_nonfunction_mt ? m->nargs + 1 : mt->max_args + 2);
2198 : 1922910 : jl_compilation_sig(ti, env, m, nspec, &newparams);
2199 [ + + ]: 1922910 : tt = (newparams ? jl_apply_tuple_type(newparams) : ti);
2200 [ + + + + ]: 2148840 : int is_compileable = ((jl_datatype_t*)ti)->isdispatchtuple ||
2201 : 225927 : jl_isa_compileable_sig(tt, m);
2202 : 1922910 : JL_GC_POP();
2203 [ + + ]: 1922910 : return is_compileable ? (jl_value_t*)tt : jl_nothing;
2204 : : }
2205 : :
2206 : : // compile-time method lookup
2207 : 4098 : jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache)
2208 : : {
2209 [ - + ]: 4098 : if (jl_has_free_typevars((jl_value_t*)types))
2210 : 0 : return NULL; // don't poison the cache due to a malformed query
2211 [ - + ]: 4098 : if (!jl_has_concrete_subtype((jl_value_t*)types))
2212 : 0 : return NULL;
2213 : :
2214 : : // find if exactly 1 method matches (issue #7302)
2215 : 4098 : size_t min_valid2 = 1;
2216 : 4098 : size_t max_valid2 = ~(size_t)0;
2217 : 4098 : int ambig = 0;
2218 : 4098 : jl_value_t *matches = jl_matching_methods(types, jl_nothing, 1, 1, world, &min_valid2, &max_valid2, &ambig);
2219 [ + - ]: 4098 : if (*min_valid < min_valid2)
2220 : 4098 : *min_valid = min_valid2;
2221 [ - + ]: 4098 : if (*max_valid > max_valid2)
2222 : 0 : *max_valid = max_valid2;
2223 [ + + + + : 4098 : if (matches == jl_false || jl_array_len(matches) != 1 || ambig)
- + ]
2224 : 16 : return NULL;
2225 : 4082 : jl_value_t *tt = NULL;
2226 : 4082 : JL_GC_PUSH2(&matches, &tt);
2227 : 4082 : jl_method_match_t *match = (jl_method_match_t*)jl_array_ptr_ref(matches, 0);
2228 : 4082 : jl_method_t *m = match->method;
2229 : 4082 : jl_svec_t *env = match->sparams;
2230 : 4082 : jl_tupletype_t *ti = match->spec_types;
2231 : 4082 : jl_method_instance_t *nf = NULL;
2232 [ + - ]: 4082 : if (jl_is_datatype(ti)) {
2233 : 4082 : jl_methtable_t *mt = jl_method_table_for((jl_value_t*)ti);
2234 [ + - ]: 4082 : if ((jl_value_t*)mt != jl_nothing) {
2235 : : // get the specialization without caching it
2236 [ + + + + ]: 4082 : if (mt_cache && ((jl_datatype_t*)ti)->isdispatchtuple) {
2237 : : // Since we also use this presence in the cache
2238 : : // to trigger compilation when producing `.ji` files,
2239 : : // inject it there now if we think it will be
2240 : : // used via dispatch later (e.g. because it was hinted via a call to `precompile`)
2241 : 3344 : JL_LOCK(&mt->writelock);
2242 : 3344 : nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, ti, m, world, min_valid2, max_valid2, env);
2243 : 3344 : JL_UNLOCK(&mt->writelock);
2244 : : }
2245 : : else {
2246 : 738 : tt = jl_normalize_to_compilable_sig(mt, ti, env, m);
2247 [ + + ]: 738 : if (tt != jl_nothing) {
2248 : 722 : nf = jl_specializations_get_linfo(m, (jl_value_t*)tt, env);
2249 : : }
2250 : : }
2251 : : }
2252 : : }
2253 : 4082 : JL_GC_POP();
2254 : 4082 : return nf;
2255 : : }
2256 : :
2257 : 4488 : static void _generate_from_hint(jl_method_instance_t *mi, size_t world)
2258 : : {
2259 : 4488 : jl_value_t *codeinst = jl_rettype_inferred(mi, world, world);
2260 [ + + ]: 4488 : if (codeinst == jl_nothing) {
2261 : 1422 : (void)jl_type_infer(mi, world, 1);
2262 : 1422 : codeinst = jl_rettype_inferred(mi, world, world);
2263 : : }
2264 [ + - ]: 4488 : if (codeinst != jl_nothing) {
2265 [ + + ]: 4488 : if (jl_atomic_load_relaxed(&((jl_code_instance_t*)codeinst)->invoke) == jl_fptr_const_return)
2266 : 88 : return; // probably not a good idea to generate code
2267 : 4400 : jl_atomic_store_relaxed(&((jl_code_instance_t*)codeinst)->precompile, 1);
2268 : : }
2269 : : }
2270 : :
2271 : 3890 : static void jl_compile_now(jl_method_instance_t *mi)
2272 : : {
2273 : 3890 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
2274 : 3890 : size_t tworld = jl_typeinf_world;
2275 : 3890 : _generate_from_hint(mi, world);
2276 [ + - + + ]: 3890 : if (jl_typeinf_func && mi->def.method->primary_world <= tworld) {
2277 : : // if it's part of the compiler, also attempt to compile for the compiler world too
2278 : 598 : _generate_from_hint(mi, tworld);
2279 : : }
2280 : 3890 : }
2281 : :
2282 : 3892 : JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
2283 : : {
2284 : 3892 : size_t world = jl_atomic_load_acquire(&jl_world_counter);
2285 : 3892 : size_t tworld = jl_typeinf_world;
2286 : 3892 : size_t min_valid = 0;
2287 : 3892 : size_t max_valid = ~(size_t)0;
2288 : 3892 : jl_method_instance_t *mi = jl_get_specialization1(types, world, &min_valid, &max_valid, 1);
2289 [ + + ]: 3892 : if (mi == NULL)
2290 : 2 : return 0;
2291 : : JL_GC_PROMISE_ROOTED(mi);
2292 : 3890 : mi->precompiled = 1;
2293 [ + - ]: 3890 : if (jl_generating_output()) {
2294 : 3890 : jl_compile_now(mi);
2295 : : // In addition to full compilation of the compilation-signature, if `types` is more specific (e.g. due to nospecialize),
2296 : : // also run inference now on the original `types`, since that may help us guide inference to find
2297 : : // additional useful methods that should be compiled
2298 : : //ALT: if (jl_is_datatype(types) && ((jl_datatype_t*)types)->isdispatchtuple && !jl_egal(mi->specTypes, types))
2299 : : //ALT: if (jl_subtype(types, mi->specTypes))
2300 [ + + ]: 3890 : if (!jl_subtype(mi->specTypes, (jl_value_t*)types)) {
2301 : 142 : jl_svec_t *tpenv2 = jl_emptysvec;
2302 : 142 : jl_value_t *types2 = NULL;
2303 : 142 : JL_GC_PUSH2(&tpenv2, &types2);
2304 : 142 : types2 = jl_type_intersection_env((jl_value_t*)types, (jl_value_t*)mi->def.method->sig, &tpenv2);
2305 : 142 : jl_method_instance_t *li2 = jl_specializations_get_linfo(mi->def.method, (jl_value_t*)types2, tpenv2);
2306 : 142 : JL_GC_POP();
2307 : 142 : li2->precompiled = 1;
2308 [ + + ]: 142 : if (jl_rettype_inferred(li2, world, world) == jl_nothing)
2309 : 140 : (void)jl_type_infer(li2, world, 1);
2310 [ + - + + ]: 142 : if (jl_typeinf_func && mi->def.method->primary_world <= tworld) {
2311 [ - + ]: 16 : if (jl_rettype_inferred(li2, tworld, tworld) == jl_nothing)
2312 : 0 : (void)jl_type_infer(li2, tworld, 1);
2313 : : }
2314 : : }
2315 : : }
2316 : : else {
2317 : : // Otherwise (this branch), assuming we are at runtime (normal JIT) and
2318 : : // we should generate the native code immediately in preparation for use.
2319 : 0 : (void)jl_compile_method_internal(mi, world);
2320 : : }
2321 : 3890 : return 1;
2322 : : }
2323 : :
2324 : : // add type of `f` to front of argument tuple type
2325 : 12 : static jl_value_t *jl_argtype_with_function(jl_function_t *f, jl_value_t *types0)
2326 : : {
2327 : 12 : jl_value_t *types = jl_unwrap_unionall(types0);
2328 : 12 : size_t l = jl_nparams(types);
2329 : 12 : jl_value_t *tt = (jl_value_t*)jl_alloc_svec(1+l);
2330 : : size_t i;
2331 : 12 : JL_GC_PUSH1(&tt);
2332 [ - + ]: 12 : if (jl_is_type(f))
2333 : 0 : jl_svecset(tt, 0, jl_wrap_Type(f));
2334 : : else
2335 : 12 : jl_svecset(tt, 0, jl_typeof(f));
2336 [ + + ]: 32 : for(i=0; i < l; i++)
2337 : 20 : jl_svecset(tt, i+1, jl_tparam(types,i));
2338 : 12 : tt = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)tt);
2339 : 12 : tt = jl_rewrap_unionall(tt, types0);
2340 : 12 : JL_GC_POP();
2341 : 12 : return tt;
2342 : : }
2343 : :
2344 : : #ifdef JL_TRACE
2345 : : static int trace_en = 0;
2346 : : static int error_en = 1;
2347 : : static void __attribute__ ((unused)) enable_trace(int x) { trace_en=x; }
2348 : : static void show_call(jl_value_t *F, jl_value_t **args, uint32_t nargs)
2349 : : {
2350 : : jl_static_show(JL_STDOUT, F);
2351 : : jl_printf(JL_STDOUT, "(");
2352 : : for(size_t i=0; i < nargs; i++) {
2353 : : if (i > 0) jl_printf(JL_STDOUT, ", ");
2354 : : jl_static_show(JL_STDOUT, jl_typeof(args[i]));
2355 : : }
2356 : : jl_printf(JL_STDOUT, ")");
2357 : : }
2358 : : #endif
2359 : :
2360 : 417662000 : STATIC_INLINE jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT
2361 : : {
2362 [ + - + - : 417662000 : assert(v && jl_typeof(v) && jl_typeof(jl_typeof(v)) == (jl_value_t*)jl_datatype_type);
+ - ]
2363 : 417662000 : return v;
2364 : : }
2365 : :
2366 : 417668000 : STATIC_INLINE jl_value_t *_jl_invoke(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl_method_instance_t *mfunc, size_t world)
2367 : : {
2368 : : // manually inlined copy of jl_method_compiled
2369 : 417668000 : jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mfunc->cache);
2370 [ + + ]: 517266000 : while (codeinst) {
2371 [ + + + + ]: 439404000 : if (codeinst->min_world <= world && world <= codeinst->max_world) {
2372 : 438752000 : jl_callptr_t invoke = jl_atomic_load_relaxed(&codeinst->invoke);
2373 [ + + ]: 438752000 : if (invoke != NULL) {
2374 : 339806000 : jl_value_t *res = invoke(F, args, nargs, codeinst);
2375 : 339800000 : return verify_type(res);
2376 : : }
2377 : : }
2378 : 99598100 : codeinst = jl_atomic_load_relaxed(&codeinst->next);
2379 : : }
2380 [ - + ]: 77862500 : int64_t last_alloc = jl_options.malloc_log ? jl_gc_diff_total_bytes() : 0;
2381 : 77862500 : int last_errno = errno;
2382 : : #ifdef _OS_WINDOWS_
2383 : : DWORD last_error = GetLastError();
2384 : : #endif
2385 : 77862500 : codeinst = jl_compile_method_internal(mfunc, world);
2386 : : #ifdef _OS_WINDOWS_
2387 : : SetLastError(last_error);
2388 : : #endif
2389 : 77862500 : errno = last_errno;
2390 [ - + ]: 77862500 : if (jl_options.malloc_log)
2391 : 0 : jl_gc_sync_total_bytes(last_alloc); // discard allocation count from compilation
2392 : 77862500 : jl_callptr_t invoke = jl_atomic_load_relaxed(&codeinst->invoke);
2393 : 77862500 : jl_value_t *res = invoke(F, args, nargs, codeinst);
2394 : 77862300 : return verify_type(res);
2395 : : }
2396 : :
2397 : 2823590 : JL_DLLEXPORT jl_value_t *jl_invoke(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl_method_instance_t *mfunc)
2398 : : {
2399 : 2823590 : size_t world = jl_current_task->world_age;
2400 : 2823590 : return _jl_invoke(F, args, nargs, mfunc, world);
2401 : : }
2402 : :
2403 : 566613000 : STATIC_INLINE int sig_match_fast(jl_value_t *arg1t, jl_value_t **args, jl_value_t **sig, size_t n)
2404 : : {
2405 : : // NOTE: This function is a huge performance hot spot!!
2406 [ + + ]: 566613000 : if (arg1t != sig[0])
2407 : 218773000 : return 0;
2408 : : size_t i;
2409 [ + + ]: 827252000 : for (i = 1; i < n; i++) {
2410 : 599261000 : jl_value_t *decl = sig[i];
2411 : 599261000 : jl_value_t *a = args[i - 1];
2412 [ + + ]: 599261000 : if (jl_typeof(a) != decl) {
2413 : : /*
2414 : : we are only matching concrete types here, and those types are
2415 : : hash-consed, so pointer comparison should work.
2416 : : */
2417 : 119850000 : return 0;
2418 : : }
2419 : : }
2420 : 227991000 : return 1;
2421 : : }
2422 : :
2423 : : _Atomic(jl_typemap_entry_t*) call_cache[N_CALL_CACHE] JL_GLOBALLY_ROOTED;
2424 : : static _Atomic(uint8_t) pick_which[N_CALL_CACHE];
2425 : : #ifdef JL_GF_PROFILE
2426 : : size_t ncalls;
2427 : : void call_cache_stats()
2428 : : {
2429 : : int pick_which_stat[4] = {0, 0, 0, 0};
2430 : : int i, count = 0;
2431 : : for (i = 0; i < N_CALL_CACHE; i++) {
2432 : : if (jl_atomic_load_relaxed(&call_cache[i]))
2433 : : count++;
2434 : : ++pick_which_stat[jl_atomic_load_relaxed(&pick_which[i]) & 3];
2435 : : }
2436 : : jl_safe_printf("cache occupied: %d / %d; pick_which stats: {%d, %d, %d, %d}\n",
2437 : : count, N_CALL_CACHE,
2438 : : pick_which_stat[0], pick_which_stat[1], pick_which_stat[2], pick_which_stat[3]);
2439 : : }
2440 : : #endif
2441 : :
2442 : 414845000 : STATIC_INLINE jl_method_instance_t *jl_lookup_generic_(jl_value_t *F, jl_value_t **args, uint32_t nargs,
2443 : : uint32_t callsite, size_t world)
2444 : : {
2445 : : #ifdef JL_GF_PROFILE
2446 : : ncalls++;
2447 : : #endif
2448 : : #ifdef JL_TRACE
2449 : : int traceen = trace_en; //&& ((char*)&mt < jl_stack_hi-6000000);
2450 : : if (traceen)
2451 : : show_call(F, args, nargs);
2452 : : #endif
2453 : 414845000 : nargs++; // add F to argument count
2454 : 414845000 : jl_value_t *FT = jl_typeof(F);
2455 : :
2456 : : /*
2457 : : search order:
2458 : : check associative hash based on callsite address for leafsig match
2459 : : look at concrete signatures
2460 : : if there is an exact match, return it
2461 : : otherwise look for a matching generic signature
2462 : : if no concrete or generic match, raise error
2463 : : if no generic match, use the concrete one even if inexact
2464 : : otherwise instantiate the generic method and use it
2465 : : */
2466 : : // compute the entry hashes
2467 : : // use different parts of the value
2468 : : // so that a collision across all of
2469 : : // them is less likely
2470 : 414845000 : uint32_t cache_idx[4] = {
2471 : 414845000 : (callsite) & (N_CALL_CACHE - 1),
2472 : 414845000 : (callsite >> 8) & (N_CALL_CACHE - 1),
2473 : 414845000 : (callsite >> 16) & (N_CALL_CACHE - 1),
2474 : 414845000 : (callsite >> 24 | callsite << 8) & (N_CALL_CACHE - 1)};
2475 : 414845000 : jl_typemap_entry_t *entry = NULL;
2476 : 414845000 : jl_methtable_t *mt = NULL;
2477 : : int i;
2478 : : // check each cache entry to see if it matches
2479 : : //#pragma unroll
2480 : : //for (i = 0; i < 4; i++) {
2481 : : // LOOP_BODY(i);
2482 : : //}
2483 : : #define LOOP_BODY(_i) do { \
2484 : : i = _i; \
2485 : : entry = jl_atomic_load_relaxed(&call_cache[cache_idx[i]]); \
2486 : : if (entry && nargs == jl_svec_len(entry->sig->parameters) && \
2487 : : sig_match_fast(FT, args, jl_svec_data(entry->sig->parameters), nargs) && \
2488 : : world >= entry->min_world && world <= entry->max_world) { \
2489 : : goto have_entry; \
2490 : : } \
2491 : : } while (0);
2492 [ + + + + : 414845000 : LOOP_BODY(0);
+ + + - +
- ]
2493 [ + + + + : 303284000 : LOOP_BODY(1);
+ + + - +
- ]
2494 [ + + + + : 204410000 : LOOP_BODY(2);
+ + + - +
- ]
2495 [ + + + + : 194675000 : LOOP_BODY(3);
+ + + - +
- ]
2496 : : #undef LOOP_BODY
2497 : 186855000 : i = 4;
2498 : 186855000 : jl_tupletype_t *tt = NULL;
2499 : : int64_t last_alloc;
2500 [ + - ]: 186855000 : if (i == 4) {
2501 : : // if no method was found in the associative cache, check the full cache
2502 : : JL_TIMING(METHOD_LOOKUP_FAST);
2503 : 186855000 : mt = jl_gf_mtable(F);
2504 : 186855000 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
2505 : 186855000 : entry = NULL;
2506 [ + + ]: 186855000 : if (leafcache != (jl_array_t*)jl_an_empty_vec_any &&
2507 [ + + ]: 110722000 : jl_typeis(jl_atomic_load_relaxed(&mt->cache), jl_typemap_level_type)) {
2508 : : // hashing args is expensive, but looking at mt->cache is probably even more expensive
2509 : 57455400 : tt = lookup_arg_type_tuple(F, args, nargs);
2510 [ + + ]: 57455400 : if (tt != NULL)
2511 : 49868600 : entry = lookup_leafcache(leafcache, (jl_value_t*)tt, world);
2512 : : }
2513 [ + + ]: 186855000 : if (entry == NULL) {
2514 : 140815000 : jl_typemap_t *cache = jl_atomic_load_relaxed(&mt->cache); // XXX: gc root required?
2515 : 140815000 : entry = jl_typemap_assoc_exact(cache, F, args, nargs, jl_cachearg_offset(mt), world);
2516 [ + + ]: 140815000 : if (entry == NULL) {
2517 [ - + ]: 22936400 : last_alloc = jl_options.malloc_log ? jl_gc_diff_total_bytes() : 0;
2518 [ + + ]: 22936400 : if (tt == NULL) {
2519 : 22936400 : tt = arg_type_tuple(F, args, nargs);
2520 : 22936400 : entry = lookup_leafcache(leafcache, (jl_value_t*)tt, world);
2521 : : }
2522 : : }
2523 : : }
2524 [ + + + + : 186855000 : if (entry != NULL && entry->isleafsig && entry->simplesig == (void*)jl_nothing && entry->guardsigs == jl_emptysvec) {
+ - + - ]
2525 : : // put the entry into the cache if it's valid for a leafsig lookup,
2526 : : // using pick_which to slightly randomize where it ends up
2527 : : // (intentionally not atomically synchronized, since we're just using it for randomness)
2528 : : // TODO: use the thread's `cong` instead as a source of randomness
2529 : 6159990 : int which = jl_atomic_load_relaxed(&pick_which[cache_idx[0]]) + 1;
2530 : 6159990 : jl_atomic_store_relaxed(&pick_which[cache_idx[0]], which);
2531 : 6159990 : jl_atomic_store_release(&call_cache[cache_idx[which & 3]], entry);
2532 : : }
2533 : : }
2534 : :
2535 : : jl_method_instance_t *mfunc;
2536 [ + + ]: 186855000 : if (entry) {
2537 : 186845000 : have_entry:
2538 : 414835000 : mfunc = entry->func.linfo;
2539 : : }
2540 : : else {
2541 : 10010 : JL_GC_PUSH1(&tt);
2542 [ - + ]: 10010 : assert(tt);
2543 : 10010 : JL_LOCK(&mt->writelock);
2544 : : // cache miss case
2545 : : JL_TIMING(METHOD_LOOKUP_SLOW);
2546 : 10010 : mfunc = jl_mt_assoc_by_type(mt, tt, world);
2547 : 10010 : JL_UNLOCK(&mt->writelock);
2548 : 10010 : JL_GC_POP();
2549 [ - + ]: 10010 : if (jl_options.malloc_log)
2550 : 0 : jl_gc_sync_total_bytes(last_alloc); // discard allocation count from compilation
2551 [ + + ]: 10010 : if (mfunc == NULL) {
2552 : : #ifdef JL_TRACE
2553 : : if (error_en)
2554 : : show_call(F, args, nargs);
2555 : : #endif
2556 : 662 : jl_method_error(F, args, nargs, world);
2557 : : // unreachable
2558 : : }
2559 : : }
2560 : :
2561 : : #ifdef JL_TRACE
2562 : : if (traceen)
2563 : : jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->def.method->file), mfunc->def.method->line);
2564 : : #endif
2565 : 414845000 : return mfunc;
2566 : : }
2567 : :
2568 : 414845000 : JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t *F, jl_value_t **args, uint32_t nargs)
2569 : : {
2570 : 414845000 : size_t world = jl_current_task->world_age;
2571 : 414845000 : jl_method_instance_t *mfunc = jl_lookup_generic_(F, args, nargs,
2572 : 414845000 : jl_int32hash_fast(jl_return_address()),
2573 : : world);
2574 : : JL_GC_PROMISE_ROOTED(mfunc);
2575 : 414845000 : return _jl_invoke(F, args, nargs, mfunc, world);
2576 : : }
2577 : :
2578 : 10517 : static jl_method_match_t *_gf_invoke_lookup(jl_value_t *types JL_PROPAGATES_ROOT, jl_value_t *mt, size_t world, size_t *min_valid, size_t *max_valid)
2579 : : {
2580 : 10517 : jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)types);
2581 [ + - - + ]: 10517 : if (jl_is_tuple_type(unw) && jl_tparam0(unw) == jl_bottom_type)
2582 : 0 : return NULL;
2583 [ + - ]: 10517 : if (mt == jl_nothing)
2584 : 10517 : mt = (jl_value_t*)jl_method_table_for(unw);
2585 [ - + ]: 10517 : if (mt == jl_nothing)
2586 : 0 : mt = NULL;
2587 : 10517 : jl_value_t *matches = ml_matches((jl_methtable_t*)mt, (jl_tupletype_t*)types, 1, 0, 0, world, 1, min_valid, max_valid, NULL);
2588 [ + - + + ]: 10517 : if (matches == jl_false || jl_array_len(matches) != 1)
2589 : 696 : return NULL;
2590 : 9821 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(matches, 0);
2591 : 9821 : return matc;
2592 : : }
2593 : :
2594 : 32 : JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_value_t *types, jl_value_t *mt, size_t world)
2595 : : {
2596 : : // Deprecated: Use jl_gf_invoke_lookup_worlds for future development
2597 : 32 : size_t min_valid = 0;
2598 : 32 : size_t max_valid = ~(size_t)0;
2599 : 32 : jl_method_match_t *matc = _gf_invoke_lookup(types, mt, world, &min_valid, &max_valid);
2600 [ + + ]: 32 : if (matc == NULL)
2601 : 6 : return jl_nothing;
2602 : 26 : return (jl_value_t*)matc->method;
2603 : : }
2604 : :
2605 : :
2606 : 162 : JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup_worlds(jl_value_t *types, jl_value_t *mt, size_t world, size_t *min_world, size_t *max_world)
2607 : : {
2608 : 162 : jl_method_match_t *matc = _gf_invoke_lookup(types, mt, world, min_world, max_world);
2609 [ - + ]: 162 : if (matc == NULL)
2610 : 0 : return jl_nothing;
2611 : 162 : return (jl_value_t*)matc;
2612 : : }
2613 : :
2614 : : // invoke()
2615 : : // this does method dispatch with a set of types to match other than the
2616 : : // types of the actual arguments. this means it sometimes does NOT call the
2617 : : // most specific method for the argument types, so we need different logic.
2618 : : // first we use the given types to look up a definition, then we perform
2619 : : // caching and specialization within just that definition.
2620 : : // every definition has its own private method table for this purpose.
2621 : : //
2622 : : // NOTE: assumes argument type is a subtype of the lookup type.
2623 : 12 : jl_value_t *jl_gf_invoke(jl_value_t *types0, jl_value_t *gf, jl_value_t **args, size_t nargs)
2624 : : {
2625 : 12 : size_t world = jl_current_task->world_age;
2626 : 12 : jl_value_t *types = NULL;
2627 : 12 : JL_GC_PUSH1(&types);
2628 : 12 : types = jl_argtype_with_function(gf, types0);
2629 : 12 : jl_method_t *method = (jl_method_t*)jl_gf_invoke_lookup(types, jl_nothing, world);
2630 : : JL_GC_PROMISE_ROOTED(method);
2631 : :
2632 [ - + ]: 12 : if ((jl_value_t*)method == jl_nothing) {
2633 : 0 : jl_method_error_bare(gf, types0, world);
2634 : : // unreachable
2635 : : }
2636 : :
2637 : : // now we have found the matching definition.
2638 : : // next look for or create a specialization of this definition.
2639 : 12 : JL_GC_POP();
2640 : 12 : return jl_gf_invoke_by_method(method, gf, args, nargs);
2641 : : }
2642 : :
2643 : 12 : jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value_t **args, size_t nargs)
2644 : : {
2645 : 12 : jl_method_instance_t *mfunc = NULL;
2646 : 12 : jl_typemap_entry_t *tm = NULL;
2647 : 12 : jl_typemap_t *invokes = jl_atomic_load_relaxed(&method->invokes);
2648 [ - + ]: 12 : if (invokes != jl_nothing)
2649 : 0 : tm = jl_typemap_assoc_exact(invokes, gf, args, nargs, 1, 1);
2650 [ - + ]: 12 : if (tm) {
2651 : 0 : mfunc = tm->func.linfo;
2652 : : }
2653 : : else {
2654 [ - + ]: 12 : int64_t last_alloc = jl_options.malloc_log ? jl_gc_diff_total_bytes() : 0;
2655 : 12 : jl_svec_t *tpenv = jl_emptysvec;
2656 : 12 : jl_tupletype_t *tt = NULL;
2657 : 12 : JL_GC_PUSH2(&tpenv, &tt);
2658 : 12 : JL_LOCK(&method->writelock);
2659 : 12 : invokes = jl_atomic_load_relaxed(&method->invokes);
2660 : 12 : tm = jl_typemap_assoc_exact(invokes, gf, args, nargs, 1, 1);
2661 [ - + ]: 12 : if (tm) {
2662 : 0 : mfunc = tm->func.linfo;
2663 : : }
2664 : : else {
2665 : 12 : tt = arg_type_tuple(gf, args, nargs);
2666 [ - + ]: 12 : if (jl_is_unionall(method->sig)) {
2667 : 0 : int sub = jl_subtype_matching((jl_value_t*)tt, (jl_value_t*)method->sig, &tpenv);
2668 [ # # ]: 0 : assert(sub); (void)sub;
2669 : : }
2670 : :
2671 : 12 : mfunc = cache_method(NULL, &method->invokes, (jl_value_t*)method, tt, method, 1, 1, ~(size_t)0, tpenv);
2672 : : }
2673 : 12 : JL_UNLOCK(&method->writelock);
2674 : 12 : JL_GC_POP();
2675 [ - + ]: 12 : if (jl_options.malloc_log)
2676 : 0 : jl_gc_sync_total_bytes(last_alloc); // discard allocation count from compilation
2677 : : }
2678 : : JL_GC_PROMISE_ROOTED(mfunc);
2679 : 12 : size_t world = jl_current_task->world_age;
2680 : 12 : return _jl_invoke(gf, args, nargs - 1, mfunc, world);
2681 : : }
2682 : :
2683 : : // Return value is rooted globally
2684 : 16576 : jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_t *module, jl_datatype_t *st)
2685 : : {
2686 : : // type name is function name prefixed with #
2687 : 16576 : size_t l = strlen(jl_symbol_name(name));
2688 : : char *prefixed;
2689 : 16576 : prefixed = (char*)malloc_s(l+2);
2690 : 16576 : prefixed[0] = '#';
2691 : 16576 : strcpy(&prefixed[1], jl_symbol_name(name));
2692 : 16576 : jl_sym_t *tname = jl_symbol(prefixed);
2693 : 16576 : free(prefixed);
2694 : 16576 : jl_datatype_t *ftype = (jl_datatype_t*)jl_new_datatype(
2695 : : tname, module, st, jl_emptysvec, jl_emptysvec, jl_emptysvec, jl_emptysvec,
2696 : : 0, 0, 0);
2697 [ - + ]: 16576 : assert(jl_is_datatype(ftype));
2698 : 16576 : JL_GC_PUSH1(&ftype);
2699 : 16576 : ftype->name->mt->name = name;
2700 : 16576 : jl_gc_wb(ftype->name->mt, name);
2701 : 16576 : jl_set_const(module, tname, (jl_value_t*)ftype);
2702 : 16576 : jl_value_t *f = jl_new_struct(ftype);
2703 : 16576 : ftype->instance = f; jl_gc_wb(ftype, f);
2704 : 16576 : JL_GC_POP();
2705 : 16576 : return (jl_function_t*)f;
2706 : : }
2707 : :
2708 : 167839 : JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_value_t *ty)
2709 : : {
2710 : 167839 : jl_methtable_t *mt = jl_argument_method_table(ty);
2711 [ - + ]: 167839 : if ((jl_value_t*)mt == jl_nothing)
2712 : 0 : jl_error("cannot get keyword sorter for abstract type");
2713 [ + + ]: 167839 : if (!mt->kwsorter) {
2714 : 1075 : JL_LOCK(&mt->writelock);
2715 [ + - ]: 1075 : if (!mt->kwsorter) {
2716 : : char *name;
2717 [ + + ]: 1075 : if (mt == jl_nonfunction_mt) {
2718 : 1 : name = jl_symbol_name(mt->name);
2719 : : }
2720 : : else {
2721 : 1074 : jl_datatype_t *dt = (jl_datatype_t*)jl_argument_datatype(ty);
2722 [ - + ]: 1074 : assert(jl_is_datatype(dt));
2723 : 1074 : name = jl_symbol_name(dt->name->name);
2724 [ + + ]: 1074 : if (name[0] == '#')
2725 : 1073 : name++;
2726 : : }
2727 : 1075 : size_t l = strlen(name);
2728 : 1075 : char *suffixed = (char*)malloc_s(l+5);
2729 : 1075 : strcpy(&suffixed[0], name);
2730 : 1075 : strcpy(&suffixed[l], "##kw");
2731 : 1075 : jl_sym_t *fname = jl_symbol(suffixed);
2732 : 1075 : free(suffixed);
2733 : 1075 : mt->kwsorter = jl_new_generic_function_with_supertype(fname, mt->module, jl_function_type);
2734 : 1075 : jl_gc_wb(mt, mt->kwsorter);
2735 : : }
2736 : 1075 : JL_UNLOCK(&mt->writelock);
2737 : : }
2738 : 167839 : return mt->kwsorter;
2739 : : }
2740 : :
2741 : 15456 : jl_function_t *jl_new_generic_function(jl_sym_t *name, jl_module_t *module)
2742 : : {
2743 : 15456 : return jl_new_generic_function_with_supertype(name, module, jl_function_type);
2744 : : }
2745 : :
2746 : : struct ml_matches_env {
2747 : : // inputs:
2748 : : struct typemap_intersection_env match;
2749 : : int intersections;
2750 : : size_t world;
2751 : : int lim;
2752 : : // results:
2753 : : jl_value_t *t; // array of method matches
2754 : : size_t min_valid;
2755 : : size_t max_valid;
2756 : : // temporary:
2757 : : jl_method_match_t *matc; // current working method match
2758 : : };
2759 : :
2760 : : enum SIGNATURE_FULLY_COVERS {
2761 : : NOT_FULLY_COVERS = 0,
2762 : : FULLY_COVERS = 1,
2763 : : SENTINEL = 2,
2764 : : };
2765 : :
2766 : 2461340 : static jl_method_match_t *make_method_match(jl_tupletype_t *spec_types, jl_svec_t *sparams, jl_method_t *method, enum SIGNATURE_FULLY_COVERS fully_covers)
2767 : : {
2768 : 2461340 : jl_task_t *ct = jl_current_task;
2769 : 2461340 : jl_method_match_t *match = (jl_method_match_t*)jl_gc_alloc(ct->ptls, sizeof(jl_method_match_t), jl_method_match_type);
2770 : 2461340 : match->spec_types = spec_types;
2771 : 2461340 : match->sparams = sparams;
2772 : 2461340 : match->method = method;
2773 : 2461340 : match->fully_covers = fully_covers;
2774 : 2461340 : return match;
2775 : : }
2776 : :
2777 : 1007780 : static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersection_env *closure0)
2778 : : {
2779 : 1007780 : struct ml_matches_env *closure = container_of(closure0, struct ml_matches_env, match);
2780 [ + + + + ]: 1007780 : if (closure->intersections == 0 && !closure0->issubty)
2781 : 188 : return 1;
2782 [ + + ]: 1007590 : if (closure->world < ml->min_world) {
2783 : : // ignore method table entries that are part of a later world
2784 [ + + ]: 1038 : if (closure->max_valid >= ml->min_world)
2785 : 894 : closure->max_valid = ml->min_world - 1;
2786 : 1038 : return 1;
2787 : : }
2788 [ + + ]: 1006550 : else if (closure->world > ml->max_world) {
2789 : : // ignore method table entries that have been replaced in the current world
2790 [ + + ]: 28 : if (closure->min_valid <= ml->max_world)
2791 : 12 : closure->min_valid = ml->max_world + 1;
2792 : 28 : return 1;
2793 : : }
2794 : : else {
2795 : : // intersect the env valid range with method's valid range
2796 [ + + ]: 1006520 : if (closure->min_valid < ml->min_world)
2797 : 456737 : closure->min_valid = ml->min_world;
2798 [ - + ]: 1006520 : if (closure->max_valid > ml->max_world)
2799 : 0 : closure->max_valid = ml->max_world;
2800 : : }
2801 : 1006520 : jl_method_t *meth = ml->func.method;
2802 [ + + + + ]: 1006520 : if (closure->lim >= 0 && jl_is_dispatch_tupletype(meth->sig)) {
2803 [ + + ]: 72171 : if (closure->lim == 0)
2804 : 8758 : return 0;
2805 : 63413 : closure->lim--;
2806 : : }
2807 : 1995530 : closure->matc = make_method_match((jl_tupletype_t*)closure->match.ti,
2808 : : closure->match.env, meth,
2809 : 997765 : closure->match.issubty ? FULLY_COVERS : NOT_FULLY_COVERS);
2810 : 997765 : size_t len = jl_array_len(closure->t);
2811 [ + + ]: 997765 : if (len == 0) {
2812 : 357794 : closure->t = (jl_value_t*)jl_alloc_vec_any(1);
2813 : 357794 : jl_array_ptr_set(closure->t, 0, (jl_value_t*)closure->matc);
2814 : : }
2815 : : else {
2816 : 639971 : jl_array_ptr_1d_push((jl_array_t*)closure->t, (jl_value_t*)closure->matc);
2817 : : }
2818 : 997765 : return 1;
2819 : : }
2820 : :
2821 : 0 : static int ml_mtable_visitor(jl_methtable_t *mt, void *env)
2822 : : {
2823 : 0 : return jl_typemap_intersection_visitor(jl_atomic_load_relaxed(&mt->defs), 0, (struct typemap_intersection_env*)env);
2824 : : }
2825 : :
2826 : : // This is the collect form of calling jl_typemap_intersection_visitor
2827 : : // with optimizations to skip fully shadowed methods.
2828 : : //
2829 : : // Returns a match as an array of svec(argtypes, static_params, Method, fully-covers).
2830 : : //
2831 : : // See below for the meaning of lim.
2832 : : //
2833 : : // fully-covers is a Bool indicating subtyping, though temporarily it may be
2834 : : // tri-values, with `nothing` indicating a match that is not a subtype, but
2835 : : // which is dominated by one which is (and thus should be excluded unless ambiguous)
2836 : 1825160 : static jl_value_t *ml_matches(jl_methtable_t *mt,
2837 : : jl_tupletype_t *type, int lim, int include_ambiguous,
2838 : : int intersections, size_t world, int cache_result,
2839 : : size_t *min_valid, size_t *max_valid, int *ambig)
2840 : : {
2841 : 1825160 : int has_ambiguity = 0;
2842 : 1825160 : jl_value_t *unw = jl_unwrap_unionall((jl_value_t*)type);
2843 [ - + ]: 1825160 : assert(jl_is_datatype(unw));
2844 : 1825160 : size_t l = jl_svec_len(((jl_datatype_t*)unw)->parameters);
2845 : 1825160 : jl_value_t *va = NULL;
2846 [ + - ]: 1825160 : if (l > 0) {
2847 : 1825160 : va = jl_tparam(unw, l - 1);
2848 [ + + ]: 1825160 : if (jl_is_vararg(va))
2849 : 5316 : va = jl_unwrap_vararg(va);
2850 : : else
2851 : 1819840 : va = NULL;
2852 : : }
2853 : 1825160 : struct ml_matches_env env = {{ml_matches_visitor, (jl_value_t*)type, va,
2854 : : /* .ti = */ NULL, /* .env = */ jl_emptysvec, /* .issubty = */ 0},
2855 : : intersections, world, lim, /* .t = */ jl_an_empty_vec_any,
2856 : 1825160 : /* .min_valid = */ *min_valid, /* .max_valid = */ *max_valid, /* .matc = */ NULL};
2857 : 1825160 : struct jl_typemap_assoc search = {(jl_value_t*)type, world, jl_emptysvec, 1, ~(size_t)0};
2858 : 1825160 : jl_value_t *isect2 = NULL;
2859 : 1825160 : JL_GC_PUSH6(&env.t, &env.matc, &env.match.env, &search.env, &env.match.ti, &isect2);
2860 : :
2861 [ + - ]: 1825160 : if (mt) {
2862 : : // check the leaf cache if this type can be in there
2863 [ + + ]: 1825160 : if (((jl_datatype_t*)unw)->isdispatchtuple) {
2864 : 1610630 : jl_array_t *leafcache = jl_atomic_load_relaxed(&mt->leafcache);
2865 : 1610630 : jl_typemap_entry_t *entry = lookup_leafcache(leafcache, (jl_value_t*)type, world);
2866 [ + + ]: 1610630 : if (entry) {
2867 : 1288450 : jl_method_instance_t *mi = entry->func.linfo;
2868 : 1288450 : jl_method_t *meth = mi->def.method;
2869 [ + + ]: 1288450 : if (!jl_is_unionall(meth->sig)) {
2870 : 813123 : env.match.env = jl_emptysvec;
2871 : 813123 : env.match.ti = unw;
2872 : : }
2873 [ + + ]: 475327 : else if (jl_egal((jl_value_t*)type, mi->specTypes)) {
2874 : 475315 : env.match.env = mi->sparam_vals;
2875 : 475315 : env.match.ti = mi->specTypes;
2876 : : }
2877 : : else {
2878 : : // this just calls jl_subtype_env (since we know that `type <: meth->sig` by transitivity)
2879 : 12 : env.match.ti = jl_type_intersection_env((jl_value_t*)type, (jl_value_t*)meth->sig, &env.match.env);
2880 : : }
2881 : 1288450 : env.matc = make_method_match((jl_tupletype_t*)env.match.ti,
2882 : : env.match.env, meth, FULLY_COVERS);
2883 : 1288450 : env.t = (jl_value_t*)jl_alloc_vec_any(1);
2884 : 1288450 : jl_array_ptr_set(env.t, 0, env.matc);
2885 [ + - ]: 1288450 : if (*min_valid < entry->min_world)
2886 : 1288450 : *min_valid = entry->min_world;
2887 [ - + ]: 1288450 : if (*max_valid > entry->max_world)
2888 : 0 : *max_valid = entry->max_world;
2889 : 1288450 : JL_GC_POP();
2890 : 1288450 : return env.t;
2891 : : }
2892 : : }
2893 : : // then check the full cache if it seems profitable
2894 [ + + ]: 536709 : if (((jl_datatype_t*)unw)->isdispatchtuple) {
2895 : 322177 : jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(jl_atomic_load_relaxed(&mt->cache), &search, jl_cachearg_offset(mt), /*subtype*/1);
2896 [ + + - + : 322177 : if (entry && (((jl_datatype_t*)unw)->isdispatchtuple || entry->guardsigs == jl_emptysvec)) {
- - ]
2897 : 175129 : jl_method_instance_t *mi = entry->func.linfo;
2898 : 175129 : jl_method_t *meth = mi->def.method;
2899 [ + + + - ]: 175129 : if (!jl_is_unionall(meth->sig) && ((jl_datatype_t*)unw)->isdispatchtuple) {
2900 : 146396 : env.match.env = jl_emptysvec;
2901 : 146396 : env.match.ti = unw;
2902 : : }
2903 : : else {
2904 : : // this just calls jl_subtype_env (since we know that `type <: meth->sig` by transitivity)
2905 : 28733 : env.match.ti = jl_type_intersection_env((jl_value_t*)type, (jl_value_t*)meth->sig, &env.match.env);
2906 : : }
2907 : 175129 : env.matc = make_method_match((jl_tupletype_t*)env.match.ti,
2908 : : env.match.env, meth, FULLY_COVERS);
2909 : 175129 : env.t = (jl_value_t*)jl_alloc_vec_any(1);
2910 : 175129 : jl_array_ptr_set(env.t, 0, env.matc);
2911 [ + - ]: 175129 : if (*min_valid < entry->min_world)
2912 : 175129 : *min_valid = entry->min_world;
2913 [ - + ]: 175129 : if (*max_valid > entry->max_world)
2914 : 0 : *max_valid = entry->max_world;
2915 : 175129 : JL_GC_POP();
2916 : 175129 : return env.t;
2917 : : }
2918 : : }
2919 [ + + ]: 361580 : if (!jl_typemap_intersection_visitor(jl_atomic_load_relaxed(&mt->defs), 0, &env.match)) {
2920 : 8758 : JL_GC_POP();
2921 : 8758 : return jl_false;
2922 : : }
2923 : : }
2924 : : else {
2925 : : // else: scan everything
2926 [ # # ]: 0 : if (!jl_foreach_reachable_mtable(ml_mtable_visitor, &env.match)) {
2927 : 0 : JL_GC_POP();
2928 : 0 : return jl_false;
2929 : : }
2930 : : }
2931 : 352822 : *min_valid = env.min_valid;
2932 : 352822 : *max_valid = env.max_valid;
2933 : : // done with many of these values now
2934 : 352822 : env.match.ti = NULL; env.matc = NULL; env.match.env = NULL; search.env = NULL;
2935 : 352822 : size_t i, j, len = jl_array_len(env.t);
2936 : 352822 : jl_method_match_t *minmax = NULL;
2937 : 352822 : int minmax_ambig = 0;
2938 : 352822 : int all_subtypes = 1;
2939 [ + + ]: 352822 : if (len > 1) {
2940 : : // first try to pre-process the results to find the most specific
2941 : : // result that fully covers the input, since we can do this in linear
2942 : : // time, and the rest is O(n^2)
2943 : : // - first find a candidate for the best of these method results
2944 [ + + ]: 908708 : for (i = 0; i < len; i++) {
2945 : 756143 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
2946 [ + + ]: 756143 : if (matc->fully_covers == FULLY_COVERS) {
2947 : 299417 : jl_method_t *m = matc->method;
2948 [ + + ]: 299417 : if (minmax != NULL) {
2949 : 163454 : jl_method_t *minmaxm = minmax->method;
2950 [ + + ]: 163454 : if (jl_type_morespecific((jl_value_t*)minmaxm->sig, (jl_value_t*)m->sig))
2951 : 89594 : continue;
2952 : : }
2953 : 209823 : minmax = matc;
2954 : : }
2955 : : else {
2956 : 456726 : all_subtypes = 0;
2957 : : }
2958 : : }
2959 : : // - then see if it dominated all of the other choices
2960 [ + + ]: 152565 : if (minmax != NULL) {
2961 [ + - ]: 452611 : for (i = 0; i < len; i++) {
2962 : 452611 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
2963 [ + + ]: 452611 : if (matc == minmax)
2964 : 135963 : break;
2965 [ + + ]: 316648 : if (matc->fully_covers == FULLY_COVERS) {
2966 : 75370 : jl_method_t *m = matc->method;
2967 : 75370 : jl_method_t *minmaxm = minmax->method;
2968 [ - + ]: 75370 : if (!jl_type_morespecific((jl_value_t*)minmaxm->sig, (jl_value_t*)m->sig)) {
2969 : 0 : minmax_ambig = 1;
2970 : 0 : minmax = NULL;
2971 : 0 : has_ambiguity = 1;
2972 : 0 : break;
2973 : : }
2974 : : }
2975 : : }
2976 : : }
2977 : : // - it may even dominate some choices that are not subtypes!
2978 : : // move those into the subtype group, where we're filter them out shortly after
2979 : : // (potentially avoiding reporting these as an ambiguity, and
2980 : : // potentially allowing us to hit the next fast path)
2981 : : // - we could always check here if *any* FULLY_COVERS method is
2982 : : // more-specific (instead of just considering minmax), but that may
2983 : : // cost much extra and is less likely to help us hit a fast path
2984 : : // (we will look for this later, when we compute ambig_groupid, for
2985 : : // correctness)
2986 [ + + + + ]: 152565 : if (!all_subtypes && minmax != NULL) {
2987 : 32749 : jl_method_t *minmaxm = minmax->method;
2988 : 32749 : all_subtypes = 1;
2989 [ + + ]: 371375 : for (i = 0; i < len; i++) {
2990 : 338626 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
2991 [ + + ]: 338626 : if (matc->fully_covers != FULLY_COVERS) {
2992 : 294335 : jl_method_t *m = matc->method;
2993 [ + + ]: 294335 : if (jl_type_morespecific((jl_value_t*)minmaxm->sig, (jl_value_t*)m->sig))
2994 : 1605 : matc->fully_covers = SENTINEL; // put a sentinel value here for sorting
2995 : : else
2996 : 292730 : all_subtypes = 0;
2997 : : }
2998 : : }
2999 : : }
3000 : : // - now we might have a fast-return here, if we see that
3001 : : // we've already processed all of the possible outputs
3002 [ + + ]: 152565 : if (all_subtypes) {
3003 [ - + ]: 103310 : if (minmax_ambig) {
3004 [ # # ]: 0 : if (!include_ambiguous) {
3005 : 0 : len = 0;
3006 : 0 : env.t = jl_an_empty_vec_any;
3007 : : }
3008 [ # # ]: 0 : else if (lim == 1) {
3009 : 0 : JL_GC_POP();
3010 : 0 : return jl_false;
3011 : : }
3012 : : }
3013 : : else {
3014 [ - + ]: 103310 : assert(minmax != NULL);
3015 : 103310 : jl_array_ptr_set(env.t, 0, minmax);
3016 : 103310 : jl_array_del_end((jl_array_t*)env.t, len - 1);
3017 : 103310 : len = 1;
3018 : : }
3019 : : }
3020 : : }
3021 [ + + ]: 352822 : if (len > 1) {
3022 : : // need to partially domsort the graph now into a list
3023 : : // (this is an insertion sort attempt)
3024 : : // if we have a minmax method, we ignore anything less specific
3025 : : // we'll clean that up next
3026 [ + + ]: 500677 : for (i = 1; i < len; i++) {
3027 : 451422 : env.matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3028 : 451422 : jl_method_t *m = env.matc->method;
3029 : 451422 : int subt = env.matc->fully_covers != NOT_FULLY_COVERS;
3030 [ + + - + : 451422 : if ((minmax != NULL || (minmax_ambig && !include_ambiguous)) && subt) {
- - + + ]
3031 : 36393 : continue; // already the biggest (skip will filter others)
3032 : : }
3033 [ + + ]: 9460560 : for (j = 0; j < i; j++) {
3034 : 9167480 : jl_method_match_t *matc2 = (jl_method_match_t *)jl_array_ptr_ref(env.t, i - j - 1);
3035 : 9167480 : jl_method_t *m2 = matc2->method;
3036 : 9167480 : int subt2 = matc2->fully_covers != NOT_FULLY_COVERS;
3037 [ + + - + ]: 9167480 : if (!subt2 && subt)
3038 : 0 : break;
3039 [ + + ]: 9167480 : if (subt == subt2) {
3040 [ + + ]: 9104770 : if (lim != -1) {
3041 [ + - + + ]: 9104770 : if (subt || !jl_has_empty_intersection(m->sig, m2->sig))
3042 [ + + ]: 196526 : if (!jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig))
3043 : 121948 : break;
3044 : : }
3045 : : else {
3046 : : // if unlimited, use approximate sorting, with the only
3047 : : // main downside being that it may be overly-
3048 : : // conservative at reporting existence of ambiguities
3049 [ - + ]: 2 : if (jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig))
3050 : 0 : break;
3051 : : }
3052 : : }
3053 : 9045540 : jl_array_ptr_set(env.t, i - j, matc2);
3054 : : }
3055 : 415029 : jl_array_ptr_set(env.t, i - j, env.matc);
3056 : : }
3057 : 49255 : char *skip = (char*)alloca(len);
3058 : 49255 : memset(skip, 0, len);
3059 : : // if we had a minmax method (any subtypes), now may now be able to
3060 : : // quickly cleanup some of our sort result
3061 [ + + - + : 49255 : if (minmax != NULL || (minmax_ambig && !include_ambiguous)) {
- - ]
3062 [ + + ]: 370939 : for (i = 0; i < len; i++) {
3063 : 338286 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3064 [ + + + + ]: 338286 : if (minmax != matc && matc->fully_covers != NOT_FULLY_COVERS) {
3065 : 12903 : skip[i] = 1;
3066 : : }
3067 : : }
3068 : : }
3069 [ + + - + : 49255 : if (include_ambiguous && lim == -1 && ambig == NULL && !minmax_ambig) {
- - - - ]
3070 : : // in this case, we don't actually need to compute the ambiguity
3071 : : // information at all as the user doesn't need us to filter them
3072 : : // out or report them
3073 : : }
3074 : : else {
3075 : : // now that the results are (mostly) sorted, assign group numbers to each ambiguity
3076 : : // by computing the specificity-ambiguity matrix covering this query
3077 : 49255 : uint32_t *ambig_groupid = (uint32_t*)alloca(len * sizeof(uint32_t));
3078 [ + + ]: 549932 : for (i = 0; i < len; i++)
3079 : 500677 : ambig_groupid[i] = i;
3080 : : // as we go, keep a rough count of how many methods are disjoint, which
3081 : : // gives us a lower bound on how many methods we will be returning
3082 : : // and lets us stop early if we reach our limit
3083 : 49255 : int ndisjoint = minmax ? 1 : 0;
3084 [ + + ]: 533200 : for (i = 0; i < len; i++) {
3085 : 492929 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3086 [ + + ]: 492929 : if (skip[i]) {
3087 : : // if there was a minmax method, we can just pretend the rest are all in the same group:
3088 : : // they're all together but unsorted in the list, since we'll drop them all later anyways
3089 [ - + ]: 8984 : assert(matc->fully_covers != NOT_FULLY_COVERS);
3090 [ + + ]: 8984 : if (ambig_groupid[len - 1] > i)
3091 : 4785 : ambig_groupid[len - 1] = i; // ambiguity covering range [i:len)
3092 : 8984 : break;
3093 : : }
3094 : 483945 : jl_method_t *m = matc->method;
3095 : 483945 : int subt = matc->fully_covers == FULLY_COVERS; // jl_subtype((jl_value_t*)type, (jl_value_t*)m->sig)
3096 : 483945 : int rsubt = jl_egal((jl_value_t*)matc->spec_types, m->sig);
3097 : 483945 : int disjoint = 1;
3098 [ + + ]: 10785900 : for (j = len; j > i; j--) {
3099 [ + + ]: 10761900 : if (ambig_groupid[j - 1] < i) {
3100 : 48236 : disjoint = 0;
3101 : 48236 : break;
3102 : : }
3103 : 10713700 : jl_method_match_t *matc2 = (jl_method_match_t*)jl_array_ptr_ref(env.t, j - 1);
3104 : : // can't use skip[j - 1] here, since we still need to make sure the minmax dominates
3105 : 10713700 : jl_method_t *m2 = matc2->method;
3106 : 10713700 : int subt2 = matc2->fully_covers == FULLY_COVERS; // jl_subtype((jl_value_t*)type, (jl_value_t*)m2->sig)
3107 : 10713700 : int rsubt2 = jl_egal((jl_value_t*)matc2->spec_types, m2->sig);
3108 : : jl_value_t *ti;
3109 [ + + + + : 10713700 : if (!subt && !subt2 && rsubt && rsubt2 && lim == -1 && ambig == NULL)
+ + + + +
+ + - ]
3110 : : // these would only be filtered out of the list as
3111 : : // ambiguous if they are also type-equal, as we
3112 : : // aren't skipping matches and the user doesn't
3113 : : // care if we report any ambiguities
3114 : 6 : continue;
3115 [ + + ]: 10713700 : if (jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig))
3116 : 743175 : continue;
3117 [ + + ]: 9970490 : if (subt) {
3118 : 28742 : ti = (jl_value_t*)matc2->spec_types;
3119 : 28742 : isect2 = NULL;
3120 : : }
3121 [ + + ]: 9941750 : else if (subt2) {
3122 : 5676 : ti = (jl_value_t*)matc->spec_types;
3123 : 5676 : isect2 = NULL;
3124 : : }
3125 : : else {
3126 : 9936070 : jl_type_intersection2((jl_value_t*)matc->spec_types, (jl_value_t*)matc2->spec_types, &env.match.ti, &isect2);
3127 : 9936070 : ti = env.match.ti;
3128 : : }
3129 [ + + ]: 9970490 : if (ti != jl_bottom_type) {
3130 : 499055 : disjoint = 0;
3131 : : // m and m2 are ambiguous, but let's see if we can find another method (m3)
3132 : : // that dominates their intersection, and means we can ignore this
3133 : : size_t k;
3134 [ + + ]: 10521700 : for (k = i; k > 0; k--) {
3135 : 10110000 : jl_method_match_t *matc3 = (jl_method_match_t*)jl_array_ptr_ref(env.t, k - 1);
3136 : 10110000 : jl_method_t *m3 = matc3->method;
3137 [ + + + + : 10110000 : if ((jl_subtype(ti, m3->sig) || (isect2 && jl_subtype(isect2, m3->sig)))
- + ]
3138 [ + + ]: 466415 : && jl_type_morespecific((jl_value_t*)m3->sig, (jl_value_t*)m->sig)
3139 [ + + ]: 94736 : && jl_type_morespecific((jl_value_t*)m3->sig, (jl_value_t*)m2->sig))
3140 : 87337 : break;
3141 : : }
3142 [ + + ]: 499055 : if (k == 0) {
3143 : 411718 : ambig_groupid[j - 1] = i; // ambiguity covering range [i:j)
3144 : 411718 : isect2 = NULL;
3145 : 411718 : break;
3146 : : }
3147 : : }
3148 : 9558770 : isect2 = NULL;
3149 : : }
3150 [ + + - + ]: 483945 : if (disjoint && lim >= 0) {
3151 : 0 : ndisjoint += 1;
3152 [ # # ]: 0 : if (ndisjoint > lim) {
3153 : 0 : JL_GC_POP();
3154 : 0 : return jl_false;
3155 : : }
3156 : : }
3157 : : }
3158 : : // then we'll merge those numbers to assign each item in the group the same number
3159 : 49255 : uint32_t groupid = 0;
3160 : 49255 : uint32_t grouphi = 0;
3161 [ + + ]: 549932 : for (i = 0; i < len; i++) {
3162 : 500677 : j = len - i - 1;
3163 : 500677 : uint32_t agid = ambig_groupid[j];
3164 [ + + ]: 500677 : if (agid != j) { // thus agid < j
3165 [ + + ]: 19029 : if (grouphi == 0) {
3166 : 13859 : groupid = agid;
3167 : 13859 : grouphi = j;
3168 : : }
3169 [ + - ]: 5170 : else if (agid < groupid) {
3170 : 5170 : groupid = agid;
3171 : : }
3172 : : }
3173 [ + + + + ]: 500677 : if (grouphi && j == groupid) {
3174 : : do {
3175 : 62115 : ambig_groupid[grouphi--] = groupid;
3176 [ + + ]: 62115 : } while (grouphi > j);
3177 : 13859 : ambig_groupid[j] = groupid;
3178 : 13859 : groupid = 0;
3179 : 13859 : grouphi = 0;
3180 : : }
3181 : : }
3182 : : // always remove matches after the first subtype, now that we've sorted the list for ambiguities
3183 [ + + ]: 537865 : for (i = 0; i < len; i++) {
3184 : 488610 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3185 [ + + ]: 488610 : if (matc->fully_covers == FULLY_COVERS) { // jl_subtype((jl_value_t*)type, (jl_value_t*)m->sig)
3186 : 32653 : uint32_t agid = ambig_groupid[i];
3187 [ + + + + ]: 70172 : while (i < len && agid == ambig_groupid[i])
3188 : 37519 : i++; // keep ambiguous ones
3189 [ + + ]: 39854 : for (; i < len; i++)
3190 : 7201 : skip[i] = 1; // drop the rest
3191 : : }
3192 : : }
3193 : : // when limited, skip matches that are covered by earlier ones (and aren't perhaps ambiguous with them)
3194 [ + + ]: 49255 : if (lim != -1) {
3195 [ + + ]: 508731 : for (i = 0; i < len; i++) {
3196 [ + + ]: 492131 : if (skip[i])
3197 : 4361 : continue;
3198 : 487770 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3199 : 487770 : jl_method_t *m = matc->method;
3200 : 487770 : jl_tupletype_t *ti = matc->spec_types;
3201 [ + + ]: 487770 : if (matc->fully_covers == FULLY_COVERS)
3202 : 32653 : break; // remaining matches are ambiguous or already skipped
3203 [ + + ]: 10460800 : for (j = 0; j < i; j++) {
3204 : 10036100 : jl_method_match_t *matc2 = (jl_method_match_t*)jl_array_ptr_ref(env.t, j);
3205 : 10036100 : jl_method_t *m2 = matc2->method;
3206 [ + + ]: 10036100 : if (jl_subtype((jl_value_t*)ti, m2->sig)) {
3207 [ + + ]: 30636 : if (ambig_groupid[i] != ambig_groupid[j]) {
3208 : 24284 : skip[i] = 1;
3209 : 24284 : break;
3210 : : }
3211 [ + - ]: 6352 : else if (!include_ambiguous) {
3212 [ + + ]: 6352 : if (!jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig)) {
3213 : 6106 : skip[i] = 1;
3214 : 6106 : break;
3215 : : }
3216 : : }
3217 : : }
3218 : : }
3219 : : }
3220 : : }
3221 : : // Compute whether anything could be ambiguous by seeing if any two
3222 : : // remaining methods in the result are in the same ambiguity group.
3223 [ - + ]: 49255 : assert(len > 0);
3224 : 49255 : uint32_t agid = ambig_groupid[0];
3225 [ + + ]: 417007 : for (i = 1; i < len; i++) {
3226 [ + + ]: 374547 : if (!skip[i]) {
3227 [ + + ]: 339652 : if (agid == ambig_groupid[i]) {
3228 : 6795 : has_ambiguity = 1;
3229 : 6795 : break;
3230 : : }
3231 : 332857 : agid = ambig_groupid[i];
3232 : : }
3233 : : }
3234 : : // If we're only returning possible matches, now filter out any method
3235 : : // whose intersection is fully ambiguous with the group it is in.
3236 [ + + ]: 49255 : if (!include_ambiguous) {
3237 [ + + ]: 513209 : for (i = 0; i < len; i++) {
3238 [ + + ]: 465535 : if (skip[i])
3239 : 42106 : continue;
3240 : 423429 : uint32_t agid = ambig_groupid[i];
3241 : 423429 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3242 : 423429 : jl_method_t *m = matc->method;
3243 : 423429 : jl_tupletype_t *ti = matc->spec_types;
3244 : 423429 : int subt = matc->fully_covers == FULLY_COVERS; // jl_subtype((jl_value_t*)type, (jl_value_t*)m->sig)
3245 : 423429 : char ambig1 = 0;
3246 [ + + + + ]: 945896 : for (j = agid; j < len && ambig_groupid[j] == agid; j++) {
3247 [ + + ]: 559496 : if (j == i)
3248 : 391587 : continue;
3249 : 167909 : jl_method_match_t *matc2 = (jl_method_match_t*)jl_array_ptr_ref(env.t, j);
3250 : 167909 : jl_method_t *m2 = matc2->method;
3251 : 167909 : int subt2 = matc2->fully_covers == FULLY_COVERS; // jl_subtype((jl_value_t*)type, (jl_value_t*)m2->sig)
3252 : : // if their intersection contributes to the ambiguity cycle
3253 [ + + + + : 167909 : if (subt || subt2 || !jl_has_empty_intersection((jl_value_t*)ti, m2->sig)) {
+ + ]
3254 : : // and the contribution of m is ambiguous with the portion of the cycle from m2
3255 [ + + + + ]: 61770 : if (subt2 || jl_subtype((jl_value_t*)ti, m2->sig)) {
3256 : : // but they aren't themselves simply ordered (here
3257 : : // we don't consider that a third method might be
3258 : : // disrupting that ordering and just consider them
3259 : : // pairwise to keep this simple).
3260 [ + + + + ]: 30437 : if (!jl_type_morespecific((jl_value_t*)m->sig, (jl_value_t*)m2->sig) &&
3261 : 5696 : !jl_type_morespecific((jl_value_t*)m2->sig, (jl_value_t*)m->sig)) {
3262 : 5646 : ambig1 = 1;
3263 : : }
3264 : : }
3265 : : else {
3266 : : // otherwise some aspect of m is not ambiguous
3267 : 37029 : ambig1 = 0;
3268 : 37029 : break;
3269 : : }
3270 : : }
3271 : : }
3272 [ + + ]: 423429 : if (ambig1)
3273 : 3789 : skip[i] = 1;
3274 : : }
3275 : : }
3276 : : }
3277 : : // cleanup array to remove skipped entries
3278 [ + + ]: 549932 : for (i = 0, j = 0; i < len; i++) {
3279 : 500677 : jl_method_match_t *matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, i);
3280 [ + + ]: 500677 : if (!skip[i]) {
3281 : 453595 : jl_array_ptr_set(env.t, j++, matc);
3282 : : // remove our sentinel entry markers
3283 [ - + ]: 453595 : if (matc->fully_covers == SENTINEL)
3284 : 0 : matc->fully_covers = NOT_FULLY_COVERS;
3285 : : }
3286 : : }
3287 [ + + ]: 49255 : if (j != len)
3288 : 20288 : jl_array_del_end((jl_array_t*)env.t, len - j);
3289 : 49255 : len = j;
3290 : : }
3291 [ + - + + : 352822 : if (mt && cache_result && ((jl_datatype_t*)unw)->isdispatchtuple) { // cache_result parameter keeps this from being recursive
+ + ]
3292 [ + + + - ]: 146870 : if (len == 1 && !has_ambiguity) {
3293 : 143328 : env.matc = (jl_method_match_t*)jl_array_ptr_ref(env.t, 0);
3294 : 143328 : jl_method_t *meth = env.matc->method;
3295 : 143328 : jl_svec_t *tpenv = env.matc->sparams;
3296 : 143328 : JL_LOCK(&mt->writelock);
3297 : 143328 : cache_method(mt, &mt->cache, (jl_value_t*)mt, (jl_tupletype_t*)unw, meth, world, env.min_valid, env.max_valid, tpenv);
3298 : 143328 : JL_UNLOCK(&mt->writelock);
3299 : : }
3300 : : }
3301 [ + + ]: 352822 : if (ambig != NULL)
3302 : 328781 : *ambig = has_ambiguity;
3303 : 352822 : JL_GC_POP();
3304 [ + + + + ]: 352822 : if (lim >= 0 && len > lim)
3305 : 23958 : return jl_false;
3306 : 328864 : return env.t;
3307 : : }
3308 : :
3309 : : // see if it might be possible to construct an instance of `typ`
3310 : : // if n_uninitialized == 0, but a fieldtype is Union{},
3311 : : // that type will not be constructable, for example, tested recursively
3312 : 4098 : int jl_has_concrete_subtype(jl_value_t *typ)
3313 : : {
3314 [ - + ]: 4098 : if (typ == jl_bottom_type)
3315 : 0 : return 0;
3316 : 4098 : typ = jl_unwrap_unionall(typ);
3317 [ - + ]: 4098 : if (jl_is_vararg(typ))
3318 : 0 : typ = jl_unwrap_vararg(typ);
3319 [ - + ]: 4098 : if (!jl_is_datatype(typ))
3320 : 0 : return 1;
3321 : 4098 : return ((jl_datatype_t*)typ)->has_concrete_subtype;
3322 : : }
3323 : :
3324 : : // TODO: separate the codegen and typeinf locks
3325 : : // currently using a coarser lock seems like
3326 : : // the best way to avoid acquisition priority
3327 : : // ordering violations
3328 : : //static jl_mutex_t typeinf_lock;
3329 : : #define typeinf_lock jl_codegen_lock
3330 : :
3331 : : static uint64_t inference_start_time = 0;
3332 : : static uint8_t inference_is_measuring_compile_time = 0;
3333 : :
3334 : 7278 : JL_DLLEXPORT void jl_typeinf_begin(void)
3335 : : {
3336 : 7278 : JL_LOCK(&typeinf_lock);
3337 [ - + ]: 7278 : if (jl_atomic_load_relaxed(&jl_measure_compile_time_enabled)) {
3338 : 0 : inference_start_time = jl_hrtime();
3339 : 0 : inference_is_measuring_compile_time = 1;
3340 : : }
3341 : 7278 : }
3342 : :
3343 : 7278 : JL_DLLEXPORT void jl_typeinf_end(void)
3344 : : {
3345 [ + + - + ]: 7278 : if (typeinf_lock.count == 1 && inference_is_measuring_compile_time) {
3346 : 0 : jl_atomic_fetch_add_relaxed(&jl_cumulative_compile_time, (jl_hrtime() - inference_start_time));
3347 : 0 : inference_is_measuring_compile_time = 0;
3348 : : }
3349 : 7278 : JL_UNLOCK(&typeinf_lock);
3350 : 7278 : }
3351 : :
3352 : : #ifdef __cplusplus
3353 : : }
3354 : : #endif
|