Skip to content

Commit 3301280

Browse files
committed
[JSC] Add signpost intervals for compiler queued and ready time
https://bugs.webkit.org/show_bug.cgi?id=290813 rdar://148287594 Reviewed by Yijia Huang. There's already signpost intervals to mark when a plan is actively being compiled. Let's add signposts for the intervals that the plan is (a) in the worklist queue and (b) ready but not yet finalized. These latencies can also be significant and may help with tuning the JITWorklist policies. This implementation marks the signposts while the JITWorklist lock is held which leads to the simplest implementation. I've checked that this doesn't seem to impact the contention on the lock to a level that is meaningful for benchmarks. We could move this to out from under the lock, but that would complicate the code a bit since these intervals cross thread boundaries. Formatting the CodeBlock into the signpost metadata is relatively costly, so this is done upfront once per plan and saved. This does cost 8 bytes in the JITPlan even when signposts are disabled, but that seems acceptable. * Source/JavaScriptCore/jit/JITPlan.cpp: (JSC::JITPlan::JITPlan): (JSC::JITPlan::cancel): (JSC::JITPlan::notifyCompiling): (JSC::JITPlan::notifyReady): (JSC::signpostId): (JSC::JITPlan::signpostMessage): (JSC::JITPlan::beginSignpostImpl): (JSC::JITPlan::endSignpostImpl): (JSC::JITPlan::compileInThread): * Source/JavaScriptCore/jit/JITPlan.h: (JSC::JITPlan::beginSignpost): (JSC::JITPlan::endSignpost): * Source/JavaScriptCore/jit/JITWorklist.cpp: (JSC::JITWorklist::enqueue): (JSC::JITWorklist::completeAllReadyPlansForVM): (JSC::JITWorklist::cancelAllPlansForVM): * Source/WTF/wtf/SystemTracing.h: Canonical link: https://commits.webkit.org/293052@main
1 parent 5ad70d1 commit 3301280

4 files changed

Lines changed: 104 additions & 13 deletions

File tree

‎Source/JavaScriptCore/jit/JITPlan.cpp‎

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ JITPlan::JITPlan(JITCompilationMode mode, CodeBlock* codeBlock)
5151
: m_mode(mode)
5252
, m_vm(&codeBlock->vm())
5353
, m_codeBlock(codeBlock)
54+
, m_signpostMessage(signpostMessage())
5455
{
5556
m_vm->changeNumberOfActiveJITPlans(1);
5657
}
@@ -66,6 +67,8 @@ void JITPlan::cancel()
6667
RELEASE_ASSERT(m_stage != JITPlanStage::Canceled);
6768
RELEASE_ASSERT(!safepointKeepsDependenciesLive());
6869
ASSERT(m_vm);
70+
71+
endSignpost(JITPlan::SignpostDetail::Canceled);
6972
m_vm->changeNumberOfActiveJITPlans(-1);
7073
m_stage = JITPlanStage::Canceled;
7174
m_vm = nullptr;
@@ -74,12 +77,18 @@ void JITPlan::cancel()
7477

7578
void JITPlan::notifyCompiling()
7679
{
80+
ASSERT(m_stage == JITPlanStage::Preparing);
81+
endSignpost();
7782
m_stage = JITPlanStage::Compiling;
83+
beginSignpost();
7884
}
7985

8086
void JITPlan::notifyReady()
8187
{
88+
ASSERT(m_stage == JITPlanStage::Compiling);
89+
endSignpost();
8290
m_stage = JITPlanStage::Ready;
91+
beginSignpost();
8392
}
8493

8594
auto JITPlan::tier() const -> Tier
@@ -174,6 +183,69 @@ bool JITPlan::reportCompileTimes() const
174183
|| (Options::reportFTLCompileTimes() && isFTL());
175184
}
176185

