bb9f33df969f1c492ce83a5621012af211fef9b0
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. */
11 #include "mozilla/Assertions.h"
12 #include "mozilla/MathAlgorithms.h"
13 #include "mozilla/PodOperations.h"
14 #include "mozilla/ThreadLocal.h"
20 #include "vm/HelperThreads.h"
26 #include "js/Utility.h"
30 using mozilla::CeilingLog2Size
;
31 using mozilla::PodArrayZero
;
33 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
34 /* For OOM testing functionality in Utility.h. */
37 mozilla::Atomic
<AutoEnterOOMUnsafeRegion
*> AutoEnterOOMUnsafeRegion::owner_
;
41 JS_PUBLIC_DATA(uint32_t) targetThread
= 0;
42 JS_PUBLIC_DATA(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;
48 InitThreadType(void) {
49 return threadType
.init();
53 SetThreadType(ThreadType type
) {
59 return threadType
.get();
63 SimulateOOMAfter(uint64_t allocations
, uint32_t thread
, bool always
) {
64 MOZ_ASSERT(counter
+ allocations
> counter
);
65 MOZ_ASSERT(thread
> js::oom::THREAD_TYPE_NONE
&& thread
< js::oom::THREAD_TYPE_MAX
);
66 targetThread
= thread
;
67 maxAllocations
= counter
+ allocations
;
73 if (targetThread
!= THREAD_TYPE_NONE
&& targetThread
!= THREAD_TYPE_MAIN
)
74 HelperThreadState().waitForAllThreads();
75 targetThread
= THREAD_TYPE_NONE
;
76 maxAllocations
= UINT64_MAX
;
83 #endif // defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
86 JS_Assert(const char* s
, const char* file
, int ln
)
88 MOZ_ReportAssertionFailure(s
, file
, ln
);
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.
103 AllTheNonBasicVanillaNewAllocations()
105 // posix_memalign and aligned_alloc aren't available on all Linux
107 // valloc was deprecated in Android 5.0
109 //posix_memalign((void**)&q, 16, 16);
112 intptr_t(malloc(16)) +
113 intptr_t(calloc(1, 16)) +
114 intptr_t(realloc(nullptr, 16)) +
118 intptr_t(new char[16]) +
119 intptr_t(memalign(16, 16)) +
121 //intptr_t(aligned_alloc(16, 16)) +
122 //intptr_t(valloc(4096)) +
123 intptr_t(strdup("dummy"));
125 printf("%u\n", uint32_t(p
)); // make sure |p| is not optimized away
127 free((int*)p
); // this would crash if ever actually called
136 #ifdef JS_BASIC_STATS
141 * Histogram bins count occurrences of values <= the bin label, as follows:
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
147 * We wish to count occurrences of 0 and 1 values separately, always.
150 BinToVal(unsigned logscale
, unsigned bin
)
152 MOZ_ASSERT(bin
<= 10);
153 if (bin
<= 1 || logscale
== 0)
158 MOZ_ASSERT(logscale
== 10);
159 return uint32_t(pow(10.0, (double) bin
));
163 ValToBin(unsigned logscale
, uint32_t val
)
169 bin
= (logscale
== 10)
170 ? (unsigned) ceil(log10((double) val
))
172 ? (unsigned) CeilingLog2Size(val
)
174 return Min(bin
, 10U);
178 JS_BasicStatsAccum(JSBasicStats
* bs
, uint32_t val
)
180 unsigned oldscale
, newscale
, bin
;
187 bs
->sqsum
+= (double)val
* val
;
189 oldscale
= bs
->logscale
;
190 if (oldscale
!= 10) {
191 mean
= bs
->sum
/ bs
->num
;
192 if (bs
->max
> 16 && mean
> 8) {
193 newscale
= (bs
->max
> 1e6
&& mean
> 1000) ? 10 : 2;
194 if (newscale
!= oldscale
) {
195 uint32_t newhist
[11], newbin
;
197 PodArrayZero(newhist
);
198 for (bin
= 0; bin
<= 10; bin
++) {
199 newbin
= ValToBin(newscale
, BinToVal(oldscale
, bin
));
200 newhist
[newbin
] += bs
->hist
[bin
];
202 js_memcpy(bs
->hist
, newhist
, sizeof bs
->hist
);
203 bs
->logscale
= newscale
;
208 bin
= ValToBin(bs
->logscale
, val
);
213 JS_MeanAndStdDev(uint32_t num
, double sum
, double sqsum
, double* sigma
)
217 if (num
== 0 || sum
== 0) {
222 var
= num
* sqsum
- sum
* sum
;
223 if (var
< 0 || num
== 1)
226 var
/= (double)num
* (num
- 1);
228 /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
229 *sigma
= (var
!= 0) ? sqrt(var
) : 0;
234 JS_DumpBasicStats(JSBasicStats
* bs
, const char* title
, FILE* fp
)
238 mean
= JS_MeanAndStdDevBS(bs
, &sigma
);
239 fprintf(fp
, "\nmean %s %g, std. deviation %g, max %lu\n",
240 title
, mean
, sigma
, (unsigned long) bs
->max
);
241 JS_DumpHistogram(bs
, fp
);
245 JS_DumpHistogram(JSBasicStats
* bs
, FILE* fp
)
251 for (bin
= 0, max
= 0, sum
= 0; bin
<= 10; bin
++) {
258 for (bin
= 0; bin
<= 10; bin
++) {
259 unsigned val
= BinToVal(bs
->logscale
, bin
);
260 unsigned end
= (bin
== 10) ? 0 : BinToVal(bs
->logscale
, bin
+ 1);
263 fprintf(fp
, " [%6u]", val
);
265 fprintf(fp
, "[%6u, %6u]", val
, end
- 1);
267 fprintf(fp
, "[%6u, +inf]", val
);
268 fprintf(fp
, ": %8u ", cnt
);
270 if (max
> 1e6
&& mean
> 1e3
)
271 cnt
= uint32_t(ceil(log10((double) cnt
)));
272 else if (max
> 16 && mean
> 8)
273 cnt
= CeilingLog2Size(cnt
);
274 for (unsigned i
= 0; i
< cnt
; i
++)
281 #endif /* JS_BASIC_STATS */