Skip to content

Commit aa18d37

Browse files
authored
fix #38224, set and use DataType.zeroinit in arrays (#38444)
1 parent 8de4268 commit aa18d37

File tree

6 files changed

+33
-15
lines changed

6 files changed

+33
-15
lines changed

src/array.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ size_t jl_arr_xtralloc_limit = 0;
7575
#define MAXINTVAL (((size_t)-1)>>1)
7676

7777
static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims,
78-
int isunboxed, int hasptr, int isunion, int elsz)
78+
int8_t isunboxed, int8_t hasptr, int8_t isunion, int8_t zeroinit, int elsz)
7979
{
8080
jl_ptls_t ptls = jl_get_ptls_states();
8181
size_t i, tot, nel=1;
@@ -123,8 +123,6 @@ static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims,
123123
// No allocation or safepoint allowed after this
124124
a->flags.how = 0;
125125
data = (char*)a + doffs;
126-
if (tot > 0 && (!isunboxed || hasptr || isunion)) // TODO: check for zeroinit
127-
memset(data, 0, tot);
128126
}
129127
else {
130128
tsz = JL_ARRAY_ALIGN(tsz, JL_CACHE_BYTE_ALIGNMENT); // align whole object
@@ -135,12 +133,11 @@ static jl_array_t *_new_array_(jl_value_t *atype, uint32_t ndims, size_t *dims,
135133
// No allocation or safepoint allowed after this
136134
a->flags.how = 2;
137135
jl_gc_track_malloced_array(ptls, a);
138-
if (tot > 0 && (!isunboxed || hasptr || isunion)) // TODO: check for zeroinit
139-
// need to zero out isbits union array selector bytes to ensure a valid type index
140-
memset(data, 0, tot);
141136
}
142137
a->flags.pooled = tsz <= GC_MAX_SZCLASS;
143138

139+
if (zeroinit)
140+
memset(data, 0, tot);
144141
a->data = data;
145142
if (JL_ARRAY_IMPL_NUL && elsz == 1)
146143
((char*)data)[tot - 1] = '\0';
@@ -186,14 +183,15 @@ static inline jl_array_t *_new_array(jl_value_t *atype, uint32_t ndims, size_t *
186183
else {
187184
elsz = LLT_ALIGN(elsz, al);
188185
}
186+
int zi = !isunboxed || hasptr || isunion || (jl_is_datatype(eltype) && ((jl_datatype_t*)eltype)->zeroinit);
189187

190-
return _new_array_(atype, ndims, dims, isunboxed, hasptr, isunion, elsz);
188+
return _new_array_(atype, ndims, dims, isunboxed, hasptr, isunion, zi, elsz);
191189
}
192190

193191
jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims,
194192
int isunboxed, int hasptr, int isunion, int elsz)
195193
{
196-
return _new_array_(atype, ndims, dims, isunboxed, hasptr, isunion, elsz);
194+
return _new_array_(atype, ndims, dims, isunboxed, hasptr, isunion, 0, elsz);
197195
}
198196

