LCOV - code coverage report
Current view: top level - js/src - jsutil.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 5 116 4.3 %
Date: 2017-07-14 16:53:18 Functions: 2 13 15.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : /* Various JS utility functions. */
       8             : 
       9             : #include "jsutil.h"
      10             : 
      11             : #include "mozilla/Assertions.h"
      12             : #include "mozilla/MathAlgorithms.h"
      13             : #include "mozilla/PodOperations.h"
      14             : #include "mozilla/ThreadLocal.h"
      15             : 
      16             : #include <stdio.h>
      17             : 
      18             : #include "jstypes.h"
      19             : 
      20             : #include "vm/HelperThreads.h"
      21             : 
      22             : #ifdef WIN32
      23             : #    include "jswin.h"
      24             : #endif
      25             : 
      26             : #include "js/Utility.h"
      27             : 
      28             : using namespace js;
      29             : 
      30             : using mozilla::CeilingLog2Size;
      31             : using mozilla::PodArrayZero;
      32             : 
      33             : #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
      34             : /* For OOM testing functionality in Utility.h. */
      35             : namespace js {
      36             : 
      37             : mozilla::Atomic<AutoEnterOOMUnsafeRegion*> AutoEnterOOMUnsafeRegion::owner_;
      38             : 
      39             : namespace oom {
      40             : 
      41             : JS_PUBLIC_DATA(uint32_t) targetThread = 0;
      42             : MOZ_THREAD_LOCAL(uint32_t) threadType;
      43             : JS_PUBLIC_DATA(uint64_t) maxAllocations = UINT64_MAX;
      44             : JS_PUBLIC_DATA(uint64_t) counter = 0;
      45             : JS_PUBLIC_DATA(bool) failAlways = true;
      46             : 
      47             : bool
      48           3 : InitThreadType(void) {
      49           3 :     return threadType.init();
      50             : }
      51             : 
      52             : void
      53          58 : SetThreadType(ThreadType type) {
      54          58 :     threadType.set(type);
      55          58 : }
      56             : 
      57             : uint32_t
      58           0 : GetThreadType(void) {
      59           0 :     return threadType.get();
      60             : }
      61             : 
      62             : void
      63           0 : SimulateOOMAfter(uint64_t allocations, uint32_t thread, bool always) {
      64           0 :     MOZ_ASSERT(counter + allocations > counter);
      65           0 :     MOZ_ASSERT(thread > js::oom::THREAD_TYPE_NONE && thread < js::oom::THREAD_TYPE_MAX);
      66           0 :     targetThread = thread;
      67           0 :     maxAllocations = counter + allocations;
      68           0 :     failAlways = always;
      69           0 : }
      70             : 
      71             : void
      72           0 : ResetSimulatedOOM() {
      73           0 :     if (targetThread != THREAD_TYPE_NONE && targetThread != THREAD_TYPE_COOPERATING)
      74           0 :         HelperThreadState().waitForAllThreads();
      75           0 :     targetThread = THREAD_TYPE_NONE;
      76           0 :     maxAllocations = UINT64_MAX;
      77           0 :     failAlways = false;
      78           0 : }
      79             : 
      80             : 
      81             : } // namespace oom
      82             : } // namespace js
      83             : #endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
      84             : 
      85             : JS_PUBLIC_API(void)
      86           0 : JS_Assert(const char* s, const char* file, int ln)
      87             : {
      88           0 :     MOZ_ReportAssertionFailure(s, file, ln);
      89           0 :     MOZ_CRASH();
      90             : }
      91             : 
      92             : #ifdef __linux__
      93             : 
      94             : #include <malloc.h>
      95             : #include <stdlib.h>
      96             : 
      97             : namespace js {
      98             : 
      99             : // This function calls all the vanilla heap allocation functions.  It is never
     100             : // called, and exists purely to help config/check_vanilla_allocations.py.  See
     101             : // that script for more details.
     102             : extern MOZ_COLD void
     103           0 : AllTheNonBasicVanillaNewAllocations()
     104             : {
     105             :     // posix_memalign and aligned_alloc aren't available on all Linux
     106             :     // configurations.
     107             :     // valloc was deprecated in Android 5.0
     108             :     //char* q;
     109             :     //posix_memalign((void**)&q, 16, 16);
     110             : 
     111             :     intptr_t p =
     112           0 :         intptr_t(malloc(16)) +
     113           0 :         intptr_t(calloc(1, 16)) +
     114           0 :         intptr_t(realloc(nullptr, 16)) +
     115           0 :         intptr_t(new char) +
     116           0 :         intptr_t(new char) +
     117           0 :         intptr_t(new char) +
     118           0 :         intptr_t(new char[16]) +
     119           0 :         intptr_t(memalign(16, 16)) +
     120             :         //intptr_t(q) +
     121             :         //intptr_t(aligned_alloc(16, 16)) +
     122             :         //intptr_t(valloc(4096)) +
     123           0 :         intptr_t(strdup("dummy"));
     124             : 
     125           0 :     printf("%u\n", uint32_t(p));  // make sure |p| is not optimized away
     126             : 
     127           0 :     free((int*)p);      // this would crash if ever actually called
     128             : 
     129           0 :     MOZ_CRASH();
     130             : }
     131             : 
     132             : } // namespace js
     133             : 
     134             : #endif // __linux__
     135             : 
     136             : #ifdef JS_BASIC_STATS
     137             : 
     138             : #include <math.h>
     139             : 
     140             : /*
     141             :  * Histogram bins count occurrences of values <= the bin label, as follows:
     142             :  *
     143             :  *   linear:  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10 or more
     144             :  *     2**x:  0,   1,   2,   4,   8,  16,  32,  64, 128, 256, 512 or more
     145             :  *    10**x:  0,   1,  10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more
     146             :  *
     147             :  * We wish to count occurrences of 0 and 1 values separately, always.
     148             :  */
     149             : static uint32_t
     150           0 : BinToVal(unsigned logscale, unsigned bin)
     151             : {
     152           0 :     MOZ_ASSERT(bin <= 10);
     153           0 :     if (bin <= 1 || logscale == 0)
     154           0 :         return bin;
     155           0 :     --bin;
     156           0 :     if (logscale == 2)
     157           0 :         return JS_BIT(bin);
     158           0 :     MOZ_ASSERT(logscale == 10);
     159           0 :     return uint32_t(pow(10.0, (double) bin));
     160             : }
     161             : 
     162             : static unsigned
     163           0 : ValToBin(unsigned logscale, uint32_t val)
     164             : {
     165             :     unsigned bin;
     166             : 
     167           0 :     if (val <= 1)
     168           0 :         return val;
     169           0 :     bin = (logscale == 10)
     170           0 :         ? (unsigned) ceil(log10((double) val))
     171             :         : (logscale == 2)
     172           0 :         ? (unsigned) CeilingLog2Size(val)
     173             :         : val;
     174           0 :     return Min(bin, 10U);
     175             : }
     176             : 
     177             : void
     178           0 : JS_BasicStatsAccum(JSBasicStats* bs, uint32_t val)
     179             : {
     180             :     unsigned oldscale, newscale, bin;
     181             :     double mean;
     182             : 
     183           0 :     ++bs->num;
     184           0 :     if (bs->max < val)
     185           0 :         bs->max = val;
     186           0 :     bs->sum += val;
     187           0 :     bs->sqsum += (double)val * val;
     188             : 
     189           0 :     oldscale = bs->logscale;
     190           0 :     if (oldscale != 10) {
     191           0 :         mean = bs->sum / bs->num;
     192           0 :         if (bs->max > 16 && mean > 8) {
     193           0 :             newscale = (bs->max > 1e6 && mean > 1000) ? 10 : 2;
     194           0 :             if (newscale != oldscale) {
     195             :                 uint32_t newhist[11], newbin;
     196             : 
     197           0 :                 PodArrayZero(newhist);
     198           0 :                 for (bin = 0; bin <= 10; bin++) {
     199           0 :                     newbin = ValToBin(newscale, BinToVal(oldscale, bin));
     200           0 :                     newhist[newbin] += bs->hist[bin];
     201             :                 }
     202           0 :                 js_memcpy(bs->hist, newhist, sizeof bs->hist);
     203           0 :                 bs->logscale = newscale;
     204             :             }
     205             :         }
     206             :     }
     207             : 
     208           0 :     bin = ValToBin(bs->logscale, val);
     209           0 :     ++bs->hist[bin];
     210           0 : }
     211             : 
     212             : double
     213           0 : JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double* sigma)
     214             : {
     215             :     double var;
     216             : 
     217           0 :     if (num == 0 || sum == 0) {
     218           0 :         *sigma = 0;
     219           0 :         return 0;
     220             :     }
     221             : 
     222           0 :     var = num * sqsum - sum * sum;
     223           0 :     if (var < 0 || num == 1)
     224           0 :         var = 0;
     225             :     else
     226           0 :         var /= (double)num * (num - 1);
     227             : 
     228             :     /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
     229           0 :     *sigma = (var != 0) ? sqrt(var) : 0;
     230           0 :     return sum / num;
     231             : }
     232             : 
     233             : void
     234           0 : JS_DumpBasicStats(JSBasicStats* bs, const char* title, FILE* fp)
     235             : {
     236             :     double mean, sigma;
     237             : 
     238           0 :     mean = JS_MeanAndStdDevBS(bs, &sigma);
     239           0 :     fprintf(fp, "\nmean %s %g, std. deviation %g, max %lu\n",
     240           0 :             title, mean, sigma, (unsigned long) bs->max);
     241           0 :     JS_DumpHistogram(bs, fp);
     242           0 : }
     243             : 
     244             : void
     245           0 : JS_DumpHistogram(JSBasicStats* bs, FILE* fp)
     246             : {
     247             :     unsigned bin;
     248             :     uint32_t cnt, max;
     249             :     double sum, mean;
     250             : 
     251           0 :     for (bin = 0, max = 0, sum = 0; bin <= 10; bin++) {
     252           0 :         cnt = bs->hist[bin];
     253           0 :         if (max < cnt)
     254           0 :             max = cnt;
     255           0 :         sum += cnt;
     256             :     }
     257           0 :     mean = sum / cnt;
     258           0 :     for (bin = 0; bin <= 10; bin++) {
     259           0 :         unsigned val = BinToVal(bs->logscale, bin);
     260           0 :         unsigned end = (bin == 10) ? 0 : BinToVal(bs->logscale, bin + 1);
     261           0 :         cnt = bs->hist[bin];
     262           0 :         if (val + 1 == end)
     263           0 :             fprintf(fp, "        [%6u]", val);
     264           0 :         else if (end != 0)
     265           0 :             fprintf(fp, "[%6u, %6u]", val, end - 1);
     266             :         else
     267           0 :             fprintf(fp, "[%6u,   +inf]", val);
     268           0 :         fprintf(fp, ": %8u ", cnt);
     269           0 :         if (cnt != 0) {
     270           0 :             if (max > 1e6 && mean > 1e3)
     271           0 :                 cnt = uint32_t(ceil(log10((double) cnt)));
     272           0 :             else if (max > 16 && mean > 8)
     273           0 :                 cnt = CeilingLog2Size(cnt);
     274           0 :             for (unsigned i = 0; i < cnt; i++)
     275           0 :                 putc('*', fp);
     276             :         }
     277           0 :         putc('\n', fp);
     278             :     }
     279           0 : }
     280             : 
     281             : #endif /* JS_BASIC_STATS */

Generated by: LCOV version 1.13