LCOV - code coverage report
Current view: top level - src - datatype.c (source / functions) Hit Total Coverage
Test: [test only] commit 0f242327d2cc9bd130497f44b6350c924185606a Lines: 1006 1095 91.9 %
Date: 2022-07-16 23:42:53 Functions: 77 85 90.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 747 920 81.2 %

           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 DataTypes
       5                 :            :   basic operations on struct and bits values
       6                 :            : */
       7                 :            : 
       8                 :            : #include <stdlib.h>
       9                 :            : #include <string.h>
      10                 :            : #include <stdarg.h>
      11                 :            : #include "julia.h"
      12                 :            : #include "julia_internal.h"
      13                 :            : #include "julia_assert.h"
      14                 :            : #include "julia_gcext.h"
      15                 :            : 
      16                 :            : #ifdef __cplusplus
      17                 :            : extern "C" {
      18                 :            : #endif
      19                 :            : 
      20                 :            : // allocating TypeNames -----------------------------------------------------------
      21                 :            : 
      22                 :      64230 : static int is10digit(char c) JL_NOTSAFEPOINT
      23                 :            : {
      24   [ +  +  +  + ]:      64230 :     return (c >= '0' && c <= '9');
      25                 :            : }
      26                 :            : 
      27                 :      40302 : static jl_sym_t *jl_demangle_typename(jl_sym_t *s) JL_NOTSAFEPOINT
      28                 :            : {
      29                 :      40302 :     char *n = jl_symbol_name(s);
      30         [ +  + ]:      40302 :     if (n[0] != '#')
      31                 :          9 :         return s;
      32                 :      40293 :     char *end = strrchr(n, '#');
      33                 :            :     int32_t len;
      34   [ +  +  +  + ]:      40293 :     if (end == n || end == n+1)
      35                 :      12773 :         len = strlen(n) - 1;
      36                 :            :     else
      37                 :      27520 :         len = (end-n) - 1;  // extract `f` from `#f#...`
      38         [ +  + ]:      40293 :     if (is10digit(n[1]))
      39                 :      23315 :         return _jl_symbol(n, len+1);
      40                 :      16978 :     return _jl_symbol(&n[1], len);
      41                 :            : }
      42                 :            : 
      43                 :      40302 : JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module)
      44                 :            : {
      45                 :      40302 :     jl_task_t *ct = jl_current_task;
      46                 :            :     jl_methtable_t *mt =
      47                 :      40302 :         (jl_methtable_t*)jl_gc_alloc(ct->ptls, sizeof(jl_methtable_t),
      48                 :            :                                      jl_methtable_type);
      49                 :      40302 :     mt->name = jl_demangle_typename(name);
      50                 :      40302 :     mt->module = module;
      51                 :      40302 :     jl_atomic_store_relaxed(&mt->defs, jl_nothing);
      52                 :      40302 :     jl_atomic_store_relaxed(&mt->leafcache, (jl_array_t*)jl_an_empty_vec_any);
      53                 :      40302 :     jl_atomic_store_relaxed(&mt->cache, jl_nothing);
      54                 :      40302 :     mt->max_args = 0;
      55                 :      40302 :     mt->kwsorter = NULL;
      56                 :      40302 :     mt->backedges = NULL;
      57                 :      40302 :     JL_MUTEX_INIT(&mt->writelock);
      58                 :      40302 :     mt->offs = 0;
      59                 :      40302 :     mt->frozen = 0;
      60                 :      40302 :     return mt;
      61                 :            : }
      62                 :            : 
      63                 :      42544 : JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *module, int abstract, int mutabl)
      64                 :            : {
      65                 :      42544 :     jl_task_t *ct = jl_current_task;
      66                 :            :     jl_typename_t *tn =
      67                 :      42544 :         (jl_typename_t*)jl_gc_alloc(ct->ptls, sizeof(jl_typename_t),
      68                 :            :                                     jl_typename_type);
      69                 :      42544 :     tn->name = name;
      70                 :      42544 :     tn->module = module;
      71                 :      42544 :     tn->wrapper = NULL;
      72                 :      42544 :     jl_atomic_store_release(&tn->Typeofwrapper, NULL);
      73                 :      42544 :     jl_atomic_store_relaxed(&tn->cache, jl_emptysvec);
      74                 :      42544 :     jl_atomic_store_relaxed(&tn->linearcache, jl_emptysvec);
      75                 :      42544 :     tn->names = NULL;
      76         [ +  + ]:      42544 :     tn->hash = bitmix(bitmix(module ? module->build_id : 0, name->hash), 0xa1ada1da);
      77                 :      42544 :     tn->abstract = abstract;
      78                 :      42544 :     tn->mutabl = mutabl;
      79                 :      42544 :     tn->mayinlinealloc = 0;
      80                 :      42544 :     tn->mt = NULL;
      81                 :      42544 :     tn->partial = NULL;
      82                 :      42544 :     tn->atomicfields = NULL;
      83                 :      42544 :     tn->constfields = NULL;
      84                 :      42544 :     tn->max_methods = 0;
      85                 :      42544 :     return tn;
      86                 :            : }
      87                 :            : 
      88                 :            : // allocating DataTypes -----------------------------------------------------------
      89                 :            : 
      90                 :        204 : jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_module_t *module, jl_datatype_t *super, jl_svec_t *parameters)
      91                 :            : {
      92                 :        204 :     return jl_new_datatype((jl_sym_t*)name, module, super, parameters, jl_emptysvec, jl_emptysvec, jl_emptysvec, 1, 0, 0);
      93                 :            : }
      94                 :            : 
      95                 :  187375000 : jl_datatype_t *jl_new_uninitialized_datatype(void)
      96                 :            : {
      97                 :  187375000 :     jl_task_t *ct = jl_current_task;
      98                 :  187375000 :     jl_datatype_t *t = (jl_datatype_t*)jl_gc_alloc(ct->ptls, sizeof(jl_datatype_t), jl_datatype_type);
      99                 :  187375000 :     t->hash = 0;
     100                 :  187375000 :     t->hasfreetypevars = 0;
     101                 :  187375000 :     t->isdispatchtuple = 0;
     102                 :  187375000 :     t->isbitstype = 0;
     103                 :  187375000 :     t->zeroinit = 0;
     104                 :  187375000 :     t->has_concrete_subtype = 1;
     105                 :  187375000 :     t->cached_by_hash = 0;
     106                 :  187375000 :     t->name = NULL;
     107                 :  187375000 :     t->super = NULL;
     108                 :  187375000 :     t->parameters = NULL;
     109                 :  187375000 :     t->layout = NULL;
     110                 :  187375000 :     t->types = NULL;
     111                 :  187375000 :     t->instance = NULL;
     112                 :  187375000 :     return t;
     113                 :            : }
     114                 :            : 
     115                 :    1856440 : static jl_datatype_layout_t *jl_get_layout(uint32_t nfields,
     116                 :            :                                            uint32_t npointers,
     117                 :            :                                            uint32_t alignment,
     118                 :            :                                            int haspadding,
     119                 :            :                                            jl_fielddesc32_t desc[],
     120                 :            :                                            uint32_t pointers[]) JL_NOTSAFEPOINT
     121                 :            : {
     122         [ -  + ]:    1856440 :     assert(alignment); // should have been verified by caller
     123                 :            : 
     124                 :            :     // compute the smallest fielddesc type that can hold the layout description
     125                 :    1856440 :     int fielddesc_type = 0;
     126         [ +  + ]:    1856440 :     if (nfields > 0) {
     127                 :    1856340 :         uint32_t max_size = 0;
     128                 :    1856340 :         uint32_t max_offset = desc[nfields - 1].offset;
     129   [ +  +  +  + ]:    1856340 :         if (npointers > 0 && pointers[npointers - 1] > max_offset)
     130                 :     164431 :             max_offset = pointers[npointers - 1];
     131         [ +  + ]:   53057400 :         for (size_t i = 0; i < nfields; i++) {
     132         [ +  + ]:   51201100 :             if (desc[i].size > max_size)
     133                 :    2187580 :                 max_size = desc[i].size;
     134                 :            :         }
     135                 :    1856340 :         jl_fielddesc8_t maxdesc8 = { 0, max_size, max_offset };
     136                 :    1856340 :         jl_fielddesc16_t maxdesc16 = { 0, max_size, max_offset };
     137                 :    1856340 :         jl_fielddesc32_t maxdesc32 = { 0, max_size, max_offset };
     138   [ +  +  +  + ]:    1856340 :         if (maxdesc8.size != max_size || maxdesc8.offset != max_offset) {
     139                 :      31411 :             fielddesc_type = 1;
     140   [ +  +  +  + ]:      31411 :             if (maxdesc16.size != max_size || maxdesc16.offset != max_offset) {
     141                 :         51 :                 fielddesc_type = 2;
     142   [ +  -  -  + ]:         51 :                 if (maxdesc32.size != max_size || maxdesc32.offset != max_offset) {
     143                 :          0 :                     assert(0); // should have been verified by caller
     144                 :            :                 }
     145                 :            :             }
     146                 :            :         }
     147                 :            :     }
     148                 :            : 
     149                 :            :     // allocate a new descriptor
     150                 :            :     // TODO: lots of these are the same--take advantage of the fact these are immutable to combine them
     151                 :    1856440 :     uint32_t fielddesc_size = jl_fielddesc_size(fielddesc_type);
     152                 :    1856440 :     jl_datatype_layout_t *flddesc = (jl_datatype_layout_t*)jl_gc_perm_alloc(
     153                 :    1856440 :                 sizeof(jl_datatype_layout_t) + nfields * fielddesc_size + (npointers << fielddesc_type),
     154                 :            :                 0, 4, 0);
     155                 :    1856440 :     flddesc->nfields = nfields;
     156                 :    1856440 :     flddesc->alignment = alignment;
     157                 :    1856440 :     flddesc->haspadding = haspadding;
     158                 :    1856440 :     flddesc->fielddesc_type = fielddesc_type;
     159                 :    1856440 :     flddesc->npointers = npointers;
     160         [ +  + ]:    1856440 :     flddesc->first_ptr = (npointers > 0 ? pointers[0] : -1);
     161                 :            : 
     162                 :            :     // fill out the fields of the new descriptor
     163                 :    1856440 :     jl_fielddesc8_t* desc8 = (jl_fielddesc8_t*)jl_dt_layout_fields(flddesc);
     164                 :    1856440 :     jl_fielddesc16_t* desc16 = (jl_fielddesc16_t*)jl_dt_layout_fields(flddesc);
     165                 :    1856440 :     jl_fielddesc32_t* desc32 = (jl_fielddesc32_t*)jl_dt_layout_fields(flddesc);
     166         [ +  + ]:   53057500 :     for (size_t i = 0; i < nfields; i++) {
     167         [ +  + ]:   51201100 :         if (fielddesc_type == 0) {
     168                 :   45988500 :             desc8[i].offset = desc[i].offset;
     169                 :   45988500 :             desc8[i].size = desc[i].size;
     170                 :   45988500 :             desc8[i].isptr = desc[i].isptr;
     171                 :            :         }
     172         [ +  + ]:    5212580 :         else if (fielddesc_type == 1) {
     173                 :     212400 :             desc16[i].offset = desc[i].offset;
     174                 :     212400 :             desc16[i].size = desc[i].size;
     175                 :     212400 :             desc16[i].isptr = desc[i].isptr;
     176                 :            :         }
     177                 :            :         else {
     178                 :    5000180 :             desc32[i].offset = desc[i].offset;
     179                 :    5000180 :             desc32[i].size = desc[i].size;
     180                 :    5000180 :             desc32[i].isptr = desc[i].isptr;
     181                 :            :         }
     182                 :            :     }
     183                 :    1856440 :     uint8_t* ptrs8 = (uint8_t*)jl_dt_layout_ptrs(flddesc);
     184                 :    1856440 :     uint16_t* ptrs16 = (uint16_t*)jl_dt_layout_ptrs(flddesc);
     185                 :    1856440 :     uint32_t* ptrs32 = (uint32_t*)jl_dt_layout_ptrs(flddesc);
     186         [ +  + ]:    9218740 :     for (size_t i = 0; i < npointers; i++) {
     187         [ +  + ]:    7362290 :         if (fielddesc_type == 0) {
     188                 :    3127000 :             ptrs8[i] = pointers[i];
     189                 :            :         }
     190         [ +  + ]:    4235290 :         else if (fielddesc_type == 1) {
     191                 :     205153 :             ptrs16[i] = pointers[i];
     192                 :            :         }
     193                 :            :         else {
     194                 :    4030140 :             ptrs32[i] = pointers[i];
     195                 :            :         }
     196                 :            :     }
     197                 :    1856440 :     return flddesc;
     198                 :            : }
     199                 :            : 
     200                 :            : // Determine if homogeneous tuple with fields of type t will have
     201                 :            : // a special alignment beyond normal Julia rules.
     202                 :            : // Return special alignment if one exists, 0 if normal alignment rules hold.
     203                 :            : // A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
     204                 :            : // For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
     205                 :            : // without LLVM being available.
     206                 :     193463 : unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
     207                 :            : {
     208         [ +  + ]:     193463 :     if (!jl_is_vecelement_type(t))
     209                 :     192156 :         return 0;
     210         [ -  + ]:       1307 :     assert(jl_datatype_nfields(t) == 1);
     211                 :       1307 :     jl_value_t *ty = jl_field_type((jl_datatype_t*)t, 0);
     212         [ -  + ]:       1307 :     if (!jl_is_primitivetype(ty))
     213                 :            :         // LLVM requires that a vector element be a primitive type.
     214                 :            :         // LLVM allows pointer types as vector elements, but until a
     215                 :            :         // motivating use case comes up for Julia, we reject pointers.
     216                 :          0 :         return 0;
     217                 :       1307 :     size_t elsz = jl_datatype_size(ty);
     218   [ +  +  +  +  :       1307 :     if (elsz != 1 && elsz != 2 && elsz != 4 && elsz != 8)
             +  +  -  + ]
     219                 :            :         // Only handle power-of-two-sized elements (for now)
     220                 :          0 :         return 0;
     221                 :       1307 :     size_t size = nfields * elsz;
     222                 :            :     // Use natural alignment for this vector: this matches LLVM and clang.
     223                 :       1307 :     return next_power_of_two(size);
     224                 :            : }
     225                 :            : 
     226                 :    2529490 : STATIC_INLINE int jl_is_datatype_make_singleton(jl_datatype_t *d) JL_NOTSAFEPOINT
     227                 :            : {
     228   [ +  +  +  -  :    2529490 :     return (!d->name->abstract && jl_datatype_size(d) == 0 && d != jl_symbol_type && d->name != jl_array_typename &&
             +  -  +  + ]
     229   [ +  -  +  + ]:    5058980 :             d->isconcretetype && !d->name->mutabl);
     230                 :            : }
     231                 :            : 
     232                 :    2529490 : STATIC_INLINE void jl_maybe_allocate_singleton_instance(jl_datatype_t *st) JL_NOTSAFEPOINT
     233                 :            : {
     234         [ +  + ]:    2529490 :     if (jl_is_datatype_make_singleton(st)) {
     235                 :            :         // It's possible for st to already have an ->instance if it was redefined
     236         [ +  + ]:      95449 :         if (!st->instance)
     237                 :      95448 :             st->instance = jl_gc_permobj(0, st);
     238                 :            :     }
     239                 :    2529490 : }
     240                 :            : 
     241                 :            : // return whether all concrete subtypes of this type have the same layout
     242                 : 2281580000 : int jl_struct_try_layout(jl_datatype_t *dt)
     243                 :            : {
     244         [ +  + ]: 2281580000 :     if (dt->layout)
     245                 : 2281190000 :         return 1;
     246         [ +  + ]:     395473 :     else if (!jl_has_fixed_layout(dt))
     247                 :     395470 :         return 0;
     248                 :            :     // jl_has_fixed_layout also ensured that dt->types is assigned now
     249                 :          3 :     jl_compute_field_offsets(dt);
     250         [ -  + ]:          3 :     assert(dt->layout);
     251                 :          3 :     return 1;
     252                 :            : }
     253                 :            : 
     254                 : 3764190000 : int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree)
     255                 :            : {
     256   [ +  +  +  + ]: 3764190000 :     if (ty->name->mayinlinealloc && jl_struct_try_layout(ty)) {
     257         [ +  + ]: 2258470000 :         if (ty->layout->npointers > 0) {
     258         [ +  + ]:  205486000 :             if (pointerfree)
     259                 :   24332500 :                 return 0;
     260         [ +  + ]:  181153000 :             if (ty->name->n_uninitialized != 0)
     261                 :     135325 :                 return 0;
     262         [ -  + ]:  181018000 :             if (ty->layout->fielddesc_type > 1) // GC only implements support for 8 and 16 (not array32)
     263                 :          0 :                 return 0;
     264                 :            :         }
     265                 : 2234000000 :         return 1;
     266                 :            :     }
     267                 : 1505720000 :     return 0;
     268                 :            : }
     269                 :            : 
     270                 : 3863370000 : static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield)
     271                 :            : {
     272         [ +  + ]: 3863370000 :     if (jl_is_uniontype(ty)) {
     273                 :  111407000 :         unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align, asfield);
     274         [ +  + ]:  111407000 :         if (na == 0)
     275                 :   21940200 :             return 0;
     276                 :   89467200 :         unsigned nb = union_isinlinable(((jl_uniontype_t*)ty)->b, 1, nbytes, align, asfield);
     277         [ +  + ]:   89467200 :         if (nb == 0)
     278                 :   36613400 :             return 0;
     279                 :   52853800 :         return na + nb;
     280                 :            :     }
     281   [ +  +  +  + ]: 3751970000 :     if (jl_is_datatype(ty) && jl_datatype_isinlinealloc((jl_datatype_t*)ty, pointerfree)) {
     282                 : 2221810000 :         size_t sz = jl_datatype_size(ty);
     283                 : 2221810000 :         size_t al = jl_datatype_align(ty);
     284                 :            :         // primitive types in struct slots need their sizes aligned. issue #37974
     285   [ +  +  +  + ]: 2221810000 :         if (asfield && jl_is_primitivetype(ty))
     286                 : 1648620000 :             sz = LLT_ALIGN(sz, al);
     287         [ +  + ]: 2221810000 :         if (*nbytes < sz)
     288                 : 2089870000 :             *nbytes = sz;
     289         [ +  + ]: 2221810000 :         if (*align < al)
     290                 : 2125390000 :             *align = al;
     291                 : 2221810000 :         return 1;
     292                 :            :     }
     293                 : 1530150000 :     return 0;
     294                 :            : }
     295                 :            : 
     296                 :       5718 : int jl_uniontype_size(jl_value_t *ty, size_t *sz)
     297                 :            : {
     298                 :       5718 :     size_t al = 0;
     299                 :       5718 :     return union_isinlinable(ty, 0, sz, &al, 0) != 0;
     300                 :            : }
     301                 :            : 
     302                 : 3662490000 : JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al)
     303                 :            : {
     304                 : 3662490000 :     unsigned countbits = union_isinlinable(eltype, 0, fsz, al, 1);
     305   [ +  +  +  - ]: 3662490000 :     return (countbits > 0 && countbits < 127) ? countbits : 0;
     306                 :            : }
     307                 :            : 
     308                 :    2307570 : JL_DLLEXPORT int jl_stored_inline(jl_value_t *eltype)
     309                 :            : {
     310                 :    2307570 :     size_t fsz = 0, al = 0;
     311                 :    2307570 :     return jl_islayout_inline(eltype, &fsz, &al);
     312                 :            : }
     313                 :            : 
     314                 :            : // whether instances of this type can use pointer comparison for `===`
     315                 :    5333970 : int jl_pointer_egal(jl_value_t *t)
     316                 :            : {
     317         [ +  + ]:    5333970 :     if (t == (jl_value_t*)jl_any_type)
     318                 :      27641 :         return 0; // when setting up the initial types, jl_is_type_type gets confused about this
     319         [ +  + ]:    5306330 :     if (t == (jl_value_t*)jl_symbol_type)
     320                 :     164535 :         return 1;
     321         [ +  + ]:    5141800 :     if (t == (jl_value_t*)jl_bool_type)
     322                 :         55 :         return 1;
     323   [ +  +  +  + ]:    5141740 :     if (jl_is_mutable_datatype(jl_unwrap_unionall(t)) && // excludes abstract types
     324         [ +  + ]:    4961120 :         t != (jl_value_t*)jl_string_type && // technically mutable, but compared by contents
     325   [ +  +  +  + ]:    9756030 :         t != (jl_value_t*)jl_simplevector_type &&
     326                 :    4877620 :         !jl_is_kind(t))
     327                 :    4752510 :         return 1;
     328   [ +  +  +  + ]:     389226 :     if ((jl_is_datatype(t) && jl_is_datatype_singleton((jl_datatype_t*)t)) ||
     329         [ -  + ]:     363210 :         t == (jl_value_t*)jl_typeofbottom_type->super)
     330                 :      26016 :         return 1;
     331   [ +  +  +  + ]:     363210 :     if (jl_is_type_type(t) && jl_is_datatype(jl_tparam0(t))) {
     332                 :            :         // need to use typeseq for most types
     333                 :            :         // but can compare some types by pointer
     334                 :      24115 :         jl_datatype_t *dt = (jl_datatype_t*)jl_tparam0(t);
     335                 :            :         // `Core.TypeofBottom` and `Type{Union{}}` are used interchangeably
     336                 :            :         // with different pointer values even though `Core.TypeofBottom` is a concrete type.
     337                 :            :         // See `Core.Compiler.hasuniquerep`
     338         [ +  + ]:      24115 :         if (dt != jl_typeofbottom_type &&
     339   [ +  +  +  + ]:      21353 :             (dt->isconcretetype || jl_svec_len(dt->parameters) == 0)) {
     340                 :            :             // Concrete types have unique pointer values
     341                 :            :             // If the type has zero type parameters it'll also have only one possible
     342                 :            :             // pointer value.
     343                 :      20427 :             return 1;
     344                 :            :         }
     345                 :            :     }
     346         [ +  + ]:     342783 :     if (jl_is_uniontype(t)) {
     347                 :      21299 :         jl_uniontype_t *u = (jl_uniontype_t*)t;
     348   [ +  +  +  + ]:      21299 :         return jl_pointer_egal(u->a) && jl_pointer_egal(u->b);
     349                 :            :     }
     350                 :     321484 :     return 0;
     351                 :            : }
     352                 :            : 
     353                 :          0 : static void throw_ovf(int should_malloc, void *desc, jl_datatype_t* st, int offset)
     354                 :            : {
     355         [ #  # ]:          0 :     if (should_malloc)
     356                 :          0 :         free(desc);
     357                 :          0 :     jl_errorf("type %s has field offset %d that exceeds the page size", jl_symbol_name(st->name->name), offset);
     358                 :            : }
     359                 :            : 
     360                 :    5132330 : void jl_compute_field_offsets(jl_datatype_t *st)
     361                 :            : {
     362                 :    5132330 :     const uint64_t max_offset = (((uint64_t)1) << 32) - 1;
     363                 :    5132330 :     const uint64_t max_size = max_offset >> 1;
     364                 :            : 
     365         [ -  + ]:    5132330 :     if (st->name->wrapper == NULL)
     366                 :          0 :         return; // we got called too early--we'll be back
     367                 :    5132330 :     jl_datatype_t *w = (jl_datatype_t*)jl_unwrap_unionall(st->name->wrapper);
     368   [ +  +  +  + ]:    5132330 :     if (st == w && st->layout) {
     369                 :            :         // this check allows us to force re-computation of the layout for some types during init
     370                 :         16 :         st->layout = NULL;
     371                 :         16 :         st->size = 0;
     372                 :         16 :         st->zeroinit = 0;
     373                 :         16 :         st->has_concrete_subtype = 1;
     374                 :            :     }
     375   [ +  +  +  + ]:    5132330 :     int isbitstype = st->isconcretetype && st->name->mayinlinealloc;
     376                 :            :     // If layout doesn't depend on type parameters, it's stored in st->name->wrapper
     377                 :            :     // and reused by all subtypes.
     378         [ +  + ]:    5132330 :     if (w->layout) {
     379                 :    3234960 :         st->layout = w->layout;
     380                 :    3234960 :         st->size = w->size;
     381                 :    3234960 :         st->zeroinit = w->zeroinit;
     382                 :    3234960 :         st->has_concrete_subtype = w->has_concrete_subtype;
     383         [ +  + ]:    3234960 :         if (!jl_is_layout_opaque(st->layout)) { // e.g. jl_array_typename
     384   [ +  +  +  + ]:     635079 :             st->isbitstype = isbitstype && st->layout->npointers == 0;
     385                 :     635079 :             jl_maybe_allocate_singleton_instance(st);
     386                 :            :         }
     387                 :    3234960 :         return;
     388                 :            :     }
     389   [ +  -  +  - ]:    1897360 :     assert(st->types && w->types);
     390                 :    1897360 :     size_t i, nfields = jl_svec_len(st->types);
     391         [ -  + ]:    1897360 :     assert(st->name->n_uninitialized <= nfields);
     392         [ +  + ]:    1897360 :     if (nfields == 0) {
     393                 :            :         // if we have no fields, we can trivially skip the rest
     394   [ +  +  +  + ]:      38077 :         if (st == jl_symbol_type || st == jl_string_type) {
     395                 :            :             // opaque layout - heap-allocated blob
     396                 :            :             static const jl_datatype_layout_t opaque_byte_layout = {0, 1, -1, 1, 0, 0};
     397                 :          2 :             st->layout = &opaque_byte_layout;
     398                 :          2 :             return;
     399                 :            :         }
     400   [ +  +  +  +  :      38075 :         else if (st == jl_simplevector_type || st == jl_module_type || st->name == jl_array_typename) {
                   +  + ]
     401                 :            :             static const jl_datatype_layout_t opaque_ptr_layout = {0, 1, -1, sizeof(void*), 0, 0};
     402                 :          4 :             st->layout = &opaque_ptr_layout;
     403                 :          4 :             return;
     404                 :            :         }
     405                 :            :         else {
     406                 :            :             // reuse the same layout for all singletons
     407                 :            :             static const jl_datatype_layout_t singleton_layout = {0, 0, -1, 1, 0, 0};
     408                 :      38071 :             st->layout = &singleton_layout;
     409                 :            :         }
     410                 :            :     }
     411                 :            :     else {
     412                 :            :         // compute a conservative estimate of whether there could exist an instance of a subtype of this
     413   [ +  +  +  + ]:   53063700 :         for (i = 0; st->has_concrete_subtype && i < nfields - st->name->n_uninitialized; i++) {
     414                 :   51204400 :             jl_value_t *fld = jl_svecref(st->types, i);
     415         [ +  + ]:   51204400 :             if (fld == jl_bottom_type)
     416                 :        264 :                 st->has_concrete_subtype = 0;
     417                 :            :             else
     418   [ +  +  +  + ]:   51204100 :                 st->has_concrete_subtype = !jl_is_datatype(fld) || ((jl_datatype_t *)fld)->has_concrete_subtype;
     419                 :            :         }
     420                 :            :         // compute layout for the wrapper object if the field types have no free variables
     421   [ +  +  +  + ]:    1859290 :         if (!st->isconcretetype && !jl_has_fixed_layout(st)) {
     422         [ -  + ]:       2946 :             assert(st == w); // otherwise caller should not have requested this layout
     423                 :       2946 :             return;
     424                 :            :         }
     425                 :            :     }
     426                 :            : 
     427   [ +  +  +  + ]:   47251600 :     for (i = 0; isbitstype && i < nfields; i++) {
     428                 :   45357200 :         jl_value_t *fld = jl_field_type(st, i);
     429                 :   45357200 :         isbitstype = jl_isbits(fld);
     430                 :            :     }
     431                 :            : 
     432                 :            :     // if we didn't reuse the layout above, compute it now
     433         [ +  + ]:    1894410 :     if (st->layout == NULL) {
     434                 :    1856340 :         size_t descsz = nfields * sizeof(jl_fielddesc32_t);
     435                 :            :         jl_fielddesc32_t *desc;
     436                 :            :         uint32_t *pointers;
     437                 :    1856340 :         int should_malloc = descsz >= jl_page_size;
     438         [ +  + ]:    1856340 :         if (should_malloc)
     439                 :         19 :             desc = (jl_fielddesc32_t*)malloc_s(descsz);
     440                 :            :         else
     441                 :    1856320 :             desc = (jl_fielddesc32_t*)alloca(descsz);
     442                 :    1856340 :         size_t sz = 0;
     443                 :    1856340 :         size_t alignm = 1;
     444                 :    1856340 :         int zeroinit = 0;
     445                 :    1856340 :         int haspadding = 0;
     446                 :    1856340 :         int homogeneous = 1;
     447                 :    1856340 :         int needlock = 0;
     448                 :    1856340 :         uint32_t npointers = 0;
     449                 :    1856340 :         jl_value_t *firstty = jl_field_type(st, 0);
     450         [ +  + ]:   53057400 :         for (i = 0; i < nfields; i++) {
     451                 :   51201100 :             jl_value_t *fld = jl_field_type(st, i);
     452                 :   51201100 :             int isatomic = jl_field_isatomic(st, i);
     453                 :   51201100 :             size_t fsz = 0, al = 1;
     454   [ +  +  +  +  :   51201100 :             if (jl_islayout_inline(fld, &fsz, &al) && (!isatomic || jl_is_datatype(fld))) { // aka jl_datatype_isinlinealloc
                   +  + ]
     455         [ -  + ]:   46116400 :                 if (__unlikely(fsz > max_size))
     456                 :            :                     // Should never happen
     457                 :          0 :                     throw_ovf(should_malloc, desc, st, fsz);
     458                 :   46116400 :                 desc[i].isptr = 0;
     459         [ +  + ]:   46116400 :                 if (jl_is_uniontype(fld)) {
     460                 :         99 :                     haspadding = 1;
     461                 :         99 :                     fsz += 1; // selector byte
     462                 :         99 :                     zeroinit = 1;
     463                 :            :                 }
     464                 :            :                 else {
     465                 :   46116400 :                     uint32_t fld_npointers = ((jl_datatype_t*)fld)->layout->npointers;
     466         [ +  + ]:   46116400 :                     if (((jl_datatype_t*)fld)->layout->haspadding)
     467                 :     408042 :                         haspadding = 1;
     468   [ +  +  +  + ]:   46116400 :                     if (i >= nfields - st->name->n_uninitialized && fld_npointers &&
     469         [ +  + ]:         55 :                         fld_npointers * sizeof(void*) != fsz) {
     470                 :            :                         // field may be undef (may be uninitialized and contains pointer),
     471                 :            :                         // and contains non-pointer fields of non-zero sizes.
     472                 :         27 :                         haspadding = 1;
     473                 :            :                     }
     474         [ +  + ]:   46116400 :                     if (!zeroinit)
     475                 :   44685900 :                         zeroinit = ((jl_datatype_t*)fld)->zeroinit;
     476                 :   46116400 :                     npointers += fld_npointers;
     477                 :            :                 }
     478                 :            :             }
     479                 :            :             else {
     480                 :    5084620 :                 fsz = sizeof(void*);
     481         [ -  + ]:    5084620 :                 if (fsz > MAX_ALIGN)
     482                 :          0 :                     fsz = MAX_ALIGN;
     483                 :    5084620 :                 al = fsz;
     484                 :    5084620 :                 desc[i].isptr = 1;
     485                 :    5084620 :                 zeroinit = 1;
     486                 :    5084620 :                 npointers++;
     487         [ +  + ]:    5084620 :                 if (!jl_pointer_egal(fld)) {
     488                 :            :                     // this somewhat poorly named flag says whether some of the bits can be non-unique
     489                 :     294468 :                     haspadding = 1;
     490                 :            :                 }
     491                 :            :             }
     492   [ +  +  +  + ]:   51201100 :             if (isatomic && fsz > MAX_ATOMIC_SIZE)
     493                 :          1 :                 needlock = 1;
     494   [ +  +  +  + ]:   51201100 :             if (isatomic && fsz <= MAX_ATOMIC_SIZE)
     495                 :         41 :                 al = fsz = next_power_of_two(fsz);
     496         [ +  + ]:   51201100 :             if (al != 0) {
     497                 :   51201100 :                 size_t alsz = LLT_ALIGN(sz, al);
     498         [ +  + ]:   51201100 :                 if (alsz != sz)
     499                 :      73818 :                     haspadding = 1;
     500                 :   51201100 :                 sz = alsz;
     501         [ +  + ]:   51201100 :                 if (al > alignm)
     502                 :    1809980 :                     alignm = al;
     503                 :            :             }
     504                 :   51201100 :             homogeneous &= firstty == fld;
     505                 :   51201100 :             desc[i].offset = sz;
     506                 :   51201100 :             desc[i].size = fsz;
     507         [ -  + ]:   51201100 :             if (__unlikely(max_offset - sz < fsz))
     508                 :          0 :                 throw_ovf(should_malloc, desc, st, sz);
     509                 :   51201100 :             sz += fsz;
     510                 :            :         }
     511         [ +  + ]:    1856340 :         if (needlock) {
     512                 :          1 :             size_t offset = LLT_ALIGN(sizeof(jl_mutex_t), alignm);
     513         [ +  + ]:          3 :             for (i = 0; i < nfields; i++) {
     514                 :          2 :                 desc[i].offset += offset;
     515                 :            :             }
     516         [ -  + ]:          1 :             if (__unlikely(max_offset - sz < offset))
     517                 :          0 :                 throw_ovf(should_malloc, desc, st, sz);
     518                 :          1 :             sz += offset;
     519                 :          1 :             haspadding = 1;
     520                 :            :         }
     521   [ +  +  +  + ]:    1856340 :         if (homogeneous && jl_is_tuple_type(st)) {
     522                 :            :             // Some tuples become LLVM vectors with stronger alignment than what was calculated above.
     523                 :      52461 :             unsigned al = jl_special_vector_alignment(nfields, firstty);
     524         [ -  + ]:      52461 :             assert(al % alignm == 0);
     525         [ +  + ]:      52461 :             if (al > alignm)
     526                 :        248 :                 alignm = al;
     527                 :            :         }
     528                 :    1856340 :         st->size = LLT_ALIGN(sz, alignm);
     529         [ +  + ]:    1856340 :         if (st->size > sz)
     530                 :      72121 :             haspadding = 1;
     531   [ +  +  +  + ]:    1856340 :         if (should_malloc && npointers)
     532                 :          6 :             pointers = (uint32_t*)malloc_s(npointers * sizeof(uint32_t));
     533                 :            :         else
     534                 :    1856340 :             pointers = (uint32_t*)alloca(npointers * sizeof(uint32_t));
     535                 :    1856340 :         size_t ptr_i = 0;
     536         [ +  + ]:   53057400 :         for (i = 0; i < nfields; i++) {
     537                 :   51201100 :             jl_value_t *fld = jl_field_type(st, i);
     538                 :   51201100 :             uint32_t offset = desc[i].offset / sizeof(jl_value_t**);
     539         [ +  + ]:   51201100 :             if (desc[i].isptr)
     540                 :    5084620 :                 pointers[ptr_i++] = offset;
     541         [ +  + ]:   46116400 :             else if (jl_is_datatype(fld)) {
     542                 :   46116400 :                 int j, npointers = ((jl_datatype_t*)fld)->layout->npointers;
     543         [ +  + ]:   48394000 :                 for (j = 0; j < npointers; j++) {
     544                 :    2277670 :                     pointers[ptr_i++] = offset + jl_ptr_offset((jl_datatype_t*)fld, j);
     545                 :            :                 }
     546                 :            :             }
     547                 :            :         }
     548         [ -  + ]:    1856340 :         assert(ptr_i == npointers);
     549                 :    1856340 :         st->layout = jl_get_layout(nfields, npointers, alignm, haspadding, desc, pointers);
     550         [ +  + ]:    1856340 :         if (should_malloc) {
     551                 :         19 :             free(desc);
     552         [ +  + ]:         19 :             if (npointers)
     553                 :          6 :                 free(pointers);
     554                 :            :         }
     555                 :    1856340 :         st->zeroinit = zeroinit;
     556                 :            :     }
     557                 :            :     // now finish deciding if this instantiation qualifies for special properties
     558   [ +  +  -  + ]:    1894410 :     assert(!isbitstype || st->layout->npointers == 0); // the definition of isbits
     559                 :    1894410 :     st->isbitstype = isbitstype;
     560                 :    1894410 :     jl_maybe_allocate_singleton_instance(st);
     561                 :    1894410 :     return;
     562                 :            : }
     563                 :            : 
     564                 :      26176 : static int is_anonfn_typename(char *name)
     565                 :            : {
     566   [ +  +  +  + ]:      26176 :     if (name[0] != '#' || name[1] == '#')
     567                 :       2239 :         return 0;
     568                 :      23937 :     char *other = strrchr(name, '#');
     569   [ +  -  +  + ]:      23937 :     return other > &name[1] && is10digit(other[1]);
     570                 :            : }
     571                 :            : 
     572                 :      42539 : JL_DLLEXPORT jl_datatype_t *jl_new_datatype(
     573                 :            :         jl_sym_t *name,
     574                 :            :         jl_module_t *module,
     575                 :            :         jl_datatype_t *super,
     576                 :            :         jl_svec_t *parameters,
     577                 :            :         jl_svec_t *fnames,
     578                 :            :         jl_svec_t *ftypes,
     579                 :            :         jl_svec_t *fattrs,
     580                 :            :         int abstract, int mutabl,
     581                 :            :         int ninitialized)
     582                 :            : {
     583                 :      42539 :     jl_datatype_t *t = NULL;
     584                 :      42539 :     jl_typename_t *tn = NULL;
     585                 :      42539 :     JL_GC_PUSH2(&t, &tn);
     586                 :            : 
     587         [ -  + ]:      42539 :     assert(parameters);
     588                 :            : 
     589                 :            :     // init enough before possibly calling jl_new_typename_in
     590                 :      42539 :     t = jl_new_uninitialized_datatype();
     591                 :      42539 :     t->super = super;
     592         [ +  + ]:      42539 :     if (super != NULL) jl_gc_wb(t, t->super);
     593                 :      42539 :     t->parameters = parameters;
     594                 :      42539 :     jl_gc_wb(t, t->parameters);
     595                 :      42539 :     t->types = ftypes;
     596         [ +  + ]:      42539 :     if (ftypes != NULL) jl_gc_wb(t, t->types);
     597                 :      42539 :     t->size = 0;
     598                 :            : 
     599                 :      42539 :     t->name = NULL;
     600         [ +  + ]:      42539 :     if (jl_is_typename(name)) {
     601                 :            :         // This code-path is used by the Serialization module to bypass normal expectations
     602                 :        373 :         tn = (jl_typename_t*)name;
     603                 :        373 :         tn->abstract = abstract;
     604                 :        373 :         tn->mutabl = mutabl;
     605                 :            :     }
     606                 :            :     else {
     607                 :      42166 :         tn = jl_new_typename_in((jl_sym_t*)name, module, abstract, mutabl);
     608   [ +  +  +  +  :      42166 :         if (super == jl_function_type || super == jl_builtin_type || is_anonfn_typename(jl_symbol_name(name))) {
                   +  + ]
     609                 :            :             // Callable objects (including compiler-generated closures) get independent method tables
     610                 :            :             // as an optimization
     611                 :      39926 :             tn->mt = jl_new_method_table(name, module);
     612                 :      39926 :             jl_gc_wb(tn, tn->mt);
     613   [ +  +  +  + ]:      39926 :             if (jl_svec_len(parameters) == 0 && !abstract)
     614                 :      37403 :                 tn->mt->offs = 1;
     615                 :            :         }
     616                 :            :         else {
     617                 :            :             // Everything else, gets to use the unified table
     618                 :       2240 :             tn->mt = jl_nonfunction_mt;
     619                 :            :         }
     620                 :            :     }
     621                 :      42539 :     t->name = tn;
     622                 :      42539 :     jl_gc_wb(t, t->name);
     623                 :      42539 :     t->name->names = fnames;
     624                 :      42539 :     jl_gc_wb(t->name, t->name->names);
     625                 :      42539 :     tn->n_uninitialized = jl_svec_len(fnames) - ninitialized;
     626                 :            : 
     627                 :      42539 :     uint32_t *volatile atomicfields = NULL;
     628                 :      42539 :     uint32_t *volatile constfields = NULL;
     629                 :            :     int i;
     630   [ +  +  +  + ]:      85077 :     JL_TRY {
     631         [ +  + ]:      42585 :         for (i = 0; i + 1 < jl_svec_len(fattrs); i += 2) {
     632                 :         47 :             jl_value_t *fldi = jl_svecref(fattrs, i);
     633                 :         47 :             jl_sym_t *attr = (jl_sym_t*)jl_svecref(fattrs, i + 1);
     634         [ -  + ]:         47 :             JL_TYPECHK(typeassert, long, fldi);
     635         [ -  + ]:         47 :             JL_TYPECHK(typeassert, symbol, (jl_value_t*)attr);
     636                 :         47 :             size_t fldn = jl_unbox_long(fldi);
     637   [ +  -  -  + ]:         47 :             if (fldn < 1 || fldn > jl_svec_len(fnames))
     638                 :          0 :                 jl_errorf("invalid field attribute %lld", (long long)fldn);
     639                 :         47 :             fldn--;
     640         [ +  + ]:         47 :             if (attr == jl_atomic_sym) {
     641         [ -  + ]:         29 :                 if (!mutabl)
     642                 :          0 :                     jl_errorf("invalid field attribute atomic for immutable struct");
     643         [ +  + ]:         29 :                 if (atomicfields == NULL) {
     644                 :         21 :                     size_t nb = (jl_svec_len(fnames) + 31) / 32 * sizeof(uint32_t);
     645                 :         21 :                     atomicfields = (uint32_t*)malloc_s(nb);
     646                 :         21 :                     memset(atomicfields, 0, nb);
     647                 :            :                 }
     648                 :         29 :                 atomicfields[fldn / 32] |= 1 << (fldn % 32);
     649                 :            :             }
     650         [ +  - ]:         18 :             else if (attr == jl_const_sym) {
     651         [ +  + ]:         18 :                 if (!mutabl)
     652                 :          1 :                     jl_errorf("invalid field attribute const for immutable struct");
     653         [ +  + ]:         17 :                 if (constfields == NULL) {
     654                 :          9 :                     size_t nb = (jl_svec_len(fnames) + 31) / 32 * sizeof(uint32_t);
     655                 :          9 :                     constfields = (uint32_t*)malloc_s(nb);
     656                 :          9 :                     memset(constfields, 0, nb);
     657                 :            :                 }
     658                 :         17 :                 constfields[fldn / 32] |= 1 << (fldn % 32);
     659                 :            :             }
     660                 :            :             else {
     661                 :          0 :                 jl_errorf("invalid field attribute %s", jl_symbol_name(attr));
     662                 :            :             }
     663                 :            :         }
     664                 :            :     }
     665         [ +  - ]:          1 :     JL_CATCH {
     666                 :          1 :         free(atomicfields);
     667                 :          1 :         free(constfields);
     668                 :          1 :         jl_rethrow();
     669                 :            :     }
     670                 :      42538 :     tn->atomicfields = atomicfields;
     671                 :      42538 :     tn->constfields = constfields;
     672                 :            : 
     673         [ +  - ]:      42538 :     if (t->name->wrapper == NULL) {
     674                 :      42538 :         t->name->wrapper = (jl_value_t*)t;
     675                 :      42538 :         jl_gc_wb(t->name, t);
     676                 :      42538 :         int i, np = jl_svec_len(parameters);
     677         [ +  + ]:      47919 :         for (i = np - 1; i >= 0; i--) {
     678                 :       5381 :             t->name->wrapper = jl_new_struct(jl_unionall_type, jl_svecref(parameters, i), t->name->wrapper);
     679                 :       5381 :             jl_gc_wb(t->name, t->name->wrapper);
     680                 :            :         }
     681   [ +  +  +  +  :      42538 :         if (!mutabl && !abstract && ftypes != NULL)
                   +  + ]
     682                 :      16491 :             tn->mayinlinealloc = 1;
     683                 :            :     }
     684                 :      42538 :     jl_precompute_memoized_dt(t, 0);
     685                 :            : 
     686   [ +  +  +  + ]:      42538 :     if (!abstract && t->types != NULL)
     687                 :      16503 :         jl_compute_field_offsets(t);
     688                 :            : 
     689                 :      42538 :     JL_GC_POP();
     690                 :      42538 :     return t;
     691                 :            : }
     692                 :            : 
     693                 :        103 : JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *module,
     694                 :            :                                                  jl_datatype_t *super,
     695                 :            :                                                  jl_svec_t *parameters, size_t nbits)
     696                 :            : {
     697                 :        103 :     jl_datatype_t *bt = jl_new_datatype((jl_sym_t*)name, module, super, parameters,
     698                 :            :                                         jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 0, 0);
     699                 :        103 :     uint32_t nbytes = (nbits + 7) / 8;
     700                 :        103 :     uint32_t alignm = next_power_of_two(nbytes);
     701         [ +  + ]:        103 :     if (alignm > MAX_ALIGN)
     702                 :          8 :         alignm = MAX_ALIGN;
     703                 :        103 :     bt->isbitstype = (parameters == jl_emptysvec);
     704                 :        103 :     bt->size = nbytes;
     705                 :        103 :     bt->layout = jl_get_layout(0, 0, alignm, 0, NULL, NULL);
     706                 :        103 :     bt->instance = NULL;
     707                 :        103 :     return bt;
     708                 :            : }
     709                 :            : 
     710                 :          0 : JL_DLLEXPORT jl_datatype_t * jl_new_foreign_type(jl_sym_t *name,
     711                 :            :                                                  jl_module_t *module,
     712                 :            :                                                  jl_datatype_t *super,
     713                 :            :                                                  jl_markfunc_t markfunc,
     714                 :            :                                                  jl_sweepfunc_t sweepfunc,
     715                 :            :                                                  int haspointers,
     716                 :            :                                                  int large)
     717                 :            : {
     718                 :          0 :     jl_datatype_t *bt = jl_new_datatype(name, module, super,
     719                 :            :       jl_emptysvec, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 1, 0);
     720         [ #  # ]:          0 :     bt->size = large ? GC_MAX_SZCLASS+1 : 0;
     721                 :            :     jl_datatype_layout_t *layout = (jl_datatype_layout_t *)
     722                 :          0 :       jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) + sizeof(jl_fielddescdyn_t),
     723                 :            :         0, 4, 0);
     724                 :          0 :     layout->nfields = 0;
     725                 :          0 :     layout->alignment = sizeof(void *);
     726                 :          0 :     layout->haspadding = 1;
     727                 :          0 :     layout->npointers = haspointers;
     728                 :          0 :     layout->fielddesc_type = 3;
     729                 :          0 :     jl_fielddescdyn_t * desc =
     730                 :            :       (jl_fielddescdyn_t *) ((char *)layout + sizeof(*layout));
     731                 :          0 :     desc->markfunc = markfunc;
     732                 :          0 :     desc->sweepfunc = sweepfunc;
     733                 :          0 :     bt->layout = layout;
     734                 :          0 :     bt->instance = NULL;
     735                 :          0 :     return bt;
     736                 :            : }
     737                 :            : 
     738                 :       9504 : JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt)
     739                 :            : {
     740   [ +  -  +  -  :       9504 :     return jl_is_datatype(dt) && dt->layout && dt->layout->fielddesc_type == 3;
                   -  + ]
     741                 :            : }
     742                 :            : 
     743                 :            : 
     744                 :            : // bits constructors ----------------------------------------------------------
     745                 :            : 
     746                 :            : #if MAX_ATOMIC_SIZE > MAX_POINTERATOMIC_SIZE
     747                 :            : #error MAX_ATOMIC_SIZE too large
     748                 :            : #endif
     749                 :            : #if MAX_ATOMIC_SIZE >= 16 && !defined(_P64)
     750                 :            : #error 12 byte GC pool size alignment unimplemented for 32-bit
     751                 :            : #endif
     752                 :            : #if MAX_POINTERATOMIC_SIZE > 16
     753                 :            : #error MAX_POINTERATOMIC_SIZE too large
     754                 :            : #endif
     755                 :            : #if BYTE_ORDER != LITTLE_ENDIAN
     756                 :            : #error using masks for atomics (instead of memcpy like nb == 16) assumes little endian
     757                 :            : #endif
     758                 :            : 
     759                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
     760                 :            : typedef struct _jl_uint128_t {
     761                 :            :     uint64_t a;
     762                 :            :     uint64_t b;
     763                 :            : } jl_uint128_t;
     764                 :            : #endif
     765                 :            : 
     766                 :         20 : static inline uint32_t zext_read32(const jl_value_t *x, size_t nb) JL_NOTSAFEPOINT
     767                 :            : {
     768                 :         20 :     uint32_t y = *(uint32_t*)x;
     769         [ +  + ]:         20 :     if (nb == 4)
     770                 :         10 :         return y;
     771                 :            :     else // if (nb == 3)
     772                 :         10 :         return 0xffffffu & y;
     773                 :            : }
     774                 :            : 
     775                 :            : #if MAX_POINTERATOMIC_SIZE >= 8
     776                 :        139 : static inline uint64_t zext_read64(const jl_value_t *x, size_t nb) JL_NOTSAFEPOINT
     777                 :            : {
     778                 :        139 :     uint64_t y = *(uint64_t*)x;
     779         [ +  - ]:        139 :     if (nb == 8)
     780                 :        139 :         return y;
     781         [ #  # ]:          0 :     else if (nb == 7)
     782                 :          0 :         return 0xffffffffffffffu & y;
     783         [ #  # ]:          0 :     else if (nb == 6)
     784                 :          0 :         return 0xffffffffffffu & y;
     785                 :            :     else // if (nb == 5)
     786                 :          0 :         return 0xffffffffffu & y;
     787                 :            : }
     788                 :            : #endif
     789                 :            : 
     790                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
     791                 :            : static inline jl_uint128_t zext_read128(const jl_value_t *x, size_t nb) JL_NOTSAFEPOINT
     792                 :            : {
     793                 :            :     jl_uint128_t y = {0};
     794                 :            :     if (nb == 16)
     795                 :            :         y = *(jl_uint128_t*)x;
     796                 :            :     else
     797                 :            :         memcpy(&y, x, nb);
     798                 :            :     return y;
     799                 :            : }
     800                 :            : #endif
     801                 :            : 
     802                 : 1089170000 : JL_DLLEXPORT jl_value_t *jl_new_bits(jl_value_t *dt, const void *data)
     803                 :            : {
     804                 :            :     // data may not have the alignment required by the size
     805                 :            :     // but will always have the alignment required by the datatype
     806         [ -  + ]: 1089170000 :     assert(jl_is_datatype(dt));
     807                 : 1089170000 :     jl_datatype_t *bt = (jl_datatype_t*)dt;
     808                 : 1089170000 :     size_t nb = jl_datatype_size(bt);
     809                 :            :     // some types have special pools to minimize allocations
     810         [ +  + ]: 1089170000 :     if (nb == 0)               return jl_new_struct_uninit(bt); // returns bt->instance
     811   [ +  +  +  + ]:  911379000 :     if (bt == jl_bool_type)    return (1 & *(int8_t*)data) ? jl_true : jl_false;
     812         [ +  + ]:  878286000 :     if (bt == jl_uint8_type)   return jl_box_uint8(*(uint8_t*)data);
     813         [ +  + ]:  871093000 :     if (bt == jl_int64_type)   return jl_box_int64(*(int64_t*)data);
     814         [ +  + ]:  710360000 :     if (bt == jl_int32_type)   return jl_box_int32(*(int32_t*)data);
     815         [ +  + ]:  101113000 :     if (bt == jl_int8_type)    return jl_box_int8(*(int8_t*)data);
     816         [ +  + ]:  100340000 :     if (bt == jl_int16_type)   return jl_box_int16(*(int16_t*)data);
     817         [ +  + ]:  100335000 :     if (bt == jl_uint64_type)  return jl_box_uint64(*(uint64_t*)data);
     818         [ +  + ]:   96306300 :     if (bt == jl_uint32_type)  return jl_box_uint32(*(uint32_t*)data);
     819         [ +  + ]:   95352600 :     if (bt == jl_uint16_type)  return jl_box_uint16(*(uint16_t*)data);
     820         [ +  + ]:   95346700 :     if (bt == jl_char_type)    return jl_box_char(*(uint32_t*)data);
     821                 :            : 
     822                 :   94872000 :     jl_task_t *ct = jl_current_task;
     823                 :   94872000 :     jl_value_t *v = jl_gc_alloc(ct->ptls, nb, bt);
     824                 :   94872000 :     memcpy(jl_assume_aligned(v, sizeof(void*)), data, nb);
     825                 :   94872000 :     return v;
     826                 :            : }
     827                 :            : 
     828                 :        128 : JL_DLLEXPORT jl_value_t *jl_atomic_new_bits(jl_value_t *dt, const char *data)
     829                 :            : {
     830                 :            :     // data must have the required alignment for an atomic of the given size
     831         [ -  + ]:        128 :     assert(jl_is_datatype(dt));
     832                 :        128 :     jl_datatype_t *bt = (jl_datatype_t*)dt;
     833                 :        128 :     size_t nb = jl_datatype_size(bt);
     834                 :            :     // some types have special pools to minimize allocations
     835         [ +  + ]:        128 :     if (nb == 0)               return jl_new_struct_uninit(bt); // returns bt->instance
     836   [ +  +  +  + ]:        112 :     if (bt == jl_bool_type)    return (1 & jl_atomic_load((_Atomic(int8_t)*)data)) ? jl_true : jl_false;
     837         [ -  + ]:        100 :     if (bt == jl_uint8_type)   return jl_box_uint8(jl_atomic_load((_Atomic(uint8_t)*)data));
     838         [ +  + ]:        100 :     if (bt == jl_int64_type)   return jl_box_int64(jl_atomic_load((_Atomic(int64_t)*)data));
     839         [ -  + ]:         66 :     if (bt == jl_int32_type)   return jl_box_int32(jl_atomic_load((_Atomic(int32_t)*)data));
     840         [ -  + ]:         66 :     if (bt == jl_int8_type)    return jl_box_int8(jl_atomic_load((_Atomic(int8_t)*)data));
     841         [ -  + ]:         66 :     if (bt == jl_int16_type)   return jl_box_int16(jl_atomic_load((_Atomic(int16_t)*)data));
     842         [ -  + ]:         66 :     if (bt == jl_uint64_type)  return jl_box_uint64(jl_atomic_load((_Atomic(uint64_t)*)data));
     843         [ -  + ]:         66 :     if (bt == jl_uint32_type)  return jl_box_uint32(jl_atomic_load((_Atomic(uint32_t)*)data));
     844         [ -  + ]:         66 :     if (bt == jl_uint16_type)  return jl_box_uint16(jl_atomic_load((_Atomic(uint16_t)*)data));
     845         [ -  + ]:         66 :     if (bt == jl_char_type)    return jl_box_char(jl_atomic_load((_Atomic(uint32_t)*)data));
     846                 :            : 
     847                 :         66 :     jl_task_t *ct = jl_current_task;
     848                 :         66 :     jl_value_t *v = jl_gc_alloc(ct->ptls, nb, bt);
     849                 :            :     // data is aligned to the power of two,
     850                 :            :     // we will write too much of v, but the padding should exist
     851         [ -  + ]:         66 :     if (nb == 1)
     852                 :          0 :         *(uint8_t*) v = jl_atomic_load((_Atomic(uint8_t)*)data);
     853         [ -  + ]:         66 :     else if (nb <= 2)
     854                 :          0 :         *(uint16_t*)v = jl_atomic_load((_Atomic(uint16_t)*)data);
     855         [ +  + ]:         66 :     else if (nb <= 4)
     856                 :         18 :         *(uint32_t*)v = jl_atomic_load((_Atomic(uint32_t)*)data);
     857                 :            : #if MAX_POINTERATOMIC_SIZE >= 8
     858         [ +  - ]:         48 :     else if (nb <= 8)
     859                 :         48 :         *(uint64_t*)v = jl_atomic_load((_Atomic(uint64_t)*)data);
     860                 :            : #endif
     861                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
     862                 :            :     else if (nb <= 16)
     863                 :            :         *(jl_uint128_t*)v = jl_atomic_load((_Atomic(jl_uint128_t)*)data);
     864                 :            : #endif
     865                 :            :     else
     866                 :          0 :         abort();
     867                 :         66 :     return v;
     868                 :            : }
     869                 :            : 
     870                 :         31 : JL_DLLEXPORT void jl_atomic_store_bits(char *dst, const jl_value_t *src, int nb)
     871                 :            : {
     872                 :            :     // dst must have the required alignment for an atomic of the given size
     873                 :            :     // src must be aligned by the GC
     874                 :            :     // we may therefore read too much from src, but will zero the excess bits
     875                 :            :     // before the store (so that we can get faster cmpswap later)
     876         [ +  + ]:         31 :     if (nb == 0)
     877                 :            :         ;
     878         [ +  + ]:         26 :     else if (nb == 1)
     879                 :          4 :         jl_atomic_store((_Atomic(uint8_t)*)dst, *(uint8_t*)src);
     880         [ -  + ]:         22 :     else if (nb == 2)
     881                 :          0 :         jl_atomic_store((_Atomic(uint16_t)*)dst, *(uint16_t*)src);
     882         [ +  + ]:         22 :     else if (nb <= 4)
     883                 :          2 :         jl_atomic_store((_Atomic(uint32_t)*)dst, zext_read32(src, nb));
     884                 :            : #if MAX_POINTERATOMIC_SIZE >= 8
     885         [ +  - ]:         20 :     else if (nb <= 8)
     886                 :         20 :         jl_atomic_store((_Atomic(uint64_t)*)dst, zext_read64(src, nb));
     887                 :            : #endif
     888                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
     889                 :            :     else if (nb <= 16)
     890                 :            :         jl_atomic_store((_Atomic(jl_uint128_t)*)dst, zext_read128(src, nb));
     891                 :            : #endif
     892                 :            :     else
     893                 :          0 :         abort();
     894                 :         31 : }
     895                 :            : 
     896                 :         34 : JL_DLLEXPORT jl_value_t *jl_atomic_swap_bits(jl_value_t *dt, char *dst, const jl_value_t *src, int nb)
     897                 :            : {
     898                 :            :     // dst must have the required alignment for an atomic of the given size
     899         [ -  + ]:         34 :     assert(jl_is_datatype(dt));
     900                 :         34 :     jl_datatype_t *bt = (jl_datatype_t*)dt;
     901                 :            :     // some types have special pools to minimize allocations
     902         [ +  + ]:         34 :     if (nb == 0)               return jl_new_struct_uninit(bt); // returns bt->instance
     903   [ +  +  +  + ]:         28 :     if (bt == jl_bool_type)    return (1 & jl_atomic_exchange((_Atomic(int8_t)*)dst, 1 & *(int8_t*)src)) ? jl_true : jl_false;
     904         [ -  + ]:         23 :     if (bt == jl_uint8_type)   return jl_box_uint8(jl_atomic_exchange((_Atomic(uint8_t)*)dst, *(int8_t*)src));
     905         [ +  + ]:         23 :     if (bt == jl_int64_type)   return jl_box_int64(jl_atomic_exchange((_Atomic(int64_t)*)dst, *(int64_t*)src));
     906         [ -  + ]:         15 :     if (bt == jl_int32_type)   return jl_box_int32(jl_atomic_exchange((_Atomic(int32_t)*)dst, *(int32_t*)src));
     907         [ -  + ]:         15 :     if (bt == jl_int8_type)    return jl_box_int8(jl_atomic_exchange((_Atomic(int8_t)*)dst, *(int8_t*)src));
     908         [ -  + ]:         15 :     if (bt == jl_int16_type)   return jl_box_int16(jl_atomic_exchange((_Atomic(int16_t)*)dst, *(int16_t*)src));
     909         [ -  + ]:         15 :     if (bt == jl_uint64_type)  return jl_box_uint64(jl_atomic_exchange((_Atomic(uint64_t)*)dst, *(uint64_t*)src));
     910         [ -  + ]:         15 :     if (bt == jl_uint32_type)  return jl_box_uint32(jl_atomic_exchange((_Atomic(uint32_t)*)dst, *(uint32_t*)src));
     911         [ -  + ]:         15 :     if (bt == jl_uint16_type)  return jl_box_uint16(jl_atomic_exchange((_Atomic(uint16_t)*)dst, *(uint16_t*)src));
     912         [ -  + ]:         15 :     if (bt == jl_char_type)    return jl_box_char(jl_atomic_exchange((_Atomic(uint32_t)*)dst, *(uint32_t*)src));
     913                 :            : 
     914                 :         15 :     jl_task_t *ct = jl_current_task;
     915                 :         15 :     jl_value_t *v = jl_gc_alloc(ct->ptls, jl_datatype_size(bt), bt);
     916         [ -  + ]:         15 :     if (nb == 1)
     917                 :          0 :         *(uint8_t*)v = jl_atomic_exchange((_Atomic(uint8_t)*)dst, *(uint8_t*)src);
     918         [ -  + ]:         15 :     else if (nb == 2)
     919                 :          0 :         *(uint16_t*)v = jl_atomic_exchange((_Atomic(uint16_t)*)dst, *(uint16_t*)src);
     920         [ +  + ]:         15 :     else if (nb <= 4)
     921                 :          2 :         *(uint32_t*)v = jl_atomic_exchange((_Atomic(uint32_t)*)dst, zext_read32(src, nb));
     922                 :            : #if MAX_POINTERATOMIC_SIZE >= 8
     923         [ +  - ]:         13 :     else if (nb <= 8)
     924                 :         13 :         *(uint64_t*)v = jl_atomic_exchange((_Atomic(uint64_t)*)dst, zext_read64(src, nb));
     925                 :            : #endif
     926                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
     927                 :            :     else if (nb <= 16)
     928                 :            :         *(jl_uint128_t*)v = jl_atomic_exchange((_Atomic(jl_uint128_t)*)dst, zext_read128(src, nb));
     929                 :            : #endif
     930                 :            :     else
     931                 :          0 :         abort();
     932                 :         15 :     return v;
     933                 :            : }
     934                 :            : 
     935                 :         45 : JL_DLLEXPORT int jl_atomic_bool_cmpswap_bits(char *dst, const jl_value_t *expected, const jl_value_t *src, int nb)
     936                 :            : {
     937                 :            :     // dst must have the required alignment for an atomic of the given size
     938                 :            :     // n.b.: this can spuriously fail if there are padding bits, the caller should deal with that
     939                 :            :     int success;
     940         [ +  + ]:         45 :     if (nb == 0) {
     941                 :          6 :         success = 1;
     942                 :            :     }
     943         [ +  + ]:         39 :     else if (nb == 1) {
     944                 :          5 :         uint8_t y = *(uint8_t*)expected;
     945                 :          5 :         success = jl_atomic_cmpswap((_Atomic(uint8_t)*)dst, &y, *(uint8_t*)src);
     946                 :            :     }
     947         [ -  + ]:         34 :     else if (nb == 2) {
     948                 :          0 :         uint16_t y = *(uint16_t*)expected;
     949                 :          0 :         success = jl_atomic_cmpswap((_Atomic(uint16_t)*)dst, &y, *(uint16_t*)src);
     950                 :            :     }
     951         [ +  + ]:         34 :     else if (nb <= 4) {
     952                 :          4 :         uint32_t y = zext_read32(expected, nb);
     953                 :          4 :         uint32_t z = zext_read32(src, nb);
     954                 :          4 :         success = jl_atomic_cmpswap((_Atomic(uint32_t)*)dst, &y, z);
     955                 :            :     }
     956                 :            : #if MAX_POINTERATOMIC_SIZE >= 8
     957         [ +  - ]:         30 :     else if (nb <= 8) {
     958                 :         30 :         uint64_t y = zext_read64(expected, nb);
     959                 :         30 :         uint64_t z = zext_read64(src, nb);
     960                 :         30 :         success = jl_atomic_cmpswap((_Atomic(uint64_t)*)dst, &y, z);
     961                 :            :     }
     962                 :            : #endif
     963                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
     964                 :            :     else if (nb <= 16) {
     965                 :            :         jl_uint128_t y = zext_read128(expected, nb);
     966                 :            :         jl_uint128_t z = zext_read128(src, nb);
     967                 :            :         success = jl_atomic_cmpswap((_Atomic(jl_uint128_t)*)dst, &y, z);
     968                 :            :     }
     969                 :            : #endif
     970                 :            :     else {
     971                 :          0 :         abort();
     972                 :            :     }
     973                 :         45 :     return success;
     974                 :            : }
     975                 :            : 
     976                 :         41 : JL_DLLEXPORT jl_value_t *jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_datatype_t *rettyp, char *dst, const jl_value_t *expected, const jl_value_t *src, int nb)
     977                 :            : {
     978                 :            :     // dst must have the required alignment for an atomic of the given size
     979                 :            :     // n.b.: this does not spuriously fail if there are padding bits
     980                 :         41 :     jl_task_t *ct = jl_current_task;
     981                 :         41 :     int isptr = jl_field_isptr(rettyp, 0);
     982   [ +  +  +  + ]:         41 :     jl_value_t *y = jl_gc_alloc(ct->ptls, isptr ? nb : rettyp->size, isptr ? dt : rettyp);
     983                 :            :     int success;
     984                 :         41 :     jl_datatype_t *et = (jl_datatype_t*)jl_typeof(expected);
     985         [ +  + ]:         41 :     if (nb == 0) {
     986                 :          5 :         success = (dt == et);
     987                 :            :     }
     988         [ +  + ]:         36 :     else if (nb == 1) {
     989                 :          3 :         uint8_t *y8 = (uint8_t*)y;
     990         [ -  + ]:          3 :         assert(!dt->layout->haspadding);
     991         [ +  - ]:          3 :         if (dt == et) {
     992                 :          3 :             *y8 = *(uint8_t*)expected;
     993                 :          3 :             uint8_t z8 = *(uint8_t*)src;
     994                 :          3 :             success = jl_atomic_cmpswap((_Atomic(uint8_t)*)dst, y8, z8);
     995                 :            :         }
     996                 :            :         else {
     997                 :          0 :             *y8 = jl_atomic_load((_Atomic(uint8_t)*)dst);
     998                 :          0 :             success = 0;
     999                 :            :         }
    1000                 :            :     }
    1001         [ -  + ]:         33 :     else if (nb == 2) {
    1002                 :          0 :         uint16_t *y16 = (uint16_t*)y;
    1003         [ #  # ]:          0 :         assert(!dt->layout->haspadding);
    1004         [ #  # ]:          0 :         if (dt == et) {
    1005                 :          0 :             *y16 = *(uint16_t*)expected;
    1006                 :          0 :             uint16_t z16 = *(uint16_t*)src;
    1007                 :          0 :             success = jl_atomic_cmpswap((_Atomic(uint16_t)*)dst, y16, z16);
    1008                 :            :         }
    1009                 :            :         else {
    1010                 :          0 :             *y16 = jl_atomic_load((_Atomic(uint16_t)*)dst);
    1011                 :          0 :             success = 0;
    1012                 :            :         }
    1013                 :            :     }
    1014         [ +  + ]:         33 :     else if (nb <= 4) {
    1015                 :          6 :         uint32_t *y32 = (uint32_t*)y;
    1016         [ +  + ]:          6 :         if (dt == et) {
    1017                 :          4 :             *y32 = zext_read32(expected, nb);
    1018                 :          4 :             uint32_t z32 = zext_read32(src, nb);
    1019                 :            :             while (1) {
    1020                 :          5 :                 success = jl_atomic_cmpswap((_Atomic(uint32_t)*)dst, y32, z32);
    1021   [ +  +  +  +  :          5 :                 if (success || !dt->layout->haspadding || !jl_egal__bits(y, expected, dt))
                   +  + ]
    1022                 :            :                     break;
    1023                 :            :             }
    1024                 :            :         }
    1025                 :            :         else {
    1026                 :          2 :             *y32 = jl_atomic_load((_Atomic(uint32_t)*)dst);
    1027                 :          2 :             success = 0;
    1028                 :            :         }
    1029                 :            :     }
    1030                 :            : #if MAX_POINTERATOMIC_SIZE >= 8
    1031         [ +  - ]:         27 :     else if (nb <= 8) {
    1032                 :         27 :         uint64_t *y64 = (uint64_t*)y;
    1033         [ +  + ]:         27 :         if (dt == et) {
    1034                 :         23 :             *y64 = zext_read64(expected, nb);
    1035                 :         23 :             uint64_t z64 = zext_read64(src, nb);
    1036                 :            :             while (1) {
    1037                 :         23 :                 success = jl_atomic_cmpswap((_Atomic(uint64_t)*)dst, y64, z64);
    1038   [ +  +  -  +  :         23 :                 if (success || !dt->layout->haspadding || !jl_egal__bits(y, expected, dt))
                   -  - ]
    1039                 :            :                     break;
    1040                 :            :             }
    1041                 :            :         }
    1042                 :            :         else {
    1043                 :          4 :             *y64 = jl_atomic_load((_Atomic(uint64_t)*)dst);
    1044                 :          4 :             success = 0;
    1045                 :            :         }
    1046                 :            :     }
    1047                 :            : #endif
    1048                 :            : #if MAX_POINTERATOMIC_SIZE >= 16
    1049                 :            :     else if (nb <= 16) {
    1050                 :            :         jl_uint128_t *y128 = (jl_uint128_t*)y;
    1051                 :            :         if (dt == et) {
    1052                 :            :             *y128 = zext_read128(expected, nb);
    1053                 :            :             jl_uint128_t z128 = zext_read128(src, nb);
    1054                 :            :             while (1) {
    1055                 :            :                 success = jl_atomic_cmpswap((_Atomic(jl_uint128_t)*)dst, y128, z128);
    1056                 :            :                 if (success || !dt->layout->haspadding || !jl_egal__bits(y, expected, dt))
    1057                 :            :                     break;
    1058                 :            :             }
    1059                 :            :         }
    1060                 :            :         else {
    1061                 :            :             *y128 = jl_atomic_load((_Atomic(jl_uint128_t)*)dst);
    1062                 :            :             success = 0;
    1063                 :            :         }
    1064                 :            :     }
    1065                 :            : #endif
    1066                 :            :     else {
    1067                 :          0 :         abort();
    1068                 :            :     }
    1069         [ +  + ]:         41 :     if (isptr) {
    1070                 :          3 :         JL_GC_PUSH1(&y);
    1071                 :          3 :         jl_value_t *z = jl_gc_alloc(ct->ptls, rettyp->size, rettyp);
    1072                 :          3 :         *(jl_value_t**)z = y;
    1073                 :          3 :         JL_GC_POP();
    1074                 :          3 :         y = z;
    1075                 :          3 :         nb = sizeof(jl_value_t*);
    1076                 :            :     }
    1077                 :         41 :     *((uint8_t*)y + nb) = success ? 1 : 0;
    1078                 :         41 :     return y;
    1079                 :            : }
    1080                 :            : 
    1081                 :            : 
    1082                 :            : 
    1083                 :            : // used by boot.jl
    1084                 :          1 : JL_DLLEXPORT jl_value_t *jl_typemax_uint(jl_value_t *bt)
    1085                 :            : {
    1086                 :          1 :     uint64_t data = 0xffffffffffffffffULL;
    1087                 :          1 :     jl_task_t *ct = jl_current_task;
    1088                 :          1 :     jl_value_t *v = jl_gc_alloc(ct->ptls, sizeof(size_t), bt);
    1089                 :          1 :     memcpy(v, &data, sizeof(size_t));
    1090                 :          1 :     return v;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : #define PERMBOXN_FUNC(nb,nw)                                            \
    1094                 :            :     jl_value_t *jl_permbox##nb(jl_datatype_t *t, int##nb##_t x)         \
    1095                 :            :     {   /* NOTE: t must be a concrete isbits datatype */                \
    1096                 :            :         assert(jl_datatype_size(t) == sizeof(x));                       \
    1097                 :            :         jl_value_t *v = jl_gc_permobj(nw * sizeof(void*), t);           \
    1098                 :            :         *(int##nb##_t*)jl_data_ptr(v) = x;                              \
    1099                 :            :         return v;                                                       \
    1100                 :            :     }
    1101         [ -  + ]:     290306 : PERMBOXN_FUNC(8,  1)
    1102         [ -  + ]:    1161220 : PERMBOXN_FUNC(16, 1)
    1103         [ -  + ]:    1233880 : PERMBOXN_FUNC(32, 1)
    1104                 :            : #ifdef _P64
    1105         [ -  + ]:    2322430 : PERMBOXN_FUNC(64, 1)
    1106                 :            : #else
    1107                 :            : PERMBOXN_FUNC(64, 2)
    1108                 :            : #endif
    1109                 :            : 
    1110                 :            : #define UNBOX_FUNC(j_type,c_type)                                       \
    1111                 :            :     JL_DLLEXPORT c_type jl_unbox_##j_type(jl_value_t *v)                \
    1112                 :            :     {                                                                   \
    1113                 :            :         assert(jl_is_primitivetype(jl_typeof(v)));                      \
    1114                 :            :         assert(jl_datatype_size(jl_typeof(v)) == sizeof(c_type));       \
    1115                 :            :         return *(c_type*)jl_data_ptr(v);                                \
    1116                 :            :     }
    1117   [ #  #  #  # ]:          0 : UNBOX_FUNC(int8,   int8_t)
    1118   [ -  +  -  + ]:     209892 : UNBOX_FUNC(uint8,  uint8_t)
    1119   [ #  #  #  # ]:          0 : UNBOX_FUNC(int16,  int16_t)
    1120   [ #  #  #  # ]:          0 : UNBOX_FUNC(uint16, uint16_t)
    1121   [ -  +  -  + ]:  168591000 : UNBOX_FUNC(int32,  int32_t)
    1122   [ #  #  #  # ]:          0 : UNBOX_FUNC(uint32, uint32_t)
    1123   [ #  +  -  + ]:  309509000 : UNBOX_FUNC(int64,  int64_t)
    1124   [ -  +  -  + ]:   10639200 : UNBOX_FUNC(uint64, uint64_t)
    1125   [ -  +  -  + ]:        732 : UNBOX_FUNC(bool,   int8_t)
    1126   [ #  #  #  # ]:          0 : UNBOX_FUNC(float32, float)
    1127   [ -  +  -  + ]:        167 : UNBOX_FUNC(float64, double)
    1128   [ -  +  -  + ]:         91 : UNBOX_FUNC(voidpointer, void*)
    1129   [ #  #  #  # ]:          0 : UNBOX_FUNC(uint8pointer, uint8_t*)
    1130                 :            : 
    1131                 :            : #define BOX_FUNC(typ,c_type,pfx,nw)                                     \
    1132                 :            :     JL_DLLEXPORT jl_value_t *pfx##_##typ(c_type x)                      \
    1133                 :            :     {                                                                   \
    1134                 :            :         jl_task_t *ct = jl_current_task;                                \
    1135                 :            :         jl_value_t *v = jl_gc_alloc(ct->ptls, nw * sizeof(void*),       \
    1136                 :            :                                     jl_##typ##_type);                   \
    1137                 :            :         *(c_type*)jl_data_ptr(v) = x;                                   \
    1138                 :            :         return v;                                                       \
    1139                 :            :     }
    1140                 : 1806680000 : BOX_FUNC(float32, float,  jl_box, 1)
    1141                 :          4 : BOX_FUNC(voidpointer, void*,  jl_box, 1)
    1142                 :        173 : BOX_FUNC(uint8pointer, uint8_t*,  jl_box, 1)
    1143                 :            : #ifdef _P64
    1144                 :      21765 : BOX_FUNC(float64, double, jl_box, 1)
    1145                 :            : #else
    1146                 :            : BOX_FUNC(float64, double, jl_box, 2)
    1147                 :            : #endif
    1148                 :            : 
    1149                 :            : #define NBOX_C 1024
    1150                 :            : 
    1151                 :            : #define SIBOX_FUNC(typ,c_type,nw)\
    1152                 :            :     static jl_value_t *boxed_##typ##_cache[NBOX_C];                     \
    1153                 :            :     JL_DLLEXPORT jl_value_t *jl_box_##typ(c_type x)                     \
    1154                 :            :     {                                                                   \
    1155                 :            :         jl_task_t *ct = jl_current_task;                                \
    1156                 :            :         c_type idx = x+NBOX_C/2;                                        \
    1157                 :            :         if ((u##c_type)idx < (u##c_type)NBOX_C)                         \
    1158                 :            :             return boxed_##typ##_cache[idx];                            \
    1159                 :            :         jl_value_t *v = jl_gc_alloc(ct->ptls, nw * sizeof(void*),       \
    1160                 :            :                                     jl_##typ##_type);                   \
    1161                 :            :         *(c_type*)jl_data_ptr(v) = x;                                   \
    1162                 :            :         return v;                                                       \
    1163                 :            :     }
    1164                 :            : #define UIBOX_FUNC(typ,c_type,nw)                                       \
    1165                 :            :     static jl_value_t *boxed_##typ##_cache[NBOX_C];                     \
    1166                 :            :     JL_DLLEXPORT jl_value_t *jl_box_##typ(c_type x)                     \
    1167                 :            :     {                                                                   \
    1168                 :            :         jl_task_t *ct = jl_current_task;                                \
    1169                 :            :         if (x < NBOX_C)                                                 \
    1170                 :            :             return boxed_##typ##_cache[x];                              \
    1171                 :            :         jl_value_t *v = jl_gc_alloc(ct->ptls, nw * sizeof(void*),       \
    1172                 :            :                                     jl_##typ##_type);                   \
    1173                 :            :         *(c_type*)jl_data_ptr(v) = x;                                   \
    1174                 :            :         return v;                                                       \
    1175                 :            :     }
    1176         [ +  + ]:     890521 : SIBOX_FUNC(int16,  int16_t, 1)
    1177         [ +  + ]:  986597000 : SIBOX_FUNC(int32,  int32_t, 1)
    1178         [ +  + ]:     948644 : UIBOX_FUNC(uint16, uint16_t, 1)
    1179         [ +  + ]:    1815670 : UIBOX_FUNC(uint32, uint32_t, 1)
    1180         [ +  + ]: 1949060000 : UIBOX_FUNC(ssavalue, size_t, 1)
    1181         [ +  + ]:   39431500 : UIBOX_FUNC(slotnumber, size_t, 1)
    1182                 :            : #ifdef _P64
    1183         [ +  + ]: 1950330000 : SIBOX_FUNC(int64,  int64_t, 1)
    1184         [ +  + ]:   22034300 : UIBOX_FUNC(uint64, uint64_t, 1)
    1185                 :            : #else
    1186                 :            : SIBOX_FUNC(int64,  int64_t, 2)
    1187                 :            : UIBOX_FUNC(uint64, uint64_t, 2)
    1188                 :            : #endif
    1189                 :            : 
    1190                 :            : static jl_value_t *boxed_char_cache[128];
    1191                 :    3479080 : JL_DLLEXPORT jl_value_t *jl_box_char(uint32_t x)
    1192                 :            : {
    1193                 :    3479080 :     jl_task_t *ct = jl_current_task;
    1194                 :    3479080 :     uint32_t u = bswap_32(x);
    1195         [ +  + ]:    3479080 :     if (u < 128)
    1196                 :    3154020 :         return boxed_char_cache[(uint8_t)u];
    1197                 :     325069 :     jl_value_t *v = jl_gc_alloc(ct->ptls, sizeof(void*), jl_char_type);
    1198                 :     325069 :     *(uint32_t*)jl_data_ptr(v) = x;
    1199                 :     325069 :     return v;
    1200                 :            : }
    1201                 :            : 
    1202                 :            : JL_DLLEXPORT jl_value_t *jl_boxed_int8_cache[256];
    1203                 :     772995 : JL_DLLEXPORT jl_value_t *jl_box_int8(int8_t x)
    1204                 :            : {
    1205                 :     772995 :     return jl_boxed_int8_cache[(uint8_t)x];
    1206                 :            : }
    1207                 :            : JL_DLLEXPORT jl_value_t *jl_boxed_uint8_cache[256];
    1208                 :    8255740 : JL_DLLEXPORT jl_value_t *jl_box_uint8(uint8_t x)
    1209                 :            : {
    1210                 :    8255740 :     return jl_boxed_uint8_cache[x];
    1211                 :            : }
    1212                 :            : 
    1213                 :        567 : void jl_init_int32_int64_cache(void)
    1214                 :            : {
    1215                 :            :     int64_t i;
    1216         [ +  + ]:     581175 :     for(i=0; i < NBOX_C; i++) {
    1217                 :     580608 :         boxed_int32_cache[i]  = jl_permbox32(jl_int32_type, i-NBOX_C/2);
    1218                 :     580608 :         boxed_int64_cache[i]  = jl_permbox64(jl_int64_type, i-NBOX_C/2);
    1219                 :            : #ifdef _P64
    1220                 :     580608 :         boxed_ssavalue_cache[i] = jl_permbox64(jl_ssavalue_type, i);
    1221                 :     580608 :         boxed_slotnumber_cache[i] = jl_permbox64(jl_slotnumber_type, i);
    1222                 :            : #else
    1223                 :            :         boxed_ssavalue_cache[i] = jl_permbox32(jl_ssavalue_type, i);
    1224                 :            :         boxed_slotnumber_cache[i] = jl_permbox32(jl_slotnumber_type, i);
    1225                 :            : #endif
    1226                 :            :     }
    1227         [ +  + ]:     145719 :     for(i=0; i < 256; i++) {
    1228                 :     145152 :         jl_boxed_uint8_cache[i] = jl_permbox8(jl_uint8_type, i);
    1229                 :            :     }
    1230                 :        567 : }
    1231                 :            : 
    1232                 :        567 : void jl_init_box_caches(void)
    1233                 :            : {
    1234                 :            :     int64_t i;
    1235         [ +  + ]:      73143 :     for(i=0; i < 128; i++) {
    1236                 :      72576 :         boxed_char_cache[i] = jl_permbox32(jl_char_type, i << 24);
    1237                 :            :     }
    1238         [ +  + ]:     145719 :     for(i=0; i < 256; i++) {
    1239                 :     145152 :         jl_boxed_int8_cache[i] = jl_permbox8(jl_int8_type, i);
    1240                 :            :     }
    1241         [ +  + ]:     581175 :     for(i=0; i < NBOX_C; i++) {
    1242                 :     580608 :         boxed_int16_cache[i]  = jl_permbox16(jl_int16_type, i-NBOX_C/2);
    1243                 :     580608 :         boxed_uint16_cache[i] = jl_permbox16(jl_uint16_type, i);
    1244                 :     580608 :         boxed_uint32_cache[i] = jl_permbox32(jl_uint32_type, i);
    1245                 :     580608 :         boxed_uint64_cache[i] = jl_permbox64(jl_uint64_type, i);
    1246                 :            :     }
    1247                 :        567 : }
    1248                 :            : 
    1249                 :     430226 : JL_DLLEXPORT jl_value_t *jl_box_bool(int8_t x)
    1250                 :            : {
    1251         [ +  + ]:     430226 :     if (x)
    1252                 :      38217 :         return jl_true;
    1253                 :     392009 :     return jl_false;
    1254                 :            : }
    1255                 :            : 
    1256                 :            : // struct constructors --------------------------------------------------------
    1257                 :            : 
    1258                 :  223149000 : JL_DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...)
    1259                 :            : {
    1260                 :  223149000 :     jl_task_t *ct = jl_current_task;
    1261         [ +  + ]:  223149000 :     if (type->instance != NULL) return type->instance;
    1262                 :            :     va_list args;
    1263                 :  223133000 :     size_t i, nf = jl_datatype_nfields(type);
    1264                 :  223133000 :     va_start(args, type);
    1265                 :  223133000 :     jl_value_t *jv = jl_gc_alloc(ct->ptls, jl_datatype_size(type), type);
    1266   [ +  -  -  + ]:  223133000 :     if (nf > 0 && jl_field_offset(type, 0) != 0) {
    1267                 :          0 :         memset(jv, 0, jl_field_offset(type, 0));
    1268                 :            :     }
    1269         [ +  + ]:  670449000 :     for (i = 0; i < nf; i++) {
    1270                 :  447316000 :         set_nth_field(type, jv, i, va_arg(args, jl_value_t*), 0);
    1271                 :            :     }
    1272                 :  223133000 :     va_end(args);
    1273                 :  223133000 :     return jv;
    1274                 :            : }
    1275                 :            : 
    1276                 :   16033000 : JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na)
    1277                 :            : {
    1278                 :   16033000 :     jl_task_t *ct = jl_current_task;
    1279   [ +  +  +  + ]:   16033000 :     if (!jl_is_datatype(type) || type->layout == NULL) {
    1280                 :          2 :         jl_type_error("new", (jl_value_t*)jl_datatype_type, (jl_value_t*)type);
    1281                 :            :     }
    1282                 :   16033000 :     size_t nf = jl_datatype_nfields(type);
    1283   [ +  +  +  + ]:   16033000 :     if (nf - type->name->n_uninitialized > na || na > nf)
    1284                 :          2 :         jl_error("invalid struct allocation");
    1285         [ +  + ]:   36237000 :     for (size_t i = 0; i < na; i++) {
    1286                 :   20204000 :         jl_value_t *ft = jl_field_type_concrete(type, i);
    1287         [ +  + ]:   20204000 :         if (!jl_isa(args[i], ft))
    1288                 :          1 :             jl_type_error("new", ft, args[i]);
    1289                 :            :     }
    1290         [ +  + ]:   16033000 :     if (type->instance != NULL)
    1291                 :     793377 :         return type->instance;
    1292                 :   15239600 :     jl_value_t *jv = jl_gc_alloc(ct->ptls, jl_datatype_size(type), type);
    1293         [ +  + ]:   15239600 :     if (jl_datatype_nfields(type) > 0) {
    1294         [ -  + ]:   15239600 :         if (jl_field_offset(type, 0) != 0) {
    1295                 :          0 :             memset(jl_data_ptr(jv), 0, jl_field_offset(type, 0));
    1296                 :            :         }
    1297                 :   15239600 :         JL_GC_PUSH1(&jv);
    1298         [ +  + ]:   34842300 :         for (size_t i = 0; i < na; i++) {
    1299                 :   19602700 :             set_nth_field(type, jv, i, args[i], 0);
    1300                 :            :         }
    1301         [ +  + ]:   15239600 :         if (na < jl_datatype_nfields(type)) {
    1302                 :      14231 :             char *data = (char*)jl_data_ptr(jv);
    1303                 :      14231 :             size_t offs = jl_field_offset(type, na);
    1304                 :      14231 :             memset(data + offs, 0, jl_datatype_size(type) - offs);
    1305                 :            :         }
    1306                 :   15239600 :         JL_GC_POP();
    1307                 :            :     }
    1308                 :   15239600 :     return jv;
    1309                 :            : }
    1310                 :            : 
    1311                 :     172977 : JL_DLLEXPORT jl_value_t *jl_new_structt(jl_datatype_t *type, jl_value_t *tup)
    1312                 :            : {
    1313                 :     172977 :     jl_task_t *ct = jl_current_task;
    1314         [ -  + ]:     172977 :     if (!jl_is_tuple(tup))
    1315                 :          0 :         jl_type_error("new", (jl_value_t*)jl_tuple_type, tup);
    1316   [ +  +  +  + ]:     172977 :     if (!jl_is_datatype(type) || type->layout == NULL)
    1317                 :          3 :         jl_type_error("new", (jl_value_t *)jl_datatype_type, (jl_value_t *)type);
    1318                 :     172974 :     size_t nargs = jl_nfields(tup);
    1319                 :     172974 :     size_t nf = jl_datatype_nfields(type);
    1320   [ -  +  -  + ]:     172974 :     JL_NARGS(new, nf, nf);
    1321         [ +  + ]:     172974 :     if (type->instance != NULL) {
    1322                 :      56168 :         jl_datatype_t *tupt = (jl_datatype_t*)jl_typeof(tup);
    1323         [ +  + ]:      87612 :         for (size_t i = 0; i < nargs; i++) {
    1324                 :      31444 :             jl_value_t *ft = jl_field_type_concrete(type, i);
    1325                 :      31444 :             jl_value_t *et = jl_field_type_concrete(tupt, i);
    1326   [ +  -  +  - ]:      31444 :             assert(jl_is_concrete_type(ft) && jl_is_concrete_type(et));
    1327         [ -  + ]:      31444 :             if (et != ft)
    1328                 :          0 :                 jl_type_error("new", ft, jl_get_nth_field(tup, i));
    1329                 :            :         }
    1330                 :      56168 :         return type->instance;
    1331                 :            :     }
    1332                 :     116806 :     size_t size = jl_datatype_size(type);
    1333                 :     116806 :     jl_value_t *jv = jl_gc_alloc(ct->ptls, size, type);
    1334         [ -  + ]:     116806 :     if (nf == 0)
    1335                 :          0 :         return jv;
    1336                 :     116806 :     jl_value_t *fi = NULL;
    1337         [ +  + ]:     116806 :     if (type->zeroinit) {
    1338                 :            :         // if there are references, zero the space first to prevent the GC
    1339                 :            :         // from seeing uninitialized references during jl_get_nth_field and jl_isa,
    1340                 :            :         // which can allocate.
    1341                 :        124 :         memset(jl_data_ptr(jv), 0, size);
    1342                 :            :     }
    1343         [ -  + ]:     116682 :     else if (jl_field_offset(type, 0) != 0) {
    1344                 :          0 :         memset(jl_data_ptr(jv), 0, jl_field_offset(type, 0));
    1345                 :            :     }
    1346                 :     116806 :     JL_GC_PUSH2(&jv, &fi);
    1347         [ +  + ]:     307944 :     for (size_t i = 0; i < nargs; i++) {
    1348                 :     191138 :         jl_value_t *ft = jl_field_type_concrete(type, i);
    1349                 :     191138 :         fi = jl_get_nth_field(tup, i);
    1350         [ -  + ]:     191138 :         if (!jl_isa(fi, ft))
    1351                 :          0 :             jl_type_error("new", ft, fi);
    1352                 :     191138 :         set_nth_field(type, jv, i, fi, 0);
    1353                 :            :     }
    1354                 :     116806 :     JL_GC_POP();
    1355                 :     116806 :     return jv;
    1356                 :            : }
    1357                 :            : 
    1358                 :  478965000 : JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type)
    1359                 :            : {
    1360                 :  478965000 :     jl_task_t *ct = jl_current_task;
    1361         [ +  + ]:  478965000 :     if (type->instance != NULL) return type->instance;
    1362                 :  301141000 :     size_t size = jl_datatype_size(type);
    1363                 :  301141000 :     jl_value_t *jv = jl_gc_alloc(ct->ptls, size, type);
    1364         [ +  + ]:  301141000 :     if (size > 0)
    1365                 :  301141000 :         memset(jl_data_ptr(jv), 0, size);
    1366                 :  301141000 :     return jv;
    1367                 :            : }
    1368                 :            : 
    1369                 :            : // field access ---------------------------------------------------------------
    1370                 :            : 
    1371                 :         94 : JL_DLLEXPORT void jl_lock_value(jl_value_t *v) JL_NOTSAFEPOINT
    1372                 :            : {
    1373                 :         94 :     JL_LOCK_NOGC((jl_mutex_t*)v);
    1374                 :         94 : }
    1375                 :            : 
    1376                 :         94 : JL_DLLEXPORT void jl_unlock_value(jl_value_t *v) JL_NOTSAFEPOINT
    1377                 :            : {
    1378                 :         94 :     JL_UNLOCK_NOGC((jl_mutex_t*)v);
    1379                 :         94 : }
    1380                 :            : 
    1381                 :  258836000 : JL_DLLEXPORT int jl_field_index(jl_datatype_t *t, jl_sym_t *fld, int err)
    1382                 :            : {
    1383         [ +  + ]:  258836000 :     if (jl_is_namedtuple_type(t)) {
    1384                 :    1152090 :         jl_value_t *ns = jl_tparam0(t);
    1385         [ +  + ]:    1152090 :         if (jl_is_tuple(ns)) {
    1386                 :    1150810 :             size_t i, n = jl_nfields(ns);
    1387         [ +  + ]:    2327630 :             for (i = 0; i < n; i++) {
    1388         [ +  + ]:    1930320 :                 if (jl_get_nth_field(ns, i) == (jl_value_t*)fld) {
    1389                 :     753499 :                     return (int)i;
    1390                 :            :                 }
    1391                 :            :             }
    1392                 :            :         }
    1393                 :            :     }
    1394                 :            :     else {
    1395                 :  257684000 :         jl_svec_t *fn = jl_field_names(t);
    1396                 :  257684000 :         size_t i, n = jl_svec_len(fn);
    1397         [ +  + ]:  649914000 :         for (i = 0; i < n; i++) {
    1398         [ +  + ]:  644569000 :             if (jl_svecref(fn, i) == (jl_value_t*)fld) {
    1399                 :  252338000 :                 return (int)i;
    1400                 :            :             }
    1401                 :            :         }
    1402                 :            :     }
    1403         [ +  + ]:    5743780 :     if (err)
    1404                 :        923 :         jl_errorf("type %s has no field %s", jl_symbol_name(t->name->name),
    1405                 :            :                   jl_symbol_name(fld));
    1406                 :    5742850 :     return -1;
    1407                 :            : }
    1408                 :            : 
    1409                 : 1934600000 : JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
    1410                 :            : {
    1411                 : 1934600000 :     jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    1412         [ +  + ]: 1934600000 :     if (i >= jl_datatype_nfields(st))
    1413                 :          4 :         jl_bounds_error_int(v, i + 1);
    1414                 : 1934600000 :     size_t offs = jl_field_offset(st, i);
    1415         [ +  + ]: 1934600000 :     if (jl_field_isptr(st, i)) {
    1416                 :  928611000 :         return jl_atomic_load_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs));
    1417                 :            :     }
    1418                 : 1005990000 :     jl_value_t *ty = jl_field_type_concrete(st, i);
    1419                 : 1005990000 :     int isatomic = jl_field_isatomic(st, i);
    1420         [ +  + ]: 1005990000 :     if (jl_is_uniontype(ty)) {
    1421         [ -  + ]:      38508 :         assert(!isatomic);
    1422                 :      38508 :         size_t fsz = jl_field_size(st, i);
    1423                 :      38508 :         uint8_t sel = ((uint8_t*)v)[offs + fsz - 1];
    1424                 :      38508 :         ty = jl_nth_union_component(ty, sel);
    1425         [ +  + ]:      38508 :         if (jl_is_datatype_singleton((jl_datatype_t*)ty))
    1426                 :        314 :             return ((jl_datatype_t*)ty)->instance;
    1427                 :            :     }
    1428                 :            :     jl_value_t *r;
    1429                 : 1005990000 :     size_t fsz = jl_datatype_size(ty);
    1430   [ +  +  +  + ]: 1005990000 :     int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
    1431   [ +  +  +  + ]: 1005990000 :     if (isatomic && !needlock) {
    1432                 :        121 :         r = jl_atomic_new_bits(ty, (char*)v + offs);
    1433                 :            :     }
    1434         [ +  + ]: 1005990000 :     else if (needlock) {
    1435                 :         21 :         jl_task_t *ct = jl_current_task;
    1436                 :         21 :         r = jl_gc_alloc(ct->ptls, fsz, ty);
    1437                 :         21 :         jl_lock_value(v);
    1438                 :         21 :         memcpy((char*)r, (char*)v + offs, fsz);
    1439                 :         21 :         jl_unlock_value(v);
    1440                 :            :     }
    1441                 :            :     else {
    1442                 : 1005990000 :         r = jl_new_bits(ty, (char*)v + offs);
    1443                 :            :     }
    1444                 : 1005990000 :     return undefref_check((jl_datatype_t*)ty, r);
    1445                 :            : }
    1446                 :            : 
    1447                 :  286973000 : JL_DLLEXPORT jl_value_t *jl_get_nth_field_noalloc(jl_value_t *v JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT
    1448                 :            : {
    1449                 :  286973000 :     jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    1450         [ -  + ]:  286973000 :     assert(i < jl_datatype_nfields(st));
    1451                 :  286973000 :     size_t offs = jl_field_offset(st,i);
    1452         [ -  + ]:  286973000 :     assert(jl_field_isptr(st,i));
    1453                 :  286973000 :     return jl_atomic_load_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs));
    1454                 :            : }
    1455                 :            : 
    1456                 :  368676000 : JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i)
    1457                 :            : {
    1458                 :  368676000 :     jl_value_t *r = jl_get_nth_field(v, i);
    1459         [ +  + ]:  368676000 :     if (__unlikely(r == NULL))
    1460                 :         21 :         jl_throw(jl_undefref_exception);
    1461                 :  368676000 :     return r;
    1462                 :            : }
    1463                 :            : 
    1464                 :  605911000 : static inline void memassign_safe(int hasptr, jl_value_t *parent, char *dst, const jl_value_t *src, size_t nb) JL_NOTSAFEPOINT
    1465                 :            : {
    1466         [ +  + ]:  605911000 :     if (hasptr) {
    1467                 :            :         // assert that although dst might have some undefined bits, the src heap box should be okay with that
    1468         [ -  + ]:    2601580 :         assert(LLT_ALIGN(nb, sizeof(void*)) == LLT_ALIGN(jl_datatype_size(jl_typeof(src)), sizeof(void*)));
    1469                 :    2601580 :         size_t nptr = nb / sizeof(void*);
    1470                 :    2601580 :         memmove_refs((void**)dst, (void**)src, nptr);
    1471                 :    2601580 :         jl_gc_multi_wb(parent, src);
    1472                 :    2601580 :         src = (jl_value_t*)((char*)src + nptr * sizeof(void*));
    1473                 :    2601580 :         nb -= nptr * sizeof(void*);
    1474                 :            :     }
    1475                 :            :     else {
    1476                 :            :         // src must be a heap box.
    1477         [ -  + ]:  603309000 :         assert(nb == jl_datatype_size(jl_typeof(src)));
    1478         [ +  + ]:  603309000 :         if (nb >= 16) {
    1479                 :    4460910 :             memcpy(dst, jl_assume_aligned(src, 16), nb);
    1480                 :    4460910 :             return;
    1481                 :            :         }
    1482                 :            :     }
    1483                 :  601450000 :     memcpy(dst, jl_assume_aligned(src, sizeof(void*)), nb);
    1484                 :            : }
    1485                 :            : 
    1486                 : 1816150000 : void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *rhs, int isatomic) JL_NOTSAFEPOINT
    1487                 :            : {
    1488                 : 1816150000 :     size_t offs = jl_field_offset(st, i);
    1489         [ +  + ]: 1816150000 :     if (rhs == NULL) { // TODO: this should be invalid, but it happens frequently in ircode.c
    1490   [ +  -  +  - ]:    2099480 :         assert(jl_field_isptr(st, i) && *(jl_value_t**)((char*)v + offs) == NULL);
    1491                 :    2099480 :         return;
    1492                 :            :     }
    1493         [ +  + ]: 1814050000 :     if (jl_field_isptr(st, i)) {
    1494                 : 1208140000 :         jl_atomic_store_release((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
    1495                 : 1208140000 :         jl_gc_wb(v, rhs);
    1496                 :            :     }
    1497                 :            :     else {
    1498                 :  605913000 :         jl_value_t *ty = jl_field_type_concrete(st, i);
    1499                 :  605913000 :         jl_value_t *rty = jl_typeof(rhs);
    1500                 :            :         int hasptr;
    1501                 :  605913000 :         int isunion = jl_is_uniontype(ty);
    1502         [ +  + ]:  605913000 :         if (isunion) {
    1503         [ -  + ]:       2853 :             assert(!isatomic);
    1504                 :       2853 :             size_t fsz = jl_field_size(st, i);
    1505                 :       2853 :             uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
    1506                 :       2853 :             unsigned nth = 0;
    1507         [ -  + ]:       2853 :             if (!jl_find_union_component(ty, rty, &nth))
    1508                 :          0 :                 assert(0 && "invalid field assignment to isbits union");
    1509                 :       2853 :             *psel = nth;
    1510         [ +  + ]:       2853 :             if (jl_is_datatype_singleton((jl_datatype_t*)rty))
    1511                 :       2408 :                 return;
    1512                 :        445 :             hasptr = 0;
    1513                 :            :         }
    1514                 :            :         else {
    1515                 :  605911000 :             hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
    1516                 :            :         }
    1517                 :  605911000 :         size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
    1518   [ +  +  +  + ]:  605911000 :         int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
    1519   [ +  +  +  + ]:  605911000 :         if (isatomic && !needlock) {
    1520                 :         29 :             jl_atomic_store_bits((char*)v + offs, rhs, fsz);
    1521         [ -  + ]:         29 :             if (hasptr)
    1522                 :          0 :                 jl_gc_multi_wb(v, rhs); // rhs is immutable
    1523                 :            :         }
    1524         [ +  + ]:  605911000 :         else if (needlock) {
    1525                 :          5 :             jl_lock_value(v);
    1526                 :          5 :             memcpy((char*)v + offs, (char*)rhs, fsz);
    1527                 :          5 :             jl_unlock_value(v);
    1528                 :            :         }
    1529                 :            :         else {
    1530                 :  605911000 :             memassign_safe(hasptr, v, (char*)v + offs, rhs, fsz);
    1531                 :            :         }
    1532                 :            :     }
    1533                 :            : }
    1534                 :            : 
    1535                 :         87 : jl_value_t *swap_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *rhs, int isatomic)
    1536                 :            : {
    1537                 :         87 :     jl_value_t *ty = jl_field_type_concrete(st, i);
    1538         [ -  + ]:         87 :     if (!jl_isa(rhs, ty))
    1539                 :          0 :        jl_type_error("swapfield!", ty, rhs);
    1540                 :         87 :     size_t offs = jl_field_offset(st, i);
    1541                 :            :     jl_value_t *r;
    1542         [ +  + ]:         87 :     if (jl_field_isptr(st, i)) {
    1543         [ +  + ]:         41 :         if (isatomic)
    1544                 :         37 :             r = jl_atomic_exchange((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
    1545                 :            :         else
    1546                 :          4 :             r = jl_atomic_exchange_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
    1547                 :         41 :         jl_gc_wb(v, rhs);
    1548                 :            :     }
    1549                 :            :     else {
    1550                 :         46 :         jl_value_t *rty = jl_typeof(rhs);
    1551                 :            :         int hasptr;
    1552                 :         46 :         int isunion = jl_is_uniontype(ty);
    1553         [ +  + ]:         46 :         if (isunion) {
    1554         [ -  + ]:          2 :             assert(!isatomic);
    1555                 :          2 :             r = jl_get_nth_field(v, i);
    1556                 :          2 :             size_t fsz = jl_field_size(st, i);
    1557                 :          2 :             uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
    1558                 :          2 :             unsigned nth = 0;
    1559         [ -  + ]:          2 :             if (!jl_find_union_component(ty, rty, &nth))
    1560                 :          0 :                 assert(0 && "invalid field assignment to isbits union");
    1561                 :          2 :             *psel = nth;
    1562         [ +  + ]:          2 :             if (jl_is_datatype_singleton((jl_datatype_t*)rty))
    1563                 :          1 :                 return r;
    1564                 :          1 :             hasptr = 0;
    1565                 :            :         }
    1566                 :            :         else {
    1567                 :         44 :             hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
    1568                 :            :         }
    1569                 :         45 :         size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
    1570   [ +  +  +  + ]:         45 :         int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
    1571   [ +  +  +  + ]:         45 :         if (isatomic && !needlock) {
    1572                 :         32 :             r = jl_atomic_swap_bits(rty, (char*)v + offs, rhs, fsz);
    1573         [ -  + ]:         32 :             if (hasptr)
    1574                 :          0 :                 jl_gc_multi_wb(v, rhs); // rhs is immutable
    1575                 :            :         }
    1576                 :            :         else {
    1577         [ +  + ]:         13 :             if (needlock) {
    1578                 :          6 :                 jl_task_t *ct = jl_current_task;
    1579                 :          6 :                 r = jl_gc_alloc(ct->ptls, fsz, ty);
    1580                 :          6 :                 jl_lock_value(v);
    1581                 :          6 :                 memcpy((char*)r, (char*)v + offs, fsz);
    1582                 :          6 :                 memcpy((char*)v + offs, (char*)rhs, fsz);
    1583                 :          6 :                 jl_unlock_value(v);
    1584                 :            :             }
    1585                 :            :             else {
    1586         [ +  + ]:          7 :                 if (!isunion)
    1587                 :          6 :                     r = jl_new_bits(ty, (char*)v + offs);
    1588                 :          7 :                 memassign_safe(hasptr, v, (char*)v + offs, rhs, fsz);
    1589                 :            :             }
    1590   [ +  +  +  + ]:         13 :             if (needlock || !isunion)
    1591                 :         12 :                 r = undefref_check((jl_datatype_t*)ty, r);
    1592                 :            :         }
    1593                 :            :     }
    1594         [ +  + ]:         86 :     if (__unlikely(r == NULL))
    1595                 :          5 :         jl_throw(jl_undefref_exception);
    1596                 :         81 :     return r;
    1597                 :            : }
    1598                 :            : 
    1599                 :        100 : jl_value_t *modify_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *op, jl_value_t *rhs, int isatomic)
    1600                 :            : {
    1601                 :        100 :     size_t offs = jl_field_offset(st, i);
    1602                 :        100 :     jl_value_t *ty = jl_field_type_concrete(st, i);
    1603                 :        100 :     jl_value_t *r = jl_get_nth_field_checked(v, i);
    1604   [ +  +  +  + ]:         95 :     if (isatomic && jl_field_isptr(st, i))
    1605                 :         34 :         jl_fence(); // load was previously only relaxed
    1606                 :            :     jl_value_t **args;
    1607                 :         95 :     JL_GC_PUSHARGS(args, 2);
    1608                 :         95 :     args[0] = r;
    1609                 :          0 :     while (1) {
    1610                 :         95 :         args[1] = rhs;
    1611                 :         95 :         jl_value_t *y = jl_apply_generic(op, args, 2);
    1612                 :         95 :         args[1] = y;
    1613         [ -  + ]:         95 :         if (!jl_isa(y, ty))
    1614                 :          0 :             jl_type_error("modifyfield!", ty, y);
    1615         [ +  + ]:         95 :         if (jl_field_isptr(st, i)) {
    1616                 :         38 :             _Atomic(jl_value_t*) *p = (_Atomic(jl_value_t*)*)((char*)v + offs);
    1617   [ +  +  +  - ]:         38 :             if (isatomic ? jl_atomic_cmpswap(p, &r, y) : jl_atomic_cmpswap_relaxed(p, &r, y))
    1618                 :         38 :                 break;
    1619                 :            :         }
    1620                 :            :         else {
    1621                 :         57 :             jl_value_t *yty = jl_typeof(y);
    1622                 :         57 :             jl_value_t *rty = jl_typeof(r);
    1623                 :            :             int hasptr;
    1624                 :         57 :             int isunion = jl_is_uniontype(ty);
    1625         [ +  + ]:         57 :             if (isunion) {
    1626         [ -  + ]:          2 :                 assert(!isatomic);
    1627                 :          2 :                 hasptr = 0;
    1628                 :            :             }
    1629                 :            :             else {
    1630                 :         55 :                 hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
    1631                 :            :             }
    1632                 :         57 :             size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
    1633   [ +  +  +  + ]:         57 :             int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
    1634   [ +  +  +  + ]:         57 :             if (isatomic && !needlock) {
    1635         [ +  - ]:         42 :                 if (jl_atomic_bool_cmpswap_bits((char*)v + offs, r, y, fsz)) {
    1636         [ -  + ]:         42 :                     if (hasptr)
    1637                 :          0 :                         jl_gc_multi_wb(v, y); // y is immutable
    1638                 :         42 :                     break;
    1639                 :            :                 }
    1640                 :          0 :                 r = jl_atomic_new_bits(ty, (char*)v + offs);
    1641                 :            :             }
    1642                 :            :             else {
    1643         [ +  + ]:         15 :                 if (needlock)
    1644                 :          7 :                     jl_lock_value(v);
    1645                 :         15 :                 int success = memcmp((char*)v + offs, r, fsz) == 0;
    1646         [ +  - ]:         15 :                 if (success) {
    1647         [ +  + ]:         15 :                     if (isunion) {
    1648                 :          2 :                         size_t fsz = jl_field_size(st, i);
    1649                 :          2 :                         uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
    1650                 :          2 :                         success = (jl_typeof(r) == jl_nth_union_component(ty, *psel));
    1651         [ +  - ]:          2 :                         if (success) {
    1652                 :          2 :                             unsigned nth = 0;
    1653         [ -  + ]:          2 :                             if (!jl_find_union_component(ty, yty, &nth))
    1654                 :          0 :                                 assert(0 && "invalid field assignment to isbits union");
    1655                 :          2 :                             *psel = nth;
    1656         [ +  - ]:          2 :                             if (jl_is_datatype_singleton((jl_datatype_t*)yty))
    1657                 :          2 :                                 break;
    1658                 :            :                         }
    1659                 :          0 :                         fsz = jl_datatype_size((jl_datatype_t*)yty); // need to shrink-wrap the final copy
    1660                 :            :                     }
    1661                 :            :                     else {
    1662   [ +  -  +  - ]:         13 :                         assert(yty == ty && rty == ty);
    1663                 :            :                     }
    1664                 :         13 :                     memassign_safe(hasptr, v, (char*)v + offs, y, fsz);
    1665                 :            :                 }
    1666         [ +  + ]:         13 :                 if (needlock)
    1667                 :          7 :                     jl_unlock_value(v);
    1668         [ +  - ]:         13 :                 if (success)
    1669                 :         13 :                     break;
    1670                 :          0 :                 r = jl_get_nth_field(v, i);
    1671                 :            :             }
    1672                 :            :         }
    1673                 :          0 :         args[0] = r;
    1674                 :          0 :         jl_gc_safepoint();
    1675                 :            :     }
    1676                 :            :     // args[0] == r (old)
    1677                 :            :     // args[1] == y (new)
    1678                 :         95 :     jl_datatype_t *rettyp = jl_apply_modify_type(ty);
    1679                 :            :     JL_GC_PROMISE_ROOTED(rettyp); // (JL_ALWAYS_LEAFTYPE)
    1680                 :         95 :     args[0] = jl_new_struct(rettyp, args[0], args[1]);
    1681                 :         95 :     JL_GC_POP();
    1682                 :         95 :     return args[0];
    1683                 :            : }
    1684                 :            : 
    1685                 :        124 : jl_value_t *replace_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t *expected, jl_value_t *rhs, int isatomic)
    1686                 :            : {
    1687                 :        124 :     jl_value_t *ty = jl_field_type_concrete(st, i);
    1688         [ +  + ]:        124 :     if (!jl_isa(rhs, ty))
    1689                 :          4 :         jl_type_error("replacefield!", ty, rhs);
    1690                 :        120 :     size_t offs = jl_field_offset(st, i);
    1691                 :        120 :     jl_value_t *r = expected;
    1692                 :        120 :     jl_datatype_t *rettyp = jl_apply_cmpswap_type(ty);
    1693                 :            :     JL_GC_PROMISE_ROOTED(rettyp); // (JL_ALWAYS_LEAFTYPE)
    1694         [ +  + ]:        120 :     if (jl_field_isptr(st, i)) {
    1695                 :         46 :         _Atomic(jl_value_t*) *p = (_Atomic(jl_value_t*)*)((char*)v + offs);
    1696                 :            :         int success;
    1697                 :            :         while (1) {
    1698         [ +  + ]:         48 :             success = isatomic ? jl_atomic_cmpswap(p, &r, rhs) : jl_atomic_cmpswap_relaxed(p, &r, rhs);
    1699         [ +  + ]:         48 :             if (success)
    1700                 :         26 :                 jl_gc_wb(v, rhs);
    1701         [ +  + ]:         48 :             if (__unlikely(r == NULL))
    1702                 :          6 :                 jl_throw(jl_undefref_exception);
    1703   [ +  +  +  + ]:         42 :             if (success || !jl_egal(r, expected))
    1704                 :            :                 break;
    1705                 :            :         }
    1706                 :         40 :         JL_GC_PUSH1(&r);
    1707         [ +  + ]:         40 :         r = jl_new_struct(rettyp, r, success ? jl_true : jl_false);
    1708                 :         40 :         JL_GC_POP();
    1709                 :            :     }
    1710                 :            :     else {
    1711                 :            :         int hasptr;
    1712                 :         74 :         int isunion = jl_is_uniontype(ty);
    1713                 :            :         int needlock;
    1714                 :         74 :         jl_value_t *rty = ty;
    1715                 :         74 :         size_t fsz = jl_field_size(st, i);
    1716         [ +  + ]:         74 :         if (isunion) {
    1717         [ -  + ]:          8 :             assert(!isatomic);
    1718                 :          8 :             hasptr = 0;
    1719                 :          8 :             needlock = 0;
    1720                 :          8 :             isatomic = 0; // this makes GCC happy
    1721                 :            :         }
    1722                 :            :         else {
    1723                 :         66 :             hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
    1724                 :         66 :             fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
    1725   [ +  +  +  + ]:         66 :             needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
    1726                 :            :         }
    1727   [ +  +  +  + ]:        110 :         if (isatomic && !needlock) {
    1728                 :         36 :             r = jl_atomic_cmpswap_bits((jl_datatype_t*)ty, rettyp, (char*)v + offs, r, rhs, fsz);
    1729                 :         36 :             int success = *((uint8_t*)r + fsz);
    1730   [ +  +  -  + ]:         36 :             if (success && hasptr)
    1731                 :          0 :                 jl_gc_multi_wb(v, rhs); // rhs is immutable
    1732                 :            :         }
    1733                 :            :         else {
    1734                 :         38 :             jl_task_t *ct = jl_current_task;
    1735                 :         38 :             uint8_t *psel = NULL;
    1736         [ +  + ]:         38 :             if (isunion) {
    1737                 :          8 :                 psel = &((uint8_t*)v)[offs + fsz - 1];
    1738                 :          8 :                 rty = jl_nth_union_component(rty, *psel);
    1739                 :            :             }
    1740         [ -  + ]:         38 :             assert(!jl_field_isptr(rettyp, 0));
    1741                 :         38 :             r = jl_gc_alloc(ct->ptls, rettyp->size, (jl_value_t*)rettyp);
    1742                 :         38 :             int success = (rty == jl_typeof(expected));
    1743         [ +  + ]:         38 :             if (needlock)
    1744                 :          6 :                 jl_lock_value(v);
    1745                 :         38 :             memcpy((char*)r, (char*)v + offs, fsz); // copy field, including union bits
    1746         [ +  + ]:         38 :             if (success) {
    1747                 :         35 :                 size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
    1748         [ -  + ]:         35 :                 if (((jl_datatype_t*)rty)->layout->haspadding)
    1749                 :          0 :                     success = jl_egal__bits(r, expected, (jl_datatype_t*)rty);
    1750                 :            :                 else
    1751                 :         35 :                     success = memcmp((char*)r, (char*)expected, fsz) == 0;
    1752                 :            :             }
    1753                 :         38 :             *((uint8_t*)r + fsz) = success ? 1 : 0;
    1754         [ +  + ]:         38 :             if (success) {
    1755                 :         28 :                 jl_value_t *rty = jl_typeof(rhs);
    1756                 :         28 :                 size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
    1757         [ +  + ]:         28 :                 if (isunion) {
    1758                 :          6 :                     unsigned nth = 0;
    1759         [ -  + ]:          6 :                     if (!jl_find_union_component(ty, rty, &nth))
    1760                 :          0 :                         assert(0 && "invalid field assignment to isbits union");
    1761                 :          6 :                     *psel = nth;
    1762         [ +  + ]:          6 :                     if (jl_is_datatype_singleton((jl_datatype_t*)rty))
    1763                 :          3 :                         return r;
    1764                 :            :                 }
    1765                 :         25 :                 memassign_safe(hasptr, v, (char*)v + offs, rhs, fsz);
    1766                 :            :             }
    1767         [ +  + ]:         35 :             if (needlock)
    1768                 :          6 :                 jl_unlock_value(v);
    1769                 :            :         }
    1770                 :         71 :         r = undefref_check((jl_datatype_t*)rty, r);
    1771         [ -  + ]:         71 :         if (__unlikely(r == NULL))
    1772                 :          0 :             jl_throw(jl_undefref_exception);
    1773                 :            :     }
    1774                 :        111 :     return r;
    1775                 :            : }
    1776                 :            : 
    1777                 :   18776000 : JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT
    1778                 :            : {
    1779                 :   18776000 :     jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
    1780                 :   18776000 :     size_t offs = jl_field_offset(st, i);
    1781                 :   18776000 :     _Atomic(jl_value_t*) *fld = (_Atomic(jl_value_t*)*)((char*)v + offs);
    1782         [ +  + ]:   18776000 :     if (!jl_field_isptr(st, i)) {
    1783                 :    2297850 :         jl_datatype_t *ft = (jl_datatype_t*)jl_field_type_concrete(st, i);
    1784   [ +  +  +  + ]:    2297850 :         if (!jl_is_datatype(ft) || ft->layout->first_ptr < 0)
    1785                 :    2216560 :             return 2; // isbits are always defined
    1786                 :      81292 :         fld += ft->layout->first_ptr;
    1787                 :            :     }
    1788                 :   16559400 :     jl_value_t *fval = jl_atomic_load_relaxed(fld);
    1789                 :   16559400 :     return fval != NULL ? 1 : 0;
    1790                 :            : }
    1791                 :            : 
    1792                 :        816 : JL_DLLEXPORT size_t jl_get_field_offset(jl_datatype_t *ty, int field)
    1793                 :            : {
    1794   [ +  +  +  +  :        816 :     if (!jl_struct_try_layout(ty) || field > jl_datatype_nfields(ty) || field < 1)
                   +  + ]
    1795                 :          3 :         jl_bounds_error_int((jl_value_t*)ty, field);
    1796                 :        813 :     return jl_field_offset(ty, field - 1);
    1797                 :            : }
    1798                 :            : 
    1799                 :            : #ifdef __cplusplus
    1800                 :            : }
    1801                 :            : #endif

Generated by: LCOV version 1.14