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 : 24044 : static int is10digit(char c) JL_NOTSAFEPOINT
23 : : {
24 [ + + + + ]: 24044 : return (c >= '0' && c <= '9');
25 : : }
26 : :
27 : 20315 : static jl_sym_t *jl_demangle_typename(jl_sym_t *s) JL_NOTSAFEPOINT
28 : : {
29 : 20315 : char *n = jl_symbol_name(s);
30 [ + + ]: 20315 : if (n[0] != '#')
31 : 5 : return s;
32 : 20310 : char *end = strrchr(n, '#');
33 : : int32_t len;
34 [ + + + + ]: 20310 : if (end == n || end == n+1)
35 : 13172 : len = strlen(n) - 1;
36 : : else
37 : 7138 : len = (end-n) - 1; // extract `f` from `#f#...`
38 [ + + ]: 20310 : if (is10digit(n[1]))
39 : 3378 : return _jl_symbol(n, len+1);
40 : 16932 : return _jl_symbol(&n[1], len);
41 : : }
42 : :
43 : 20315 : JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module)
44 : : {
45 : 20315 : jl_task_t *ct = jl_current_task;
46 : : jl_methtable_t *mt =
47 : 20315 : (jl_methtable_t*)jl_gc_alloc(ct->ptls, sizeof(jl_methtable_t),
48 : : jl_methtable_type);
49 : 20315 : mt->name = jl_demangle_typename(name);
50 : 20315 : mt->module = module;
51 : 20315 : jl_atomic_store_relaxed(&mt->defs, jl_nothing);
52 : 20315 : jl_atomic_store_relaxed(&mt->leafcache, (jl_array_t*)jl_an_empty_vec_any);
53 : 20315 : jl_atomic_store_relaxed(&mt->cache, jl_nothing);
54 : 20315 : mt->max_args = 0;
55 : 20315 : mt->kwsorter = NULL;
56 : 20315 : mt->backedges = NULL;
57 : 20315 : JL_MUTEX_INIT(&mt->writelock);
58 : 20315 : mt->offs = 0;
59 : 20315 : mt->frozen = 0;
60 : 20315 : return mt;
61 : : }
62 : :
63 : 22217 : JL_DLLEXPORT jl_typename_t *jl_new_typename_in(jl_sym_t *name, jl_module_t *module, int abstract, int mutabl)
64 : : {
65 : 22217 : jl_task_t *ct = jl_current_task;
66 : : jl_typename_t *tn =
67 : 22217 : (jl_typename_t*)jl_gc_alloc(ct->ptls, sizeof(jl_typename_t),
68 : : jl_typename_type);
69 : 22217 : tn->name = name;
70 : 22217 : tn->module = module;
71 : 22217 : tn->wrapper = NULL;
72 : 22217 : jl_atomic_store_release(&tn->Typeofwrapper, NULL);
73 : 22217 : jl_atomic_store_relaxed(&tn->cache, jl_emptysvec);
74 : 22217 : jl_atomic_store_relaxed(&tn->linearcache, jl_emptysvec);
75 : 22217 : tn->names = NULL;
76 [ + + ]: 22217 : tn->hash = bitmix(bitmix(module ? module->build_id : 0, name->hash), 0xa1ada1da);
77 : 22217 : tn->abstract = abstract;
78 : 22217 : tn->mutabl = mutabl;
79 : 22217 : tn->mayinlinealloc = 0;
80 : 22217 : tn->mt = NULL;
81 : 22217 : tn->partial = NULL;
82 : 22217 : tn->atomicfields = NULL;
83 : 22217 : tn->constfields = NULL;
84 : 22217 : tn->max_methods = 0;
85 : 22217 : return tn;
86 : : }
87 : :
88 : : // allocating DataTypes -----------------------------------------------------------
89 : :
90 : 203 : jl_datatype_t *jl_new_abstracttype(jl_value_t *name, jl_module_t *module, jl_datatype_t *super, jl_svec_t *parameters)
91 : : {
92 : 203 : return jl_new_datatype((jl_sym_t*)name, module, super, parameters, jl_emptysvec, jl_emptysvec, jl_emptysvec, 1, 0, 0);
93 : : }
94 : :
95 : 19913800 : jl_datatype_t *jl_new_uninitialized_datatype(void)
96 : : {
97 : 19913800 : jl_task_t *ct = jl_current_task;
98 : 19913800 : jl_datatype_t *t = (jl_datatype_t*)jl_gc_alloc(ct->ptls, sizeof(jl_datatype_t), jl_datatype_type);
99 : 19913800 : t->hash = 0;
100 : 19913800 : t->hasfreetypevars = 0;
101 : 19913800 : t->isdispatchtuple = 0;
102 : 19913800 : t->isbitstype = 0;
103 : 19913800 : t->zeroinit = 0;
104 : 19913800 : t->has_concrete_subtype = 1;
105 : 19913800 : t->cached_by_hash = 0;
106 : 19913800 : t->name = NULL;
107 : 19913800 : t->super = NULL;
108 : 19913800 : t->parameters = NULL;
109 : 19913800 : t->layout = NULL;
110 : 19913800 : t->types = NULL;
111 : 19913800 : t->instance = NULL;
112 : 19913800 : return t;
113 : : }
114 : :
115 : 174963 : 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 [ - + ]: 174963 : assert(alignment); // should have been verified by caller
123 : :
124 : : // compute the smallest fielddesc type that can hold the layout description
125 : 174963 : int fielddesc_type = 0;
126 [ + + ]: 174963 : if (nfields > 0) {
127 : 174879 : uint32_t max_size = 0;
128 : 174879 : uint32_t max_offset = desc[nfields - 1].offset;
129 [ + + + + ]: 174879 : if (npointers > 0 && pointers[npointers - 1] > max_offset)
130 : 9793 : max_offset = pointers[npointers - 1];
131 [ + + ]: 739850 : for (size_t i = 0; i < nfields; i++) {
132 [ + + ]: 564971 : if (desc[i].size > max_size)
133 : 196820 : max_size = desc[i].size;
134 : : }
135 : 174879 : jl_fielddesc8_t maxdesc8 = { 0, max_size, max_offset };
136 : 174879 : jl_fielddesc16_t maxdesc16 = { 0, max_size, max_offset };
137 : 174879 : jl_fielddesc32_t maxdesc32 = { 0, max_size, max_offset };
138 [ + + + + ]: 174879 : if (maxdesc8.size != max_size || maxdesc8.offset != max_offset) {
139 : 1375 : fielddesc_type = 1;
140 [ + + - + ]: 1375 : if (maxdesc16.size != max_size || maxdesc16.offset != max_offset) {
141 : 12 : fielddesc_type = 2;
142 [ + - - + ]: 12 : 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 : 174963 : uint32_t fielddesc_size = jl_fielddesc_size(fielddesc_type);
152 : 174963 : jl_datatype_layout_t *flddesc = (jl_datatype_layout_t*)jl_gc_perm_alloc(
153 : 174963 : sizeof(jl_datatype_layout_t) + nfields * fielddesc_size + (npointers << fielddesc_type),
154 : : 0, 4, 0);
155 : 174963 : flddesc->nfields = nfields;
156 : 174963 : flddesc->alignment = alignment;
157 : 174963 : flddesc->haspadding = haspadding;
158 : 174963 : flddesc->fielddesc_type = fielddesc_type;
159 : 174963 : flddesc->npointers = npointers;
160 [ + + ]: 174963 : flddesc->first_ptr = (npointers > 0 ? pointers[0] : -1);
161 : :
162 : : // fill out the fields of the new descriptor
163 : 174963 : jl_fielddesc8_t* desc8 = (jl_fielddesc8_t*)jl_dt_layout_fields(flddesc);
164 : 174963 : jl_fielddesc16_t* desc16 = (jl_fielddesc16_t*)jl_dt_layout_fields(flddesc);
165 : 174963 : jl_fielddesc32_t* desc32 = (jl_fielddesc32_t*)jl_dt_layout_fields(flddesc);
166 [ + + ]: 739934 : for (size_t i = 0; i < nfields; i++) {
167 [ + + ]: 564971 : if (fielddesc_type == 0) {
168 : 540269 : desc8[i].offset = desc[i].offset;
169 : 540269 : desc8[i].size = desc[i].size;
170 : 540269 : desc8[i].isptr = desc[i].isptr;
171 : : }
172 [ + + ]: 24702 : else if (fielddesc_type == 1) {
173 : 24674 : desc16[i].offset = desc[i].offset;
174 : 24674 : desc16[i].size = desc[i].size;
175 : 24674 : desc16[i].isptr = desc[i].isptr;
176 : : }
177 : : else {
178 : 28 : desc32[i].offset = desc[i].offset;
179 : 28 : desc32[i].size = desc[i].size;
180 : 28 : desc32[i].isptr = desc[i].isptr;
181 : : }
182 : : }
183 : 174963 : uint8_t* ptrs8 = (uint8_t*)jl_dt_layout_ptrs(flddesc);
184 : 174963 : uint16_t* ptrs16 = (uint16_t*)jl_dt_layout_ptrs(flddesc);
185 : 174963 : uint32_t* ptrs32 = (uint32_t*)jl_dt_layout_ptrs(flddesc);
186 [ + + ]: 603923 : for (size_t i = 0; i < npointers; i++) {
187 [ + + ]: 428960 : if (fielddesc_type == 0) {
188 : 294337 : ptrs8[i] = pointers[i];
189 : : }
190 [ + + ]: 134623 : else if (fielddesc_type == 1) {
191 : 74381 : ptrs16[i] = pointers[i];
192 : : }
193 : : else {
194 : 60242 : ptrs32[i] = pointers[i];
195 : : }
196 : : }
197 : 174963 : 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 : 10186 : unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
207 : : {
208 [ + + ]: 10186 : if (!jl_is_vecelement_type(t))
209 : 10138 : return 0;
210 [ - + ]: 48 : assert(jl_datatype_nfields(t) == 1);
211 : 48 : jl_value_t *ty = jl_field_type((jl_datatype_t*)t, 0);
212 [ - + ]: 48 : 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 : 48 : size_t elsz = jl_datatype_size(ty);
218 [ + - + - : 48 : if (elsz != 1 && elsz != 2 && elsz != 4 && elsz != 8)
+ - - + ]
219 : : // Only handle power-of-two-sized elements (for now)
220 : 0 : return 0;
221 : 48 : size_t size = nfields * elsz;
222 : : // Use natural alignment for this vector: this matches LLVM and clang.
223 : 48 : return next_power_of_two(size);
224 : : }
225 : :
226 : 211306 : STATIC_INLINE int jl_is_datatype_make_singleton(jl_datatype_t *d) JL_NOTSAFEPOINT
227 : : {
228 [ + + + - : 211306 : return (!d->name->abstract && jl_datatype_size(d) == 0 && d != jl_symbol_type && d->name != jl_array_typename &&
+ - + + ]
229 [ + - + + ]: 422612 : d->isconcretetype && !d->name->mutabl);
230 : : }
231 : :
232 : 211306 : STATIC_INLINE void jl_maybe_allocate_singleton_instance(jl_datatype_t *st) JL_NOTSAFEPOINT
233 : : {
234 [ + + ]: 211306 : if (jl_is_datatype_make_singleton(st)) {
235 : : // It's possible for st to already have an ->instance if it was redefined
236 [ + - ]: 23155 : if (!st->instance)
237 : 23155 : st->instance = jl_gc_permobj(0, st);
238 : : }
239 : 211306 : }
240 : :
241 : : // return whether all concrete subtypes of this type have the same layout
242 : 168320000 : int jl_struct_try_layout(jl_datatype_t *dt)
243 : : {
244 [ + + ]: 168320000 : if (dt->layout)
245 : 168106000 : return 1;
246 [ + - ]: 213984 : else if (!jl_has_fixed_layout(dt))
247 : 213984 : return 0;
248 : : // jl_has_fixed_layout also ensured that dt->types is assigned now
249 : 0 : jl_compute_field_offsets(dt);
250 [ # # ]: 0 : assert(dt->layout);
251 : 0 : return 1;
252 : : }
253 : :
254 : 277459000 : int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree)
255 : : {
256 [ + + + + ]: 277459000 : if (ty->name->mayinlinealloc && jl_struct_try_layout(ty)) {
257 [ + + ]: 164197000 : if (ty->layout->npointers > 0) {
258 [ + + ]: 15261200 : if (pointerfree)
259 : 1804250 : return 0;
260 [ + + ]: 13457000 : if (ty->name->n_uninitialized != 0)
261 : 32045 : return 0;
262 [ - + ]: 13424900 : if (ty->layout->fielddesc_type > 1) // GC only implements support for 8 and 16 (not array32)
263 : 0 : return 0;
264 : : }
265 : 162361000 : return 1;
266 : : }
267 : 113262000 : return 0;
268 : : }
269 : :
270 : 282058000 : static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield)
271 : : {
272 [ + + ]: 282058000 : if (jl_is_uniontype(ty)) {
273 : 6469320 : unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align, asfield);
274 [ + + ]: 6469320 : if (na == 0)
275 : 1732060 : return 0;
276 : 4737250 : unsigned nb = union_isinlinable(((jl_uniontype_t*)ty)->b, 1, nbytes, align, asfield);
277 [ + + ]: 4737250 : if (nb == 0)
278 : 2711690 : return 0;
279 : 2025560 : return na + nb;
280 : : }
281 [ + + + + ]: 275588000 : if (jl_is_datatype(ty) && jl_datatype_isinlinealloc((jl_datatype_t*)ty, pointerfree)) {
282 : 160520000 : size_t sz = jl_datatype_size(ty);
283 : 160520000 : size_t al = jl_datatype_align(ty);
284 : : // primitive types in struct slots need their sizes aligned. issue #37974
285 [ + + + + ]: 160520000 : if (asfield && jl_is_primitivetype(ty))
286 : 123735000 : sz = LLT_ALIGN(sz, al);
287 [ + + ]: 160520000 : if (*nbytes < sz)
288 : 155589000 : *nbytes = sz;
289 [ + + ]: 160520000 : if (*align < al)
290 : 158289000 : *align = al;
291 : 160520000 : return 1;
292 : : }
293 : 115069000 : return 0;
294 : : }
295 : :
296 : 5208 : int jl_uniontype_size(jl_value_t *ty, size_t *sz)
297 : : {
298 : 5208 : size_t al = 0;
299 : 5208 : return union_isinlinable(ty, 0, sz, &al, 0) != 0;
300 : : }
301 : :
302 : 270846000 : JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al)
303 : : {
304 : 270846000 : unsigned countbits = union_isinlinable(eltype, 0, fsz, al, 1);
305 [ + + + - ]: 270846000 : return (countbits > 0 && countbits < 127) ? countbits : 0;
306 : : }
307 : :
308 : 467629 : JL_DLLEXPORT int jl_stored_inline(jl_value_t *eltype)
309 : : {
310 : 467629 : size_t fsz = 0, al = 0;
311 : 467629 : return jl_islayout_inline(eltype, &fsz, &al);
312 : : }
313 : :
314 : : // whether instances of this type can use pointer comparison for `===`
315 : 306984 : int jl_pointer_egal(jl_value_t *t)
316 : : {
317 [ + + ]: 306984 : if (t == (jl_value_t*)jl_any_type)
318 : 27941 : return 0; // when setting up the initial types, jl_is_type_type gets confused about this
319 [ + + ]: 279043 : if (t == (jl_value_t*)jl_symbol_type)
320 : 62069 : return 1;
321 [ + + ]: 216974 : if (t == (jl_value_t*)jl_bool_type)
322 : 76 : return 1;
323 [ + + + + ]: 216898 : if (jl_is_mutable_datatype(jl_unwrap_unionall(t)) && // excludes abstract types
324 [ + + ]: 168100 : t != (jl_value_t*)jl_string_type && // technically mutable, but compared by contents
325 [ + + + + ]: 268374 : t != (jl_value_t*)jl_simplevector_type &&
326 : 134035 : !jl_is_kind(t))
327 : 110243 : return 1;
328 [ + + + + ]: 106655 : if ((jl_is_datatype(t) && jl_is_datatype_singleton((jl_datatype_t*)t)) ||
329 [ - + ]: 100633 : t == (jl_value_t*)jl_typeofbottom_type->super)
330 : 6022 : return 1;
331 [ + + + + ]: 100633 : 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 : 20106 : 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 [ + + ]: 20106 : if (dt != jl_typeofbottom_type &&
339 [ + + + + ]: 16446 : (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 : 16102 : return 1;
344 : : }
345 : : }
346 [ + + ]: 84531 : if (jl_is_uniontype(t)) {
347 : 7318 : jl_uniontype_t *u = (jl_uniontype_t*)t;
348 [ + + + + ]: 7318 : return jl_pointer_egal(u->a) && jl_pointer_egal(u->b);
349 : : }
350 : 77213 : 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 : 317857 : void jl_compute_field_offsets(jl_datatype_t *st)
361 : : {
362 : 317857 : const uint64_t max_offset = (((uint64_t)1) << 32) - 1;
363 : 317857 : const uint64_t max_size = max_offset >> 1;
364 : :
365 [ - + ]: 317857 : if (st->name->wrapper == NULL)
366 : 0 : return; // we got called too early--we'll be back
367 : 317857 : jl_datatype_t *w = (jl_datatype_t*)jl_unwrap_unionall(st->name->wrapper);
368 [ + + + + ]: 317857 : if (st == w && st->layout) {
369 : : // this check allows us to force re-computation of the layout for some types during init
370 : 10 : st->layout = NULL;
371 : 10 : st->size = 0;
372 : 10 : st->zeroinit = 0;
373 : 10 : st->has_concrete_subtype = 1;
374 : : }
375 [ + + + + ]: 317857 : 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 [ + + ]: 317857 : if (w->layout) {
379 : 122038 : st->layout = w->layout;
380 : 122038 : st->size = w->size;
381 : 122038 : st->zeroinit = w->zeroinit;
382 : 122038 : st->has_concrete_subtype = w->has_concrete_subtype;
383 [ + + ]: 122038 : if (!jl_is_layout_opaque(st->layout)) { // e.g. jl_array_typename
384 [ + + + + ]: 17857 : st->isbitstype = isbitstype && st->layout->npointers == 0;
385 : 17857 : jl_maybe_allocate_singleton_instance(st);
386 : : }
387 : 122038 : return;
388 : : }
389 [ + - + - ]: 195819 : assert(st->types && w->types);
390 : 195819 : size_t i, nfields = jl_svec_len(st->types);
391 [ - + ]: 195819 : assert(st->name->n_uninitialized <= nfields);
392 [ + + ]: 195819 : if (nfields == 0) {
393 : : // if we have no fields, we can trivially skip the rest
394 [ + + + + ]: 18576 : 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 [ + + + + : 18574 : 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 : 18570 : 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 [ + + + + ]: 746414 : for (i = 0; st->has_concrete_subtype && i < nfields - st->name->n_uninitialized; i++) {
414 : 569171 : jl_value_t *fld = jl_svecref(st->types, i);
415 [ + + ]: 569171 : if (fld == jl_bottom_type)
416 : 36 : st->has_concrete_subtype = 0;
417 : : else
418 [ + + + + ]: 569135 : 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 [ + + + + ]: 177243 : if (!st->isconcretetype && !jl_has_fixed_layout(st)) {
422 [ - + ]: 2364 : assert(st == w); // otherwise caller should not have requested this layout
423 : 2364 : return;
424 : : }
425 : : }
426 : :
427 [ + + + + ]: 564703 : for (i = 0; isbitstype && i < nfields; i++) {
428 : 371254 : jl_value_t *fld = jl_field_type(st, i);
429 : 371254 : isbitstype = jl_isbits(fld);
430 : : }
431 : :
432 : : // if we didn't reuse the layout above, compute it now
433 [ + + ]: 193449 : if (st->layout == NULL) {
434 : 174879 : size_t descsz = nfields * sizeof(jl_fielddesc32_t);
435 : : jl_fielddesc32_t *desc;
436 : : uint32_t *pointers;
437 : 174879 : int should_malloc = descsz >= jl_page_size;
438 [ + + ]: 174879 : if (should_malloc)
439 : 4 : desc = (jl_fielddesc32_t*)malloc_s(descsz);
440 : : else
441 : 174875 : desc = (jl_fielddesc32_t*)alloca(descsz);
442 : 174879 : size_t sz = 0;
443 : 174879 : size_t alignm = 1;
444 : 174879 : int zeroinit = 0;
445 : 174879 : int haspadding = 0;
446 : 174879 : int homogeneous = 1;
447 : 174879 : int needlock = 0;
448 : 174879 : uint32_t npointers = 0;
449 : 174879 : jl_value_t *firstty = jl_field_type(st, 0);
450 [ + + ]: 739850 : for (i = 0; i < nfields; i++) {
451 : 564971 : jl_value_t *fld = jl_field_type(st, i);
452 : 564971 : int isatomic = jl_field_isatomic(st, i);
453 : 564971 : size_t fsz = 0, al = 1;
454 [ + + + + : 564971 : if (jl_islayout_inline(fld, &fsz, &al) && (!isatomic || jl_is_datatype(fld))) { // aka jl_datatype_isinlinealloc
+ - ]
455 [ - + ]: 402445 : if (__unlikely(fsz > max_size))
456 : : // Should never happen
457 : 0 : throw_ovf(should_malloc, desc, st, fsz);
458 : 402445 : desc[i].isptr = 0;
459 [ + + ]: 402445 : if (jl_is_uniontype(fld)) {
460 : 55 : haspadding = 1;
461 : 55 : fsz += 1; // selector byte
462 : 55 : zeroinit = 1;
463 : : }
464 : : else {
465 : 402390 : uint32_t fld_npointers = ((jl_datatype_t*)fld)->layout->npointers;
466 [ + + ]: 402390 : if (((jl_datatype_t*)fld)->layout->haspadding)
467 : 50455 : haspadding = 1;
468 [ + + + + ]: 402390 : if (i >= nfields - st->name->n_uninitialized && fld_npointers &&
469 [ + + ]: 41 : 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 : 20 : haspadding = 1;
473 : : }
474 [ + + ]: 402390 : if (!zeroinit)
475 : 279814 : zeroinit = ((jl_datatype_t*)fld)->zeroinit;
476 : 402390 : npointers += fld_npointers;
477 : : }
478 : : }
479 : : else {
480 : 162526 : fsz = sizeof(void*);
481 [ - + ]: 162526 : if (fsz > MAX_ALIGN)
482 : 0 : fsz = MAX_ALIGN;
483 : 162526 : al = fsz;
484 : 162526 : desc[i].isptr = 1;
485 : 162526 : zeroinit = 1;
486 : 162526 : npointers++;
487 [ + + ]: 162526 : if (!jl_pointer_egal(fld)) {
488 : : // this somewhat poorly named flag says whether some of the bits can be non-unique
489 : 54790 : haspadding = 1;
490 : : }
491 : : }
492 [ + + - + ]: 564971 : if (isatomic && fsz > MAX_ATOMIC_SIZE)
493 : 0 : needlock = 1;
494 [ + + + - ]: 564971 : if (isatomic && fsz <= MAX_ATOMIC_SIZE)
495 : 45 : al = fsz = next_power_of_two(fsz);
496 [ + - ]: 564971 : if (al != 0) {
497 : 564971 : size_t alsz = LLT_ALIGN(sz, al);
498 [ + + ]: 564971 : if (alsz != sz)
499 : 10377 : haspadding = 1;
500 : 564971 : sz = alsz;
501 [ + + ]: 564971 : if (al > alignm)
502 : 170195 : alignm = al;
503 : : }
504 : 564971 : homogeneous &= firstty == fld;
505 : 564971 : desc[i].offset = sz;
506 : 564971 : desc[i].size = fsz;
507 [ - + ]: 564971 : if (__unlikely(max_offset - sz < fsz))
508 : 0 : throw_ovf(should_malloc, desc, st, sz);
509 : 564971 : sz += fsz;
510 : : }
511 [ - + ]: 174879 : if (needlock) {
512 : 0 : size_t offset = LLT_ALIGN(sizeof(jl_mutex_t), alignm);
513 [ # # ]: 0 : for (i = 0; i < nfields; i++) {
514 : 0 : desc[i].offset += offset;
515 : : }
516 [ # # ]: 0 : if (__unlikely(max_offset - sz < offset))
517 : 0 : throw_ovf(should_malloc, desc, st, sz);
518 : 0 : sz += offset;
519 : 0 : haspadding = 1;
520 : : }
521 [ + + + + ]: 174879 : if (homogeneous && jl_is_tuple_type(st)) {
522 : : // Some tuples become LLVM vectors with stronger alignment than what was calculated above.
523 : 5282 : unsigned al = jl_special_vector_alignment(nfields, firstty);
524 [ - + ]: 5282 : assert(al % alignm == 0);
525 [ + + ]: 5282 : if (al > alignm)
526 : 20 : alignm = al;
527 : : }
528 : 174879 : st->size = LLT_ALIGN(sz, alignm);
529 [ + + ]: 174879 : if (st->size > sz)
530 : 7954 : haspadding = 1;
531 [ + + + - ]: 174879 : if (should_malloc && npointers)
532 : 4 : pointers = (uint32_t*)malloc_s(npointers * sizeof(uint32_t));
533 : : else
534 : 174875 : pointers = (uint32_t*)alloca(npointers * sizeof(uint32_t));
535 : 174879 : size_t ptr_i = 0;
536 [ + + ]: 739850 : for (i = 0; i < nfields; i++) {
537 : 564971 : jl_value_t *fld = jl_field_type(st, i);
538 : 564971 : uint32_t offset = desc[i].offset / sizeof(jl_value_t**);
539 [ + + ]: 564971 : if (desc[i].isptr)
540 : 162526 : pointers[ptr_i++] = offset;
541 [ + + ]: 402445 : else if (jl_is_datatype(fld)) {
542 : 402390 : int j, npointers = ((jl_datatype_t*)fld)->layout->npointers;
543 [ + + ]: 668824 : for (j = 0; j < npointers; j++) {
544 : 266434 : pointers[ptr_i++] = offset + jl_ptr_offset((jl_datatype_t*)fld, j);
545 : : }
546 : : }
547 : : }
548 [ - + ]: 174879 : assert(ptr_i == npointers);
549 : 174879 : st->layout = jl_get_layout(nfields, npointers, alignm, haspadding, desc, pointers);
550 [ + + ]: 174879 : if (should_malloc) {
551 : 4 : free(desc);
552 [ + - ]: 4 : if (npointers)
553 : 4 : free(pointers);
554 : : }
555 : 174879 : st->zeroinit = zeroinit;
556 : : }
557 : : // now finish deciding if this instantiation qualifies for special properties
558 [ + + - + ]: 193449 : assert(!isbitstype || st->layout->npointers == 0); // the definition of isbits
559 : 193449 : st->isbitstype = isbitstype;
560 : 193449 : jl_maybe_allocate_singleton_instance(st);
561 : 193449 : return;
562 : : }
563 : :
564 : 5632 : static int is_anonfn_typename(char *name)
565 : : {
566 [ + + - + ]: 5632 : if (name[0] != '#' || name[1] == '#')
567 : 1898 : return 0;
568 : 3734 : char *other = strrchr(name, '#');
569 [ + - + - ]: 3734 : return other > &name[1] && is10digit(other[1]);
570 : : }
571 : :
572 : 22212 : 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 : 22212 : jl_datatype_t *t = NULL;
584 : 22212 : jl_typename_t *tn = NULL;
585 : 22212 : JL_GC_PUSH2(&t, &tn);
586 : :
587 [ - + ]: 22212 : assert(parameters);
588 : :
589 : : // init enough before possibly calling jl_new_typename_in
590 : 22212 : t = jl_new_uninitialized_datatype();
591 : 22212 : t->super = super;
592 [ + + ]: 22212 : if (super != NULL) jl_gc_wb(t, t->super);
593 : 22212 : t->parameters = parameters;
594 : 22212 : jl_gc_wb(t, t->parameters);
595 : 22212 : t->types = ftypes;
596 [ + + ]: 22212 : if (ftypes != NULL) jl_gc_wb(t, t->types);
597 : 22212 : t->size = 0;
598 : :
599 : 22212 : t->name = NULL;
600 [ - + ]: 22212 : if (jl_is_typename(name)) {
601 : : // This code-path is used by the Serialization module to bypass normal expectations
602 : 0 : tn = (jl_typename_t*)name;
603 : 0 : tn->abstract = abstract;
604 : 0 : tn->mutabl = mutabl;
605 : : }
606 : : else {
607 : 22212 : tn = jl_new_typename_in((jl_sym_t*)name, module, abstract, mutabl);
608 [ + + + + : 22212 : 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 : 20314 : tn->mt = jl_new_method_table(name, module);
612 : 20314 : jl_gc_wb(tn, tn->mt);
613 [ + + + + ]: 20314 : if (jl_svec_len(parameters) == 0 && !abstract)
614 : 18263 : tn->mt->offs = 1;
615 : : }
616 : : else {
617 : : // Everything else, gets to use the unified table
618 : 1898 : tn->mt = jl_nonfunction_mt;
619 : : }
620 : : }
621 : 22212 : t->name = tn;
622 : 22212 : jl_gc_wb(t, t->name);
623 : 22212 : t->name->names = fnames;
624 : 22212 : jl_gc_wb(t->name, t->name->names);
625 : 22212 : tn->n_uninitialized = jl_svec_len(fnames) - ninitialized;
626 : :
627 : 22212 : uint32_t *volatile atomicfields = NULL;
628 : 22212 : uint32_t *volatile constfields = NULL;
629 : : int i;
630 [ + - + + ]: 44424 : JL_TRY {
631 [ + + ]: 22273 : for (i = 0; i + 1 < jl_svec_len(fattrs); i += 2) {
632 : 61 : jl_value_t *fldi = jl_svecref(fattrs, i);
633 : 61 : jl_sym_t *attr = (jl_sym_t*)jl_svecref(fattrs, i + 1);
634 [ - + ]: 61 : JL_TYPECHK(typeassert, long, fldi);
635 [ - + ]: 61 : JL_TYPECHK(typeassert, symbol, (jl_value_t*)attr);
636 : 61 : size_t fldn = jl_unbox_long(fldi);
637 [ + - - + ]: 61 : if (fldn < 1 || fldn > jl_svec_len(fnames))
638 : 0 : jl_errorf("invalid field attribute %lld", (long long)fldn);
639 : 61 : fldn--;
640 [ + + ]: 61 : if (attr == jl_atomic_sym) {
641 [ - + ]: 45 : if (!mutabl)
642 : 0 : jl_errorf("invalid field attribute atomic for immutable struct");
643 [ + + ]: 45 : if (atomicfields == NULL) {
644 : 31 : size_t nb = (jl_svec_len(fnames) + 31) / 32 * sizeof(uint32_t);
645 : 31 : atomicfields = (uint32_t*)malloc_s(nb);
646 : 31 : memset(atomicfields, 0, nb);
647 : : }
648 : 45 : atomicfields[fldn / 32] |= 1 << (fldn % 32);
649 : : }
650 [ + - ]: 16 : else if (attr == jl_const_sym) {
651 [ - + ]: 16 : if (!mutabl)
652 : 0 : jl_errorf("invalid field attribute const for immutable struct");
653 [ + + ]: 16 : if (constfields == NULL) {
654 : 10 : size_t nb = (jl_svec_len(fnames) + 31) / 32 * sizeof(uint32_t);
655 : 10 : constfields = (uint32_t*)malloc_s(nb);
656 : 10 : memset(constfields, 0, nb);
657 : : }
658 : 16 : 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 [ # # ]: 0 : JL_CATCH {
666 : 0 : free(atomicfields);
667 : 0 : free(constfields);
668 : 0 : jl_rethrow();
669 : : }
670 : 22212 : tn->atomicfields = atomicfields;
671 : 22212 : tn->constfields = constfields;
672 : :
673 [ + - ]: 22212 : if (t->name->wrapper == NULL) {
674 : 22212 : t->name->wrapper = (jl_value_t*)t;
675 : 22212 : jl_gc_wb(t->name, t);
676 : 22212 : int i, np = jl_svec_len(parameters);
677 [ + + ]: 26879 : for (i = np - 1; i >= 0; i--) {
678 : 4667 : t->name->wrapper = jl_new_struct(jl_unionall_type, jl_svecref(parameters, i), t->name->wrapper);
679 : 4667 : jl_gc_wb(t->name, t->name->wrapper);
680 : : }
681 [ + + + + : 22212 : if (!mutabl && !abstract && ftypes != NULL)
+ + ]
682 : 16689 : tn->mayinlinealloc = 1;
683 : : }
684 : 22212 : jl_precompute_memoized_dt(t, 0);
685 : :
686 [ + + + + ]: 22212 : if (!abstract && t->types != NULL)
687 : 16701 : jl_compute_field_offsets(t);
688 : :
689 : 22212 : JL_GC_POP();
690 : 22212 : return t;
691 : : }
692 : :
693 : 84 : 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 : 84 : 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 : 84 : uint32_t nbytes = (nbits + 7) / 8;
700 : 84 : uint32_t alignm = next_power_of_two(nbytes);
701 [ + + ]: 84 : if (alignm > MAX_ALIGN)
702 : 2 : alignm = MAX_ALIGN;
703 : 84 : bt->isbitstype = (parameters == jl_emptysvec);
704 : 84 : bt->size = nbytes;
705 : 84 : bt->layout = jl_get_layout(0, 0, alignm, 0, NULL, NULL);
706 : 84 : bt->instance = NULL;
707 : 84 : 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 : 28 : JL_DLLEXPORT int jl_is_foreign_type(jl_datatype_t *dt)
739 : : {
740 [ + - + - : 28 : 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 : 0 : static inline uint32_t zext_read32(const jl_value_t *x, size_t nb) JL_NOTSAFEPOINT
767 : : {
768 : 0 : uint32_t y = *(uint32_t*)x;
769 [ # # ]: 0 : if (nb == 4)
770 : 0 : return y;
771 : : else // if (nb == 3)
772 : 0 : return 0xffffffu & y;
773 : : }
774 : :
775 : : #if MAX_POINTERATOMIC_SIZE >= 8
776 : 0 : static inline uint64_t zext_read64(const jl_value_t *x, size_t nb) JL_NOTSAFEPOINT
777 : : {
778 : 0 : uint64_t y = *(uint64_t*)x;
779 [ # # ]: 0 : if (nb == 8)
780 : 0 : 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 : 154014000 : 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 [ - + ]: 154014000 : assert(jl_is_datatype(dt));
807 : 154014000 : jl_datatype_t *bt = (jl_datatype_t*)dt;
808 : 154014000 : size_t nb = jl_datatype_size(bt);
809 : : // some types have special pools to minimize allocations
810 [ + + ]: 154014000 : if (nb == 0) return jl_new_struct_uninit(bt); // returns bt->instance
811 [ + + + + ]: 148910000 : if (bt == jl_bool_type) return (1 & *(int8_t*)data) ? jl_true : jl_false;
812 [ + + ]: 144139000 : if (bt == jl_uint8_type) return jl_box_uint8(*(uint8_t*)data);
813 [ + + ]: 142914000 : if (bt == jl_int64_type) return jl_box_int64(*(int64_t*)data);
814 [ + + ]: 67886800 : if (bt == jl_int32_type) return jl_box_int32(*(int32_t*)data);
815 [ + + ]: 26593600 : if (bt == jl_int8_type) return jl_box_int8(*(int8_t*)data);
816 [ - + ]: 26549600 : if (bt == jl_int16_type) return jl_box_int16(*(int16_t*)data);
817 [ + + ]: 26549600 : if (bt == jl_uint64_type) return jl_box_uint64(*(uint64_t*)data);
818 [ + + ]: 25261300 : if (bt == jl_uint32_type) return jl_box_uint32(*(uint32_t*)data);
819 [ + + ]: 24767100 : if (bt == jl_uint16_type) return jl_box_uint16(*(uint16_t*)data);
820 [ + + ]: 24764400 : if (bt == jl_char_type) return jl_box_char(*(uint32_t*)data);
821 : :
822 : 24762100 : jl_task_t *ct = jl_current_task;
823 : 24762100 : jl_value_t *v = jl_gc_alloc(ct->ptls, nb, bt);
824 : 24762100 : memcpy(jl_assume_aligned(v, sizeof(void*)), data, nb);
825 : 24762100 : return v;
826 : : }
827 : :
828 : 0 : 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 [ # # ]: 0 : assert(jl_is_datatype(dt));
832 : 0 : jl_datatype_t *bt = (jl_datatype_t*)dt;
833 : 0 : size_t nb = jl_datatype_size(bt);
834 : : // some types have special pools to minimize allocations
835 [ # # ]: 0 : if (nb == 0) return jl_new_struct_uninit(bt); // returns bt->instance
836 [ # # # # ]: 0 : if (bt == jl_bool_type) return (1 & jl_atomic_load((_Atomic(int8_t)*)data)) ? jl_true : jl_false;
837 [ # # ]: 0 : if (bt == jl_uint8_type) return jl_box_uint8(jl_atomic_load((_Atomic(uint8_t)*)data));
838 [ # # ]: 0 : if (bt == jl_int64_type) return jl_box_int64(jl_atomic_load((_Atomic(int64_t)*)data));
839 [ # # ]: 0 : if (bt == jl_int32_type) return jl_box_int32(jl_atomic_load((_Atomic(int32_t)*)data));
840 [ # # ]: 0 : if (bt == jl_int8_type) return jl_box_int8(jl_atomic_load((_Atomic(int8_t)*)data));
841 [ # # ]: 0 : if (bt == jl_int16_type) return jl_box_int16(jl_atomic_load((_Atomic(int16_t)*)data));
842 [ # # ]: 0 : if (bt == jl_uint64_type) return jl_box_uint64(jl_atomic_load((_Atomic(uint64_t)*)data));
843 [ # # ]: 0 : if (bt == jl_uint32_type) return jl_box_uint32(jl_atomic_load((_Atomic(uint32_t)*)data));
844 [ # # ]: 0 : if (bt == jl_uint16_type) return jl_box_uint16(jl_atomic_load((_Atomic(uint16_t)*)data));
845 [ # # ]: 0 : if (bt == jl_char_type) return jl_box_char(jl_atomic_load((_Atomic(uint32_t)*)data));
846 : :
847 : 0 : jl_task_t *ct = jl_current_task;
848 : 0 : 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 [ # # ]: 0 : if (nb == 1)
852 : 0 : *(uint8_t*) v = jl_atomic_load((_Atomic(uint8_t)*)data);
853 [ # # ]: 0 : else if (nb <= 2)
854 : 0 : *(uint16_t*)v = jl_atomic_load((_Atomic(uint16_t)*)data);
855 [ # # ]: 0 : else if (nb <= 4)
856 : 0 : *(uint32_t*)v = jl_atomic_load((_Atomic(uint32_t)*)data);
857 : : #if MAX_POINTERATOMIC_SIZE >= 8
858 [ # # ]: 0 : else if (nb <= 8)
859 : 0 : *(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 : 0 : return v;
868 : : }
869 : :
870 : 0 : 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 [ # # ]: 0 : if (nb == 0)
877 : : ;
878 [ # # ]: 0 : else if (nb == 1)
879 : 0 : jl_atomic_store((_Atomic(uint8_t)*)dst, *(uint8_t*)src);
880 [ # # ]: 0 : else if (nb == 2)
881 : 0 : jl_atomic_store((_Atomic(uint16_t)*)dst, *(uint16_t*)src);
882 [ # # ]: 0 : else if (nb <= 4)
883 : 0 : jl_atomic_store((_Atomic(uint32_t)*)dst, zext_read32(src, nb));
884 : : #if MAX_POINTERATOMIC_SIZE >= 8
885 [ # # ]: 0 : else if (nb <= 8)
886 : 0 : 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 : 0 : }
895 : :
896 : 0 : 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 [ # # ]: 0 : assert(jl_is_datatype(dt));
900 : 0 : jl_datatype_t *bt = (jl_datatype_t*)dt;
901 : : // some types have special pools to minimize allocations
902 [ # # ]: 0 : if (nb == 0) return jl_new_struct_uninit(bt); // returns bt->instance
903 [ # # # # ]: 0 : if (bt == jl_bool_type) return (1 & jl_atomic_exchange((_Atomic(int8_t)*)dst, 1 & *(int8_t*)src)) ? jl_true : jl_false;
904 [ # # ]: 0 : if (bt == jl_uint8_type) return jl_box_uint8(jl_atomic_exchange((_Atomic(uint8_t)*)dst, *(int8_t*)src));
905 [ # # ]: 0 : if (bt == jl_int64_type) return jl_box_int64(jl_atomic_exchange((_Atomic(int64_t)*)dst, *(int64_t*)src));
906 [ # # ]: 0 : if (bt == jl_int32_type) return jl_box_int32(jl_atomic_exchange((_Atomic(int32_t)*)dst, *(int32_t*)src));
907 [ # # ]: 0 : if (bt == jl_int8_type) return jl_box_int8(jl_atomic_exchange((_Atomic(int8_t)*)dst, *(int8_t*)src));
908 [ # # ]: 0 : if (bt == jl_int16_type) return jl_box_int16(jl_atomic_exchange((_Atomic(int16_t)*)dst, *(int16_t*)src));
909 [ # # ]: 0 : if (bt == jl_uint64_type) return jl_box_uint64(jl_atomic_exchange((_Atomic(uint64_t)*)dst, *(uint64_t*)src));
910 [ # # ]: 0 : if (bt == jl_uint32_type) return jl_box_uint32(jl_atomic_exchange((_Atomic(uint32_t)*)dst, *(uint32_t*)src));
911 [ # # ]: 0 : if (bt == jl_uint16_type) return jl_box_uint16(jl_atomic_exchange((_Atomic(uint16_t)*)dst, *(uint16_t*)src));
912 [ # # ]: 0 : if (bt == jl_char_type) return jl_box_char(jl_atomic_exchange((_Atomic(uint32_t)*)dst, *(uint32_t*)src));
913 : :
914 : 0 : jl_task_t *ct = jl_current_task;
915 : 0 : jl_value_t *v = jl_gc_alloc(ct->ptls, jl_datatype_size(bt), bt);
916 [ # # ]: 0 : if (nb == 1)
917 : 0 : *(uint8_t*)v = jl_atomic_exchange((_Atomic(uint8_t)*)dst, *(uint8_t*)src);
918 [ # # ]: 0 : else if (nb == 2)
919 : 0 : *(uint16_t*)v = jl_atomic_exchange((_Atomic(uint16_t)*)dst, *(uint16_t*)src);
920 [ # # ]: 0 : else if (nb <= 4)
921 : 0 : *(uint32_t*)v = jl_atomic_exchange((_Atomic(uint32_t)*)dst, zext_read32(src, nb));
922 : : #if MAX_POINTERATOMIC_SIZE >= 8
923 [ # # ]: 0 : else if (nb <= 8)
924 : 0 : *(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 : 0 : return v;
933 : : }
934 : :
935 : 0 : 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 [ # # ]: 0 : if (nb == 0) {
941 : 0 : success = 1;
942 : : }
943 [ # # ]: 0 : else if (nb == 1) {
944 : 0 : uint8_t y = *(uint8_t*)expected;
945 : 0 : success = jl_atomic_cmpswap((_Atomic(uint8_t)*)dst, &y, *(uint8_t*)src);
946 : : }
947 [ # # ]: 0 : 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 [ # # ]: 0 : else if (nb <= 4) {
952 : 0 : uint32_t y = zext_read32(expected, nb);
953 : 0 : uint32_t z = zext_read32(src, nb);
954 : 0 : success = jl_atomic_cmpswap((_Atomic(uint32_t)*)dst, &y, z);
955 : : }
956 : : #if MAX_POINTERATOMIC_SIZE >= 8
957 [ # # ]: 0 : else if (nb <= 8) {
958 : 0 : uint64_t y = zext_read64(expected, nb);
959 : 0 : uint64_t z = zext_read64(src, nb);
960 : 0 : 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 : 0 : return success;
974 : : }
975 : :
976 : 0 : 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 : 0 : jl_task_t *ct = jl_current_task;
981 : 0 : int isptr = jl_field_isptr(rettyp, 0);
982 [ # # # # ]: 0 : jl_value_t *y = jl_gc_alloc(ct->ptls, isptr ? nb : rettyp->size, isptr ? dt : rettyp);
983 : : int success;
984 : 0 : jl_datatype_t *et = (jl_datatype_t*)jl_typeof(expected);
985 [ # # ]: 0 : if (nb == 0) {
986 : 0 : success = (dt == et);
987 : : }
988 [ # # ]: 0 : else if (nb == 1) {
989 : 0 : uint8_t *y8 = (uint8_t*)y;
990 [ # # ]: 0 : assert(!dt->layout->haspadding);
991 [ # # ]: 0 : if (dt == et) {
992 : 0 : *y8 = *(uint8_t*)expected;
993 : 0 : uint8_t z8 = *(uint8_t*)src;
994 : 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : else if (nb <= 4) {
1015 : 0 : uint32_t *y32 = (uint32_t*)y;
1016 [ # # ]: 0 : if (dt == et) {
1017 : 0 : *y32 = zext_read32(expected, nb);
1018 : 0 : uint32_t z32 = zext_read32(src, nb);
1019 : : while (1) {
1020 : 0 : success = jl_atomic_cmpswap((_Atomic(uint32_t)*)dst, y32, z32);
1021 [ # # # # : 0 : if (success || !dt->layout->haspadding || !jl_egal__bits(y, expected, dt))
# # ]
1022 : : break;
1023 : : }
1024 : : }
1025 : : else {
1026 : 0 : *y32 = jl_atomic_load((_Atomic(uint32_t)*)dst);
1027 : 0 : success = 0;
1028 : : }
1029 : : }
1030 : : #if MAX_POINTERATOMIC_SIZE >= 8
1031 [ # # ]: 0 : else if (nb <= 8) {
1032 : 0 : uint64_t *y64 = (uint64_t*)y;
1033 [ # # ]: 0 : if (dt == et) {
1034 : 0 : *y64 = zext_read64(expected, nb);
1035 : 0 : uint64_t z64 = zext_read64(src, nb);
1036 : : while (1) {
1037 : 0 : success = jl_atomic_cmpswap((_Atomic(uint64_t)*)dst, y64, z64);
1038 [ # # # # : 0 : if (success || !dt->layout->haspadding || !jl_egal__bits(y, expected, dt))
# # ]
1039 : : break;
1040 : : }
1041 : : }
1042 : : else {
1043 : 0 : *y64 = jl_atomic_load((_Atomic(uint64_t)*)dst);
1044 : 0 : 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 [ # # ]: 0 : if (isptr) {
1070 : 0 : JL_GC_PUSH1(&y);
1071 : 0 : jl_value_t *z = jl_gc_alloc(ct->ptls, rettyp->size, rettyp);
1072 : 0 : *(jl_value_t**)z = y;
1073 : 0 : JL_GC_POP();
1074 : 0 : y = z;
1075 : 0 : nb = sizeof(jl_value_t*);
1076 : : }
1077 : 0 : *((uint8_t*)y + nb) = success ? 1 : 0;
1078 : 0 : 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 [ - + ]: 7682 : PERMBOXN_FUNC(8, 1)
1102 [ - + ]: 30720 : PERMBOXN_FUNC(16, 1)
1103 [ - + ]: 32731 : PERMBOXN_FUNC(32, 1)
1104 : : #ifdef _P64
1105 [ - + ]: 61440 : 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 [ - + - + ]: 72381 : UNBOX_FUNC(uint8, uint8_t)
1119 [ # # # # ]: 0 : UNBOX_FUNC(int16, int16_t)
1120 [ # # # # ]: 0 : UNBOX_FUNC(uint16, uint16_t)
1121 [ - + - + ]: 20325400 : UNBOX_FUNC(int32, int32_t)
1122 [ # # # # ]: 0 : UNBOX_FUNC(uint32, uint32_t)
1123 [ - + - + ]: 89597300 : UNBOX_FUNC(int64, int64_t)
1124 [ - + - + ]: 1111590 : UNBOX_FUNC(uint64, uint64_t)
1125 [ - + - + ]: 1026 : UNBOX_FUNC(bool, int8_t)
1126 [ # # # # ]: 0 : UNBOX_FUNC(float32, float)
1127 [ - + - + ]: 4 : UNBOX_FUNC(float64, double)
1128 [ - + - + ]: 12 : 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 : 548 : BOX_FUNC(float32, float, jl_box, 1)
1141 : 0 : BOX_FUNC(voidpointer, void*, jl_box, 1)
1142 : 346 : BOX_FUNC(uint8pointer, uint8_t*, jl_box, 1)
1143 : : #ifdef _P64
1144 : 4424 : 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 [ + + ]: 6 : SIBOX_FUNC(int16, int16_t, 1)
1177 [ + + ]: 71891500 : SIBOX_FUNC(int32, int32_t, 1)
1178 [ + + ]: 3173 : UIBOX_FUNC(uint16, uint16_t, 1)
1179 [ + + ]: 744337 : UIBOX_FUNC(uint32, uint32_t, 1)
1180 [ + + ]: 136443000 : UIBOX_FUNC(ssavalue, size_t, 1)
1181 [ + - ]: 4123660 : UIBOX_FUNC(slotnumber, size_t, 1)
1182 : : #ifdef _P64
1183 [ + + ]: 154316000 : SIBOX_FUNC(int64, int64_t, 1)
1184 [ + + ]: 13190400 : 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 : 27703 : JL_DLLEXPORT jl_value_t *jl_box_char(uint32_t x)
1192 : : {
1193 : 27703 : jl_task_t *ct = jl_current_task;
1194 : 27703 : uint32_t u = bswap_32(x);
1195 [ + + ]: 27703 : if (u < 128)
1196 : 25697 : return boxed_char_cache[(uint8_t)u];
1197 : 2006 : jl_value_t *v = jl_gc_alloc(ct->ptls, sizeof(void*), jl_char_type);
1198 : 2006 : *(uint32_t*)jl_data_ptr(v) = x;
1199 : 2006 : return v;
1200 : : }
1201 : :
1202 : : JL_DLLEXPORT jl_value_t *jl_boxed_int8_cache[256];
1203 : 44001 : JL_DLLEXPORT jl_value_t *jl_box_int8(int8_t x)
1204 : : {
1205 : 44001 : return jl_boxed_int8_cache[(uint8_t)x];
1206 : : }
1207 : : JL_DLLEXPORT jl_value_t *jl_boxed_uint8_cache[256];
1208 : 1441750 : JL_DLLEXPORT jl_value_t *jl_box_uint8(uint8_t x)
1209 : : {
1210 : 1441750 : return jl_boxed_uint8_cache[x];
1211 : : }
1212 : :
1213 : 15 : void jl_init_int32_int64_cache(void)
1214 : : {
1215 : : int64_t i;
1216 [ + + ]: 15375 : for(i=0; i < NBOX_C; i++) {
1217 : 15360 : boxed_int32_cache[i] = jl_permbox32(jl_int32_type, i-NBOX_C/2);
1218 : 15360 : boxed_int64_cache[i] = jl_permbox64(jl_int64_type, i-NBOX_C/2);
1219 : : #ifdef _P64
1220 : 15360 : boxed_ssavalue_cache[i] = jl_permbox64(jl_ssavalue_type, i);
1221 : 15360 : 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 [ + + ]: 3855 : for(i=0; i < 256; i++) {
1228 : 3840 : jl_boxed_uint8_cache[i] = jl_permbox8(jl_uint8_type, i);
1229 : : }
1230 : 15 : }
1231 : :
1232 : 15 : void jl_init_box_caches(void)
1233 : : {
1234 : : int64_t i;
1235 [ + + ]: 1935 : for(i=0; i < 128; i++) {
1236 : 1920 : boxed_char_cache[i] = jl_permbox32(jl_char_type, i << 24);
1237 : : }
1238 [ + + ]: 3855 : for(i=0; i < 256; i++) {
1239 : 3840 : jl_boxed_int8_cache[i] = jl_permbox8(jl_int8_type, i);
1240 : : }
1241 [ + + ]: 15375 : for(i=0; i < NBOX_C; i++) {
1242 : 15360 : boxed_int16_cache[i] = jl_permbox16(jl_int16_type, i-NBOX_C/2);
1243 : 15360 : boxed_uint16_cache[i] = jl_permbox16(jl_uint16_type, i);
1244 : 15360 : boxed_uint32_cache[i] = jl_permbox32(jl_uint32_type, i);
1245 : 15360 : boxed_uint64_cache[i] = jl_permbox64(jl_uint64_type, i);
1246 : : }
1247 : 15 : }
1248 : :
1249 : 906 : JL_DLLEXPORT jl_value_t *jl_box_bool(int8_t x)
1250 : : {
1251 [ + + ]: 906 : if (x)
1252 : 371 : return jl_true;
1253 : 535 : return jl_false;
1254 : : }
1255 : :
1256 : : // struct constructors --------------------------------------------------------
1257 : :
1258 : 28390300 : JL_DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...)
1259 : : {
1260 : 28390300 : jl_task_t *ct = jl_current_task;
1261 [ + + ]: 28390300 : if (type->instance != NULL) return type->instance;
1262 : : va_list args;
1263 : 28373700 : size_t i, nf = jl_datatype_nfields(type);
1264 : 28373700 : va_start(args, type);
1265 : 28373700 : jl_value_t *jv = jl_gc_alloc(ct->ptls, jl_datatype_size(type), type);
1266 [ + - - + ]: 28373700 : if (nf > 0 && jl_field_offset(type, 0) != 0) {
1267 : 0 : memset(jv, 0, jl_field_offset(type, 0));
1268 : : }
1269 [ + + ]: 85951100 : for (i = 0; i < nf; i++) {
1270 : 57577400 : set_nth_field(type, jv, i, va_arg(args, jl_value_t*), 0);
1271 : : }
1272 : 28373700 : va_end(args);
1273 : 28373700 : return jv;
1274 : : }
1275 : :
1276 : 4917660 : JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args, uint32_t na)
1277 : : {
1278 : 4917660 : jl_task_t *ct = jl_current_task;
1279 [ + - - + ]: 4917660 : if (!jl_is_datatype(type) || type->layout == NULL) {
1280 : 0 : jl_type_error("new", (jl_value_t*)jl_datatype_type, (jl_value_t*)type);
1281 : : }
1282 : 4917660 : size_t nf = jl_datatype_nfields(type);
1283 [ + - - + ]: 4917660 : if (nf - type->name->n_uninitialized > na || na > nf)
1284 : 0 : jl_error("invalid struct allocation");
1285 [ + + ]: 13798700 : for (size_t i = 0; i < na; i++) {
1286 : 8881010 : jl_value_t *ft = jl_field_type_concrete(type, i);
1287 [ - + ]: 8881010 : if (!jl_isa(args[i], ft))
1288 : 0 : jl_type_error("new", ft, args[i]);
1289 : : }
1290 [ + + ]: 4917660 : if (type->instance != NULL)
1291 : 171043 : return type->instance;
1292 : 4746620 : jl_value_t *jv = jl_gc_alloc(ct->ptls, jl_datatype_size(type), type);
1293 [ + - ]: 4746620 : if (jl_datatype_nfields(type) > 0) {
1294 [ - + ]: 4746620 : if (jl_field_offset(type, 0) != 0) {
1295 : 0 : memset(jl_data_ptr(jv), 0, jl_field_offset(type, 0));
1296 : : }
1297 : 4746620 : JL_GC_PUSH1(&jv);
1298 [ + + ]: 13422900 : for (size_t i = 0; i < na; i++) {
1299 : 8676300 : set_nth_field(type, jv, i, args[i], 0);
1300 : : }
1301 [ + + ]: 4746620 : if (na < jl_datatype_nfields(type)) {
1302 : 13735 : char *data = (char*)jl_data_ptr(jv);
1303 : 13735 : size_t offs = jl_field_offset(type, na);
1304 : 13735 : memset(data + offs, 0, jl_datatype_size(type) - offs);
1305 : : }
1306 : 4746620 : JL_GC_POP();
1307 : : }
1308 : 4746620 : return jv;
1309 : : }
1310 : :
1311 : 171067 : JL_DLLEXPORT jl_value_t *jl_new_structt(jl_datatype_t *type, jl_value_t *tup)
1312 : : {
1313 : 171067 : jl_task_t *ct = jl_current_task;
1314 [ - + ]: 171067 : if (!jl_is_tuple(tup))
1315 : 0 : jl_type_error("new", (jl_value_t*)jl_tuple_type, tup);
1316 [ + - - + ]: 171067 : if (!jl_is_datatype(type) || type->layout == NULL)
1317 : 0 : jl_type_error("new", (jl_value_t *)jl_datatype_type, (jl_value_t *)type);
1318 : 171067 : size_t nargs = jl_nfields(tup);
1319 : 171067 : size_t nf = jl_datatype_nfields(type);
1320 [ - + - + ]: 171067 : JL_NARGS(new, nf, nf);
1321 [ + + ]: 171067 : if (type->instance != NULL) {
1322 : 55244 : jl_datatype_t *tupt = (jl_datatype_t*)jl_typeof(tup);
1323 [ + + ]: 85746 : for (size_t i = 0; i < nargs; i++) {
1324 : 30502 : jl_value_t *ft = jl_field_type_concrete(type, i);
1325 : 30502 : jl_value_t *et = jl_field_type_concrete(tupt, i);
1326 [ + - + - ]: 30502 : assert(jl_is_concrete_type(ft) && jl_is_concrete_type(et));
1327 [ - + ]: 30502 : if (et != ft)
1328 : 0 : jl_type_error("new", ft, jl_get_nth_field(tup, i));
1329 : : }
1330 : 55244 : return type->instance;
1331 : : }
1332 : 115823 : size_t size = jl_datatype_size(type);
1333 : 115823 : jl_value_t *jv = jl_gc_alloc(ct->ptls, size, type);
1334 [ - + ]: 115823 : if (nf == 0)
1335 : 0 : return jv;
1336 : 115823 : jl_value_t *fi = NULL;
1337 [ + + ]: 115823 : 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 : 24 : memset(jl_data_ptr(jv), 0, size);
1342 : : }
1343 [ - + ]: 115799 : else if (jl_field_offset(type, 0) != 0) {
1344 : 0 : memset(jl_data_ptr(jv), 0, jl_field_offset(type, 0));
1345 : : }
1346 : 115823 : JL_GC_PUSH2(&jv, &fi);
1347 [ + + ]: 305510 : for (size_t i = 0; i < nargs; i++) {
1348 : 189687 : jl_value_t *ft = jl_field_type_concrete(type, i);
1349 : 189687 : fi = jl_get_nth_field(tup, i);
1350 [ - + ]: 189687 : if (!jl_isa(fi, ft))
1351 : 0 : jl_type_error("new", ft, fi);
1352 : 189687 : set_nth_field(type, jv, i, fi, 0);
1353 : : }
1354 : 115823 : JL_GC_POP();
1355 : 115823 : return jv;
1356 : : }
1357 : :
1358 : 30029600 : JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type)
1359 : : {
1360 : 30029600 : jl_task_t *ct = jl_current_task;
1361 [ + + ]: 30029600 : if (type->instance != NULL) return type->instance;
1362 : 24925600 : size_t size = jl_datatype_size(type);
1363 : 24925600 : jl_value_t *jv = jl_gc_alloc(ct->ptls, size, type);
1364 [ + - ]: 24925600 : if (size > 0)
1365 : 24925600 : memset(jl_data_ptr(jv), 0, size);
1366 : 24925600 : return jv;
1367 : : }
1368 : :
1369 : : // field access ---------------------------------------------------------------
1370 : :
1371 : 0 : JL_DLLEXPORT void jl_lock_value(jl_value_t *v) JL_NOTSAFEPOINT
1372 : : {
1373 : 0 : JL_LOCK_NOGC((jl_mutex_t*)v);
1374 : 0 : }
1375 : :
1376 : 0 : JL_DLLEXPORT void jl_unlock_value(jl_value_t *v) JL_NOTSAFEPOINT
1377 : : {
1378 : 0 : JL_UNLOCK_NOGC((jl_mutex_t*)v);
1379 : 0 : }
1380 : :
1381 : 61424500 : JL_DLLEXPORT int jl_field_index(jl_datatype_t *t, jl_sym_t *fld, int err)
1382 : : {
1383 [ + + ]: 61424500 : if (jl_is_namedtuple_type(t)) {
1384 : 858671 : jl_value_t *ns = jl_tparam0(t);
1385 [ + + ]: 858671 : if (jl_is_tuple(ns)) {
1386 : 858211 : size_t i, n = jl_nfields(ns);
1387 [ + + ]: 1849100 : for (i = 0; i < n; i++) {
1388 [ + + ]: 1480770 : if (jl_get_nth_field(ns, i) == (jl_value_t*)fld) {
1389 : 489879 : return (int)i;
1390 : : }
1391 : : }
1392 : : }
1393 : : }
1394 : : else {
1395 : 60565800 : jl_svec_t *fn = jl_field_names(t);
1396 : 60565800 : size_t i, n = jl_svec_len(fn);
1397 [ + + ]: 152879000 : for (i = 0; i < n; i++) {
1398 [ + + ]: 148029000 : if (jl_svecref(fn, i) == (jl_value_t*)fld) {
1399 : 55714900 : return (int)i;
1400 : : }
1401 : : }
1402 : : }
1403 [ + + ]: 5219700 : if (err)
1404 : 380 : jl_errorf("type %s has no field %s", jl_symbol_name(t->name->name),
1405 : : jl_symbol_name(fld));
1406 : 5219320 : return -1;
1407 : : }
1408 : :
1409 : 208201000 : JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
1410 : : {
1411 : 208201000 : jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
1412 [ - + ]: 208201000 : if (i >= jl_datatype_nfields(st))
1413 : 0 : jl_bounds_error_int(v, i + 1);
1414 : 208201000 : size_t offs = jl_field_offset(st, i);
1415 [ + + ]: 208201000 : if (jl_field_isptr(st, i)) {
1416 : 81381700 : return jl_atomic_load_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs));
1417 : : }
1418 : 126820000 : jl_value_t *ty = jl_field_type_concrete(st, i);
1419 : 126820000 : int isatomic = jl_field_isatomic(st, i);
1420 [ + + ]: 126820000 : if (jl_is_uniontype(ty)) {
1421 [ - + ]: 36444 : assert(!isatomic);
1422 : 36444 : size_t fsz = jl_field_size(st, i);
1423 : 36444 : uint8_t sel = ((uint8_t*)v)[offs + fsz - 1];
1424 : 36444 : ty = jl_nth_union_component(ty, sel);
1425 [ + + ]: 36444 : if (jl_is_datatype_singleton((jl_datatype_t*)ty))
1426 : 98 : return ((jl_datatype_t*)ty)->instance;
1427 : : }
1428 : : jl_value_t *r;
1429 : 126820000 : size_t fsz = jl_datatype_size(ty);
1430 [ - + - - ]: 126820000 : int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
1431 [ - + - - ]: 126820000 : if (isatomic && !needlock) {
1432 : 0 : r = jl_atomic_new_bits(ty, (char*)v + offs);
1433 : : }
1434 [ - + ]: 126820000 : else if (needlock) {
1435 : 0 : jl_task_t *ct = jl_current_task;
1436 : 0 : r = jl_gc_alloc(ct->ptls, fsz, ty);
1437 : 0 : jl_lock_value(v);
1438 : 0 : memcpy((char*)r, (char*)v + offs, fsz);
1439 : 0 : jl_unlock_value(v);
1440 : : }
1441 : : else {
1442 : 126820000 : r = jl_new_bits(ty, (char*)v + offs);
1443 : : }
1444 : 126820000 : return undefref_check((jl_datatype_t*)ty, r);
1445 : : }
1446 : :
1447 : 35636200 : JL_DLLEXPORT jl_value_t *jl_get_nth_field_noalloc(jl_value_t *v JL_PROPAGATES_ROOT, size_t i) JL_NOTSAFEPOINT
1448 : : {
1449 : 35636200 : jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
1450 [ - + ]: 35636200 : assert(i < jl_datatype_nfields(st));
1451 : 35636200 : size_t offs = jl_field_offset(st,i);
1452 [ - + ]: 35636200 : assert(jl_field_isptr(st,i));
1453 : 35636200 : return jl_atomic_load_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs));
1454 : : }
1455 : :
1456 : 113446000 : JL_DLLEXPORT jl_value_t *jl_get_nth_field_checked(jl_value_t *v, size_t i)
1457 : : {
1458 : 113446000 : jl_value_t *r = jl_get_nth_field(v, i);
1459 [ - + ]: 113446000 : if (__unlikely(r == NULL))
1460 : 0 : jl_throw(jl_undefref_exception);
1461 : 113446000 : return r;
1462 : : }
1463 : :
1464 : 92005200 : 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 [ + + ]: 92005200 : if (hasptr) {
1467 : : // assert that although dst might have some undefined bits, the src heap box should be okay with that
1468 [ - + ]: 2066700 : assert(LLT_ALIGN(nb, sizeof(void*)) == LLT_ALIGN(jl_datatype_size(jl_typeof(src)), sizeof(void*)));
1469 : 2066700 : size_t nptr = nb / sizeof(void*);
1470 : 2066700 : memmove_refs((void**)dst, (void**)src, nptr);
1471 : 2066700 : jl_gc_multi_wb(parent, src);
1472 : 2066700 : src = (jl_value_t*)((char*)src + nptr * sizeof(void*));
1473 : 2066700 : nb -= nptr * sizeof(void*);
1474 : : }
1475 : : else {
1476 : : // src must be a heap box.
1477 [ - + ]: 89938500 : assert(nb == jl_datatype_size(jl_typeof(src)));
1478 [ + + ]: 89938500 : if (nb >= 16) {
1479 : 3225680 : memcpy(dst, jl_assume_aligned(src, 16), nb);
1480 : 3225680 : return;
1481 : : }
1482 : : }
1483 : 88779500 : memcpy(dst, jl_assume_aligned(src, sizeof(void*)), nb);
1484 : : }
1485 : :
1486 : 212406000 : 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 : 212406000 : size_t offs = jl_field_offset(st, i);
1489 [ + + ]: 212406000 : if (rhs == NULL) { // TODO: this should be invalid, but it happens frequently in ircode.c
1490 [ + - + - ]: 217625 : assert(jl_field_isptr(st, i) && *(jl_value_t**)((char*)v + offs) == NULL);
1491 : 217625 : return;
1492 : : }
1493 [ + + ]: 212188000 : if (jl_field_isptr(st, i)) {
1494 : 120183000 : jl_atomic_store_release((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
1495 : 120183000 : jl_gc_wb(v, rhs);
1496 : : }
1497 : : else {
1498 : 92005200 : jl_value_t *ty = jl_field_type_concrete(st, i);
1499 : 92005200 : jl_value_t *rty = jl_typeof(rhs);
1500 : : int hasptr;
1501 : 92005200 : int isunion = jl_is_uniontype(ty);
1502 [ + + ]: 92005200 : if (isunion) {
1503 [ - + ]: 106 : assert(!isatomic);
1504 : 106 : size_t fsz = jl_field_size(st, i);
1505 : 106 : uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
1506 : 106 : unsigned nth = 0;
1507 [ - + ]: 106 : if (!jl_find_union_component(ty, rty, &nth))
1508 : 0 : assert(0 && "invalid field assignment to isbits union");
1509 : 106 : *psel = nth;
1510 [ + + ]: 106 : if (jl_is_datatype_singleton((jl_datatype_t*)rty))
1511 : 52 : return;
1512 : 54 : hasptr = 0;
1513 : : }
1514 : : else {
1515 : 92005100 : hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
1516 : : }
1517 : 92005200 : size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
1518 [ - + - - ]: 92005200 : int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
1519 [ - + - - ]: 92005200 : if (isatomic && !needlock) {
1520 : 0 : jl_atomic_store_bits((char*)v + offs, rhs, fsz);
1521 [ # # ]: 0 : if (hasptr)
1522 : 0 : jl_gc_multi_wb(v, rhs); // rhs is immutable
1523 : : }
1524 [ - + ]: 92005200 : else if (needlock) {
1525 : 0 : jl_lock_value(v);
1526 : 0 : memcpy((char*)v + offs, (char*)rhs, fsz);
1527 : 0 : jl_unlock_value(v);
1528 : : }
1529 : : else {
1530 : 92005200 : memassign_safe(hasptr, v, (char*)v + offs, rhs, fsz);
1531 : : }
1532 : : }
1533 : : }
1534 : :
1535 : 0 : 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 : 0 : jl_value_t *ty = jl_field_type_concrete(st, i);
1538 [ # # ]: 0 : if (!jl_isa(rhs, ty))
1539 : 0 : jl_type_error("swapfield!", ty, rhs);
1540 : 0 : size_t offs = jl_field_offset(st, i);
1541 : : jl_value_t *r;
1542 [ # # ]: 0 : if (jl_field_isptr(st, i)) {
1543 [ # # ]: 0 : if (isatomic)
1544 : 0 : r = jl_atomic_exchange((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
1545 : : else
1546 : 0 : r = jl_atomic_exchange_relaxed((_Atomic(jl_value_t*)*)((char*)v + offs), rhs);
1547 : 0 : jl_gc_wb(v, rhs);
1548 : : }
1549 : : else {
1550 : 0 : jl_value_t *rty = jl_typeof(rhs);
1551 : : int hasptr;
1552 : 0 : int isunion = jl_is_uniontype(ty);
1553 [ # # ]: 0 : if (isunion) {
1554 [ # # ]: 0 : assert(!isatomic);
1555 : 0 : r = jl_get_nth_field(v, i);
1556 : 0 : size_t fsz = jl_field_size(st, i);
1557 : 0 : uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
1558 : 0 : unsigned nth = 0;
1559 [ # # ]: 0 : if (!jl_find_union_component(ty, rty, &nth))
1560 : 0 : assert(0 && "invalid field assignment to isbits union");
1561 : 0 : *psel = nth;
1562 [ # # ]: 0 : if (jl_is_datatype_singleton((jl_datatype_t*)rty))
1563 : 0 : return r;
1564 : 0 : hasptr = 0;
1565 : : }
1566 : : else {
1567 : 0 : hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
1568 : : }
1569 : 0 : size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
1570 [ # # # # ]: 0 : int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
1571 [ # # # # ]: 0 : if (isatomic && !needlock) {
1572 : 0 : r = jl_atomic_swap_bits(rty, (char*)v + offs, rhs, fsz);
1573 [ # # ]: 0 : if (hasptr)
1574 : 0 : jl_gc_multi_wb(v, rhs); // rhs is immutable
1575 : : }
1576 : : else {
1577 [ # # ]: 0 : if (needlock) {
1578 : 0 : jl_task_t *ct = jl_current_task;
1579 : 0 : r = jl_gc_alloc(ct->ptls, fsz, ty);
1580 : 0 : jl_lock_value(v);
1581 : 0 : memcpy((char*)r, (char*)v + offs, fsz);
1582 : 0 : memcpy((char*)v + offs, (char*)rhs, fsz);
1583 : 0 : jl_unlock_value(v);
1584 : : }
1585 : : else {
1586 [ # # ]: 0 : if (!isunion)
1587 : 0 : r = jl_new_bits(ty, (char*)v + offs);
1588 : 0 : memassign_safe(hasptr, v, (char*)v + offs, rhs, fsz);
1589 : : }
1590 [ # # # # ]: 0 : if (needlock || !isunion)
1591 : 0 : r = undefref_check((jl_datatype_t*)ty, r);
1592 : : }
1593 : : }
1594 [ # # ]: 0 : if (__unlikely(r == NULL))
1595 : 0 : jl_throw(jl_undefref_exception);
1596 : 0 : return r;
1597 : : }
1598 : :
1599 : 0 : 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 : 0 : size_t offs = jl_field_offset(st, i);
1602 : 0 : jl_value_t *ty = jl_field_type_concrete(st, i);
1603 : 0 : jl_value_t *r = jl_get_nth_field_checked(v, i);
1604 [ # # # # ]: 0 : if (isatomic && jl_field_isptr(st, i))
1605 : 0 : jl_fence(); // load was previously only relaxed
1606 : : jl_value_t **args;
1607 : 0 : JL_GC_PUSHARGS(args, 2);
1608 : 0 : args[0] = r;
1609 : 0 : while (1) {
1610 : 0 : args[1] = rhs;
1611 : 0 : jl_value_t *y = jl_apply_generic(op, args, 2);
1612 : 0 : args[1] = y;
1613 [ # # ]: 0 : if (!jl_isa(y, ty))
1614 : 0 : jl_type_error("modifyfield!", ty, y);
1615 [ # # ]: 0 : if (jl_field_isptr(st, i)) {
1616 : 0 : _Atomic(jl_value_t*) *p = (_Atomic(jl_value_t*)*)((char*)v + offs);
1617 [ # # # # ]: 0 : if (isatomic ? jl_atomic_cmpswap(p, &r, y) : jl_atomic_cmpswap_relaxed(p, &r, y))
1618 : 0 : break;
1619 : : }
1620 : : else {
1621 : 0 : jl_value_t *yty = jl_typeof(y);
1622 : 0 : jl_value_t *rty = jl_typeof(r);
1623 : : int hasptr;
1624 : 0 : int isunion = jl_is_uniontype(ty);
1625 [ # # ]: 0 : if (isunion) {
1626 [ # # ]: 0 : assert(!isatomic);
1627 : 0 : hasptr = 0;
1628 : : }
1629 : : else {
1630 : 0 : hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
1631 : : }
1632 : 0 : size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
1633 [ # # # # ]: 0 : int needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
1634 [ # # # # ]: 0 : if (isatomic && !needlock) {
1635 [ # # ]: 0 : if (jl_atomic_bool_cmpswap_bits((char*)v + offs, r, y, fsz)) {
1636 [ # # ]: 0 : if (hasptr)
1637 : 0 : jl_gc_multi_wb(v, y); // y is immutable
1638 : 0 : break;
1639 : : }
1640 : 0 : r = jl_atomic_new_bits(ty, (char*)v + offs);
1641 : : }
1642 : : else {
1643 [ # # ]: 0 : if (needlock)
1644 : 0 : jl_lock_value(v);
1645 : 0 : int success = memcmp((char*)v + offs, r, fsz) == 0;
1646 [ # # ]: 0 : if (success) {
1647 [ # # ]: 0 : if (isunion) {
1648 : 0 : size_t fsz = jl_field_size(st, i);
1649 : 0 : uint8_t *psel = &((uint8_t*)v)[offs + fsz - 1];
1650 : 0 : success = (jl_typeof(r) == jl_nth_union_component(ty, *psel));
1651 [ # # ]: 0 : if (success) {
1652 : 0 : unsigned nth = 0;
1653 [ # # ]: 0 : if (!jl_find_union_component(ty, yty, &nth))
1654 : 0 : assert(0 && "invalid field assignment to isbits union");
1655 : 0 : *psel = nth;
1656 [ # # ]: 0 : if (jl_is_datatype_singleton((jl_datatype_t*)yty))
1657 : 0 : break;
1658 : : }
1659 : 0 : fsz = jl_datatype_size((jl_datatype_t*)yty); // need to shrink-wrap the final copy
1660 : : }
1661 : : else {
1662 [ # # # # ]: 0 : assert(yty == ty && rty == ty);
1663 : : }
1664 : 0 : memassign_safe(hasptr, v, (char*)v + offs, y, fsz);
1665 : : }
1666 [ # # ]: 0 : if (needlock)
1667 : 0 : jl_unlock_value(v);
1668 [ # # ]: 0 : if (success)
1669 : 0 : 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 : 0 : jl_datatype_t *rettyp = jl_apply_modify_type(ty);
1679 : : JL_GC_PROMISE_ROOTED(rettyp); // (JL_ALWAYS_LEAFTYPE)
1680 : 0 : args[0] = jl_new_struct(rettyp, args[0], args[1]);
1681 : 0 : JL_GC_POP();
1682 : 0 : return args[0];
1683 : : }
1684 : :
1685 : 0 : 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 : 0 : jl_value_t *ty = jl_field_type_concrete(st, i);
1688 [ # # ]: 0 : if (!jl_isa(rhs, ty))
1689 : 0 : jl_type_error("replacefield!", ty, rhs);
1690 : 0 : size_t offs = jl_field_offset(st, i);
1691 : 0 : jl_value_t *r = expected;
1692 : 0 : jl_datatype_t *rettyp = jl_apply_cmpswap_type(ty);
1693 : : JL_GC_PROMISE_ROOTED(rettyp); // (JL_ALWAYS_LEAFTYPE)
1694 [ # # ]: 0 : if (jl_field_isptr(st, i)) {
1695 : 0 : _Atomic(jl_value_t*) *p = (_Atomic(jl_value_t*)*)((char*)v + offs);
1696 : : int success;
1697 : : while (1) {
1698 [ # # ]: 0 : success = isatomic ? jl_atomic_cmpswap(p, &r, rhs) : jl_atomic_cmpswap_relaxed(p, &r, rhs);
1699 [ # # ]: 0 : if (success)
1700 : 0 : jl_gc_wb(v, rhs);
1701 [ # # ]: 0 : if (__unlikely(r == NULL))
1702 : 0 : jl_throw(jl_undefref_exception);
1703 [ # # # # ]: 0 : if (success || !jl_egal(r, expected))
1704 : : break;
1705 : : }
1706 : 0 : JL_GC_PUSH1(&r);
1707 [ # # ]: 0 : r = jl_new_struct(rettyp, r, success ? jl_true : jl_false);
1708 : 0 : JL_GC_POP();
1709 : : }
1710 : : else {
1711 : : int hasptr;
1712 : 0 : int isunion = jl_is_uniontype(ty);
1713 : : int needlock;
1714 : 0 : jl_value_t *rty = ty;
1715 : 0 : size_t fsz = jl_field_size(st, i);
1716 [ # # ]: 0 : if (isunion) {
1717 [ # # ]: 0 : assert(!isatomic);
1718 : 0 : hasptr = 0;
1719 : 0 : needlock = 0;
1720 : 0 : isatomic = 0; // this makes GCC happy
1721 : : }
1722 : : else {
1723 : 0 : hasptr = ((jl_datatype_t*)ty)->layout->npointers > 0;
1724 : 0 : fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
1725 [ # # # # ]: 0 : needlock = (isatomic && fsz > MAX_ATOMIC_SIZE);
1726 : : }
1727 [ # # # # ]: 0 : if (isatomic && !needlock) {
1728 : 0 : r = jl_atomic_cmpswap_bits((jl_datatype_t*)ty, rettyp, (char*)v + offs, r, rhs, fsz);
1729 : 0 : int success = *((uint8_t*)r + fsz);
1730 [ # # # # ]: 0 : if (success && hasptr)
1731 : 0 : jl_gc_multi_wb(v, rhs); // rhs is immutable
1732 : : }
1733 : : else {
1734 : 0 : jl_task_t *ct = jl_current_task;
1735 : 0 : uint8_t *psel = NULL;
1736 [ # # ]: 0 : if (isunion) {
1737 : 0 : psel = &((uint8_t*)v)[offs + fsz - 1];
1738 : 0 : rty = jl_nth_union_component(rty, *psel);
1739 : : }
1740 [ # # ]: 0 : assert(!jl_field_isptr(rettyp, 0));
1741 : 0 : r = jl_gc_alloc(ct->ptls, rettyp->size, (jl_value_t*)rettyp);
1742 : 0 : int success = (rty == jl_typeof(expected));
1743 [ # # ]: 0 : if (needlock)
1744 : 0 : jl_lock_value(v);
1745 : 0 : memcpy((char*)r, (char*)v + offs, fsz); // copy field, including union bits
1746 [ # # ]: 0 : if (success) {
1747 : 0 : size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
1748 [ # # ]: 0 : if (((jl_datatype_t*)rty)->layout->haspadding)
1749 : 0 : success = jl_egal__bits(r, expected, (jl_datatype_t*)rty);
1750 : : else
1751 : 0 : success = memcmp((char*)r, (char*)expected, fsz) == 0;
1752 : : }
1753 : 0 : *((uint8_t*)r + fsz) = success ? 1 : 0;
1754 [ # # ]: 0 : if (success) {
1755 : 0 : jl_value_t *rty = jl_typeof(rhs);
1756 : 0 : size_t fsz = jl_datatype_size((jl_datatype_t*)rty); // need to shrink-wrap the final copy
1757 [ # # ]: 0 : if (isunion) {
1758 : 0 : unsigned nth = 0;
1759 [ # # ]: 0 : if (!jl_find_union_component(ty, rty, &nth))
1760 : 0 : assert(0 && "invalid field assignment to isbits union");
1761 : 0 : *psel = nth;
1762 [ # # ]: 0 : if (jl_is_datatype_singleton((jl_datatype_t*)rty))
1763 : 0 : return r;
1764 : : }
1765 : 0 : memassign_safe(hasptr, v, (char*)v + offs, rhs, fsz);
1766 : : }
1767 [ # # ]: 0 : if (needlock)
1768 : 0 : jl_unlock_value(v);
1769 : : }
1770 : 0 : r = undefref_check((jl_datatype_t*)rty, r);
1771 [ # # ]: 0 : if (__unlikely(r == NULL))
1772 : 0 : jl_throw(jl_undefref_exception);
1773 : : }
1774 : 0 : return r;
1775 : : }
1776 : :
1777 : 1042580 : JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT
1778 : : {
1779 : 1042580 : jl_datatype_t *st = (jl_datatype_t*)jl_typeof(v);
1780 : 1042580 : size_t offs = jl_field_offset(st, i);
1781 : 1042580 : _Atomic(jl_value_t*) *fld = (_Atomic(jl_value_t*)*)((char*)v + offs);
1782 [ + + ]: 1042580 : if (!jl_field_isptr(st, i)) {
1783 : 308236 : jl_datatype_t *ft = (jl_datatype_t*)jl_field_type_concrete(st, i);
1784 [ + + + + ]: 308236 : if (!jl_is_datatype(ft) || ft->layout->first_ptr < 0)
1785 : 302007 : return 2; // isbits are always defined
1786 : 6229 : fld += ft->layout->first_ptr;
1787 : : }
1788 : 740568 : jl_value_t *fval = jl_atomic_load_relaxed(fld);
1789 : 740568 : return fval != NULL ? 1 : 0;
1790 : : }
1791 : :
1792 : 2 : JL_DLLEXPORT size_t jl_get_field_offset(jl_datatype_t *ty, int field)
1793 : : {
1794 [ + - + - : 2 : if (!jl_struct_try_layout(ty) || field > jl_datatype_nfields(ty) || field < 1)
- + ]
1795 : 0 : jl_bounds_error_int((jl_value_t*)ty, field);
1796 : 2 : return jl_field_offset(ty, field - 1);
1797 : : }
1798 : :
1799 : : #ifdef __cplusplus
1800 : : }
1801 : : #endif
|