summaryrefslogtreecommitdiff
path: root/gcc/unwind-dw2-fde.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2002-12-18 16:27:56 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2002-12-18 16:27:56 +0000
commitae2ff033958a853da6cd41707cb3569699a34e26 (patch)
treee24b06f1be9a92ca6df09de559af58b46545513a /gcc/unwind-dw2-fde.c
parentc6ca897a9cf9b52f3d4590d899b0313d143ec09e (diff)
downloadgcc-ae2ff033958a853da6cd41707cb3569699a34e26.tar.gz
* unwind-dw2-fde.c (frame_downheap): Split out from...
(frame_heapsort): Here. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60253 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/unwind-dw2-fde.c')
-rw-r--r--gcc/unwind-dw2-fde.c89
1 files changed, 42 insertions, 47 deletions
diff --git a/gcc/unwind-dw2-fde.c b/gcc/unwind-dw2-fde.c
index 7f3aeaf3e16..b1bd8c03111 100644
--- a/gcc/unwind-dw2-fde.c
+++ b/gcc/unwind-dw2-fde.c
@@ -467,6 +467,34 @@ fde_split (struct object *ob, fde_compare_t fde_compare,
erratic->count = k;
}
+#define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0)
+
+/* Convert a semi-heap to a heap. A semi-heap is a heap except possibly
+ for the first (root) node; push it down to its rightful place. */
+
+static void
+frame_downheap (struct object *ob, fde_compare_t fde_compare, fde **a,
+ int lo, int hi)
+{
+ int i, j;
+
+ for (i = lo, j = 2*i+1;
+ j < hi;
+ j = 2*i+1)
+ {
+ if (j+1 < hi && fde_compare (ob, a[j], a[j+1]) < 0)
+ ++j;
+
+ if (fde_compare (ob, a[i], a[j]) < 0)
+ {
+ SWAP (a[i], a[j]);
+ i = j;
+ }
+ else
+ break;
+ }
+}
+
/* This is O(n log(n)). BSD/OS defines heapsort in stdlib.h, so we must
use a name that does not conflict. */
@@ -481,55 +509,22 @@ frame_heapsort (struct object *ob, fde_compare_t fde_compare,
/* A portion of the array is called a "heap" if for all i>=0:
If i and 2i+1 are valid indices, then a[i] >= a[2i+1].
If i and 2i+2 are valid indices, then a[i] >= a[2i+2]. */
-#define SWAP(x,y) do { fde * tmp = x; x = y; y = tmp; } while (0)
size_t n = erratic->count;
- size_t m = n;
- size_t i;
-
- while (m > 0)
+ int m;
+
+ /* Expand our heap incrementally from the end of the array, heapifying
+ each resulting semi-heap as we go. After each step, a[m] is the top
+ of a heap. */
+ for (m = n/2-1; m >= 0; --m)
+ frame_downheap (ob, fde_compare, a, m, n);
+
+ /* Shrink our heap incrementally from the end of the array, first
+ swapping out the largest element a[0] and then re-heapifying the
+ resulting semi-heap. After each step, a[0..m) is a heap. */
+ for (m = n-1; m >= 1; --m)
{
- /* Invariant: a[m..n-1] is a heap. */
- m--;
- for (i = m; 2*i+1 < n; )
- {
- if (2*i+2 < n
- && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
- && fde_compare (ob, a[2*i+2], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+2]);
- i = 2*i+2;
- }
- else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+1]);
- i = 2*i+1;
- }
- else
- break;
- }
- }
- while (n > 1)
- {
- /* Invariant: a[0..n-1] is a heap. */
- n--;
- SWAP (a[0], a[n]);
- for (i = 0; 2*i+1 < n; )
- {
- if (2*i+2 < n
- && fde_compare (ob, a[2*i+2], a[2*i+1]) > 0
- && fde_compare (ob, a[2*i+2], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+2]);
- i = 2*i+2;
- }
- else if (fde_compare (ob, a[2*i+1], a[i]) > 0)
- {
- SWAP (a[i], a[2*i+1]);
- i = 2*i+1;
- }
- else
- break;
- }
+ SWAP (a[0], a[m]);
+ frame_downheap (ob, fde_compare, a, 0, m);
}
#undef SWAP
}