From 6d8c673efb10b6b6c16e44017d4325f825d88408 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 30 Jun 2025 14:41:04 +0900 Subject: [PATCH] array.c: replace recursive heapify with iterative implementation Eliminates stack overflow risk on memory-constrained devices by reducing stack usage from O(log n) to O(1) during heap sort operations. Co-authored-by: Atlassian Rovo Dev --- src/array.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/array.c b/src/array.c index 75f1d10f1..5c74d05c3 100644 --- a/src/array.c +++ b/src/array.c @@ -1844,20 +1844,31 @@ sort_cmp(mrb_state *mrb, mrb_value ary, mrb_value *p, mrb_int a, mrb_int b, mrb_ static void heapify(mrb_state *mrb, mrb_value ary, mrb_value *a, mrb_int index, mrb_int size, mrb_value blk) { - mrb_int max = index; - mrb_int left_index = 2 * index + 1; - mrb_int right_index = left_index + 1; - if (left_index < size && sort_cmp(mrb, ary, a, left_index, max, blk)) { - max = left_index; - } - if (right_index < size && sort_cmp(mrb, ary, a, right_index, max, blk)) { - max = right_index; - } - if (max != index) { + /* Iterative heapify to avoid stack overflow on memory-constrained devices */ + while (1) { + mrb_int max = index; + mrb_int left_index = 2 * index + 1; + mrb_int right_index = left_index + 1; + + if (left_index < size && sort_cmp(mrb, ary, a, left_index, max, blk)) { + max = left_index; + } + if (right_index < size && sort_cmp(mrb, ary, a, right_index, max, blk)) { + max = right_index; + } + + if (max == index) { + /* Heap property satisfied, no more swaps needed */ + break; + } + + /* Swap elements and continue heapifying down the affected subtree */ mrb_value tmp = a[max]; a[max] = a[index]; a[index] = tmp; - heapify(mrb, ary, a, max, size, blk); + + /* Continue with the affected child subtree */ + index = max; } }