1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsutil.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,237 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* Various JS utility functions. */ 1.11 + 1.12 +#include "jsutil.h" 1.13 + 1.14 +#include "mozilla/Assertions.h" 1.15 +#include "mozilla/MathAlgorithms.h" 1.16 +#include "mozilla/PodOperations.h" 1.17 + 1.18 +#include <stdio.h> 1.19 + 1.20 +#include "jstypes.h" 1.21 + 1.22 +#ifdef WIN32 1.23 +# include "jswin.h" 1.24 +#endif 1.25 + 1.26 +#include "js/Utility.h" 1.27 + 1.28 +using namespace js; 1.29 + 1.30 +using mozilla::CeilingLog2Size; 1.31 +using mozilla::PodArrayZero; 1.32 + 1.33 +#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT) 1.34 +/* For JS_OOM_POSSIBLY_FAIL in jsutil.h. */ 1.35 +JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations = UINT32_MAX; 1.36 +JS_PUBLIC_DATA(uint32_t) OOM_counter = 0; 1.37 +#endif 1.38 + 1.39 +/* 1.40 + * Checks the assumption that JS_FUNC_TO_DATA_PTR and JS_DATA_TO_FUNC_PTR 1.41 + * macros uses to implement casts between function and data pointers. 1.42 + */ 1.43 +JS_STATIC_ASSERT(sizeof(void *) == sizeof(void (*)())); 1.44 + 1.45 +JS_PUBLIC_API(void) 1.46 +JS_Assert(const char *s, const char *file, int ln) 1.47 +{ 1.48 + MOZ_ReportAssertionFailure(s, file, ln); 1.49 + MOZ_CRASH(); 1.50 +} 1.51 + 1.52 +#ifdef __linux__ 1.53 + 1.54 +#include <malloc.h> 1.55 +#include <stdlib.h> 1.56 + 1.57 +namespace js { 1.58 + 1.59 +// This function calls all the vanilla heap allocation functions. It is never 1.60 +// called, and exists purely to help config/check_vanilla_allocations.py. See 1.61 +// that script for more details. 1.62 +extern void 1.63 +AllTheNonBasicVanillaNewAllocations() 1.64 +{ 1.65 + // posix_memalign and aligned_alloc aren't available on all Linux 1.66 + // configurations. 1.67 + //char *q; 1.68 + //posix_memalign((void**)&q, 16, 16); 1.69 + 1.70 + intptr_t p = 1.71 + intptr_t(malloc(16)) + 1.72 + intptr_t(calloc(1, 16)) + 1.73 + intptr_t(realloc(nullptr, 16)) + 1.74 + intptr_t(new char) + 1.75 + intptr_t(new char) + 1.76 + intptr_t(new char) + 1.77 + intptr_t(new char[16]) + 1.78 + intptr_t(memalign(16, 16)) + 1.79 + //intptr_t(q) + 1.80 + //intptr_t(aligned_alloc(16, 16)) + 1.81 + intptr_t(valloc(4096)) + 1.82 + intptr_t(strdup("dummy")); 1.83 + 1.84 + printf("%u\n", uint32_t(p)); // make sure |p| is not optimized away 1.85 + 1.86 + free((int*)p); // this would crash if ever actually called 1.87 + 1.88 + MOZ_CRASH(); 1.89 +} 1.90 + 1.91 +} // namespace js 1.92 + 1.93 +#endif // __linux__ 1.94 + 1.95 +#ifdef JS_BASIC_STATS 1.96 + 1.97 +#include <math.h> 1.98 + 1.99 +/* 1.100 + * Histogram bins count occurrences of values <= the bin label, as follows: 1.101 + * 1.102 + * linear: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or more 1.103 + * 2**x: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or more 1.104 + * 10**x: 0, 1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more 1.105 + * 1.106 + * We wish to count occurrences of 0 and 1 values separately, always. 1.107 + */ 1.108 +static uint32_t 1.109 +BinToVal(unsigned logscale, unsigned bin) 1.110 +{ 1.111 + JS_ASSERT(bin <= 10); 1.112 + if (bin <= 1 || logscale == 0) 1.113 + return bin; 1.114 + --bin; 1.115 + if (logscale == 2) 1.116 + return JS_BIT(bin); 1.117 + JS_ASSERT(logscale == 10); 1.118 + return uint32_t(pow(10.0, (double) bin)); 1.119 +} 1.120 + 1.121 +static unsigned 1.122 +ValToBin(unsigned logscale, uint32_t val) 1.123 +{ 1.124 + unsigned bin; 1.125 + 1.126 + if (val <= 1) 1.127 + return val; 1.128 + bin = (logscale == 10) 1.129 + ? (unsigned) ceil(log10((double) val)) 1.130 + : (logscale == 2) 1.131 + ? (unsigned) CeilingLog2Size(val) 1.132 + : val; 1.133 + return Min(bin, 10U); 1.134 +} 1.135 + 1.136 +void 1.137 +JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val) 1.138 +{ 1.139 + unsigned oldscale, newscale, bin; 1.140 + double mean; 1.141 + 1.142 + ++bs->num; 1.143 + if (bs->max < val) 1.144 + bs->max = val; 1.145 + bs->sum += val; 1.146 + bs->sqsum += (double)val * val; 1.147 + 1.148 + oldscale = bs->logscale; 1.149 + if (oldscale != 10) { 1.150 + mean = bs->sum / bs->num; 1.151 + if (bs->max > 16 && mean > 8) { 1.152 + newscale = (bs->max > 1e6 && mean > 1000) ? 10 : 2; 1.153 + if (newscale != oldscale) { 1.154 + uint32_t newhist[11], newbin; 1.155 + 1.156 + PodArrayZero(newhist); 1.157 + for (bin = 0; bin <= 10; bin++) { 1.158 + newbin = ValToBin(newscale, BinToVal(oldscale, bin)); 1.159 + newhist[newbin] += bs->hist[bin]; 1.160 + } 1.161 + js_memcpy(bs->hist, newhist, sizeof bs->hist); 1.162 + bs->logscale = newscale; 1.163 + } 1.164 + } 1.165 + } 1.166 + 1.167 + bin = ValToBin(bs->logscale, val); 1.168 + ++bs->hist[bin]; 1.169 +} 1.170 + 1.171 +double 1.172 +JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma) 1.173 +{ 1.174 + double var; 1.175 + 1.176 + if (num == 0 || sum == 0) { 1.177 + *sigma = 0; 1.178 + return 0; 1.179 + } 1.180 + 1.181 + var = num * sqsum - sum * sum; 1.182 + if (var < 0 || num == 1) 1.183 + var = 0; 1.184 + else 1.185 + var /= (double)num * (num - 1); 1.186 + 1.187 + /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */ 1.188 + *sigma = (var != 0) ? sqrt(var) : 0; 1.189 + return sum / num; 1.190 +} 1.191 + 1.192 +void 1.193 +JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp) 1.194 +{ 1.195 + double mean, sigma; 1.196 + 1.197 + mean = JS_MeanAndStdDevBS(bs, &sigma); 1.198 + fprintf(fp, "\nmean %s %g, std. deviation %g, max %lu\n", 1.199 + title, mean, sigma, (unsigned long) bs->max); 1.200 + JS_DumpHistogram(bs, fp); 1.201 +} 1.202 + 1.203 +void 1.204 +JS_DumpHistogram(JSBasicStats *bs, FILE *fp) 1.205 +{ 1.206 + unsigned bin; 1.207 + uint32_t cnt, max; 1.208 + double sum, mean; 1.209 + 1.210 + for (bin = 0, max = 0, sum = 0; bin <= 10; bin++) { 1.211 + cnt = bs->hist[bin]; 1.212 + if (max < cnt) 1.213 + max = cnt; 1.214 + sum += cnt; 1.215 + } 1.216 + mean = sum / cnt; 1.217 + for (bin = 0; bin <= 10; bin++) { 1.218 + unsigned val = BinToVal(bs->logscale, bin); 1.219 + unsigned end = (bin == 10) ? 0 : BinToVal(bs->logscale, bin + 1); 1.220 + cnt = bs->hist[bin]; 1.221 + if (val + 1 == end) 1.222 + fprintf(fp, " [%6u]", val); 1.223 + else if (end != 0) 1.224 + fprintf(fp, "[%6u, %6u]", val, end - 1); 1.225 + else 1.226 + fprintf(fp, "[%6u, +inf]", val); 1.227 + fprintf(fp, ": %8u ", cnt); 1.228 + if (cnt != 0) { 1.229 + if (max > 1e6 && mean > 1e3) 1.230 + cnt = uint32_t(ceil(log10((double) cnt))); 1.231 + else if (max > 16 && mean > 8) 1.232 + cnt = CeilingLog2Size(cnt); 1.233 + for (unsigned i = 0; i < cnt; i++) 1.234 + putc('*', fp); 1.235 + } 1.236 + putc('\n', fp); 1.237 + } 1.238 +} 1.239 + 1.240 +#endif /* JS_BASIC_STATS */