1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef jit_PerfSpewer_h
8 #define jit_PerfSpewer_h
13 #include "jit/BaselineFrameInfo.h"
14 #include "jit/CacheIR.h"
15 #include "jit/JitCode.h"
17 #include "js/AllocPolicy.h"
18 #include "js/JitCodeAPI.h"
19 #include "js/Vector.h"
20 #include "vm/JSScript.h"
24 using ProfilerJitCodeVector
= Vector
<JS::JitCodeRecord
, 0, SystemAllocPolicy
>;
26 void ResetPerfSpewer(bool enabled
);
28 struct AutoLockPerfSpewer
{
30 ~AutoLockPerfSpewer();
43 jsbytecode
* bytecodepc
= nullptr;
45 // This string is used to replace the opcode, to define things like
46 // Prologue/Epilogue, or to add operand info.
49 explicit OpcodeEntry(uint32_t offset_
, unsigned opcode_
, UniqueChars
& str_
,
51 : offset(offset_
), opcode(opcode_
), bytecodepc(pc
) {
52 str
= std::move(str_
);
55 explicit OpcodeEntry(uint32_t offset_
, unsigned opcode_
, UniqueChars
& str_
)
56 : offset(offset_
), opcode(opcode_
) {
57 str
= std::move(str_
);
59 explicit OpcodeEntry(uint32_t offset_
, UniqueChars
& str_
)
61 str
= std::move(str_
);
63 explicit OpcodeEntry(uint32_t offset_
, unsigned opcode_
)
64 : offset(offset_
), opcode(opcode_
) {}
66 explicit OpcodeEntry(jsbytecode
* pc
) : bytecodepc(pc
) {}
68 OpcodeEntry(OpcodeEntry
&& copy
) {
71 bytecodepc
= copy
.bytecodepc
;
72 str
= std::move(copy
.str
);
75 // Do not copy the UniqueChars member.
76 OpcodeEntry(OpcodeEntry
& copy
) = delete;
78 Vector
<OpcodeEntry
, 0, SystemAllocPolicy
> opcodes_
;
80 uint32_t lir_opcode_length
= 0;
81 uint32_t js_opcode_length
= 0;
83 virtual JS::JitTier
GetTier() { return JS::JitTier::Other
; }
85 virtual const char* CodeName(unsigned op
) = 0;
87 virtual void saveJitCodeSourceInfo(JSScript
* script
, JitCode
* code
,
88 JS::JitCodeRecord
* record
,
89 AutoLockPerfSpewer
& lock
);
91 void saveDebugInfo(JSScript
* script
, JitCode
* code
,
92 JS::JitCodeRecord
* profilerRecord
,
93 AutoLockPerfSpewer
& lock
);
95 void saveProfile(JitCode
* code
, UniqueChars
& desc
, JSScript
* script
);
97 void saveJitCodeIRInfo(JitCode
* code
, JS::JitCodeRecord
* profilerRecord
,
98 AutoLockPerfSpewer
& lock
);
101 PerfSpewer() = default;
103 void recordOffset(MacroAssembler
& masm
, const char*);
107 static void CollectJitCodeInfo(UniqueChars
& function_name
, JitCode
* code
,
108 JS::JitCodeRecord
*, AutoLockPerfSpewer
& lock
);
109 static void CollectJitCodeInfo(UniqueChars
& function_name
, void* code_addr
,
111 JS::JitCodeRecord
* profilerRecord
,
112 AutoLockPerfSpewer
& lock
);
115 void CollectPerfSpewerJitCodeProfile(JitCode
* code
, const char* msg
);
116 void CollectPerfSpewerJitCodeProfile(uintptr_t base
, uint64_t size
,
119 void CollectPerfSpewerWasmMap(uintptr_t base
, uintptr_t size
,
120 const char* filename
, const char* annotation
);
121 void CollectPerfSpewerWasmFunctionMap(uintptr_t base
, uintptr_t size
,
122 const char* filename
, unsigned lineno
,
123 const char* funcName
);
125 class IonPerfSpewer
: public PerfSpewer
{
126 JS::JitTier
GetTier() override
{ return JS::JitTier::Ion
; }
127 const char* CodeName(unsigned op
) override
;
130 void recordInstruction(MacroAssembler
& masm
, LInstruction
* ins
);
131 void saveProfile(JSContext
* cx
, JSScript
* script
, JitCode
* code
);
134 class BaselineInterpreterPerfSpewer
: public PerfSpewer
{
135 JS::JitTier
GetTier() override
{ return JS::JitTier::Baseline
; }
136 const char* CodeName(unsigned op
) override
;
138 // Do nothing, BaselineInterpreter has no source to reference.
139 void saveJitCodeSourceInfo(JSScript
* script
, JitCode
* code
,
140 JS::JitCodeRecord
* record
,
141 AutoLockPerfSpewer
& lock
) override
{}
144 void recordOffset(MacroAssembler
& masm
, JSOp op
);
145 void recordOffset(MacroAssembler
& masm
, const char* name
);
146 void saveProfile(JitCode
* code
);
149 class BaselinePerfSpewer
: public PerfSpewer
{
150 JS::JitTier
GetTier() override
{ return JS::JitTier::Baseline
; }
151 const char* CodeName(unsigned op
) override
;
154 void recordInstruction(JSContext
* cx
, MacroAssembler
& masm
, jsbytecode
* pc
,
155 CompilerFrameInfo
& frame
);
156 void saveProfile(JSContext
* cx
, JSScript
* script
, JitCode
* code
);
159 class InlineCachePerfSpewer
: public PerfSpewer
{
160 JS::JitTier
GetTier() override
{ return JS::JitTier::IC
; }
161 const char* CodeName(unsigned op
) override
;
164 void recordInstruction(MacroAssembler
& masm
, CacheOp op
);
167 class BaselineICPerfSpewer
: public InlineCachePerfSpewer
{
168 void saveJitCodeSourceInfo(JSScript
* script
, JitCode
* code
,
169 JS::JitCodeRecord
* record
,
170 AutoLockPerfSpewer
& lock
) override
{
171 // Baseline IC stubs are shared and have no source code to reference.
176 void saveProfile(JitCode
* code
, const char* stubName
);
179 class IonICPerfSpewer
: public InlineCachePerfSpewer
{
181 explicit IonICPerfSpewer(jsbytecode
* pc
);
183 void saveJitCodeSourceInfo(JSScript
* script
, JitCode
* code
,
184 JS::JitCodeRecord
* record
,
185 AutoLockPerfSpewer
& lock
) override
;
187 void saveProfile(JSContext
* cx
, JSScript
* script
, JitCode
* code
,
188 const char* stubName
);
191 class PerfSpewerRangeRecorder
{
192 using OffsetPair
= std::tuple
<uint32_t, UniqueChars
>;
193 Vector
<OffsetPair
, 0, js::SystemAllocPolicy
> ranges
;
195 MacroAssembler
& masm
;
197 void appendEntry(UniqueChars
& desc
);
200 explicit PerfSpewerRangeRecorder(MacroAssembler
& masm_
) : masm(masm_
){};
201 void recordOffset(const char* name
);
202 void recordOffset(const char* name
, JSContext
* cx
, JSScript
* script
);
203 void recordVMWrapperOffset(const char* name
);
204 void collectRangesForJitCode(JitCode
* code
);
207 } // namespace js::jit
209 #endif /* jit_PerfSpewer_h */