From ab36468f5bacf52d4a82bcac13146946a753cc47 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 6 Jul 2022 08:34:07 -0400 Subject: [PATCH] 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 8cc544543d7bb978451f9076242bbad41d5184cb) --- base/sort.jl | 10 +++++----- src/jltypes.c | 35 +++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index 53ebefd1840ab..307a515dad050 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -500,12 +500,12 @@ function sort!(v::AbstractVector, lo::Integer, hi::Integer, ::InsertionSortAlg, j = i x = v[i] while j > lo - if lt(o, x, v[j-1]) - v[j] = v[j-1] - j -= 1 - continue + y = v[j-1] + if !lt(o, x, y) + break end - break + v[j] = y + j -= 1 end v[j] = x end diff --git a/src/jltypes.c b/src/jltypes.c index 72a9d257f140b..ef09f6f457fd1 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -420,10 +420,8 @@ static int datatype_name_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT // sort singletons first, then DataTypes, then UnionAlls, // ties broken alphabetically including module name & type parameters -static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT +static int union_sort_cmp(jl_value_t *a, jl_value_t *b) JL_NOTSAFEPOINT { - jl_value_t *a = *(jl_value_t**)ap; - jl_value_t *b = *(jl_value_t**)bp; if (a == NULL) return b == NULL ? 0 : 1; if (b == NULL) @@ -458,16 +456,33 @@ static int union_sort_cmp(const void *ap, const void *bp) JL_NOTSAFEPOINT } } +static void isort_union(jl_value_t **a, size_t len) JL_NOTSAFEPOINT +{ + size_t i, j; + for (i = 1; i < len; i++) { + jl_value_t *x = a[i]; + for (j = i; j > 0; j--) { + jl_value_t *y = a[j - 1]; + if (!(union_sort_cmp(x, y) < 0)) + break; + a[j] = y; + } + a[j] = x; + } +} + JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n) { - if (n == 0) return (jl_value_t*)jl_bottom_type; + if (n == 0) + return (jl_value_t*)jl_bottom_type; size_t i; - for(i=0; i < n; i++) { + for (i = 0; i < n; i++) { jl_value_t *pi = ts[i]; if (!(jl_is_type(pi) || jl_is_typevar(pi))) jl_type_error("Union", (jl_value_t*)jl_type_type, pi); } - if (n == 1) return ts[0]; + if (n == 1) + return ts[0]; size_t nt = count_union_components(ts, n); jl_value_t **temp; @@ -476,9 +491,9 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n) flatten_type_union(ts, n, temp, &count); assert(count == nt); size_t j; - for(i=0; i < nt; i++) { - int has_free = temp[i]!=NULL && jl_has_free_typevars(temp[i]); - for(j=0; j < nt; j++) { + for (i = 0; i < nt; i++) { + int has_free = temp[i] != NULL && jl_has_free_typevars(temp[i]); + for (j = 0; j < nt; j++) { if (j != i && temp[i] && temp[j]) { if (temp[i] == jl_bottom_type || temp[j] == (jl_value_t*)jl_any_type || @@ -490,7 +505,7 @@ JL_DLLEXPORT jl_value_t *jl_type_union(jl_value_t **ts, size_t n) } } } - qsort(temp, nt, sizeof(jl_value_t*), union_sort_cmp); + isort_union(temp, nt); jl_value_t **ptu = &temp[nt]; *ptu = jl_bottom_type; int k;