mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1206596: Change js::SavedStacks to use mozilla::FastBernoulliTrial. r=fitzgen
This commit is contained in:
parent
d174296950
commit
5fd3a28376
@ -868,7 +868,7 @@ SetSavedStacksRNGState(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (!ToInt32(cx, args[0], &seed))
|
||||
return false;
|
||||
|
||||
cx->compartment()->savedStacks().setRNGState((seed ^ RNG_MULTIPLIER) & RNG_MASK);
|
||||
cx->compartment()->savedStacks().setRNGState(seed, seed * 33);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -32,5 +32,5 @@ dbg.memory.trackingAllocationSites = true;
|
||||
// probability is fine.
|
||||
measure(0.0, 0);
|
||||
measure(1.0, 100);
|
||||
measure(0.1, 9);
|
||||
measure(0.5, 51);
|
||||
measure(0.1, 7);
|
||||
measure(0.5, 44);
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "vm/SavedStacks.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Move.h"
|
||||
@ -904,6 +905,10 @@ SavedFrame::toStringMethod(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
SavedStacks::init()
|
||||
{
|
||||
uint64_t seed[2];
|
||||
random_generateSeed(seed, mozilla::ArrayLength(seed));
|
||||
bernoulli.setRandomState(seed[0], seed[1]);
|
||||
|
||||
if (!pcLocationMap.init())
|
||||
return false;
|
||||
|
||||
@ -1339,7 +1344,7 @@ SavedStacks::chooseSamplingProbability(JSCompartment* compartment)
|
||||
mozilla::DebugOnly<Debugger**> begin = dbgs->begin();
|
||||
mozilla::DebugOnly<bool> foundAnyDebuggers = false;
|
||||
|
||||
allocationSamplingProbability = 0;
|
||||
double probability = 0;
|
||||
for (Debugger** dbgp = dbgs->begin(); dbgp < dbgs->end(); dbgp++) {
|
||||
// The set of debuggers had better not change while we're iterating,
|
||||
// such that the vector gets reallocated.
|
||||
@ -1347,11 +1352,13 @@ SavedStacks::chooseSamplingProbability(JSCompartment* compartment)
|
||||
|
||||
if ((*dbgp)->trackingAllocationSites && (*dbgp)->enabled) {
|
||||
foundAnyDebuggers = true;
|
||||
allocationSamplingProbability = std::max((*dbgp)->allocationSamplingProbability,
|
||||
allocationSamplingProbability);
|
||||
probability = std::max((*dbgp)->allocationSamplingProbability,
|
||||
probability);
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(foundAnyDebuggers);
|
||||
|
||||
bernoulli.setProbability(probability);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@ -1360,38 +1367,8 @@ SavedStacksMetadataCallback(JSContext* cx, JSObject* target)
|
||||
RootedObject obj(cx, target);
|
||||
|
||||
SavedStacks& stacks = cx->compartment()->savedStacks();
|
||||
if (stacks.allocationSkipCount > 0) {
|
||||
stacks.allocationSkipCount--;
|
||||
if (!stacks.bernoulli.trial())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (stacks.allocationSamplingProbability == 0.0)
|
||||
return nullptr;
|
||||
|
||||
// If the sampling probability is set to 1.0, we are always taking a sample
|
||||
// and can therefore leave allocationSkipCount at 0.
|
||||
if (stacks.allocationSamplingProbability != 1.0) {
|
||||
// Rather than generating a random number on every allocation to decide
|
||||
// if we want to sample that particular allocation (which would be
|
||||
// expensive), we calculate the number of allocations to skip before
|
||||
// taking the next sample.
|
||||
//
|
||||
// P = the probability we sample any given event.
|
||||
//
|
||||
// ~P = 1-P, the probability we don't sample a given event.
|
||||
//
|
||||
// (~P)^n = the probability that we skip at least the next n events.
|
||||
//
|
||||
// let X = random between 0 and 1.
|
||||
//
|
||||
// floor(log base ~P of X) = n, aka the number of events we should skip
|
||||
// until we take the next sample. Any value for X less than (~P)^n
|
||||
// yields a skip count greater than n, so the likelihood of a skip count
|
||||
// greater than n is (~P)^n, as required.
|
||||
double notSamplingProb = 1.0 - stacks.allocationSamplingProbability;
|
||||
stacks.allocationSkipCount = std::floor(std::log(random_nextDouble(&stacks.rngState)) /
|
||||
std::log(notSamplingProb));
|
||||
}
|
||||
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
RootedSavedFrame frame(cx);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef vm_SavedStacks_h
|
||||
#define vm_SavedStacks_h
|
||||
|
||||
#include "mozilla/FastBernoulliTrial.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsmath.h"
|
||||
#include "jswrapper.h"
|
||||
@ -151,12 +153,11 @@ class SavedStacks {
|
||||
JS::ubi::StackFrame& ubiFrame,
|
||||
MutableHandleObject outSavedFrameStack);
|
||||
|
||||
|
||||
public:
|
||||
SavedStacks()
|
||||
: frames(),
|
||||
allocationSamplingProbability(1.0),
|
||||
allocationSkipCount(0),
|
||||
rngState(0),
|
||||
bernoulli(1.0, 0x59fdad7f6b4cc573, 0x91adf38db96a9354),
|
||||
creatingSavedFrame(false)
|
||||
{ }
|
||||
|
||||
@ -167,16 +168,14 @@ class SavedStacks {
|
||||
void trace(JSTracer* trc);
|
||||
uint32_t count();
|
||||
void clear();
|
||||
void setRNGState(uint64_t state) { rngState = state; }
|
||||
void setRNGState(uint64_t state0, uint64_t state1) { bernoulli.setRandomState(state0, state1); }
|
||||
void chooseSamplingProbability(JSCompartment*);
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
private:
|
||||
SavedFrame::Set frames;
|
||||
double allocationSamplingProbability;
|
||||
uint32_t allocationSkipCount;
|
||||
uint64_t rngState;
|
||||
mozilla::FastBernoulliTrial bernoulli;
|
||||
bool creatingSavedFrame;
|
||||
|
||||
// Similar to mozilla::ReentrancyGuard, but instead of asserting against
|
||||
|
Loading…
Reference in New Issue
Block a user