Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions JSTests/stress/sampling-profiler-inlined-top-frame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
if (platformSupportsSamplingProfiler()) {
load("./sampling-profiler/samplingProfiler.js", "caller relative");

// Long enough for the call to cost next to nothing beside it, whichever tiers the two functions are in.
function inner(x) {
let sum = 0;
for (let i = 0; i < 1000; i++)
sum += (x ^ i) * 3;
return sum;
}

function outer(count) {
let total = 0;
for (let i = 0; i < count; i++)
total += inner(i);
return total;
}
noInline(outer);

// In the top tiers inner() is inlined, and only the PC tells the two apart. What is sampled on the way there does not count.
for (let i = 0; i < testLoopCount; i++)
outer(2);
samplingProfilerStackTraces();

const timeToFail = 50000;
const startTime = Date.now();
let innerSamples = 0;
let outerSamples = 0;
while (innerSamples + outerSamples < 40) {
if (Date.now() - startTime > timeToFail)
throw new Error(`after ${timeToFail} ms inner() has ${innerSamples} samples and outer() has ${outerSamples}`);
outer(100);
for (const trace of samplingProfilerStackTraces().traces) {
const name = trace.frames[0].name;
if (name === "inner")
innerSamples++;
else if (name === "outer")
outerSamples++;
}
}

if (innerSamples <= outerSamples)
throw new Error(`inner() has ${innerSamples} samples and outer() has ${outerSamples}`);
}
16 changes: 16 additions & 0 deletions JSTests/stress/sampling-profiler-start-during-ftl-compilation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ runFTLEager

// Only means something with concurrent compilation and low thresholds. The numbers are what keeps
// the FTL threads busy at the moment the profiler starts, and the process alive until they are done.
if (platformSupportsSamplingProfiler()) {
const functions = [];
for (let k = 0; k < 300; k++)
functions.push(new Function("count", `let sum = ${k}; for (let i = 0; i < count; i++) { sum += (i ^ ${k}) * 3; sum = (sum % 1000003) | 0; } return sum;`));
Comment thread
dylan-conway marked this conversation as resolved.

for (let round = 0; round < 30; round++) {
if (round === 8)
startSamplingProfiler();
for (const f of functions)
f(40);
}
}
3 changes: 2 additions & 1 deletion Source/JavaScriptCore/ftl/FTLCompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ void compile(State& state, Safepoint::Result& safepointResult)
collectIRDumpDebugInfo(state, graph, codeBlock);
collectSourceCodeDumpDebugInfo(state, codeBlock);

if (vm.shouldBuilderPCToCodeOriginMapping()) {
// The flag can turn on after FTL::State read it; B3 then kept no origins to build the map from.
if (state.proc->needsPCToOriginMap() && vm.shouldBuilderPCToCodeOriginMapping()) {
Comment thread
dylan-conway marked this conversation as resolved.
B3::PCToOriginMap originMap = state.proc->releasePCToOriginMap();
state.jitCode->common.m_pcToCodeOriginMap = makeUnique<PCToCodeOriginMap>(PCToCodeOriginMapBuilder(PCToCodeOriginMapBuilder::JSCodeOriginMap, vm, WTF::move(originMap)), *state.b3CodeLinkBuffer);
}
Expand Down
3 changes: 2 additions & 1 deletion Source/JavaScriptCore/runtime/VM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,6 @@ WTF_ALLOW_UNSAFE_BUFFER_USAGE_END
enableControlFlowProfiler();
#if ENABLE(SAMPLING_PROFILER)
if (Options::useSamplingProfiler()) {
setShouldBuildPCToCodeOriginMapping();
Ref<Stopwatch> stopwatch = Stopwatch::create();
stopwatch->start();
ensureSamplingProfiler(WTF::move(stopwatch));
Expand Down Expand Up @@ -807,6 +806,8 @@ RefPtr<VM> VM::tryCreate(HeapType heapType, WTF::RunLoop* runLoop)
SamplingProfiler& VM::ensureSamplingProfiler(Ref<Stopwatch>&& stopwatch)
{
if (!m_samplingProfiler) {
// The profiler reads these maps to place the top frame's PC, inlined functions included.
setShouldBuildPCToCodeOriginMapping();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
dylan-conway marked this conversation as resolved.
lazyInitialize(m_samplingProfiler, adoptRef(*new SamplingProfiler(*this, WTF::move(stopwatch))));
requestEntryScopeService(EntryScopeService::SamplingProfiler);
}
Expand Down
6 changes: 3 additions & 3 deletions Source/JavaScriptCore/runtime/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -1182,8 +1182,8 @@ class VM : public ThreadSafeRefCountedWithSuppressingSaferCPPChecking<VM> {
void setAllowRedeclaringSymbols(bool allowRedeclaringSymbols) { m_allowRedeclaringSymbols = allowRedeclaringSymbols; }
ALWAYS_INLINE bool allowRedeclaringSymbols() const { return m_allowRedeclaringSymbols; }

void setShouldBuildPCToCodeOriginMapping() { m_shouldBuildPCToCodeOriginMapping = true; }
bool shouldBuilderPCToCodeOriginMapping() const { return m_shouldBuildPCToCodeOriginMapping; }
void setShouldBuildPCToCodeOriginMapping() { m_shouldBuildPCToCodeOriginMapping.store(true, std::memory_order_relaxed); }
bool shouldBuilderPCToCodeOriginMapping() const { return m_shouldBuildPCToCodeOriginMapping.load(std::memory_order_relaxed); }

BytecodeIntrinsicRegistry& bytecodeIntrinsicRegistry() { return *m_bytecodeIntrinsicRegistry; }

Expand Down Expand Up @@ -1405,7 +1405,7 @@ class VM : public ThreadSafeRefCountedWithSuppressingSaferCPPChecking<VM> {
bool m_failNextNewCodeBlock { false };
bool m_globalConstRedeclarationShouldThrow { true };
bool m_allowRedeclaringSymbols { false };
bool m_shouldBuildPCToCodeOriginMapping { false };
std::atomic<bool> m_shouldBuildPCToCodeOriginMapping { false }; // The compiler threads read it.
DeletePropertyMode m_deletePropertyMode { DeletePropertyMode::Default };
HeapAnalyzer* m_activeHeapAnalyzer { nullptr };
std::unique_ptr<CodeCache> m_codeCache;
Expand Down
Loading