186+
static inline void* signpostId(JITPlan& plan)
187+
{
188+
uintptr_t id = std::bit_cast<uintptr_t>(&plan);
189+
unsigned stage = static_cast<unsigned>(plan.stage());
190+
ASSERT(!(id & 0xf));
191+
ASSERT(!(stage & ~0xfu));
192+
id |= stage;
193+
return std::bit_cast<void*>(id);
194+
}
195+
196+
CString JITPlan::signpostMessage()
197+
{
198+
if (LIKELY(!Options::useCompilerSignpost()))
199+
return CString();
200+
StringPrintStream stream;
201+
stream.print(m_mode, " ", *m_codeBlock);
202+
return stream.toCString();
203+
}
204+
205+
void JITPlan::beginSignpostImpl()
206+
{
207+
ASSERT(Options::useCompilerSignpost() && !m_signpostMessage.isNull());
208+
auto id = signpostId(*this);
209+
UNUSED_VARIABLE(id); // WTFBeginSignpost not always defined
210+
switch (m_stage) {
211+
case JITPlanStage::Preparing:
212+
WTFBeginSignpost(id, JSCJITPlanQueued, "%" PUBLIC_LOG_STRING, m_signpostMessage.data());
213+
break;
214+
case JITPlanStage::Compiling:
215+
WTFBeginSignpost(id, JSCJITCompiler, "%" PUBLIC_LOG_STRING, m_signpostMessage.data());
216+
break;
217+
case JITPlanStage::Ready:
218+
WTFBeginSignpost(id, JSCJITPlanReady, "%" PUBLIC_LOG_STRING, m_signpostMessage.data());
219+
break;
220+
case JITPlanStage::Canceled:
221+
RELEASE_ASSERT_NOT_REACHED();
222+
};
223+
}
224+
225+
void JITPlan::endSignpostImpl(JITPlan::SignpostDetail detail)
226+
{
227+
ASSERT(Options::useCompilerSignpost() && !m_signpostMessage.isNull());
228+
auto id = signpostId(*this);
229+
const char* detailStr = "";
230+
if (detail == JITPlan::SignpostDetail::Canceled)
231+
detailStr = "Canceled";
232+
UNUSED_VARIABLE(id); // WTFEndSignpost not always defined
233+
UNUSED_VARIABLE(detailStr);
234+
switch (m_stage) {
235+
case JITPlanStage::Preparing:
236+
WTFEndSignpost(id, JSCJITPlanQueued, "%" PUBLIC_LOG_STRING " %" PUBLIC_LOG_STRING, m_signpostMessage.data(), detailStr);
237+
break;
238+
case JITPlanStage::Compiling:
239+
WTFEndSignpost(id, JSCJITCompiler, "%" PUBLIC_LOG_STRING " %" PUBLIC_LOG_STRING, m_signpostMessage.data(), detailStr);
240+
break;
241+
case JITPlanStage::Ready:
242+
WTFEndSignpost(id, JSCJITPlanReady, "%" PUBLIC_LOG_STRING " %" PUBLIC_LOG_STRING, m_signpostMessage.data(), detailStr);
243+
break;
244+
case JITPlanStage::Canceled:
245+
RELEASE_ASSERT_NOT_REACHED();
246+
};
247+
}
248+
177249
void JITPlan::compileInThread(JITWorklistThread* thread)
178250
{
179251
SetForScope threadScope(m_thread, thread);
@@ -195,22 +267,9 @@ void JITPlan::compileInThread(JITWorklistThread* thread)
195267
dataLog("DFG(Plan) compiling ", *m_codeBlock, " with ", m_mode, ", instructions size = ", m_codeBlock->instructionsSize(), "\n");
196268
#endif // ENABLE(DFG_JIT)
197269

198-
CString signpostMessage;
199-
UNUSED_VARIABLE(signpostMessage);
200-
if (UNLIKELY(Options::useCompilerSignpost())) {
201-
StringPrintStream stream;
202-
stream.print(m_mode, " ", *m_codeBlock, " instructions size = ", m_codeBlock->instructionsSize());
203-
signpostMessage = stream.toCString();
204-
WTFBeginSignpost(this, JSCJITCompiler, "%" PUBLIC_LOG_STRING, signpostMessage.data() ? signpostMessage.data() : "(nullptr)");
205-
}
206-
207270
CompilationPath path = compileInThreadImpl();
208-
209271
RELEASE_ASSERT((path == CancelPath) == (m_stage == JITPlanStage::Canceled));
210272

211-
if (UNLIKELY(Options::useCompilerSignpost()))
212-
WTFEndSignpost(this, JSCJITCompiler, "%" PUBLIC_LOG_STRING, signpostMessage.data() ? signpostMessage.data() : "(nullptr)");
213-
214273
if (LIKELY(!computeCompileTimes))
215274
return;
216275

‎Source/JavaScriptCore/jit/JITPlan.h‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,40 @@ class JITPlan : public ThreadSafeRefCounted<JITPlan> {
107107

108108
void runMainThreadFinalizationTasks();
109109

110+
enum class SignpostDetail { None, Canceled };
111+
112+
CString signpostMessage();
113+
114+
void beginSignpost()
115+
{
116+
if (UNLIKELY(Options::useCompilerSignpost()))
117+
beginSignpostImpl();
118+
}
119+
120+
void endSignpost(SignpostDetail detail = SignpostDetail::None)
121+
{
122+
if (UNLIKELY(Options::useCompilerSignpost()))
123+
endSignpostImpl(detail);
124+
}
125+
110126
protected:
111127
bool computeCompileTimes() const;
112128
bool reportCompileTimes() const;
113129

114130
enum CompilationPath { FailPath, BaselinePath, DFGPath, FTLPath, CancelPath };
115131
virtual CompilationPath compileInThreadImpl() = 0;
116132

133+
void beginSignpostImpl();
134+
void endSignpostImpl(SignpostDetail);
135+
117136
JITPlanStage m_stage { JITPlanStage::Preparing };
118137
JITCompilationMode m_mode;
119138
MonotonicTime m_timeBeforeFTL;
120139
VM* m_vm;
121140
CodeBlock* m_codeBlock;
122141
JITWorklistThread* m_thread { nullptr };
123142
Vector<RefPtr<SharedTask<void()>>> m_mainThreadFinalizationTasks;
143+
CString m_signpostMessage; // Non-null iff Options::useCompilerSignpost()
124144
};
125145

126146
} // namespace JSC

