Skip to content

Commit 06a378f

Browse files
vtjnashKristofferC
authored andcommitted
union-types: use insertion (stable) sort instead of qsort (#45896)
Different platforms implement qsort differently, leading to platform-specific errors. This is a quick port of the ml_matches algorithm for use instead. For small unions (almost always), this should also be slightly faster, though insignificant. Refs #45874 (cherry picked from commit 8cc5445)
1 parent b1bd4af commit 06a378f

File tree

2 files changed

+30
-15
lines changed

2 files changed

+30
-15
lines changed

base/sort.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -499,12 +499,12 @@ function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg,
499499
j = i
500500
x = v[i]
501501
while j > lo
502-
if lt(o, x, v[j-1])
503-
v[j] = v[j-1]
504-
j -= 1
505-
continue
502+
y = v[j-1]
503+
if !lt(o, x, y)
504+
break
506505
end
507-
break
506+
v[j] = y
507+
j -= 1
508508
end
509509
v[j] = x
510510
end

src/jltypes.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,8 @@ static int datatype_name_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT
315315

316316
// sort singletons first, then DataTypes, then UnionAlls,
317317
// ties broken alphabetically including module name & type parameters
318-
static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT
318+
static int union_sort_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT
319319
{
320-
jl_value_t *a = *(jl_value_t**)ap;
321-
jl_value_t *b = *(jl_value_t**)bp;
322320
if (a == NULL)
323321
return b == NULL ? 0 : 1;
324322
if (b == NULL)
@@ -353,16 +351,33 @@ static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT
353351
}
354352
}
355353

354+
static void isort_union(jl_value_t **a, size_t len) JL_NOTSAFEPOINT
355+
{
356+
size_t i, j;
357+
for (i = 1; i < len; i++) {
358+
jl_value_t *x = a[i];
359+
for (j = i; j > 0; j--) {
360+
jl_value_t *y = a[j - 1];
361+
if (!(union_sort_cmp(x, y) < 0))
362+
break;
363+
a[j] = y;
364+
}
365+
a[j] = x;
366+
}
367+
}
368+
356369
JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
357370
{
358-
if (n == 0) return (jl_value_t*)jl_bottom_type;
371+
if (n == 0)
372+
return (jl_value_t*)jl_bottom_type;
359373
size_t i;
360-
for(i=0; i < n; i++) {
374+
for (i = 0; i < n; i++) {
361375
jl_value_t *pi = ts[i];
362376
if (!(jl_is_type(pi) || jl_is_typevar(pi)) || jl_is_vararg_type(pi))
363377
jl_type_error("Union", (jl_value_t*)jl_type_type, pi);
364378
}
365-
if (n == 1) return ts[0];
379+
if (n == 1)
380+
return ts[0];
366381

367382
size_t nt = count_union_components(ts, n);
368383
jl_value_t **temp;
@@ -371,9 +386,9 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
371386
flatten_type_union(ts, n, temp, &count);
372387
assert(count == nt);
373388
size_t j;
374-
for(i=0; i < nt; i++) {
375-
int has_free = temp[i]!=NULL && jl_has_free_typevars(temp[i]);
376-
for(j=0; j < nt; j++) {
389+
for (i = 0; i < nt; i++) {
390+
int has_free = temp[i] != NULL && jl_has_free_typevars(temp[i]);
391+
for (j = 0; j < nt; j++) {
377392
if (j != i && temp[i] && temp[j]) {
378393
if (temp[i] == temp[j] || temp[i] == jl_bottom_type ||
379394
temp[j] == (jl_value_t*)jl_any_type ||
@@ -385,7 +400,7 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n)
385400
}
386401
}
387402
}
388-
qsort(temp, nt, sizeof(jl_value_t*), union_sort_cmp);
403+
isort_union(temp, nt);
389404
jl_value_t **ptu = &temp[nt];
390405
*ptu = jl_bottom_type;
391406
int k;

0 commit comments

Comments
 (0)