js/src/jsutil.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /* Various JS utility functions. */
     9 #include "jsutil.h"
    11 #include "mozilla/Assertions.h"
    12 #include "mozilla/MathAlgorithms.h"
    13 #include "mozilla/PodOperations.h"
    15 #include <stdio.h>
    17 #include "jstypes.h"
    19 #ifdef WIN32
    20 #    include "jswin.h"
    21 #endif
    23 #include "js/Utility.h"
    25 using namespace js;
    27 using mozilla::CeilingLog2Size;
    28 using mozilla::PodArrayZero;
    30 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
    31 /* For JS_OOM_POSSIBLY_FAIL in jsutil.h. */
    32 JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations = UINT32_MAX;
    33 JS_PUBLIC_DATA(uint32_t) OOM_counter = 0;
    34 #endif
    36 /*
    37  * Checks the assumption that JS_FUNC_TO_DATA_PTR and JS_DATA_TO_FUNC_PTR
    38  * macros uses to implement casts between function and data pointers.
    39  */
    40 JS_STATIC_ASSERT(sizeof(void *) == sizeof(void (*)()));
    42 JS_PUBLIC_API(void)
    43 JS_Assert(const char *s, const char *file, int ln)
    44 {
    45     MOZ_ReportAssertionFailure(s, file, ln);
    46     MOZ_CRASH();
    47 }
    49 #ifdef __linux__
    51 #include <malloc.h>
    52 #include <stdlib.h>
    54 namespace js {
    56 // This function calls all the vanilla heap allocation functions.  It is never
    57 // called, and exists purely to help config/check_vanilla_allocations.py.  See
    58 // that script for more details.
    59 extern void
    60 AllTheNonBasicVanillaNewAllocations()
    61 {
    62     // posix_memalign and aligned_alloc aren't available on all Linux
    63     // configurations.
    64     //char *q;
    65     //posix_memalign((void**)&q, 16, 16);
    67     intptr_t p =
    68         intptr_t(malloc(16)) +
    69         intptr_t(calloc(1, 16)) +
    70         intptr_t(realloc(nullptr, 16)) +
    71         intptr_t(new char) +
    72         intptr_t(new char) +
    73         intptr_t(new char) +
    74         intptr_t(new char[16]) +
    75         intptr_t(memalign(16, 16)) +
    76         //intptr_t(q) +
    77         //intptr_t(aligned_alloc(16, 16)) +
    78         intptr_t(valloc(4096)) +
    79         intptr_t(strdup("dummy"));
    81     printf("%u\n", uint32_t(p));  // make sure |p| is not optimized away
    83     free((int*)p);      // this would crash if ever actually called
    85     MOZ_CRASH();
    86 }
    88 } // namespace js
    90 #endif // __linux__
    92 #ifdef JS_BASIC_STATS
    94 #include <math.h>
    96 /*
    97  * Histogram bins count occurrences of values <= the bin label, as follows:
    98  *
    99  *   linear:  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10 or more
   100  *     2**x:  0,   1,   2,   4,   8,  16,  32,  64, 128, 256, 512 or more
   101  *    10**x:  0,   1,  10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more
   102  *
   103  * We wish to count occurrences of 0 and 1 values separately, always.
   104  */
   105 static uint32_t
   106 BinToVal(unsigned logscale, unsigned bin)
   107 {
   108     JS_ASSERT(bin <= 10);
   109     if (bin <= 1 || logscale == 0)
   110         return bin;
   111     --bin;
   112     if (logscale == 2)
   113         return JS_BIT(bin);
   114     JS_ASSERT(logscale == 10);
   115     return uint32_t(pow(10.0, (double) bin));
   116 }
   118 static unsigned
   119 ValToBin(unsigned logscale, uint32_t val)
   120 {
   121     unsigned bin;
   123     if (val <= 1)
   124         return val;
   125     bin = (logscale == 10)
   126         ? (unsigned) ceil(log10((double) val))
   127         : (logscale == 2)
   128         ? (unsigned) CeilingLog2Size(val)
   129         : val;
   130     return Min(bin, 10U);
   131 }
   133 void
   134 JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val)
   135 {
   136     unsigned oldscale, newscale, bin;
   137     double mean;
   139     ++bs->num;
   140     if (bs->max < val)
   141         bs->max = val;
   142     bs->sum += val;
   143     bs->sqsum += (double)val * val;
   145     oldscale = bs->logscale;
   146     if (oldscale != 10) {
   147         mean = bs->sum / bs->num;
   148         if (bs->max > 16 && mean > 8) {
   149             newscale = (bs->max > 1e6 && mean > 1000) ? 10 : 2;
   150             if (newscale != oldscale) {
   151                 uint32_t newhist[11], newbin;
   153                 PodArrayZero(newhist);
   154                 for (bin = 0; bin <= 10; bin++) {
   155                     newbin = ValToBin(newscale, BinToVal(oldscale, bin));
   156                     newhist[newbin] += bs->hist[bin];
   157                 }
   158                 js_memcpy(bs->hist, newhist, sizeof bs->hist);
   159                 bs->logscale = newscale;
   160             }
   161         }
   162     }
   164     bin = ValToBin(bs->logscale, val);
   165     ++bs->hist[bin];
   166 }
   168 double
   169 JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma)
   170 {
   171     double var;
   173     if (num == 0 || sum == 0) {
   174         *sigma = 0;
   175         return 0;
   176     }
   178     var = num * sqsum - sum * sum;
   179     if (var < 0 || num == 1)
   180         var = 0;
   181     else
   182         var /= (double)num * (num - 1);
   184     /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
   185     *sigma = (var != 0) ? sqrt(var) : 0;
   186     return sum / num;
   187 }
   189 void
   190 JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp)
   191 {
   192     double mean, sigma;
   194     mean = JS_MeanAndStdDevBS(bs, &sigma);
   195     fprintf(fp, "\nmean %s %g, std. deviation %g, max %lu\n",
   196             title, mean, sigma, (unsigned long) bs->max);
   197     JS_DumpHistogram(bs, fp);
   198 }
   200 void
   201 JS_DumpHistogram(JSBasicStats *bs, FILE *fp)
   202 {
   203     unsigned bin;
   204     uint32_t cnt, max;
   205     double sum, mean;
   207     for (bin = 0, max = 0, sum = 0; bin <= 10; bin++) {
   208         cnt = bs->hist[bin];
   209         if (max < cnt)
   210             max = cnt;
   211         sum += cnt;
   212     }
   213     mean = sum / cnt;
   214     for (bin = 0; bin <= 10; bin++) {
   215         unsigned val = BinToVal(bs->logscale, bin);
   216         unsigned end = (bin == 10) ? 0 : BinToVal(bs->logscale, bin + 1);
   217         cnt = bs->hist[bin];
   218         if (val + 1 == end)
   219             fprintf(fp, "        [%6u]", val);
   220         else if (end != 0)
   221             fprintf(fp, "[%6u, %6u]", val, end - 1);
   222         else
   223             fprintf(fp, "[%6u,   +inf]", val);
   224         fprintf(fp, ": %8u ", cnt);
   225         if (cnt != 0) {
   226             if (max > 1e6 && mean > 1e3)
   227                 cnt = uint32_t(ceil(log10((double) cnt)));
   228             else if (max > 16 && mean > 8)
   229                 cnt = CeilingLog2Size(cnt);
   230             for (unsigned i = 0; i < cnt; i++)
   231                 putc('*', fp);
   232         }
   233         putc('\n', fp);
   234     }
   235 }
   237 #endif /* JS_BASIC_STATS */

mercurial