‎Source/JavaScriptCore/jit/JITWorklist.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,14 @@ CompilationResult JITWorklist::enqueue(Ref<JITPlan> plan)
8888
// Must be constructed before we allocate anything using SequesteredArenaMalloc
8989
ArenaLifetime saLifetime;
9090
#endif
91+
plan->beginSignpost();
9192
plan->compileInThread(nullptr);
93+
if (plan->stage() != JITPlanStage::Canceled)
94+
plan->endSignpost();
9295
return plan->finalize();
9396
}
97+
ASSERT(plan->stage() == JITPlanStage::Preparing);
98+
plan->beginSignpost();
9499

95100
Locker locker { *m_lock };
96101
if (Options::verboseCompilationQueue()) {
@@ -167,6 +172,7 @@ auto JITWorklist::completeAllReadyPlansForVM(VM& vm, JITCompilationKey requested
167172
dataLogLnIf(Options::verboseCompilationQueue(), *this, ": Completing ", plan->key());
168173
RELEASE_ASSERT(plan->stage() == JITPlanStage::Ready);
169174
plan->finalize();
175+
plan->endSignpost();
170176
}
171177
return resultingState;
172178
}
@@ -238,6 +244,10 @@ void JITWorklist::cancelAllPlansForVM(VM& vm)
238244

239245
Vector<RefPtr<JITPlan>, 8> myReadyPlans;
240246
removeAllReadyPlansForVM(vm, myReadyPlans, { });
247+
for (auto& plan : myReadyPlans) {
248+
ASSERT(plan->stage() == JITPlanStage::Ready);
249+
plan->endSignpost(JITPlan::SignpostDetail::Canceled);
250+
}
241251
}
242252

243253
void JITWorklist::removeDeadPlans(VM& vm)

‎Source/WTF/wtf/SystemTracing.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ WTF_EXTERN_C_END
265265
M(RegisterImportMap) \
266266
M(JSCGarbageCollector) \
267267
M(JSCJITCompiler) \
268+
M(JSCJITPlanQueued) \
269+
M(JSCJITPlanReady) \
268270
M(JSCJSGlobalObject) \
269271
M(IPCConnection) \
270272
M(StreamClientConnection) \

0 commit comments

Comments
 (0)