xpcom/glue/nsQuickSort.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2
michael@0 3 /*-
michael@0 4 * Copyright (c) 1992, 1993
michael@0 5 * The Regents of the University of California. All rights reserved.
michael@0 6 *
michael@0 7 * Redistribution and use in source and binary forms, with or without
michael@0 8 * modification, are permitted provided that the following conditions
michael@0 9 * are met:
michael@0 10 * 1. Redistributions of source code must retain the above copyright
michael@0 11 * notice, this list of conditions and the following disclaimer.
michael@0 12 * 2. Redistributions in binary form must reproduce the above copyright
michael@0 13 * notice, this list of conditions and the following disclaimer in the
michael@0 14 * documentation and/or other materials provided with the distribution.
michael@0 15 * 3. Neither the name of the University nor the names of its contributors
michael@0 16 * may be used to endorse or promote products derived from this software
michael@0 17 * without specific prior written permission.
michael@0 18 *
michael@0 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
michael@0 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
michael@0 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
michael@0 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
michael@0 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
michael@0 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
michael@0 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
michael@0 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
michael@0 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
michael@0 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
michael@0 29 * SUCH DAMAGE.
michael@0 30 */
michael@0 31
michael@0 32 /* We need this because Solaris' version of qsort is broken and
michael@0 33 * causes array bounds reads.
michael@0 34 */
michael@0 35
michael@0 36 #include <stdlib.h>
michael@0 37 #include "nsAlgorithm.h"
michael@0 38 #include "nsQuickSort.h"
michael@0 39
michael@0 40 extern "C" {
michael@0 41
michael@0 42 #if !defined(DEBUG) && (defined(__cplusplus) || defined(__gcc))
michael@0 43 # ifndef INLINE
michael@0 44 # define INLINE inline
michael@0 45 # endif
michael@0 46 #else
michael@0 47 # define INLINE
michael@0 48 #endif
michael@0 49
michael@0 50 typedef int cmp_t(const void *, const void *, void *);
michael@0 51 static INLINE char *med3(char *, char *, char *, cmp_t *, void *);
michael@0 52 static INLINE void swapfunc(char *, char *, int, int);
michael@0 53
michael@0 54 /*
michael@0 55 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
michael@0 56 */
michael@0 57 #define swapcode(TYPE, parmi, parmj, n) { \
michael@0 58 long i = (n) / sizeof (TYPE); \
michael@0 59 TYPE *pi = (TYPE *) (parmi); \
michael@0 60 TYPE *pj = (TYPE *) (parmj); \
michael@0 61 do { \
michael@0 62 TYPE t = *pi; \
michael@0 63 *pi++ = *pj; \
michael@0 64 *pj++ = t; \
michael@0 65 } while (--i > 0); \
michael@0 66 }
michael@0 67
michael@0 68 #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
michael@0 69 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
michael@0 70
michael@0 71 static INLINE void
michael@0 72 swapfunc(char *a, char *b, int n, int swaptype)
michael@0 73 {
michael@0 74 if(swaptype <= 1)
michael@0 75 swapcode(long, a, b, n)
michael@0 76 else
michael@0 77 swapcode(char, a, b, n)
michael@0 78 }
michael@0 79
michael@0 80 #define swap(a, b) \
michael@0 81 if (swaptype == 0) { \
michael@0 82 long t = *(long *)(a); \
michael@0 83 *(long *)(a) = *(long *)(b); \
michael@0 84 *(long *)(b) = t; \
michael@0 85 } else \
michael@0 86 swapfunc((char *)a, (char*)b, (int)es, swaptype)
michael@0 87
michael@0 88 #define vecswap(a, b, n) if ((n) > 0) swapfunc((char *)a, (char *)b, (int)n, swaptype)
michael@0 89
michael@0 90 static INLINE char *
michael@0 91 med3(char *a, char *b, char *c, cmp_t* cmp, void *data)
michael@0 92 {
michael@0 93 return cmp(a, b, data) < 0 ?
michael@0 94 (cmp(b, c, data) < 0 ? b : (cmp(a, c, data) < 0 ? c : a ))
michael@0 95 :(cmp(b, c, data) > 0 ? b : (cmp(a, c, data) < 0 ? a : c ));
michael@0 96 }
michael@0 97
michael@0 98 void NS_QuickSort (
michael@0 99 void *a,
michael@0 100 unsigned int n,
michael@0 101 unsigned int es,
michael@0 102 cmp_t *cmp,
michael@0 103 void *data
michael@0 104 )
michael@0 105 {
michael@0 106 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
michael@0 107 int d, r, swaptype;
michael@0 108
michael@0 109 loop: SWAPINIT(a, es);
michael@0 110 /* Use insertion sort when input is small */
michael@0 111 if (n < 7) {
michael@0 112 for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
michael@0 113 for (pl = pm; pl > (char *)a && cmp(pl - es, pl, data) > 0;
michael@0 114 pl -= es)
michael@0 115 swap(pl, pl - es);
michael@0 116 return;
michael@0 117 }
michael@0 118 /* Choose pivot */
michael@0 119 pm = (char *)a + (n / 2) * es;
michael@0 120 if (n > 7) {
michael@0 121 pl = (char *)a;
michael@0 122 pn = (char *)a + (n - 1) * es;
michael@0 123 if (n > 40) {
michael@0 124 d = (n / 8) * es;
michael@0 125 pl = med3(pl, pl + d, pl + 2 * d, cmp, data);
michael@0 126 pm = med3(pm - d, pm, pm + d, cmp, data);
michael@0 127 pn = med3(pn - 2 * d, pn - d, pn, cmp, data);
michael@0 128 }
michael@0 129 pm = med3(pl, pm, pn, cmp, data);
michael@0 130 }
michael@0 131 swap(a, pm);
michael@0 132 pa = pb = (char *)a + es;
michael@0 133
michael@0 134 pc = pd = (char *)a + (n - 1) * es;
michael@0 135 /* loop invariants:
michael@0 136 * [a, pa) = pivot
michael@0 137 * [pa, pb) < pivot
michael@0 138 * [pb, pc + es) unprocessed
michael@0 139 * [pc + es, pd + es) > pivot
michael@0 140 * [pd + es, pn) = pivot
michael@0 141 */
michael@0 142 for (;;) {
michael@0 143 while (pb <= pc && (r = cmp(pb, a, data)) <= 0) {
michael@0 144 if (r == 0) {
michael@0 145 swap(pa, pb);
michael@0 146 pa += es;
michael@0 147 }
michael@0 148 pb += es;
michael@0 149 }
michael@0 150 while (pb <= pc && (r = cmp(pc, a, data)) >= 0) {
michael@0 151 if (r == 0) {
michael@0 152 swap(pc, pd);
michael@0 153 pd -= es;
michael@0 154 }
michael@0 155 pc -= es;
michael@0 156 }
michael@0 157 if (pb > pc)
michael@0 158 break;
michael@0 159 swap(pb, pc);
michael@0 160 pb += es;
michael@0 161 pc -= es;
michael@0 162 }
michael@0 163 /* Move pivot values */
michael@0 164 pn = (char *)a + n * es;
michael@0 165 r = XPCOM_MIN(pa - (char *)a, pb - pa);
michael@0 166 vecswap(a, pb - r, r);
michael@0 167 r = XPCOM_MIN<size_t>(pd - pc, pn - pd - es);
michael@0 168 vecswap(pb, pn - r, r);
michael@0 169 /* Recursively process partitioned items */
michael@0 170 if ((r = pb - pa) > (int)es)
michael@0 171 NS_QuickSort(a, r / es, es, cmp, data);
michael@0 172 if ((r = pd - pc) > (int)es) {
michael@0 173 /* Iterate rather than recurse to save stack space */
michael@0 174 a = pn - r;
michael@0 175 n = r / es;
michael@0 176 goto loop;
michael@0 177 }
michael@0 178 /* NS_QuickSort(pn - r, r / es, es, cmp, data);*/
michael@0 179 }
michael@0 180
michael@0 181 }
michael@0 182
michael@0 183 #undef INLINE
michael@0 184 #undef swapcode
michael@0 185 #undef SWAPINIT
michael@0 186 #undef swap
michael@0 187 #undef vecswap

mercurial