From 4d3ac1c0dcd34e53f11a60888eda65dc73d78de4 Mon Sep 17 00:00:00 2001 From: Alex Lyon <arcterus@mail.com> Date: Sun, 13 May 2018 03:29:53 -0700 Subject: [PATCH] stdlib: save stack space by looping in introsort_helper() --- src/stdlib/src/sort.rs | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/stdlib/src/sort.rs b/src/stdlib/src/sort.rs index bbcd9fb1..79d1e948 100644 --- a/src/stdlib/src/sort.rs +++ b/src/stdlib/src/sort.rs @@ -25,24 +25,32 @@ fn log2(num: size_t) -> size_t { } fn introsort_helper( - base: *mut c_char, - nel: size_t, + mut base: *mut c_char, + mut nel: size_t, width: size_t, - maxdepth: size_t, + mut maxdepth: size_t, comp: extern "C" fn(*const c_void, *const c_void) -> c_int, ) { const THRESHOLD: size_t = 8; - if nel < THRESHOLD { - insertion_sort(base, nel, width, comp); - } else if nel > 1 { - if maxdepth == 0 { - heapsort(base, nel, width, comp); - } else { - let (left, right) = partition(base, nel, width, comp); - introsort_helper(base, left, width, maxdepth, comp); - let right_base = unsafe { base.add((right + 1) * width) }; - introsort_helper(right_base, nel - (right + 1), width, maxdepth - 1, comp); + // this loop is a trick to save stack space because TCO is not a thing in Rustland + // basically, we just change the arguments and loop rather than recursing for the second call + // to introsort_helper() + loop { + if nel < THRESHOLD { + insertion_sort(base, nel, width, comp); + break; + } else if nel > 1 { + if maxdepth == 0 { + heapsort(base, nel, width, comp); + break; + } else { + let (left, right) = partition(base, nel, width, comp); + introsort_helper(base, left, width, maxdepth, comp); + base = unsafe { base.add((right + 1) * width) }; + nel -= right + 1; + maxdepth -= 1; + } } } } -- GitLab