Skip to content

Commit f8a92df

Browse files
committed
fix #10981, splatting very long argument lists
The issue was an `alloca` of temporary type layout info; need to switch to the heap for very large types.
1 parent e05f6a1 commit f8a92df

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

src/alloc.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,7 +1006,12 @@ void jl_compute_field_offsets(jl_datatype_t *st)
10061006
uint64_t max_size = max_offset >> 1;
10071007

10081008
uint32_t nfields = jl_svec_len(st->types);
1009-
jl_fielddesc32_t* desc = (jl_fielddesc32_t*) alloca(nfields * sizeof(jl_fielddesc32_t));
1009+
size_t descsz = nfields * sizeof(jl_fielddesc32_t);
1010+
jl_fielddesc32_t *desc;
1011+
if (descsz < jl_page_size)
1012+
desc = (jl_fielddesc32_t*)alloca(descsz);
1013+
else
1014+
desc = (jl_fielddesc32_t*)malloc(descsz);
10101015
int haspadding = 0;
10111016
assert(st->name == jl_tuple_typename ||
10121017
st == jl_sym_type ||
@@ -1020,7 +1025,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
10201025
fsz = jl_datatype_size(ty);
10211026
// Should never happen
10221027
if (__unlikely(fsz > max_size))
1023-
jl_throw(jl_overflow_exception);
1028+
goto throw_ovf;
10241029
al = ((jl_datatype_t*)ty)->layout->alignment;
10251030
desc[i].isptr = 0;
10261031
if (((jl_datatype_t*)ty)->layout->haspadding)
@@ -1046,7 +1051,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
10461051
desc[i].offset = sz;
10471052
desc[i].size = fsz;
10481053
if (__unlikely(max_offset - sz < fsz))
1049-
jl_throw(jl_overflow_exception);
1054+
goto throw_ovf;
10501055
sz += fsz;
10511056
}
10521057
if (homogeneous && lastty!=NULL && jl_is_tuple_type(st)) {
@@ -1060,6 +1065,11 @@ void jl_compute_field_offsets(jl_datatype_t *st)
10601065
if (st->size > sz)
10611066
haspadding = 1;
10621067
st->layout = jl_get_layout(nfields, alignm, haspadding, desc);
1068+
if (descsz >= jl_page_size) free(desc);
1069+
return;
1070+
throw_ovf:
1071+
if (descsz >= jl_page_size) free(desc);
1072+
jl_throw(jl_overflow_exception);
10631073
}
10641074

10651075
extern int jl_boot_file_loaded;

test/core.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4598,3 +4598,13 @@ gVararg(a::fVararg(Int)) = length(a)
45984598
catch e
45994599
(e::ErrorException).msg
46004600
end == "generated function body is not pure. this likely means it contains a closure or comprehension."
4601+
4602+
# issue #10981, long argument lists
4603+
let a = fill(["sdf"], 2*10^6), temp_vcat(x...) = vcat(x...)
4604+
# we introduce a new function `temp_vcat` to make sure there is no existing
4605+
# method cache match, leading to a path that allocates a large tuple type.
4606+
b = temp_vcat(a...)
4607+
@test isa(b, Vector{String})
4608+
@test length(b) == 2*10^6
4609+
@test b[1] == b[end] == "sdf"
4610+
end

0 commit comments

Comments
 (0)