199197
#ifndef JL_NDEBUG
@@ -784,7 +782,7 @@ STATIC_INLINE void jl_array_grow_at_beg(jl_array_t *a, size_t idx, size_t inc,
784782
char *data = (char*)a->data;
785783
char *newdata;
786784
char *typetagdata;
787-
char *newtypetagdata;
785+
char *newtypetagdata = NULL;
788786
int isbitsunion = jl_array_isbitsunion(a);
789787
if (isbitsunion) typetagdata = jl_array_typetagdata(a);
790788
if (a->offset >= inc) {
@@ -864,10 +862,10 @@ STATIC_INLINE void jl_array_grow_at_beg(jl_array_t *a, size_t idx, size_t inc,
864862
#endif
865863
a->nrows = newnrows;
866864
a->data = newdata;
867-
if (a->flags.ptrarray || a->flags.hasptr) { // TODO: check for zeroinit
865+
if (jl_is_array_zeroinit(a)) {
868866
memset(newdata + idx * elsz, 0, nbinc);
869867
}
870-
else if (isbitsunion) {
868+
if (newtypetagdata) {
871869
memset(newtypetagdata + idx, 0, inc);
872870
}
873871
}
@@ -945,7 +943,7 @@ STATIC_INLINE void jl_array_grow_at_end(jl_array_t *a, size_t idx,
945943
a->length = newnrows;
946944
#endif
947945
a->nrows = newnrows;
948-
if (a->flags.ptrarray || a->flags.hasptr) { // TODO: check for zeroinit
946+
if (jl_is_array_zeroinit(a)) {
949947
memset(data + idx * elsz, 0, inc * elsz);
950948
}
951949
}
@@ -1201,7 +1199,7 @@ JL_DLLEXPORT jl_array_t *jl_array_copy(jl_array_t *ary)
12011199
int isunion = jl_is_uniontype(jl_tparam0(jl_typeof(ary)));
12021200
jl_array_t *new_ary = _new_array_(jl_typeof(ary), jl_array_ndims(ary),
12031201
&ary->nrows, !ary->flags.ptrarray,
1204-
ary->flags.hasptr, isunion, elsz);
1202+
ary->flags.hasptr, isunion, 0, elsz);
12051203
memcpy(new_ary->data, ary->data, len * elsz);
12061204
// ensure isbits union arrays copy their selector bytes correctly
12071205
if (jl_array_isbitsunion(ary))

src/datatype.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
544544
if (npointers)
545545
free(pointers);
546546
}
547+
st->zeroinit = zeroinit;
547548
}
548549
// now finish deciding if this instantiation qualifies for special properties
549550
assert(!isbitstype || st->layout->npointers == 0); // the definition of isbits

src/dump.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,7 @@ static jl_value_t *jl_deserialize_value_array(jl_serializer_state *s, uint8_t ta
13461346
isptr = (elsize >> 15) & 1;
13471347
hasptr = (elsize >> 14) & 1;
13481348
isunion = (elsize >> 13) & 1;
1349-
elsize = elsize & 0x3fff;
1349+
elsize = elsize & 0x1fff;
13501350
}
13511351
uintptr_t pos = backref_list.len;
13521352
arraylist_push(&backref_list, NULL);

src/ircode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ static jl_value_t *jl_decode_value_array(jl_ircode_state *s, uint8_t tag) JL_GC_
418418
isptr = (elsize >> 15) & 1;
419419
hasptr = (elsize >> 14) & 1;
420420
isunion = (elsize >> 13) & 1;
421-
elsize = elsize & 0x3fff;
421+
elsize = elsize & 0x1fff;
422422
}
423423
size_t *dims = (size_t*)alloca(ndims * sizeof(size_t));
424424
for (i = 0; i < ndims; i++) {

src/julia.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,14 @@ STATIC_INLINE int jl_is_type_type(jl_value_t *v) JL_NOTSAFEPOINT
12501250
((jl_datatype_t*)(v))->name == ((jl_datatype_t*)jl_type_type->body)->name);
12511251
}
12521252

1253+
STATIC_INLINE int jl_is_array_zeroinit(jl_array_t *a) JL_NOTSAFEPOINT
1254+
{
1255+
if (a->flags.ptrarray || a->flags.hasptr)
1256+
return 1;
1257+
jl_value_t *elty = jl_tparam0(jl_typeof(a));
1258+
return jl_is_datatype(elty) && ((jl_datatype_t*)elty)->zeroinit;
1259+
}
1260+
12531261
// object identity
12541262
JL_DLLEXPORT int jl_egal(jl_value_t *a JL_MAYBE_UNROOTED, jl_value_t *b JL_MAYBE_UNROOTED) JL_NOTSAFEPOINT;
12551263
JL_DLLEXPORT uintptr_t jl_object_id(jl_value_t *v) JL_NOTSAFEPOINT;

test/core.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7508,3 +7508,14 @@ let array = Int[]
75087508
end
75097509
@test compare_union37557(Ref{Union{Int,Vector{Int}}}(1),
75107510
Ref{Union{Int,Vector{Int}}}(1))
7511+
7512+
# issue #38224
7513+
struct S38224
7514+
i::Union{Int,Missing}
7515+
end
7516+
@test S38224.zeroinit
7517+
for _ in 1:5
7518+
let a = Vector{S38224}(undef, 1000000)
7519+
@test all(x->ismissing(x.i), a)
7520+
end
7521+
end

0 commit comments

Comments
 (0)