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
|