Loading js/src/jit/PerfSpewer.cpp +73 −5 Original line number Diff line number Diff line Loading @@ -382,13 +382,18 @@ void InlineCachePerfSpewer::recordInstruction(MacroAssembler& masm, } void IonPerfSpewer::recordInstruction(MacroAssembler& masm, LInstruction* ins) { if (!PerfIREnabled()) { if (!PerfIREnabled() && !PerfSrcEnabled()) { return; } LNode::Opcode op = ins->op(); UniqueChars opcodeStr; jsbytecode* bytecodepc = nullptr; if (MDefinition* mir = ins->mirRaw()) { bytecodepc = mir->trackedSite()->pc(); } #ifdef JS_JITSPEW if (PerfIROpsEnabled()) { Sprinter buf; Loading @@ -399,7 +404,7 @@ void IonPerfSpewer::recordInstruction(MacroAssembler& masm, LInstruction* ins) { } #endif if (!opcodes_.emplaceBack(masm.currentOffset(), static_cast<unsigned>(op), opcodeStr)) { opcodeStr, bytecodepc)) { opcodes_.clear(); AutoLockPerfSpewer lock; DisablePerfSpewer(lock); Loading Loading @@ -665,8 +670,8 @@ void PerfSpewer::saveJitCodeIRInfo(const char* desc, JitCode* code, #endif } void PerfSpewer::saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* profilerRecord, void BaselinePerfSpewer::saveJitCodeSourceInfo( JSScript* script, JitCode* code, JS::JitCodeRecord* profilerRecord, AutoLockPerfSpewer& lock) { const char* filename = script->filename(); if (!filename) { Loading Loading @@ -757,6 +762,67 @@ void PerfSpewer::saveJitCodeSourceInfo(JSScript* script, JitCode* code, } } void IonPerfSpewer::saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* profilerRecord, AutoLockPerfSpewer& lock) { const char* filename = script->filename(); if (!filename) { return; } #ifdef JS_ION_PERF bool perfProfiling = IsPerfProfiling() && FileExists(filename); if (perfProfiling) { JitDumpDebugRecord debug_record = {}; uint64_t n_records = 0; for (OpcodeEntry& entry : opcodes_) { if (entry.bytecodepc) { n_records++; } } debug_record.header.id = JIT_CODE_DEBUG_INFO; debug_record.header.total_size = sizeof(debug_record) + n_records * (sizeof(JitDumpDebugEntry) + strlen(filename) + 1); debug_record.header.timestamp = GetMonotonicTimestamp(); debug_record.code_addr = uint64_t(code->raw()); debug_record.nr_entry = n_records; WriteToJitDumpFile(&debug_record, sizeof(debug_record), lock); } #endif uint32_t lineno = 0; uint32_t colno = 0; for (OpcodeEntry& entry : opcodes_) { jsbytecode* pc = entry.bytecodepc; if (!pc) { continue; } // We could probably make this a bit faster by caching the previous pc // offset, but it currently doesn't seem noticeable when testing. lineno = PCToLineNumber(script, pc, &colno); if (JS::JitCodeSourceInfo* srcInfo = CreateProfilerSourceEntry(profilerRecord, lock)) { srcInfo->offset = entry.offset; srcInfo->lineno = lineno; srcInfo->colno = colno; srcInfo->filename = JS_smprintf("%s", filename); } #ifdef JS_ION_PERF if (perfProfiling) { WriteJitDumpDebugEntry(uint64_t(code->raw()) + entry.offset, filename, lineno, colno, lock); } #endif } } static UniqueChars GetFunctionDesc(bool ion, JSContext* cx, JSScript* script) { UniqueChars funName; if (script->function() && script->function()->displayAtom()) { Loading @@ -780,6 +846,8 @@ void IonPerfSpewer::saveProfile(JSContext* cx, JSScript* script, UniqueChars desc = GetFunctionDesc(/*ion = */ true, cx, script); if (PerfIREnabled()) { saveJitCodeIRInfo(desc.get(), code, profilerRecord, lock); } else if (PerfSrcEnabled()) { saveJitCodeSourceInfo(script, code, profilerRecord, lock); } CollectJitCodeInfo(desc, code, profilerRecord, lock); Loading js/src/jit/PerfSpewer.h +16 −3 Original line number Diff line number Diff line Loading @@ -44,11 +44,18 @@ class PerfSpewer { struct OpcodeEntry { uint32_t offset = 0; unsigned opcode = 0; jsbytecode* bytecodepc = nullptr; // This string is used to replace the opcode, to define things like // Prologue/Epilogue, or to add operand info. UniqueChars str; OpcodeEntry(uint32_t offset_, unsigned opcode_, UniqueChars& str_, jsbytecode* pc) : offset(offset_), opcode(opcode_), bytecodepc(pc) { str = std::move(str_); } OpcodeEntry(uint32_t offset_, unsigned opcode_, UniqueChars& str_) : offset(offset_), opcode(opcode_) { str = std::move(str_); Loading @@ -62,6 +69,7 @@ class PerfSpewer { OpcodeEntry(OpcodeEntry&& copy) { offset = copy.offset; opcode = copy.opcode; bytecodepc = copy.bytecodepc; str = std::move(copy.str); } Loading @@ -85,9 +93,6 @@ class PerfSpewer { void saveJitCodeIRInfo(const char* desc, JitCode* code, JS::JitCodeRecord* profilerRecord, AutoLockPerfSpewer& lock); void saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* record, AutoLockPerfSpewer& lock); static void CollectJitCodeInfo(UniqueChars& function_name, JitCode* code, JS::JitCodeRecord*, AutoLockPerfSpewer& lock); Loading @@ -114,6 +119,10 @@ class IonPerfSpewer : public PerfSpewer { public: void recordInstruction(MacroAssembler& masm, LInstruction* ins); void saveProfile(JSContext* cx, JSScript* script, JitCode* code); void saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* record, AutoLockPerfSpewer& lock); }; class BaselinePerfSpewer : public PerfSpewer { Loading @@ -124,6 +133,10 @@ class BaselinePerfSpewer : public PerfSpewer { void recordInstruction(JSContext* cx, MacroAssembler& masm, jsbytecode* pc, CompilerFrameInfo& frame); void saveProfile(JSContext* cx, JSScript* script, JitCode* code); void saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* record, AutoLockPerfSpewer& lock); }; class InlineCachePerfSpewer : public PerfSpewer { Loading Loading
js/src/jit/PerfSpewer.cpp +73 −5 Original line number Diff line number Diff line Loading @@ -382,13 +382,18 @@ void InlineCachePerfSpewer::recordInstruction(MacroAssembler& masm, } void IonPerfSpewer::recordInstruction(MacroAssembler& masm, LInstruction* ins) { if (!PerfIREnabled()) { if (!PerfIREnabled() && !PerfSrcEnabled()) { return; } LNode::Opcode op = ins->op(); UniqueChars opcodeStr; jsbytecode* bytecodepc = nullptr; if (MDefinition* mir = ins->mirRaw()) { bytecodepc = mir->trackedSite()->pc(); } #ifdef JS_JITSPEW if (PerfIROpsEnabled()) { Sprinter buf; Loading @@ -399,7 +404,7 @@ void IonPerfSpewer::recordInstruction(MacroAssembler& masm, LInstruction* ins) { } #endif if (!opcodes_.emplaceBack(masm.currentOffset(), static_cast<unsigned>(op), opcodeStr)) { opcodeStr, bytecodepc)) { opcodes_.clear(); AutoLockPerfSpewer lock; DisablePerfSpewer(lock); Loading Loading @@ -665,8 +670,8 @@ void PerfSpewer::saveJitCodeIRInfo(const char* desc, JitCode* code, #endif } void PerfSpewer::saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* profilerRecord, void BaselinePerfSpewer::saveJitCodeSourceInfo( JSScript* script, JitCode* code, JS::JitCodeRecord* profilerRecord, AutoLockPerfSpewer& lock) { const char* filename = script->filename(); if (!filename) { Loading Loading @@ -757,6 +762,67 @@ void PerfSpewer::saveJitCodeSourceInfo(JSScript* script, JitCode* code, } } void IonPerfSpewer::saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* profilerRecord, AutoLockPerfSpewer& lock) { const char* filename = script->filename(); if (!filename) { return; } #ifdef JS_ION_PERF bool perfProfiling = IsPerfProfiling() && FileExists(filename); if (perfProfiling) { JitDumpDebugRecord debug_record = {}; uint64_t n_records = 0; for (OpcodeEntry& entry : opcodes_) { if (entry.bytecodepc) { n_records++; } } debug_record.header.id = JIT_CODE_DEBUG_INFO; debug_record.header.total_size = sizeof(debug_record) + n_records * (sizeof(JitDumpDebugEntry) + strlen(filename) + 1); debug_record.header.timestamp = GetMonotonicTimestamp(); debug_record.code_addr = uint64_t(code->raw()); debug_record.nr_entry = n_records; WriteToJitDumpFile(&debug_record, sizeof(debug_record), lock); } #endif uint32_t lineno = 0; uint32_t colno = 0; for (OpcodeEntry& entry : opcodes_) { jsbytecode* pc = entry.bytecodepc; if (!pc) { continue; } // We could probably make this a bit faster by caching the previous pc // offset, but it currently doesn't seem noticeable when testing. lineno = PCToLineNumber(script, pc, &colno); if (JS::JitCodeSourceInfo* srcInfo = CreateProfilerSourceEntry(profilerRecord, lock)) { srcInfo->offset = entry.offset; srcInfo->lineno = lineno; srcInfo->colno = colno; srcInfo->filename = JS_smprintf("%s", filename); } #ifdef JS_ION_PERF if (perfProfiling) { WriteJitDumpDebugEntry(uint64_t(code->raw()) + entry.offset, filename, lineno, colno, lock); } #endif } } static UniqueChars GetFunctionDesc(bool ion, JSContext* cx, JSScript* script) { UniqueChars funName; if (script->function() && script->function()->displayAtom()) { Loading @@ -780,6 +846,8 @@ void IonPerfSpewer::saveProfile(JSContext* cx, JSScript* script, UniqueChars desc = GetFunctionDesc(/*ion = */ true, cx, script); if (PerfIREnabled()) { saveJitCodeIRInfo(desc.get(), code, profilerRecord, lock); } else if (PerfSrcEnabled()) { saveJitCodeSourceInfo(script, code, profilerRecord, lock); } CollectJitCodeInfo(desc, code, profilerRecord, lock); Loading
js/src/jit/PerfSpewer.h +16 −3 Original line number Diff line number Diff line Loading @@ -44,11 +44,18 @@ class PerfSpewer { struct OpcodeEntry { uint32_t offset = 0; unsigned opcode = 0; jsbytecode* bytecodepc = nullptr; // This string is used to replace the opcode, to define things like // Prologue/Epilogue, or to add operand info. UniqueChars str; OpcodeEntry(uint32_t offset_, unsigned opcode_, UniqueChars& str_, jsbytecode* pc) : offset(offset_), opcode(opcode_), bytecodepc(pc) { str = std::move(str_); } OpcodeEntry(uint32_t offset_, unsigned opcode_, UniqueChars& str_) : offset(offset_), opcode(opcode_) { str = std::move(str_); Loading @@ -62,6 +69,7 @@ class PerfSpewer { OpcodeEntry(OpcodeEntry&& copy) { offset = copy.offset; opcode = copy.opcode; bytecodepc = copy.bytecodepc; str = std::move(copy.str); } Loading @@ -85,9 +93,6 @@ class PerfSpewer { void saveJitCodeIRInfo(const char* desc, JitCode* code, JS::JitCodeRecord* profilerRecord, AutoLockPerfSpewer& lock); void saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* record, AutoLockPerfSpewer& lock); static void CollectJitCodeInfo(UniqueChars& function_name, JitCode* code, JS::JitCodeRecord*, AutoLockPerfSpewer& lock); Loading @@ -114,6 +119,10 @@ class IonPerfSpewer : public PerfSpewer { public: void recordInstruction(MacroAssembler& masm, LInstruction* ins); void saveProfile(JSContext* cx, JSScript* script, JitCode* code); void saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* record, AutoLockPerfSpewer& lock); }; class BaselinePerfSpewer : public PerfSpewer { Loading @@ -124,6 +133,10 @@ class BaselinePerfSpewer : public PerfSpewer { void recordInstruction(JSContext* cx, MacroAssembler& masm, jsbytecode* pc, CompilerFrameInfo& frame); void saveProfile(JSContext* cx, JSScript* script, JitCode* code); void saveJitCodeSourceInfo(JSScript* script, JitCode* code, JS::JitCodeRecord* record, AutoLockPerfSpewer& lock); }; class InlineCachePerfSpewer : public PerfSpewer { Loading