LCOV - code coverage report
Current view: top level - src - method.c (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 716 763 93.8 %
Date: 2022-07-16 23:42:53 Functions: 31 31 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 438 566 77.4 %

           Branch data     Line data    Source code
       1                 :            : // This file is a part of Julia. License is MIT: https://julialang.org/license
       2                 :            : 
       3                 :            : /*
       4                 :            :   Defining and adding methods
       5                 :            : */
       6                 :            : 
       7                 :            : #include <stdlib.h>
       8                 :            : #include <string.h>
       9                 :            : #include <stdarg.h>
      10                 :            : #include "julia.h"
      11                 :            : #include "julia_internal.h"
      12                 :            : #include "julia_assert.h"
      13                 :            : 
      14                 :            : #ifdef __cplusplus
      15                 :            : extern "C" {
      16                 :            : #endif
      17                 :            : 
      18                 :            : extern jl_value_t *jl_builtin_getfield;
      19                 :            : extern jl_value_t *jl_builtin_tuple;
      20                 :            : 
      21                 :            : jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name,
      22                 :            :     int nargs, jl_value_t *functionloc, jl_code_info_t *ci, int isva);
      23                 :            : 
      24                 :       3164 : static void check_c_types(const char *where, jl_value_t *rt, jl_value_t *at)
      25                 :            : {
      26         [ -  + ]:       3164 :     if (jl_is_svec(rt))
      27                 :          0 :         jl_errorf("%s: missing return type", where);
      28         [ -  + ]:       3164 :     JL_TYPECHKS(where, type, rt);
      29         [ -  + ]:       3164 :     if (!jl_type_mappable_to_c(rt))
      30                 :          0 :         jl_errorf("%s: return type doesn't correspond to a C type", where);
      31         [ -  + ]:       3164 :     JL_TYPECHKS(where, simplevector, at);
      32                 :       3164 :     int i, l = jl_svec_len(at);
      33         [ +  + ]:      15535 :     for (i = 0; i < l; i++) {
      34                 :      12371 :         jl_value_t *ati = jl_svecref(at, i);
      35         [ -  + ]:      12371 :         if (jl_is_vararg(ati))
      36                 :          0 :             jl_errorf("%s: Vararg not allowed for argument list", where);
      37         [ -  + ]:      12371 :         JL_TYPECHKS(where, type, ati);
      38         [ -  + ]:      12371 :         if (!jl_type_mappable_to_c(ati))
      39                 :          0 :             jl_errorf("%s: argument %d type doesn't correspond to a C type", where, i + 1);
      40                 :            :     }
      41                 :       3164 : }
      42                 :            : 
      43                 :            : // Resolve references to non-locally-defined variables to become references to global
      44                 :            : // variables in `module` (unless the rvalue is one of the type parameters in `sparam_vals`).
      45                 :    5046370 : static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_svec_t *sparam_vals,
      46                 :            :                                    int binding_effects, int eager_resolve)
      47                 :            : {
      48         [ +  + ]:    5046370 :     if (jl_is_symbol(expr)) {
      49         [ -  + ]:     385774 :         if (module == NULL)
      50                 :          0 :             return expr;
      51                 :     385774 :         return jl_module_globalref(module, (jl_sym_t*)expr);
      52                 :            :     }
      53         [ +  + ]:    4660590 :     else if (jl_is_returnnode(expr)) {
      54                 :      88902 :         jl_value_t *retval = jl_returnnode_value(expr);
      55         [ +  - ]:      88902 :         if (retval) {
      56                 :      88902 :             jl_value_t *val = resolve_globals(retval, module, sparam_vals, binding_effects, eager_resolve);
      57         [ +  + ]:      88902 :             if (val != retval) {
      58                 :       2741 :                 JL_GC_PUSH1(&val);
      59                 :       2741 :                 expr = jl_new_struct(jl_returnnode_type, val);
      60                 :       2741 :                 JL_GC_POP();
      61                 :            :             }
      62                 :            :         }
      63                 :      88902 :         return expr;
      64                 :            :     }
      65         [ +  + ]:    4571690 :     else if (jl_is_gotoifnot(expr)) {
      66                 :     114370 :         jl_value_t *cond = resolve_globals(jl_gotoifnot_cond(expr), module, sparam_vals, binding_effects, eager_resolve);
      67         [ +  + ]:     114370 :         if (cond != jl_gotoifnot_cond(expr)) {
      68                 :         74 :             intptr_t label = jl_gotoifnot_label(expr);
      69                 :         74 :             JL_GC_PUSH1(&cond);
      70                 :         74 :             expr = jl_new_struct_uninit(jl_gotoifnot_type);
      71                 :         74 :             set_nth_field(jl_gotoifnot_type, expr, 0, cond, 0);
      72                 :         74 :             jl_gotoifnot_label(expr) = label;
      73                 :         74 :             JL_GC_POP();
      74                 :            :         }
      75                 :     114370 :         return expr;
      76                 :            :     }
      77         [ +  + ]:    4457320 :     else if (jl_is_expr(expr)) {
      78                 :    1206500 :         jl_expr_t *e = (jl_expr_t*)expr;
      79   [ +  +  +  + ]:    1206500 :         if (e->head == jl_global_sym && binding_effects) {
      80                 :            :             // execute the side-effects of "global x" decl immediately:
      81                 :            :             // creates uninitialized mutable binding in module for each global
      82                 :        247 :             jl_eval_global_expr(module, e, 1);
      83                 :        247 :             expr = jl_nothing;
      84                 :            :         }
      85   [ +  +  +  - ]:    1206500 :         if (jl_is_toplevel_only_expr(expr) || e->head == jl_const_sym ||
      86   [ +  -  +  + ]:    1206150 :             e->head == jl_coverageeffect_sym || e->head == jl_copyast_sym ||
      87   [ +  -  +  - ]:    1205070 :             e->head == jl_quote_sym || e->head == jl_inert_sym ||
      88   [ +  +  +  - ]:    1205070 :             e->head == jl_meta_sym || e->head == jl_inbounds_sym ||
      89   [ +  +  +  + ]:    1204990 :             e->head == jl_boundscheck_sym || e->head == jl_loopinfo_sym ||
      90   [ +  +  +  + ]:    1204480 :             e->head == jl_aliasscope_sym || e->head == jl_popaliasscope_sym ||
      91   [ +  -  +  - ]:    1204480 :             e->head == jl_inline_sym || e->head == jl_noinline_sym) {
      92                 :            :             // ignore these
      93                 :            :         }
      94                 :            :         else {
      95                 :    1204480 :             size_t i = 0, nargs = jl_array_len(e->args);
      96         [ +  + ]:    1204480 :             if (e->head == jl_opaque_closure_method_sym) {
      97         [ -  + ]:         42 :                 if (nargs != 5) {
      98                 :          0 :                     jl_error("opaque_closure_method: invalid syntax");
      99                 :            :                 }
     100                 :         42 :                 jl_value_t *name = jl_exprarg(e, 0);
     101                 :         42 :                 jl_value_t *nargs = jl_exprarg(e, 1);
     102                 :         42 :                 int isva = jl_exprarg(e, 2) == jl_true;
     103                 :         42 :                 jl_value_t *functionloc = jl_exprarg(e, 3);
     104                 :         42 :                 jl_value_t *ci = jl_exprarg(e, 4);
     105         [ -  + ]:         42 :                 if (!jl_is_code_info(ci)) {
     106                 :          0 :                     jl_error("opaque_closure_method: lambda should be a CodeInfo");
     107                 :            :                 }
     108                 :         42 :                 jl_method_t *m = jl_make_opaque_closure_method(module, name, jl_unbox_long(nargs), functionloc, (jl_code_info_t*)ci, isva);
     109                 :         42 :                 return (jl_value_t*)m;
     110                 :            :             }
     111         [ +  + ]:    1204440 :             if (e->head == jl_cfunction_sym) {
     112   [ -  +  -  + ]:        117 :                 JL_NARGS(cfunction method definition, 5, 5); // (type, func, rt, at, cc)
     113                 :        117 :                 jl_value_t *typ = jl_exprarg(e, 0);
     114         [ -  + ]:        117 :                 if (!jl_is_type(typ))
     115                 :          0 :                     jl_error("first parameter to :cfunction must be a type");
     116         [ +  + ]:        117 :                 if (typ == (jl_value_t*)jl_voidpointer_type) {
     117                 :        112 :                     jl_value_t *a = jl_exprarg(e, 1);
     118         [ -  + ]:        112 :                     JL_TYPECHK(cfunction method definition, quotenode, a);
     119                 :        112 :                     *(jl_value_t**)a = jl_toplevel_eval(module, *(jl_value_t**)a);
     120                 :        112 :                     jl_gc_wb(a, *(jl_value_t**)a);
     121                 :            :                 }
     122                 :        117 :                 jl_value_t *rt = jl_exprarg(e, 2);
     123                 :        117 :                 jl_value_t *at = jl_exprarg(e, 3);
     124         [ +  + ]:        117 :                 if (!jl_is_type(rt)) {
     125   [ +  -  +  + ]:        214 :                     JL_TRY {
     126                 :        107 :                         rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals);
     127                 :            :                     }
     128         [ #  # ]:          0 :                     JL_CATCH {
     129         [ #  # ]:          0 :                         if (jl_typeis(jl_current_exception(), jl_errorexception_type))
     130                 :          0 :                             jl_error("could not evaluate cfunction return type (it might depend on a local variable)");
     131                 :            :                         else
     132                 :          0 :                             jl_rethrow();
     133                 :            :                     }
     134                 :        107 :                     jl_exprargset(e, 2, rt);
     135                 :            :                 }
     136         [ +  - ]:        117 :                 if (!jl_is_svec(at)) {
     137   [ +  -  +  + ]:        234 :                     JL_TRY {
     138                 :        117 :                         at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals);
     139                 :            :                     }
     140         [ #  # ]:          0 :                     JL_CATCH {
     141         [ #  # ]:          0 :                         if (jl_typeis(jl_current_exception(), jl_errorexception_type))
     142                 :          0 :                             jl_error("could not evaluate cfunction argument type (it might depend on a local variable)");
     143                 :            :                         else
     144                 :          0 :                             jl_rethrow();
     145                 :            :                     }
     146                 :        117 :                     jl_exprargset(e, 3, at);
     147                 :            :                 }
     148                 :        117 :                 check_c_types("cfunction method definition", rt, at);
     149         [ -  + ]:        117 :                 JL_TYPECHK(cfunction method definition, quotenode, jl_exprarg(e, 4));
     150         [ -  + ]:        117 :                 JL_TYPECHK(cfunction method definition, symbol, *(jl_value_t**)jl_exprarg(e, 4));
     151                 :        117 :                 return expr;
     152                 :            :             }
     153         [ +  + ]:    1204320 :             if (e->head == jl_foreigncall_sym) {
     154         [ -  + ]:       3047 :                 JL_NARGSV(ccall method definition, 5); // (fptr, rt, at, nreq, (cc, effects))
     155                 :       3047 :                 jl_value_t *rt = jl_exprarg(e, 1);
     156                 :       3047 :                 jl_value_t *at = jl_exprarg(e, 2);
     157         [ +  + ]:       3047 :                 if (!jl_is_type(rt)) {
     158   [ +  -  +  + ]:       6070 :                     JL_TRY {
     159                 :       3035 :                         rt = jl_interpret_toplevel_expr_in(module, rt, NULL, sparam_vals);
     160                 :            :                     }
     161         [ #  # ]:          0 :                     JL_CATCH {
     162         [ #  # ]:          0 :                         if (jl_typeis(jl_current_exception(), jl_errorexception_type))
     163                 :          0 :                             jl_error("could not evaluate ccall return type (it might depend on a local variable)");
     164                 :            :                         else
     165                 :          0 :                             jl_rethrow();
     166                 :            :                     }
     167                 :       3035 :                     jl_exprargset(e, 1, rt);
     168                 :            :                 }
     169         [ +  + ]:       3047 :                 if (!jl_is_svec(at)) {
     170   [ +  -  +  + ]:       6092 :                     JL_TRY {
     171                 :       3046 :                         at = jl_interpret_toplevel_expr_in(module, at, NULL, sparam_vals);
     172                 :            :                     }
     173         [ #  # ]:          0 :                     JL_CATCH {
     174         [ #  # ]:          0 :                         if (jl_typeis(jl_current_exception(), jl_errorexception_type))
     175                 :          0 :                             jl_error("could not evaluate ccall argument type (it might depend on a local variable)");
     176                 :            :                         else
     177                 :          0 :                             jl_rethrow();
     178                 :            :                     }
     179                 :       3046 :                     jl_exprargset(e, 2, at);
     180                 :            :                 }
     181                 :       3047 :                 check_c_types("ccall method definition", rt, at);
     182         [ -  + ]:       3047 :                 JL_TYPECHK(ccall method definition, long, jl_exprarg(e, 3));
     183         [ -  + ]:       3047 :                 JL_TYPECHK(ccall method definition, quotenode, jl_exprarg(e, 4));
     184                 :       3047 :                 jl_value_t *cc = jl_quotenode_value(jl_exprarg(e, 4));
     185         [ +  + ]:       3047 :                 if (!jl_is_symbol(cc)) {
     186         [ -  + ]:          2 :                     JL_TYPECHK(ccall method definition, tuple, cc);
     187         [ -  + ]:          2 :                     if (jl_nfields(cc) != 2) {
     188                 :          0 :                         jl_error("In ccall calling convention, expected two argument tuple or symbol.");
     189                 :            :                     }
     190         [ -  + ]:          2 :                     JL_TYPECHK(ccall method definition, symbol, jl_get_nth_field(cc, 0));
     191         [ -  + ]:          2 :                     JL_TYPECHK(ccall method definition, uint8, jl_get_nth_field(cc, 1));
     192                 :            :                 }
     193                 :       3047 :                 jl_exprargset(e, 0, resolve_globals(jl_exprarg(e, 0), module, sparam_vals, binding_effects, 1));
     194                 :       3047 :                 i++;
     195                 :            :             }
     196   [ +  +  -  + ]:    1204320 :             if (e->head == jl_method_sym || e->head == jl_module_sym) {
     197                 :        365 :                 i++;
     198                 :            :             }
     199         [ +  + ]:    4547590 :             for (; i < nargs; i++) {
     200                 :            :                 // TODO: this should be making a copy, not mutating the source
     201                 :    3343270 :                 jl_exprargset(e, i, resolve_globals(jl_exprarg(e, i), module, sparam_vals, binding_effects, eager_resolve));
     202                 :            :             }
     203   [ +  +  +  + ]:    1204320 :             if (e->head == jl_call_sym && jl_expr_nargs(e) == 3 &&
     204         [ +  + ]:     455684 :                     jl_is_globalref(jl_exprarg(e, 0)) &&
     205         [ +  + ]:     429630 :                     jl_is_globalref(jl_exprarg(e, 1)) &&
     206         [ +  + ]:      82193 :                     jl_is_quotenode(jl_exprarg(e, 2))) {
     207                 :            :                 // replace module_expr.sym with GlobalRef(module, sym)
     208                 :            :                 // for expressions pattern-matching to `getproperty(module_expr, :sym)` in a top-module
     209                 :            :                 // (this is expected to help inference performance)
     210                 :            :                 // TODO: this was broken by linear-IR
     211                 :      35856 :                 jl_value_t *s = jl_fieldref(jl_exprarg(e, 2), 0);
     212                 :      35856 :                 jl_value_t *me = jl_exprarg(e, 1);
     213                 :      35856 :                 jl_value_t *fe = jl_exprarg(e, 0);
     214                 :      35856 :                 jl_module_t *fe_mod = jl_globalref_mod(fe);
     215                 :      35856 :                 jl_sym_t *fe_sym = jl_globalref_name(fe);
     216                 :      35856 :                 jl_module_t *me_mod = jl_globalref_mod(me);
     217                 :      35856 :                 jl_sym_t *me_sym = jl_globalref_name(me);
     218   [ +  +  +  +  :      35856 :                 if (fe_mod->istopmod && !strcmp(jl_symbol_name(fe_sym), "getproperty") && jl_is_symbol(s)) {
                   +  - ]
     219   [ +  -  +  + ]:      35637 :                     if (eager_resolve || jl_binding_resolved_p(me_mod, me_sym)) {
     220                 :      34056 :                         jl_binding_t *b = jl_get_binding(me_mod, me_sym);
     221   [ +  -  +  + ]:      34056 :                         if (b && b->constp) {
     222                 :      34046 :                             jl_value_t *v = jl_atomic_load_relaxed(&b->value);
     223   [ +  -  +  + ]:      34046 :                             if (v && jl_is_module(v))
     224                 :      33941 :                                 return jl_module_globalref((jl_module_t*)v, (jl_sym_t*)s);
     225                 :            :                         }
     226                 :            :                     }
     227                 :            :                 }
     228                 :            :             }
     229   [ +  +  +  - ]:    1170380 :             if (e->head == jl_call_sym && nargs > 0 &&
     230         [ +  + ]:     825436 :                     jl_is_globalref(jl_exprarg(e, 0))) {
     231                 :            :                 // TODO: this hack should be deleted once llvmcall is fixed
     232                 :     743257 :                 jl_value_t *fe = jl_exprarg(e, 0);
     233                 :     743257 :                 jl_module_t *fe_mod = jl_globalref_mod(fe);
     234                 :     743257 :                 jl_sym_t *fe_sym = jl_globalref_name(fe);
     235         [ +  + ]:     743257 :                 if (jl_binding_resolved_p(fe_mod, fe_sym)) {
     236                 :            :                     // look at some known called functions
     237                 :     669359 :                     jl_binding_t *b = jl_get_binding(fe_mod, fe_sym);
     238   [ +  -  +  +  :     669359 :                     if (b && b->constp && jl_atomic_load_relaxed(&b->value) == jl_builtin_tuple) {
                   +  + ]
     239                 :            :                         size_t j;
     240         [ +  + ]:      53445 :                         for (j = 1; j < nargs; j++) {
     241         [ +  + ]:      45463 :                             if (!jl_is_quotenode(jl_exprarg(e, j)))
     242                 :      35153 :                                 break;
     243                 :            :                         }
     244         [ +  + ]:      43135 :                         if (j == nargs) {
     245                 :       7982 :                             jl_value_t *val = NULL;
     246   [ +  -  +  + ]:      15964 :                             JL_TRY {
     247                 :       7982 :                                 val = jl_interpret_toplevel_expr_in(module, (jl_value_t*)e, NULL, sparam_vals);
     248                 :            :                             }
     249         [ #  # ]:          0 :                             JL_CATCH {
     250                 :            :                             }
     251         [ +  - ]:       7982 :                             if (val)
     252                 :       7982 :                                 return val;
     253                 :            :                         }
     254                 :            :                     }
     255                 :            :                 }
     256                 :            :             }
     257                 :            :         }
     258                 :            :     }
     259                 :    4415240 :     return expr;
     260                 :            : }
     261                 :            : 
     262                 :       7435 : JL_DLLEXPORT void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *sparam_vals,
     263                 :            :                               int binding_effects)
     264                 :            : {
     265                 :       7435 :     size_t i, l = jl_array_len(stmts);
     266         [ +  + ]:     641544 :     for (i = 0; i < l; i++) {
     267                 :     634109 :         jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
     268                 :     634109 :         jl_array_ptr_set(stmts, i, resolve_globals(stmt, m, sparam_vals, binding_effects, 0));
     269                 :            :     }
     270                 :       7435 : }
     271                 :            : 
     272                 :       4780 : jl_value_t *expr_arg1(jl_value_t *expr) {
     273                 :       4780 :     jl_array_t *args = ((jl_expr_t*)expr)->args;
     274                 :       4780 :     return jl_array_ptr_ref(args, 0);
     275                 :            : }
     276                 :            : 
     277                 :            : // copy a :lambda Expr into its CodeInfo representation,
     278                 :            : // including popping of known meta nodes
     279                 :     232609 : static void jl_code_info_set_ir(jl_code_info_t *li, jl_expr_t *ir)
     280                 :            : {
     281         [ -  + ]:     232609 :     assert(jl_is_expr(ir));
     282                 :     232609 :     jl_expr_t *bodyex = (jl_expr_t*)jl_exprarg(ir, 2);
     283                 :     232609 :     jl_value_t *codelocs = jl_exprarg(ir, 3);
     284                 :     232609 :     li->linetable = jl_exprarg(ir, 4);
     285                 :     232609 :     size_t nlocs = jl_array_len(codelocs);
     286                 :     232609 :     li->codelocs = (jl_value_t*)jl_alloc_array_1d(jl_array_int32_type, nlocs);
     287                 :            :     size_t j;
     288         [ +  + ]:    4270290 :     for (j = 0; j < nlocs; j++) {
     289                 :    4037680 :         jl_arrayset((jl_array_t*)li->codelocs, jl_box_int32(jl_unbox_long(jl_arrayref((jl_array_t*)codelocs, j))),
     290                 :            :                     j);
     291                 :            :     }
     292         [ -  + ]:     232615 :     assert(jl_is_expr(bodyex));
     293                 :     232615 :     jl_array_t *body = bodyex->args;
     294                 :     232615 :     li->code = body;
     295                 :     232615 :     jl_gc_wb(li, li->code);
     296                 :     232615 :     size_t n = jl_array_len(body);
     297                 :     232615 :     jl_value_t **bd = (jl_value_t**)jl_array_ptr_data((jl_array_t*)li->code);
     298                 :     232615 :     li->ssaflags = jl_alloc_array_1d(jl_array_uint8_type, n);
     299                 :     232622 :     jl_gc_wb(li, li->ssaflags);
     300                 :     232622 :     int inbounds_depth = 0; // number of stacked inbounds
     301                 :            :     // isempty(inline_flags): no user annotation
     302                 :            :     // last(inline_flags) == 1: inline region
     303                 :            :     // last(inline_flags) == 0: noinline region
     304                 :     232622 :     arraylist_t *inline_flags = arraylist_new((arraylist_t*)malloc_s(sizeof(arraylist_t)), 0);
     305         [ +  + ]:    4270310 :     for (j = 0; j < n; j++) {
     306                 :    4037700 :         jl_value_t *st = bd[j];
     307                 :    4037700 :         int is_flag_stmt = 0;
     308                 :            :         // check :meta expression
     309   [ +  +  +  + ]:    4049310 :         if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_meta_sym) {
     310                 :      11609 :             size_t k, ins = 0, na = jl_expr_nargs(st);
     311                 :      11609 :             jl_array_t *meta = ((jl_expr_t*)st)->args;
     312         [ +  + ]:      28354 :             for (k = 0; k < na; k++) {
     313                 :      16745 :                 jl_value_t *ma = jl_array_ptr_ref(meta, k);
     314         [ +  + ]:      16745 :                 if (ma == (jl_value_t*)jl_pure_sym)
     315                 :         15 :                     li->pure = 1;
     316         [ +  + ]:      16730 :                 else if (ma == (jl_value_t*)jl_inline_sym)
     317                 :       5819 :                     li->inlineable = 1;
     318         [ +  + ]:      10911 :                 else if (ma == (jl_value_t*)jl_propagate_inbounds_sym)
     319                 :        414 :                     li->propagate_inbounds = 1;
     320         [ +  + ]:      10497 :                 else if (ma == (jl_value_t*)jl_aggressive_constprop_sym)
     321                 :         43 :                     li->constprop = 1;
     322         [ +  + ]:      10454 :                 else if (ma == (jl_value_t*)jl_no_constprop_sym)
     323                 :         43 :                     li->constprop = 2;
     324   [ +  +  +  + ]:      10411 :                 else if (jl_is_expr(ma) && ((jl_expr_t*)ma)->head == jl_purity_sym) {
     325         [ +  - ]:        122 :                     if (jl_expr_nargs(ma) == 6) {
     326                 :        122 :                         li->purity.overrides.ipo_consistent = jl_unbox_bool(jl_exprarg(ma, 0));
     327                 :        122 :                         li->purity.overrides.ipo_effect_free = jl_unbox_bool(jl_exprarg(ma, 1));
     328                 :        122 :                         li->purity.overrides.ipo_nothrow = jl_unbox_bool(jl_exprarg(ma, 2));
     329                 :        122 :                         li->purity.overrides.ipo_terminates = jl_unbox_bool(jl_exprarg(ma, 3));
     330                 :        122 :                         li->purity.overrides.ipo_terminates_locally = jl_unbox_bool(jl_exprarg(ma, 4));
     331                 :        122 :                         li->purity.overrides.ipo_notaskstate = jl_unbox_bool(jl_exprarg(ma, 5));
     332                 :            :                     }
     333                 :            :                 }
     334                 :            :                 else
     335                 :      10289 :                     jl_array_ptr_set(meta, ins++, ma);
     336                 :            :             }
     337         [ +  + ]:      11609 :             if (ins == 0)
     338                 :       6122 :                 bd[j] = jl_nothing;
     339                 :            :             else
     340                 :       5487 :                 jl_array_del_end(meta, na - ins);
     341                 :            :         }
     342                 :            :         // check other flag expressions
     343   [ +  +  +  + ]:    4026100 :         else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_inbounds_sym) {
     344                 :       4700 :             is_flag_stmt = 1;
     345                 :       4700 :             jl_value_t *arg1 = expr_arg1(st);
     346         [ +  + ]:       4700 :             if (arg1 == (jl_value_t*)jl_true)       // push
     347                 :       2350 :                 inbounds_depth += 1;
     348         [ -  + ]:       2350 :             else if (arg1 == (jl_value_t*)jl_false) // clear
     349                 :          0 :                 inbounds_depth = 0;
     350         [ +  - ]:       2350 :             else if (inbounds_depth > 0)            // pop
     351                 :       2350 :                 inbounds_depth -= 1;
     352                 :       4700 :             bd[j] = jl_nothing;
     353                 :            :         }
     354   [ +  +  +  + ]:    4021400 :         else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_inline_sym) {
     355                 :         50 :             is_flag_stmt = 1;
     356                 :         50 :             jl_value_t *arg1 = expr_arg1(st);
     357         [ +  + ]:         50 :             if (arg1 == (jl_value_t*)jl_true) // enter inline region
     358                 :         25 :                 arraylist_push(inline_flags, (void*)1);
     359                 :            :             else {                            // exit inline region
     360         [ -  + ]:         25 :                 assert(arg1 == (jl_value_t*)jl_false);
     361                 :         25 :                 arraylist_pop(inline_flags);
     362                 :            :             }
     363                 :         50 :             bd[j] = jl_nothing;
     364                 :            :         }
     365   [ +  +  +  + ]:    4021340 :         else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_noinline_sym) {
     366                 :         30 :             is_flag_stmt = 1;
     367                 :         30 :             jl_value_t *arg1 = expr_arg1(st);
     368         [ +  + ]:         30 :             if (arg1 == (jl_value_t*)jl_true) // enter noinline region
     369                 :         15 :                 arraylist_push(inline_flags, (void*)0);
     370                 :            :             else {                             // exit noinline region
     371         [ -  + ]:         15 :                 assert(arg1 == (jl_value_t*)jl_false);
     372                 :         15 :                 arraylist_pop(inline_flags);
     373                 :            :             }
     374                 :         30 :             bd[j] = jl_nothing;
     375                 :            :         }
     376   [ +  +  +  + ]:    4021320 :         else if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_return_sym) {
     377                 :     251789 :             jl_array_ptr_set(body, j, jl_new_struct(jl_returnnode_type, jl_exprarg(st, 0)));
     378                 :            :         }
     379                 :            : 
     380         [ +  + ]:    4037690 :         if (is_flag_stmt)
     381                 :       4780 :             jl_array_uint8_set(li->ssaflags, j, 0);
     382                 :            :         else {
     383                 :    4032910 :             uint8_t flag = 0;
     384         [ +  + ]:    4032910 :             if (inbounds_depth > 0)
     385                 :      58348 :                 flag |= 1 << 0;
     386         [ +  + ]:    4032910 :             if (inline_flags->len > 0) {
     387                 :         66 :                 void* inline_flag = inline_flags->items[inline_flags->len - 1];
     388         [ +  + ]:         66 :                 flag |= 1 << (inline_flag ? 1 : 2);
     389                 :            :             }
     390                 :    4032910 :             jl_array_uint8_set(li->ssaflags, j, flag);
     391                 :            :         }
     392                 :            :     }
     393         [ -  + ]:     232610 :     assert(inline_flags->len == 0); // malformed otherwise
     394                 :     232610 :     arraylist_free(inline_flags);
     395                 :     232610 :     free(inline_flags);
     396                 :     232610 :     jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ir, 1);
     397                 :     232610 :     jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0);
     398                 :     232608 :     size_t nslots = jl_array_len(vis);
     399                 :     232608 :     jl_value_t *ssavalue_types = jl_array_ptr_ref(vinfo, 2);
     400         [ -  + ]:     232609 :     assert(jl_is_long(ssavalue_types));
     401                 :     232609 :     size_t nssavalue = jl_unbox_long(ssavalue_types);
     402                 :     232610 :     li->slotnames = jl_alloc_array_1d(jl_array_symbol_type, nslots);
     403                 :     232622 :     jl_gc_wb(li, li->slotnames);
     404                 :     232622 :     li->slotflags = jl_alloc_array_1d(jl_array_uint8_type, nslots);
     405                 :     232622 :     jl_gc_wb(li, li->slotflags);
     406                 :     232622 :     li->ssavaluetypes = jl_box_long(nssavalue);
     407                 :     232622 :     jl_gc_wb(li, li->ssavaluetypes);
     408                 :            : 
     409                 :            :     // Flags that need to be copied to slotflags
     410                 :     232621 :     const uint8_t vinfo_mask = 8 | 16 | 32 | 64;
     411                 :            :     int i;
     412         [ +  + ]:     809148 :     for (i = 0; i < nslots; i++) {
     413                 :     576526 :         jl_value_t *vi = jl_array_ptr_ref(vis, i);
     414                 :     576526 :         jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(vi, 0);
     415         [ -  + ]:     576526 :         assert(jl_is_symbol(name));
     416                 :     576526 :         char *str = jl_symbol_name(name);
     417   [ +  +  +  + ]:     576526 :         if (i > 0 && name != jl_unused_sym) {
     418         [ +  + ]:     457596 :             if (str[0] == '#') {
     419                 :            :                 // convention for renamed variables: #...#original_name
     420                 :     283363 :                 char *nxt = strchr(str + 1, '#');
     421         [ +  + ]:     283363 :                 if (nxt)
     422                 :     142342 :                     name = jl_symbol(nxt+1);
     423         [ +  + ]:     141021 :                 else if (str[1] == 's')  // compiler-generated temporaries, #sXXX
     424                 :     135819 :                     name = jl_empty_sym;
     425                 :            :             }
     426                 :            :         }
     427                 :     576526 :         jl_array_ptr_set(li->slotnames, i, name);
     428                 :     576526 :         jl_array_uint8_set(li->slotflags, i, vinfo_mask & jl_unbox_long(jl_array_ptr_ref(vi, 2)));
     429                 :            :     }
     430                 :     232622 : }
     431                 :            : 
     432                 :    2335590 : JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void)
     433                 :            : {
     434                 :    2335590 :     jl_task_t *ct = jl_current_task;
     435                 :            :     jl_method_instance_t *li =
     436                 :    2335590 :         (jl_method_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_method_instance_t),
     437                 :            :                                            jl_method_instance_type);
     438                 :    2335590 :     li->def.value = NULL;
     439                 :    2335590 :     li->specTypes = NULL;
     440                 :    2335590 :     li->sparam_vals = jl_emptysvec;
     441                 :    2335590 :     li->uninferred = NULL;
     442                 :    2335590 :     li->backedges = NULL;
     443                 :    2335590 :     li->callbacks = NULL;
     444                 :    2335590 :     jl_atomic_store_relaxed(&li->cache, NULL);
     445                 :    2335590 :     li->inInference = 0;
     446                 :    2335590 :     li->precompiled = 0;
     447                 :    2335590 :     return li;
     448                 :            : }
     449                 :            : 
     450                 :   14552400 : JL_DLLEXPORT jl_code_info_t *jl_new_code_info_uninit(void)
     451                 :            : {
     452                 :   14552400 :     jl_task_t *ct = jl_current_task;
     453                 :            :     jl_code_info_t *src =
     454                 :   14552400 :         (jl_code_info_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_info_t),
     455                 :            :                                        jl_code_info_type);
     456                 :   14552400 :     src->code = NULL;
     457                 :   14552400 :     src->codelocs = NULL;
     458                 :   14552400 :     src->ssavaluetypes = NULL;
     459                 :   14552400 :     src->ssaflags = NULL;
     460                 :   14552400 :     src->method_for_inference_limit_heuristics = jl_nothing;
     461                 :   14552400 :     src->linetable = jl_nothing;
     462                 :   14552400 :     src->slotflags = NULL;
     463                 :   14552400 :     src->slotnames = NULL;
     464                 :   14552400 :     src->slottypes = jl_nothing;
     465                 :   14552400 :     src->parent = (jl_method_instance_t*)jl_nothing;
     466                 :   14552400 :     src->rettype = (jl_value_t*)jl_any_type;
     467                 :   14552400 :     src->min_world = 1;
     468                 :   14552400 :     src->max_world = ~(size_t)0;
     469                 :   14552400 :     src->inferred = 0;
     470                 :   14552400 :     src->inlineable = 0;
     471                 :   14552400 :     src->propagate_inbounds = 0;
     472                 :   14552400 :     src->pure = 0;
     473                 :   14552400 :     src->edges = jl_nothing;
     474                 :   14552400 :     src->constprop = 0;
     475                 :   14552400 :     src->purity.bits = 0;
     476                 :   14552400 :     return src;
     477                 :            : }
     478                 :            : 
     479                 :     232608 : jl_code_info_t *jl_new_code_info_from_ir(jl_expr_t *ir)
     480                 :            : {
     481                 :     232608 :     jl_code_info_t *src = NULL;
     482                 :     232608 :     JL_GC_PUSH1(&src);
     483                 :     232608 :     src = jl_new_code_info_uninit();
     484                 :     232609 :     jl_code_info_set_ir(src, ir);
     485                 :     232610 :     JL_GC_POP();
     486                 :     232610 :     return src;
     487                 :            : }
     488                 :            : 
     489                 :      76107 : void jl_add_function_name_to_lineinfo(jl_code_info_t *ci, jl_value_t *name)
     490                 :            : {
     491                 :      76107 :     jl_array_t *li = (jl_array_t*)ci->linetable;
     492                 :      76107 :     size_t i, n = jl_array_len(li);
     493                 :      76107 :     jl_value_t *rt = NULL, *lno = NULL, *inl = NULL;
     494                 :      76107 :     JL_GC_PUSH3(&rt, &lno, &inl);
     495         [ +  + ]:     315418 :     for (i = 0; i < n; i++) {
     496                 :     239311 :         jl_value_t *ln = jl_array_ptr_ref(li, i);
     497         [ -  + ]:     239311 :         assert(jl_typeis(ln, jl_lineinfonode_type));
     498                 :     239311 :         jl_value_t *mod = jl_fieldref_noalloc(ln, 0);
     499                 :     239311 :         jl_value_t *file = jl_fieldref_noalloc(ln, 2);
     500                 :     239311 :         lno = jl_fieldref(ln, 3);
     501                 :     239311 :         inl = jl_fieldref(ln, 4);
     502   [ +  -  +  + ]:     239311 :         jl_value_t *ln_name = (jl_is_int32(inl) && jl_unbox_int32(inl) == 0) ? name : jl_fieldref_noalloc(ln, 1);
     503                 :     239311 :         rt = jl_new_struct(jl_lineinfonode_type, mod, ln_name, file, lno, inl);
     504                 :     239311 :         jl_array_ptr_set(li, i, rt);
     505                 :            :     }
     506                 :      76107 :     JL_GC_POP();
     507                 :      76107 : }
     508                 :            : 
     509                 :            : // invoke (compiling if necessary) the jlcall function pointer for a method template
     510                 :       6317 : STATIC_INLINE jl_value_t *jl_call_staged(jl_method_t *def, jl_value_t *generator, jl_svec_t *sparam_vals,
     511                 :            :                                          jl_value_t **args, uint32_t nargs)
     512                 :            : {
     513                 :       6317 :     size_t n_sparams = jl_svec_len(sparam_vals);
     514                 :            :     jl_value_t **gargs;
     515                 :       6317 :     size_t totargs = 1 + n_sparams + nargs + def->isva;
     516                 :       6317 :     JL_GC_PUSHARGS(gargs, totargs);
     517                 :       6317 :     gargs[0] = generator;
     518                 :       6317 :     memcpy(&gargs[1], jl_svec_data(sparam_vals), n_sparams * sizeof(void*));
     519                 :       6317 :     memcpy(&gargs[1 + n_sparams], args, nargs * sizeof(void*));
     520         [ +  + ]:       6317 :     if (def->isva) {
     521                 :        725 :         gargs[totargs-1] = jl_f_tuple(NULL, &gargs[1 + n_sparams + def->nargs - 1], nargs - (def->nargs - 1));
     522                 :        725 :         gargs[1 + n_sparams + def->nargs - 1] = gargs[totargs - 1];
     523                 :            :     }
     524                 :       6317 :     jl_value_t *code = jl_apply(gargs, 1 + n_sparams + def->nargs);
     525                 :       6283 :     JL_GC_POP();
     526                 :       6283 :     return code;
     527                 :            : }
     528                 :            : 
     529                 :            : // Lower `ex` into Julia IR, and (if it expands into a CodeInfo) resolve global-variable
     530                 :            : // references in light of the provided type parameters.
     531                 :            : // Like `jl_expand`, if there is an error expanding the provided expression, the return value
     532                 :            : // will be an error expression (an `Expr` with `error_sym` as its head), which should be eval'd
     533                 :            : // in the caller's context.
     534                 :       6015 : JL_DLLEXPORT jl_code_info_t *jl_expand_and_resolve(jl_value_t *ex, jl_module_t *module,
     535                 :            :                                                    jl_svec_t *sparam_vals) {
     536                 :       6015 :     jl_code_info_t *func = (jl_code_info_t*)jl_expand((jl_value_t*)ex, module);
     537                 :       6014 :     JL_GC_PUSH1(&func);
     538         [ +  + ]:       6014 :     if (jl_is_code_info(func)) {
     539                 :       6008 :         jl_array_t *stmts = (jl_array_t*)func->code;
     540                 :       6008 :         jl_resolve_globals_in_ir(stmts, module, sparam_vals, 1);
     541                 :            :     }
     542                 :       6014 :     JL_GC_POP();
     543                 :       6014 :     return func;
     544                 :            : }
     545                 :            : 
     546                 :            : // Return a newly allocated CodeInfo for the function signature
     547                 :            : // effectively described by the tuple (specTypes, env, Method) inside linfo
     548                 :       6317 : JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo)
     549                 :            : {
     550         [ -  + ]:       6317 :     if (linfo->uninferred) {
     551                 :          0 :         return (jl_code_info_t*)jl_copy_ast((jl_value_t*)linfo->uninferred);
     552                 :            :     }
     553                 :            : 
     554                 :            :     JL_TIMING(STAGED_FUNCTION);
     555                 :       6317 :     jl_value_t *tt = linfo->specTypes;
     556                 :       6317 :     jl_method_t *def = linfo->def.method;
     557                 :       6317 :     jl_value_t *generator = def->generator;
     558         [ -  + ]:       6317 :     assert(generator != NULL);
     559         [ -  + ]:       6317 :     assert(jl_is_method(def));
     560                 :       6317 :     jl_code_info_t *func = NULL;
     561                 :       6317 :     jl_value_t *ex = NULL;
     562                 :       6317 :     JL_GC_PUSH2(&ex, &func);
     563                 :       6317 :     jl_task_t *ct = jl_current_task;
     564                 :       6317 :     int last_lineno = jl_lineno;
     565                 :       6317 :     int last_in = ct->ptls->in_pure_callback;
     566                 :       6317 :     size_t last_age = ct->world_age;
     567                 :            : 
     568   [ +  +  +  + ]:      12593 :     JL_TRY {
     569                 :       6317 :         ct->ptls->in_pure_callback = 1;
     570                 :            :         // and the right world
     571                 :       6317 :         ct->world_age = def->primary_world;
     572                 :            : 
     573                 :            :         // invoke code generator
     574                 :       6317 :         jl_tupletype_t *ttdt = (jl_tupletype_t*)jl_unwrap_unionall(tt);
     575                 :       6317 :         ex = jl_call_staged(def, generator, linfo->sparam_vals, jl_svec_data(ttdt->parameters), jl_nparams(ttdt));
     576                 :            : 
     577         [ +  + ]:       6283 :         if (jl_is_code_info(ex)) {
     578                 :        268 :             func = (jl_code_info_t*)ex;
     579                 :        268 :             jl_array_t *stmts = (jl_array_t*)func->code;
     580                 :        268 :             jl_resolve_globals_in_ir(stmts, def->module, linfo->sparam_vals, 1);
     581                 :            :         }
     582                 :            :         else {
     583                 :            :             // Lower the user's expression and resolve references to the type parameters
     584                 :       6015 :             func = jl_expand_and_resolve(ex, def->module, linfo->sparam_vals);
     585                 :            : 
     586         [ +  + ]:       6014 :             if (!jl_is_code_info(func)) {
     587   [ +  -  +  + ]:          6 :                 if (jl_is_expr(func) && ((jl_expr_t*)func)->head == jl_error_sym) {
     588                 :          2 :                     ct->ptls->in_pure_callback = 0;
     589                 :          2 :                     jl_toplevel_eval(def->module, (jl_value_t*)func);
     590                 :            :                 }
     591                 :          4 :                 jl_error("The function body AST defined by this @generated function is not pure. This likely means it contains a closure, a comprehension or a generator.");
     592                 :            :             }
     593                 :            :         }
     594                 :            : 
     595                 :            :         // If this generated function has an opaque closure, cache it for
     596                 :            :         // correctness of method identity
     597         [ +  + ]:     153577 :         for (int i = 0; i < jl_array_len(func->code); ++i) {
     598                 :     147302 :             jl_value_t *stmt = jl_array_ptr_ref(func->code, i);
     599   [ +  +  +  + ]:     147302 :             if (jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == jl_new_opaque_closure_sym) {
     600                 :          1 :                 linfo->uninferred = jl_copy_ast((jl_value_t*)func);
     601                 :          1 :                 jl_gc_wb(linfo, linfo->uninferred);
     602                 :          1 :                 break;
     603                 :            :             }
     604                 :            :         }
     605                 :            : 
     606                 :       6276 :         ct->ptls->in_pure_callback = last_in;
     607                 :       6276 :         jl_lineno = last_lineno;
     608                 :       6276 :         ct->world_age = last_age;
     609                 :       6276 :         jl_add_function_name_to_lineinfo(func, (jl_value_t*)def->name);
     610                 :            :     }
     611         [ +  - ]:         41 :     JL_CATCH {
     612                 :         41 :         ct->ptls->in_pure_callback = last_in;
     613                 :         41 :         jl_lineno = last_lineno;
     614                 :         41 :         jl_rethrow();
     615                 :            :     }
     616                 :       6276 :     JL_GC_POP();
     617                 :       6276 :     return func;
     618                 :            : }
     619                 :            : 
     620                 :    5281070 : JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src)
     621                 :            : {
     622                 :    5281070 :     jl_task_t *ct = jl_current_task;
     623                 :            :     jl_code_info_t *newsrc =
     624                 :    5281070 :         (jl_code_info_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_info_t),
     625                 :            :                                        jl_code_info_type);
     626                 :    5281070 :     *newsrc = *src;
     627                 :    5281070 :     return newsrc;
     628                 :            : }
     629                 :            : 
     630                 :            : // return a new lambda-info that has some extra static parameters merged in
     631                 :    2334450 : jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp)
     632                 :            : {
     633   [ +  +  -  + ]:    2334450 :     assert((size_t)jl_subtype_env_size(m->sig) == jl_svec_len(sp) || sp == jl_emptysvec);
     634                 :    2334450 :     jl_method_instance_t *new_linfo = jl_new_method_instance_uninit();
     635                 :    2334450 :     new_linfo->def.method = m;
     636                 :    2334450 :     new_linfo->specTypes = types;
     637                 :    2334450 :     new_linfo->sparam_vals = sp;
     638                 :    2334450 :     return new_linfo;
     639                 :            : }
     640                 :            : 
     641                 :      69831 : static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src)
     642                 :            : {
     643                 :            :     uint8_t j;
     644                 :      69831 :     uint8_t called = 0;
     645                 :      69831 :     int gen_only = 0;
     646   [ +  +  +  + ]:     174322 :     for (j = 1; j < m->nargs && j <= sizeof(m->nospecialize) * 8; j++) {
     647                 :     104491 :         jl_value_t *ai = jl_array_ptr_ref(src->slotnames, j);
     648         [ +  + ]:     104491 :         if (ai == (jl_value_t*)jl_unused_sym) {
     649                 :            :             // TODO: enable this. currently it triggers a bug on arguments like
     650                 :            :             // ::Type{>:Missing}
     651                 :            :             //int sn = j-1;
     652                 :            :             //m->nospecialize |= (1 << sn);
     653                 :       7113 :             continue;
     654                 :            :         }
     655         [ +  + ]:      97378 :         if (j <= 8) {
     656         [ +  + ]:      96328 :             if (jl_array_uint8_ref(src->slotflags, j) & 64)
     657                 :        657 :                 called |= (1 << (j - 1));
     658                 :            :         }
     659                 :            :     }
     660                 :      69831 :     m->called = called;
     661                 :      69831 :     m->pure = src->pure;
     662                 :      69831 :     m->constprop = src->constprop;
     663                 :      69831 :     m->purity.bits = src->purity.bits;
     664                 :      69831 :     jl_add_function_name_to_lineinfo(src, (jl_value_t*)m->name);
     665                 :            : 
     666                 :      69831 :     jl_array_t *copy = NULL;
     667                 :      69831 :     jl_svec_t *sparam_vars = jl_outer_unionall_vars(m->sig);
     668                 :      69831 :     JL_GC_PUSH3(&copy, &sparam_vars, &src);
     669         [ -  + ]:      69831 :     assert(jl_typeis(src->code, jl_array_any_type));
     670                 :      69831 :     jl_array_t *stmts = (jl_array_t*)src->code;
     671                 :      69831 :     size_t i, n = jl_array_len(stmts);
     672                 :      69831 :     copy = jl_alloc_vec_any(n);
     673         [ +  + ]:     937743 :     for (i = 0; i < n; i++) {
     674                 :     867912 :         jl_value_t *st = jl_array_ptr_ref(stmts, i);
     675   [ +  +  +  + ]:     873156 :         if (jl_is_expr(st) && ((jl_expr_t*)st)->head == jl_meta_sym) {
     676                 :       5244 :             size_t nargs = jl_expr_nargs(st);
     677   [ +  -  +  + ]:       5244 :             if (nargs >= 1 && jl_exprarg(st, 0) == (jl_value_t*)jl_nospecialize_sym) {
     678         [ +  + ]:       2161 :                 if (nargs == 1) // bare `@nospecialize` is special: it prevents specialization on all args
     679                 :         64 :                     m->nospecialize = -1;
     680                 :            :                 size_t j;
     681         [ +  + ]:       4493 :                 for (j = 1; j < nargs; j++) {
     682                 :       2332 :                     jl_value_t *aj = jl_exprarg(st, j);
     683   [ +  +  +  -  :       2332 :                     if (!jl_is_slot(aj) && !jl_is_argument(aj))
                   +  - ]
     684                 :         73 :                         continue;
     685                 :       2259 :                     int sn = (int)jl_slot_number(aj) - 2;
     686         [ -  + ]:       2259 :                     if (sn < 0) // @nospecialize on self is valid but currently ignored
     687                 :          0 :                         continue;
     688         [ -  + ]:       2259 :                     if (sn > (m->nargs - 2)) {
     689                 :          0 :                         jl_error("@nospecialize annotation applied to a non-argument");
     690                 :            :                     }
     691         [ -  + ]:       2259 :                     if (sn >= sizeof(m->nospecialize) * 8) {
     692                 :          0 :                         jl_printf(JL_STDERR,
     693                 :            :                                   "WARNING: @nospecialize annotation only supported on the first %d arguments.\n",
     694                 :            :                                   (int)(sizeof(m->nospecialize) * 8));
     695                 :          0 :                         continue;
     696                 :            :                     }
     697                 :       2259 :                     m->nospecialize |= (1 << sn);
     698                 :            :                 }
     699                 :       2161 :                 st = jl_nothing;
     700                 :            :             }
     701   [ +  -  +  + ]:       3083 :             else if (nargs >= 1 && jl_exprarg(st, 0) == (jl_value_t*)jl_specialize_sym) {
     702         [ -  + ]:          3 :                 if (nargs == 1) // bare `@specialize` is special: it causes specialization on all args
     703                 :          0 :                     m->nospecialize = 0;
     704                 :          3 :                 st = jl_nothing;
     705                 :            :             }
     706   [ +  +  +  + ]:       3080 :             else if (nargs == 2 && jl_exprarg(st, 0) == (jl_value_t*)jl_generated_sym) {
     707                 :         88 :                 m->generator = NULL;
     708                 :         88 :                 jl_value_t *gexpr = jl_exprarg(st, 1);
     709         [ +  - ]:         88 :                 if (jl_expr_nargs(gexpr) == 7) {
     710                 :            :                     // expects (new (core GeneratedFunctionStub) funcname argnames sp line file expandearly)
     711                 :         88 :                     jl_value_t *funcname = jl_exprarg(gexpr, 1);
     712         [ -  + ]:         88 :                     assert(jl_is_symbol(funcname));
     713         [ +  - ]:         88 :                     if (jl_get_global(m->module, (jl_sym_t*)funcname) != NULL) {
     714                 :         88 :                         m->generator = jl_toplevel_eval(m->module, gexpr);
     715                 :         88 :                         jl_gc_wb(m, m->generator);
     716                 :            :                     }
     717                 :            :                 }
     718         [ -  + ]:         88 :                 if (m->generator == NULL) {
     719                 :          0 :                     jl_error("invalid @generated function; try placing it in global scope");
     720                 :            :                 }
     721                 :         88 :                 st = jl_nothing;
     722                 :            :             }
     723   [ +  +  +  + ]:       2992 :             else if (nargs == 1 && jl_exprarg(st, 0) == (jl_value_t*)jl_generated_only_sym) {
     724                 :         74 :                 gen_only = 1;
     725                 :         74 :                 st = jl_nothing;
     726                 :            :             }
     727   [ +  +  +  - ]:       2918 :             else if (nargs == 2 && jl_exprarg(st, 0) == (jl_value_t*)jl_symbol("nkw")) {
     728                 :       2285 :                 m->nkw = jl_unbox_long(jl_exprarg(st, 1));
     729                 :       2285 :                 st = jl_nothing;
     730                 :            :             }
     731                 :            :         }
     732                 :            :         else {
     733                 :     862668 :             st = resolve_globals(st, m->module, sparam_vars, 1, 0);
     734                 :            :         }
     735                 :     867912 :         jl_array_ptr_set(copy, i, st);
     736                 :            :     }
     737                 :      69831 :     src = jl_copy_code_info(src);
     738                 :      69831 :     src->code = copy;
     739                 :      69831 :     jl_gc_wb(src, copy);
     740                 :      69831 :     m->slot_syms = jl_compress_argnames(src->slotnames);
     741                 :      69831 :     jl_gc_wb(m, m->slot_syms);
     742         [ +  + ]:      69831 :     if (gen_only)
     743                 :         74 :         m->source = NULL;
     744                 :            :     else
     745                 :      69757 :         m->source = (jl_value_t*)jl_compress_ir(m, src);
     746                 :      69831 :     jl_gc_wb(m, m->source);
     747                 :      69831 :     JL_GC_POP();
     748                 :      69831 : }
     749                 :            : 
     750                 :      70251 : JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module)
     751                 :            : {
     752                 :      70251 :     jl_task_t *ct = jl_current_task;
     753                 :            :     jl_method_t *m =
     754                 :      70251 :         (jl_method_t*)jl_gc_alloc(ct->ptls, sizeof(jl_method_t), jl_method_type);
     755                 :      70251 :     jl_atomic_store_relaxed(&m->specializations, jl_emptysvec);
     756                 :      70251 :     jl_atomic_store_relaxed(&m->speckeyset, (jl_array_t*)jl_an_empty_vec_any);
     757                 :      70251 :     m->sig = NULL;
     758                 :      70251 :     m->slot_syms = NULL;
     759                 :      70251 :     m->roots = NULL;
     760                 :      70251 :     m->root_blocks = NULL;
     761                 :      70251 :     m->nroots_sysimg = 0;
     762                 :      70251 :     m->ccallable = NULL;
     763                 :      70251 :     m->module = module;
     764                 :      70251 :     m->external_mt = NULL;
     765                 :      70251 :     m->source = NULL;
     766                 :      70251 :     jl_atomic_store_relaxed(&m->unspecialized, NULL);
     767                 :      70251 :     m->generator = NULL;
     768                 :      70251 :     m->name = NULL;
     769                 :      70251 :     m->file = jl_empty_sym;
     770                 :      70251 :     m->line = 0;
     771                 :      70251 :     m->called = 0xff;
     772                 :      70251 :     m->nospecialize = module->nospecialize;
     773                 :      70251 :     m->nkw = 0;
     774                 :      70251 :     jl_atomic_store_relaxed(&m->invokes, jl_nothing);
     775                 :      70251 :     m->recursion_relation = NULL;
     776                 :      70251 :     m->isva = 0;
     777                 :      70251 :     m->nargs = 0;
     778                 :      70251 :     m->primary_world = 1;
     779                 :      70251 :     m->deleted_world = ~(size_t)0;
     780                 :      70251 :     m->is_for_opaque_closure = 0;
     781                 :      70251 :     m->constprop = 0;
     782                 :      70251 :     JL_MUTEX_INIT(&m->writelock);
     783                 :      70251 :     return m;
     784                 :            : }
     785                 :            : 
     786                 :            : // method definition ----------------------------------------------------------
     787                 :            : 
     788                 :         52 : jl_method_t *jl_make_opaque_closure_method(jl_module_t *module, jl_value_t *name,
     789                 :            :     int nargs, jl_value_t *functionloc, jl_code_info_t *ci, int isva)
     790                 :            : {
     791                 :         52 :     jl_method_t *m = jl_new_method_uninit(module);
     792                 :         52 :     JL_GC_PUSH1(&m);
     793                 :            :     // TODO: Maybe have a signature of (parent method, stmt#)?
     794                 :         52 :     m->sig = (jl_value_t*)jl_anytuple_type;
     795                 :         52 :     m->isva = isva;
     796                 :         52 :     m->is_for_opaque_closure = 1;
     797         [ +  - ]:         52 :     if (name == jl_nothing) {
     798                 :         52 :         m->name = jl_symbol("opaque closure");
     799                 :            :     } else {
     800         [ #  # ]:          0 :         assert(jl_is_symbol(name));
     801                 :          0 :         m->name = (jl_sym_t*)name;
     802                 :            :     }
     803                 :         52 :     m->nargs = nargs + 1;
     804         [ -  + ]:         52 :     assert(jl_is_linenode(functionloc));
     805                 :         52 :     jl_value_t *file = jl_linenode_file(functionloc);
     806         [ +  + ]:         52 :     m->file = jl_is_symbol(file) ? (jl_sym_t*)file : jl_empty_sym;
     807                 :         52 :     m->line = jl_linenode_line(functionloc);
     808                 :         52 :     jl_method_set_source(m, ci);
     809                 :         52 :     JL_GC_POP();
     810                 :         52 :     return m;
     811                 :            : }
     812                 :            : 
     813                 :            : // empty generic function def
     814                 :      71473 : JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name,
     815                 :            :                                                  jl_module_t *module,
     816                 :            :                                                  _Atomic(jl_value_t*) *bp,
     817                 :            :                                                  jl_value_t *bp_owner,
     818                 :            :                                                  jl_binding_t *bnd)
     819                 :            : {
     820                 :      71473 :     jl_value_t *gf = NULL;
     821                 :            : 
     822   [ +  -  +  - ]:      71473 :     assert(name && bp);
     823   [ +  -  +  +  :      71473 :     if (bnd && jl_atomic_load_relaxed(&bnd->value) != NULL && !bnd->constp)
                   -  + ]
     824                 :          0 :         jl_errorf("cannot define function %s; it already has a value", jl_symbol_name(bnd->name));
     825                 :      71473 :     gf = jl_atomic_load_relaxed(bp);
     826         [ +  + ]:      71473 :     if (gf != NULL) {
     827   [ +  +  -  + ]:      56450 :         if (!jl_is_datatype_singleton((jl_datatype_t*)jl_typeof(gf)) && !jl_is_type(gf))
     828                 :          0 :             jl_errorf("cannot define function %s; it already has a value", jl_symbol_name(name));
     829                 :            :     }
     830         [ +  - ]:      71473 :     if (bnd)
     831                 :      71473 :         bnd->constp = 1;
     832         [ +  + ]:      71473 :     if (gf == NULL) {
     833                 :      15023 :         gf = (jl_value_t*)jl_new_generic_function(name, module);
     834                 :      15023 :         jl_atomic_store(bp, gf); // TODO: fix constp assignment data race
     835         [ +  - ]:      15023 :         if (bp_owner) jl_gc_wb(bp_owner, gf);
     836                 :            :     }
     837                 :      71473 :     return gf;
     838                 :            : }
     839                 :            : 
     840                 :  139591000 : static jl_methtable_t *first_methtable(jl_value_t *a JL_PROPAGATES_ROOT, int got_tuple1) JL_NOTSAFEPOINT
     841                 :            : {
     842         [ +  + ]:  139591000 :     if (jl_is_datatype(a)) {
     843         [ +  + ]:  139007000 :         if (got_tuple1) {
     844                 :   69602200 :             jl_methtable_t *mt = ((jl_datatype_t*)a)->name->mt;
     845         [ +  + ]:   69602200 :             if (mt != NULL)
     846                 :   69601900 :                 return mt;
     847                 :            :         }
     848         [ +  + ]:   69404700 :         if (jl_is_tuple_type(a)) {
     849         [ +  - ]:   69404300 :             if (jl_nparams(a) >= 1)
     850                 :   69404300 :                 return first_methtable(jl_tparam0(a), 1);
     851                 :            :         }
     852                 :            :     }
     853         [ -  + ]:     584028 :     else if (jl_is_typevar(a)) {
     854                 :          0 :         return first_methtable(((jl_tvar_t*)a)->ub, got_tuple1);
     855                 :            :     }
     856         [ +  + ]:     584028 :     else if (jl_is_unionall(a)) {
     857                 :     584002 :         return first_methtable(((jl_unionall_t*)a)->body, got_tuple1);
     858                 :            :     }
     859         [ +  + ]:         26 :     else if (jl_is_uniontype(a)) {
     860                 :         25 :         jl_uniontype_t *u = (jl_uniontype_t*)a;
     861                 :         25 :         jl_methtable_t *m1 = first_methtable(u->a, got_tuple1);
     862         [ +  + ]:         25 :         if ((jl_value_t*)m1 != jl_nothing) {
     863                 :         24 :             jl_methtable_t *m2 = first_methtable(u->b, got_tuple1);
     864         [ +  + ]:         24 :             if (m1 == m2)
     865                 :         11 :                 return m1;
     866                 :            :         }
     867                 :            :     }
     868                 :        390 :     return (jl_methtable_t*)jl_nothing;
     869                 :            : }
     870                 :            : 
     871                 :            : // get the MethodTable for dispatch, or `nothing` if cannot be determined
     872                 :   69404300 : JL_DLLEXPORT jl_methtable_t *jl_method_table_for(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
     873                 :            : {
     874                 :   69404300 :     return first_methtable(argtypes, 0);
     875                 :            : }
     876                 :            : 
     877                 :      25918 : JL_DLLEXPORT jl_methtable_t *jl_method_get_table(jl_method_t *method JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
     878                 :            : {
     879         [ +  + ]:      25918 :     return method->external_mt ? (jl_methtable_t*)method->external_mt : jl_method_table_for(method->sig);
     880                 :            : }
     881                 :            : 
     882                 :            : // get the MethodTable implied by a single given type, or `nothing`
     883                 :     197927 : JL_DLLEXPORT jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
     884                 :            : {
     885                 :     197927 :     return first_methtable(argt, 1);
     886                 :            : }
     887                 :            : 
     888                 :            : jl_array_t *jl_all_methods JL_GLOBALLY_ROOTED;
     889                 :            : 
     890                 :      69789 : JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata,
     891                 :            :                                         jl_methtable_t *mt,
     892                 :            :                                         jl_code_info_t *f,
     893                 :            :                                         jl_module_t *module)
     894                 :            : {
     895                 :            :     // argdata is svec(svec(types...), svec(typevars...), functionloc)
     896                 :      69789 :     jl_svec_t *atypes = (jl_svec_t*)jl_svecref(argdata, 0);
     897                 :      69789 :     jl_svec_t *tvars = (jl_svec_t*)jl_svecref(argdata, 1);
     898                 :      69789 :     jl_value_t *functionloc = jl_svecref(argdata, 2);
     899                 :      69789 :     size_t nargs = jl_svec_len(atypes);
     900                 :      69789 :     int isva = jl_is_vararg(jl_svecref(atypes, nargs - 1));
     901         [ -  + ]:      69789 :     assert(jl_is_svec(atypes));
     902         [ -  + ]:      69789 :     assert(nargs > 0);
     903         [ -  + ]:      69789 :     assert(jl_is_svec(tvars));
     904   [ +  -  +  +  :      69789 :     if (!jl_is_type(jl_svecref(atypes, 0)) || (isva && nargs == 1))
                   -  + ]
     905                 :          0 :         jl_error("function type in method definition is not a type");
     906                 :            :     jl_sym_t *name;
     907                 :      69789 :     jl_method_t *m = NULL;
     908                 :      69789 :     jl_value_t *argtype = NULL;
     909                 :      69789 :     JL_GC_PUSH3(&f, &m, &argtype);
     910                 :      69789 :     size_t i, na = jl_svec_len(atypes);
     911                 :            : 
     912                 :      69789 :     argtype = (jl_value_t*)jl_apply_tuple_type(atypes);
     913         [ +  + ]:      79857 :     for (i = jl_svec_len(tvars); i > 0; i--) {
     914                 :      10068 :         jl_value_t *tv = jl_svecref(tvars, i - 1);
     915         [ -  + ]:      10068 :         if (!jl_is_typevar(tv))
     916                 :          0 :             jl_type_error("method signature", (jl_value_t*)jl_tvar_type, tv);
     917                 :      10068 :         argtype = jl_new_struct(jl_unionall_type, tv, argtype);
     918                 :            :     }
     919                 :            : 
     920                 :      69789 :     jl_methtable_t *external_mt = mt;
     921         [ +  + ]:      69789 :     if (!mt)
     922                 :      69782 :         mt = jl_method_table_for(argtype);
     923         [ +  + ]:      69789 :     if ((jl_value_t*)mt == jl_nothing)
     924                 :          7 :         jl_error("Method dispatch is unimplemented currently for this method signature");
     925         [ +  + ]:      69782 :     if (mt->frozen)
     926                 :          3 :         jl_error("cannot add methods to a builtin function");
     927                 :            : 
     928                 :            :     // TODO: derive our debug name from the syntax instead of the type
     929                 :      69779 :     name = mt->name;
     930   [ +  +  +  +  :      69779 :     if (mt == jl_type_type_mt || mt == jl_nonfunction_mt || external_mt) {
                   +  + ]
     931                 :            :         // our value for `name` is bad, try to guess what the syntax might have had,
     932                 :            :         // like `jl_static_show_func_sig` might have come up with
     933                 :       6087 :         jl_datatype_t *dt = jl_first_argument_datatype(argtype);
     934         [ +  + ]:       6087 :         if (dt != NULL) {
     935                 :       6086 :             name = dt->name->name;
     936         [ +  + ]:       6086 :             if (jl_is_type_type((jl_value_t*)dt)) {
     937                 :       5945 :                 dt = (jl_datatype_t*)jl_argument_datatype(jl_tparam0(dt));
     938         [ +  + ]:       5945 :                 if ((jl_value_t*)dt != jl_nothing) {
     939                 :       5935 :                     name = dt->name->name;
     940                 :            :                 }
     941                 :            :             }
     942                 :            :         }
     943                 :            :     }
     944         [ +  + ]:      69779 :     if (!jl_is_code_info(f)) {
     945                 :            :         // this occurs when there is a closure being added to an out-of-scope function
     946                 :            :         // the user should only do this at the toplevel
     947                 :            :         // the result is that the closure variables get interpolated directly into the IR
     948                 :        236 :         f = jl_new_code_info_from_ir((jl_expr_t*)f);
     949                 :            :     }
     950                 :      69779 :     m = jl_new_method_uninit(module);
     951                 :      69779 :     m->external_mt = (jl_value_t*)external_mt;
     952         [ +  + ]:      69779 :     if (external_mt)
     953                 :          7 :         jl_gc_wb(m, external_mt);
     954                 :      69779 :     m->sig = argtype;
     955                 :      69779 :     m->name = name;
     956                 :      69779 :     m->isva = isva;
     957                 :      69779 :     m->nargs = nargs;
     958         [ -  + ]:      69779 :     assert(jl_is_linenode(functionloc));
     959                 :      69779 :     jl_value_t *file = jl_linenode_file(functionloc);
     960         [ +  - ]:      69779 :     m->file = jl_is_symbol(file) ? (jl_sym_t*)file : jl_empty_sym;
     961                 :      69779 :     m->line = jl_linenode_line(functionloc);
     962                 :      69779 :     jl_method_set_source(m, f);
     963                 :            : 
     964         [ -  + ]:      69779 :     if (jl_has_free_typevars(argtype)) {
     965                 :          0 :         jl_exceptionf(jl_argumenterror_type,
     966                 :            :                       "method definition for %s at %s:%d has free type variables",
     967                 :            :                       jl_symbol_name(name),
     968                 :          0 :                       jl_symbol_name(m->file),
     969                 :          0 :                       m->line);
     970                 :            :     }
     971                 :            : 
     972         [ +  + ]:     245119 :     for (i = 0; i < na; i++) {
     973                 :     175343 :         jl_value_t *elt = jl_svecref(atypes, i);
     974   [ +  +  +  +  :     175343 :         if (!jl_is_type(elt) && !jl_is_typevar(elt) && !jl_is_vararg(elt)) {
                   +  + ]
     975                 :          2 :             jl_sym_t *argname = (jl_sym_t*)jl_array_ptr_ref(f->slotnames, i);
     976         [ +  + ]:          2 :             if (argname == jl_unused_sym)
     977                 :          1 :                 jl_exceptionf(jl_argumenterror_type,
     978                 :            :                               "invalid type for argument number %d in method definition for %s at %s:%d",
     979                 :            :                               i,
     980                 :            :                               jl_symbol_name(name),
     981                 :          1 :                               jl_symbol_name(m->file),
     982                 :          1 :                               m->line);
     983                 :            :             else
     984                 :          1 :                 jl_exceptionf(jl_argumenterror_type,
     985                 :            :                               "invalid type for argument %s in method definition for %s at %s:%d",
     986                 :            :                               jl_symbol_name(argname),
     987                 :            :                               jl_symbol_name(name),
     988                 :          1 :                               jl_symbol_name(m->file),
     989                 :          1 :                               m->line);
     990                 :            :         }
     991   [ +  +  +  + ]:     175341 :         if (jl_is_vararg(elt) && i < na-1)
     992                 :          1 :             jl_exceptionf(jl_argumenterror_type,
     993                 :            :                           "Vararg on non-final argument in method definition for %s at %s:%d",
     994                 :            :                           jl_symbol_name(name),
     995                 :          1 :                           jl_symbol_name(m->file),
     996                 :          1 :                           m->line);
     997                 :            :     }
     998                 :            : 
     999                 :            : #ifdef RECORD_METHOD_ORDER
    1000                 :            :     if (jl_all_methods == NULL)
    1001                 :            :         jl_all_methods = jl_alloc_vec_any(0);
    1002                 :            : #endif
    1003         [ -  + ]:      69776 :     if (jl_all_methods != NULL) {
    1004         [ #  # ]:          0 :         while (jl_array_len(jl_all_methods) < m->primary_world)
    1005                 :          0 :             jl_array_ptr_1d_push(jl_all_methods, NULL);
    1006                 :          0 :         jl_array_ptr_1d_push(jl_all_methods, (jl_value_t*)m);
    1007                 :            :     }
    1008                 :            : 
    1009                 :      69776 :     jl_method_table_insert(mt, m, NULL);
    1010         [ +  + ]:      69776 :     if (jl_newmeth_tracer)
    1011                 :          2 :         jl_call_tracer(jl_newmeth_tracer, (jl_value_t*)m);
    1012                 :      69776 :     JL_GC_POP();
    1013                 :            : 
    1014                 :      69776 :     return m;
    1015                 :            : }
    1016                 :            : 
    1017                 :            : // root blocks
    1018                 :            : 
    1019                 :            : // This section handles method roots. Roots are GC-preserved items needed to
    1020                 :            : // represent lowered, type-inferred, and/or compiled code. These items are
    1021                 :            : // stored in a flat list (`m.roots`), and during serialization and
    1022                 :            : // deserialization of code we replace C-pointers to these items with a
    1023                 :            : // relocatable reference. We use a bipartite reference, `(key, index)` pair,
    1024                 :            : // where `key` identifies the module that added the root and `index` numbers
    1025                 :            : // just those roots with the same `key`.
    1026                 :            : //
    1027                 :            : // During precompilation (serialization), we save roots that were added to
    1028                 :            : // methods that are tagged with this package's module-key, even for "external"
    1029                 :            : // methods not owned by a module currently being precompiled. During
    1030                 :            : // deserialization, we load the new roots and append them to the method. When
    1031                 :            : // code is deserialized (see ircode.c), we replace the bipartite reference with
    1032                 :            : // the pointer to the memory address in the current session. The bipartite
    1033                 :            : // reference allows us to cache both roots and references in precompilation .ji
    1034                 :            : // files using a naming scheme that is independent of which packages are loaded
    1035                 :            : // in arbitrary order.
    1036                 :            : //
    1037                 :            : // To track the module-of-origin for each root, methods also have a
    1038                 :            : // `root_blocks` field that uses run-length encoding (RLE) storing `key` and the
    1039                 :            : // (absolute) integer index within `roots` at which a block of roots with that
    1040                 :            : // key begins. This makes it possible to look up an individual `(key, index)`
    1041                 :            : // pair fairly efficiently. A given `key` may possess more than one block; the
    1042                 :            : // `index` continues to increment regardless of block boundaries.
    1043                 :            : //
    1044                 :            : // Roots with `key = 0` are considered to be of unknown origin, and
    1045                 :            : // CodeInstances referencing such roots will remain unserializable unless all
    1046                 :            : // such roots were added at the time of system image creation. To track this
    1047                 :            : // additional data, we use two fields:
    1048                 :            : //
    1049                 :            : // - methods have an `nroots_sysimg` field to count the number of roots defined
    1050                 :            : //   at the time of writing the system image (such occur first in the list of
    1051                 :            : //   roots). These are the cases with `key = 0` that do not prevent
    1052                 :            : //   serialization.
    1053                 :            : // - CodeInstances have a `relocatability` field which when 1 indicates that
    1054                 :            : //   every root is "safe," meaning it was either added at sysimg creation or is
    1055                 :            : //   tagged with a non-zero `key`. Even a single unsafe root will cause this to
    1056                 :            : //   have value 0.
    1057                 :            : 
    1058                 :            : // Get the key of the current (final) block of roots
    1059                 :    3755140 : static uint64_t current_root_id(jl_array_t *root_blocks)
    1060                 :            : {
    1061         [ +  + ]:    3755140 :     if (!root_blocks)
    1062                 :    3635140 :         return 0;
    1063         [ -  + ]:     119999 :     assert(jl_is_array(root_blocks));
    1064                 :     119999 :     size_t nx2 = jl_array_len(root_blocks);
    1065         [ +  + ]:     119999 :     if (nx2 == 0)
    1066                 :       3130 :         return 0;
    1067                 :     116869 :     uint64_t *blocks = (uint64_t*)jl_array_data(root_blocks);
    1068                 :     116869 :     return blocks[nx2-2];
    1069                 :            : }
    1070                 :            : 
    1071                 :            : // Add a new block of `len` roots with key `modid` (module id)
    1072                 :       6677 : static void add_root_block(jl_array_t *root_blocks, uint64_t modid, size_t len)
    1073                 :            : {
    1074         [ -  + ]:       6677 :     assert(jl_is_array(root_blocks));
    1075                 :       6677 :     jl_array_grow_end(root_blocks, 2);
    1076                 :       6677 :     uint64_t *blocks = (uint64_t*)jl_array_data(root_blocks);
    1077                 :       6677 :     int nx2 = jl_array_len(root_blocks);
    1078                 :       6677 :     blocks[nx2-2] = modid;
    1079                 :       6677 :     blocks[nx2-1] = len;
    1080                 :       6677 : }
    1081                 :            : 
    1082                 :            : // Allocate storage for roots
    1083                 :    3755350 : static void prepare_method_for_roots(jl_method_t *m, uint64_t modid)
    1084                 :            : {
    1085         [ +  + ]:    3755350 :     if (!m->roots) {
    1086                 :          1 :         m->roots = jl_alloc_vec_any(0);
    1087                 :          1 :         jl_gc_wb(m, m->roots);
    1088                 :            :     }
    1089   [ +  +  +  + ]:    3755350 :     if (!m->root_blocks && modid != 0) {
    1090                 :       3330 :         m->root_blocks = jl_alloc_array_1d(jl_array_uint64_type, 0);
    1091                 :       3330 :         jl_gc_wb(m, m->root_blocks);
    1092                 :            :     }
    1093                 :    3755350 : }
    1094                 :            : 
    1095                 :            : // Add a single root with owner `mod` to a method
    1096                 :    3755140 : JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root)
    1097                 :            : {
    1098                 :    3755140 :     JL_GC_PUSH2(&m, &root);
    1099                 :    3755140 :     uint64_t modid = 0;
    1100         [ +  + ]:    3755140 :     if (mod) {
    1101         [ -  + ]:      15086 :         assert(jl_is_module(mod));
    1102                 :      15086 :         modid = mod->build_id;
    1103                 :            :     }
    1104         [ -  + ]:    3755140 :     assert(jl_is_method(m));
    1105                 :    3755140 :     prepare_method_for_roots(m, modid);
    1106         [ +  + ]:    3755140 :     if (current_root_id(m->root_blocks) != modid)
    1107                 :       6460 :         add_root_block(m->root_blocks, modid, jl_array_len(m->roots));
    1108                 :    3755140 :     jl_array_ptr_1d_push(m->roots, root);
    1109                 :    3755140 :     JL_GC_POP();
    1110                 :    3755140 : }
    1111                 :            : 
    1112                 :            : // Add a list of roots with key `modid` to a method
    1113                 :        217 : void jl_append_method_roots(jl_method_t *m, uint64_t modid, jl_array_t* roots)
    1114                 :            : {
    1115                 :        217 :     JL_GC_PUSH2(&m, &roots);
    1116         [ -  + ]:        217 :     assert(jl_is_method(m));
    1117         [ -  + ]:        217 :     assert(jl_is_array(roots));
    1118                 :        217 :     prepare_method_for_roots(m, modid);
    1119                 :        217 :     add_root_block(m->root_blocks, modid, jl_array_len(m->roots));
    1120                 :        217 :     jl_array_ptr_1d_append(m->roots, roots);
    1121                 :        217 :     JL_GC_POP();
    1122                 :        217 : }
    1123                 :            : 
    1124                 :            : // given the absolute index i of a root, retrieve its relocatable reference
    1125                 :            : // returns 1 if the root is relocatable
    1126                 :  128259000 : int get_root_reference(rle_reference *rr, jl_method_t *m, size_t i)
    1127                 :            : {
    1128         [ +  + ]:  128259000 :     if (!m->root_blocks) {
    1129                 :  122976000 :         rr->key = 0;
    1130                 :  122976000 :         rr->index = i;
    1131                 :  122976000 :         return i < m->nroots_sysimg;
    1132                 :            :     }
    1133                 :    5283600 :     rle_index_to_reference(rr, i, (uint64_t*)jl_array_data(m->root_blocks), jl_array_len(m->root_blocks), 0);
    1134         [ +  + ]:    5283600 :     if (rr->key)
    1135                 :    1354300 :         return 1;
    1136                 :    3929300 :     return i < m->nroots_sysimg;
    1137                 :            : }
    1138                 :            : 
    1139                 :            : // get a root, given its key and index relative to the key
    1140                 :            : // this is the relocatable way to get a root from m->roots
    1141                 :  137837000 : jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index)
    1142                 :            : {
    1143         [ +  + ]:  137837000 :     if (!m->root_blocks) {
    1144         [ -  + ]:  133232000 :         assert(key == 0);
    1145                 :  133232000 :         return jl_array_ptr_ref(m->roots, index);
    1146                 :            :     }
    1147                 :    4604340 :     rle_reference rr = {key, index};
    1148                 :    4604340 :     size_t i = rle_reference_to_index(&rr, (uint64_t*)jl_array_data(m->root_blocks), jl_array_len(m->root_blocks), 0);
    1149                 :    4604340 :     return jl_array_ptr_ref(m->roots, i);
    1150                 :            : }
    1151                 :            : 
    1152                 :            : // Count the number of roots added by module with id `key`
    1153                 :       3138 : int nroots_with_key(jl_method_t *m, uint64_t key)
    1154                 :            : {
    1155                 :       3138 :     size_t nroots = 0;
    1156         [ +  + ]:       3138 :     if (m->roots)
    1157                 :       2647 :         nroots = jl_array_len(m->roots);
    1158         [ +  + ]:       3138 :     if (!m->root_blocks)
    1159         [ -  + ]:       3034 :         return key == 0 ? nroots : 0;
    1160                 :        104 :     uint64_t *rletable = (uint64_t*)jl_array_data(m->root_blocks);
    1161                 :        104 :     size_t j, nblocks2 = jl_array_len(m->root_blocks);
    1162                 :        104 :     int nwithkey = 0;
    1163         [ +  + ]:        221 :     for (j = 0; j < nblocks2; j+=2) {
    1164         [ +  + ]:        117 :         if (rletable[j] == key)
    1165         [ +  + ]:         85 :             nwithkey += (j+3 < nblocks2 ? rletable[j+3] : nroots) - rletable[j+1];
    1166                 :            :     }
    1167                 :        104 :     return nwithkey;
    1168                 :            : }
    1169                 :            : 
    1170                 :            : #ifdef __cplusplus
    1171                 :            : }
    1172                 :            : #endif

Generated by: LCOV version 1.14