Bug 1206594: Update SavedStacks sampling probability only when a Debugger changes its probability, not on every sample taken. r=fitzgen
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1730,17 +1730,17 @@ Debugger::logTenurePromotion(JSRuntime*
tenurePromotionsLogOverflowed = true;
}
}
bool
Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
double when)
{
- MOZ_ASSERT(trackingAllocationSites);
+ MOZ_ASSERT(trackingAllocationSites && enabled);
AutoCompartment ac(cx, object);
RootedObject wrappedFrame(cx, frame);
if (!cx->compartment()->wrap(cx, &wrappedFrame))
return false;
RootedAtom ctorName(cx);
{
@@ -2327,26 +2327,30 @@ Debugger::addAllocationsTracking(JSConte
if (Debugger::cannotTrackAllocations(debuggee)) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET);
return false;
}
debuggee.compartment()->setObjectMetadataCallback(SavedStacksMetadataCallback);
+ debuggee.compartment()->chooseAllocationSamplingProbability();
return true;
}
/* static */ void
Debugger::removeAllocationsTracking(GlobalObject& global)
{
// If there are still Debuggers that are observing allocations, we cannot
- // remove the metadata callback yet.
- if (isObservedByDebuggerTrackingAllocations(global))
+ // remove the metadata callback yet. Recompute the sampling probability
+ // based on the remaining debuggers' needs.
+ if (isObservedByDebuggerTrackingAllocations(global)) {
+ global.compartment()->chooseAllocationSamplingProbability();
return;
+ }
global.compartment()->forgetObjectMetadataCallback();
}
bool
Debugger::addAllocationsTrackingForAllDebuggees(JSContext* cx)
{
MOZ_ASSERT(trackingAllocationSites);
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -309,17 +309,26 @@ DebuggerMemory::setAllocationSamplingPro
if (probability < 0.0 || probability > 1.0) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
"(set allocationSamplingProbability)'s parameter",
"not a number between 0 and 1");
return false;
}
- memory->getDebugger()->allocationSamplingProbability = probability;
+ Debugger* dbg = memory->getDebugger();
+ dbg->allocationSamplingProbability = probability;
+
+ // If this is a change any debuggees would observe, have all debuggee
+ // compartments recompute their sampling probabilities.
+ if (dbg->enabled && dbg->trackingAllocationSites) {
+ for (WeakGlobalObjectSet::Range r = dbg->debuggees.all(); !r.empty(); r.popFront())
+ r.front()->compartment()->chooseAllocationSamplingProbability();
+ }
+
args.rval().setUndefined();
return true;
}
/* static */ bool
DebuggerMemory::getAllocationsLogOverflowed(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGGER_MEMORY(cx, argc, vp, "(get allocationsLogOverflowed)", args, memory);
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -1360,17 +1360,16 @@ SavedStacksMetadataCallback(JSContext* c
RootedObject obj(cx, target);
SavedStacks& stacks = cx->compartment()->savedStacks();
if (stacks.allocationSkipCount > 0) {
stacks.allocationSkipCount--;
return nullptr;
}
- stacks.chooseSamplingProbability(cx->compartment());
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