Bug 1145924 - Ensure JSRuntime is kept in sync with the profiler. (r=djvj)

This commit is contained in:
Shu-yu Guo 2015-03-23 20:33:01 -07:00
parent 1cf6ce3a0f
commit ff15a447de
5 changed files with 47 additions and 6 deletions

View File

@ -718,6 +718,14 @@ JitcodeGlobalTable::verifySkiplist()
}
#endif // DEBUG
void
JitcodeGlobalTable::setAllEntriesAsExpired(JSRuntime *rt)
{
AutoSuppressProfilerSampling suppressSampling(rt);
for (Range r(*this); !r.empty(); r.popFront())
r.front()->setAsExpired();
}
bool
JitcodeGlobalTable::markIteratively(JSTracer *trc)
{
@ -762,7 +770,7 @@ JitcodeGlobalTable::markIteratively(JSTracer *trc)
// types used by optimizations and scripts used for pc to line number
// mapping, alive as well.
if (!entry->isSampled(gen, lapCount)) {
entry->setGeneration(UINT32_MAX);
entry->setAsExpired();
if (!entry->baseEntry().isJitcodeMarkedFromAnyThread())
continue;
}

View File

@ -601,6 +601,9 @@ class JitcodeGlobalEntry
void setGeneration(uint32_t gen) {
baseEntry().setGeneration(gen);
}
void setAsExpired() {
baseEntry().setGeneration(UINT32_MAX);
}
bool isSampled(uint32_t currentGen, uint32_t lapCount) {
return baseEntry().isSampled(currentGen, lapCount);
}
@ -953,6 +956,7 @@ class JitcodeGlobalTable
void removeEntry(JitcodeGlobalEntry &entry, JitcodeGlobalEntry **prevTower, JSRuntime *rt);
void releaseEntry(JitcodeGlobalEntry &entry, JitcodeGlobalEntry **prevTower, JSRuntime *rt);
void setAllEntriesAsExpired(JSRuntime *rt);
bool markIteratively(JSTracer *trc);
void sweep(JSRuntime *rt);

View File

@ -696,18 +696,34 @@ struct JSRuntime : public JS::shadow::Runtime,
uint32_t profilerSampleBufferGen() {
return profilerSampleBufferGen_;
}
void resetProfilerSampleBufferGen() {
profilerSampleBufferGen_ = 0;
}
void setProfilerSampleBufferGen(uint32_t gen) {
profilerSampleBufferGen_ = gen;
// May be called from sampler thread or signal handler; use
// compareExchange to make sure we have monotonic increase.
for (;;) {
uint32_t curGen = profilerSampleBufferGen_;
if (curGen >= gen)
break;
if (profilerSampleBufferGen_.compareExchange(curGen, gen))
break;
}
}
uint32_t profilerSampleBufferLapCount() {
MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
return profilerSampleBufferLapCount_;
}
void resetProfilerSampleBufferLapCount() {
profilerSampleBufferLapCount_ = 1;
}
void updateProfilerSampleBufferLapCount(uint32_t lapCount) {
MOZ_ASSERT(profilerSampleBufferLapCount_ > 0);
// Use compareExchange to make sure we have monotonic increase.
// May be called from sampler thread or signal handler; use
// compareExchange to make sure we have monotonic increase.
for (;;) {
uint32_t curLapCount = profilerSampleBufferLapCount_;
if (curLapCount >= lapCount)

View File

@ -14,6 +14,7 @@
#include "jit/BaselineFrame.h"
#include "jit/BaselineJIT.h"
#include "jit/JitcodeMap.h"
#include "jit/JitFrameIterator.h"
#include "jit/JitFrames.h"
#include "vm/StringBuffer.h"
@ -87,6 +88,15 @@ SPSProfiler::enable(bool enabled)
*/
ReleaseAllJITCode(rt->defaultFreeOp());
// This function is called when the Gecko profiler makes a new TableTicker
// (and thus, a new circular buffer). Set all current entries in the
// JitcodeGlobalTable as expired and reset the buffer generation and lap
// count.
if (rt->hasJitRuntime() && rt->jitRuntime()->hasJitcodeGlobalTable())
rt->jitRuntime()->getJitcodeGlobalTable()->setAllEntriesAsExpired(rt);
rt->resetProfilerSampleBufferGen();
rt->resetProfilerSampleBufferLapCount();
// Ensure that lastProfilingFrame is null before 'enabled' becomes true.
if (rt->jitActivation) {
rt->jitActivation->setLastProfilingFrame(nullptr);
@ -466,8 +476,8 @@ AutoSuppressProfilerSampling::AutoSuppressProfilerSampling(JSRuntime *rt
AutoSuppressProfilerSampling::~AutoSuppressProfilerSampling()
{
if (previouslyEnabled_)
rt_->enableProfilerSampling();
if (previouslyEnabled_)
rt_->enableProfilerSampling();
}
void *

View File

@ -635,7 +635,10 @@ void mergeStacksIntoProfile(ThreadProfile& aProfile, TickSample* aSample, Native
uint32_t lapCount = aProfile.bufferGeneration() - startBufferGen;
// Update the JS runtime with the current profile sample buffer generation.
if (pseudoStack->mRuntime) {
//
// Do not do this for synchronous sampling, which create their own
// ProfileBuffers.
if (!aSample->isSamplingCurrentThread && pseudoStack->mRuntime) {
JS::UpdateJSRuntimeProfilerSampleBufferGen(pseudoStack->mRuntime,
aProfile.bufferGeneration(),
lapCount);