diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj
index e946c2f4..c38a0e23 100644
--- a/profiler/build/win32/Tracy.vcxproj
+++ b/profiler/build/win32/Tracy.vcxproj
@@ -123,6 +123,7 @@
+
@@ -214,6 +215,7 @@
+
diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters
index 889c26ee..d7b38add 100644
--- a/profiler/build/win32/Tracy.vcxproj.filters
+++ b/profiler/build/win32/Tracy.vcxproj.filters
@@ -222,6 +222,9 @@
server
+
+ server
+
@@ -530,6 +533,9 @@
server
+
+ server
+
diff --git a/server/TracySourceContents.cpp b/server/TracySourceContents.cpp
new file mode 100644
index 00000000..8ab92f77
--- /dev/null
+++ b/server/TracySourceContents.cpp
@@ -0,0 +1,89 @@
+#include "TracySourceContents.hpp"
+#include "TracyView.hpp"
+#include "TracyWorker.hpp"
+
+namespace tracy
+{
+
+SourceContents::SourceContents()
+ : m_file( nullptr )
+ , m_fileStringIdx( 0 )
+ , m_data( nullptr )
+ , m_dataBuf( nullptr )
+ , m_dataSize( 0 )
+{
+}
+
+SourceContents::~SourceContents()
+{
+ delete[] m_dataBuf;
+}
+
+void SourceContents::Parse( const char* fileName, const Worker& worker, const View& view )
+{
+ if( m_file == fileName ) return;
+
+ m_file = fileName;
+ m_fileStringIdx = worker.FindStringIdx( fileName );
+ m_lines.clear();
+ if( fileName )
+ {
+ uint32_t sz;
+ const auto srcCache = worker.GetSourceFileFromCache( fileName );
+ if( srcCache.data != nullptr )
+ {
+ m_data = srcCache.data;
+ sz = srcCache.len;
+ }
+ else
+ {
+ FILE* f = fopen( view.SourceSubstitution( fileName ), "rb" );
+ if( f )
+ {
+ fseek( f, 0, SEEK_END );
+ sz = ftell( f );
+ fseek( f, 0, SEEK_SET );
+ if( sz > m_dataSize )
+ {
+ delete[] m_dataBuf;
+ m_dataBuf = new char[sz];
+ m_dataSize = sz;
+ }
+ fread( m_dataBuf, 1, sz, f );
+ m_data = m_dataBuf;
+ fclose( f );
+ }
+ else
+ {
+ m_file = nullptr;
+ }
+ }
+
+ if( m_file )
+ {
+ Tokenizer tokenizer;
+ auto txt = m_data;
+ for(;;)
+ {
+ auto end = txt;
+ while( *end != '\n' && *end != '\r' && end - m_data < sz ) end++;
+ m_lines.emplace_back( Tokenizer::Line { txt, end, tokenizer.Tokenize( txt, end ) } );
+ if( end - m_data == sz ) break;
+ if( *end == '\n' )
+ {
+ end++;
+ if( end - m_data < sz && *end == '\r' ) end++;
+ }
+ else if( *end == '\r' )
+ {
+ end++;
+ if( end - m_data < sz && *end == '\n' ) end++;
+ }
+ if( end - m_data == sz ) break;
+ txt = end;
+ }
+ }
+ }
+}
+
+}
diff --git a/server/TracySourceContents.hpp b/server/TracySourceContents.hpp
new file mode 100644
index 00000000..54eefd66
--- /dev/null
+++ b/server/TracySourceContents.hpp
@@ -0,0 +1,43 @@
+#ifndef __TRACYSOURCECONTENTS_HPP__
+#define __TRACYSOURCECONTENTS_HPP__
+
+#include
+#include
+
+#include "TracySourceTokenizer.hpp"
+
+namespace tracy
+{
+
+class View;
+class Worker;
+
+class SourceContents
+{
+public:
+ SourceContents();
+ ~SourceContents();
+
+ void Parse( const char* fileName, const Worker& worker, const View& view );
+
+ const std::vector& get() const { return m_lines; }
+ bool empty() const { return m_lines.empty(); }
+
+ const char* filename() const { return m_file; }
+ uint32_t idx() const { return m_fileStringIdx; }
+ bool is_cached() const { return m_data != m_dataBuf; }
+
+private:
+ const char* m_file;
+ uint32_t m_fileStringIdx;
+
+ const char* m_data;
+ char* m_dataBuf;
+ size_t m_dataSize;
+
+ std::vector m_lines;
+};
+
+}
+
+#endif
diff --git a/server/TracySourceTokenizer.cpp b/server/TracySourceTokenizer.cpp
index 03e64582..0ce8f3ed 100644
--- a/server/TracySourceTokenizer.cpp
+++ b/server/TracySourceTokenizer.cpp
@@ -75,10 +75,10 @@ static unordered_flat_set G
}
}
-void Tokenizer::Reset()
+Tokenizer::Tokenizer()
+ : m_isInComment( false )
+ , m_isInPreprocessor( false )
{
- m_isInComment = false;
- m_isInPreprocessor = false;
}
std::vector Tokenizer::Tokenize( const char* begin, const char* end )
diff --git a/server/TracySourceTokenizer.hpp b/server/TracySourceTokenizer.hpp
index 68818f19..b02e0aef 100644
--- a/server/TracySourceTokenizer.hpp
+++ b/server/TracySourceTokenizer.hpp
@@ -38,7 +38,8 @@ public:
std::vector tokens;
};
- void Reset();
+ Tokenizer();
+
std::vector Tokenize( const char* begin, const char* end );
private:
diff --git a/server/TracySourceView.cpp b/server/TracySourceView.cpp
index 96e3312a..74704339 100644
--- a/server/TracySourceView.cpp
+++ b/server/TracySourceView.cpp
@@ -72,13 +72,8 @@ enum { JumpArrowBase = 9 };
SourceView::SourceView( ImFont* font, GetWindowCallback gwcb )
: m_font( font )
- , m_file( nullptr )
- , m_fileStringIdx( 0 )
, m_symAddr( 0 )
, m_targetAddr( 0 )
- , m_data( nullptr )
- , m_dataBuf( nullptr )
- , m_dataSize( 0 )
, m_targetLine( 0 )
, m_selectedLine( 0 )
, m_asmSelected( -1 )
@@ -296,11 +291,6 @@ SourceView::SourceView( ImFont* font, GetWindowCallback gwcb )
s_regMapX86[X86_REG_K7] = RegsX86::k7;
}
-SourceView::~SourceView()
-{
- delete[] m_dataBuf;
-}
-
static constexpr uint32_t PackCpuInfo( uint32_t cpuid )
{
return ( cpuid & 0xFFF ) | ( ( cpuid & 0xFFF0000 ) >> 4 );
@@ -407,7 +397,7 @@ void SourceView::OpenSource( const char* fileName, int line, const View& view, c
m_asm.clear();
ParseSource( fileName, worker, view );
- assert( !m_lines.empty() );
+ assert( !m_source.empty() );
}
void SourceView::OpenSymbol( const char* fileName, int line, uint64_t baseAddr, uint64_t symAddr, const Worker& worker, const View& view )
@@ -429,7 +419,7 @@ void SourceView::OpenSymbol( const char* fileName, int line, uint64_t baseAddr,
void SourceView::SelectViewMode()
{
- if( !m_lines.empty() )
+ if( !m_source.empty() )
{
if( !m_asm.empty() )
{
@@ -449,70 +439,10 @@ void SourceView::SelectViewMode()
void SourceView::ParseSource( const char* fileName, const Worker& worker, const View& view )
{
- if( m_file != fileName )
+ if( m_source.filename() != fileName )
{
m_srcWidth = 0;
- m_file = fileName;
- m_fileStringIdx = worker.FindStringIdx( fileName );
- m_lines.clear();
- if( fileName )
- {
- uint32_t sz;
- const auto srcCache = worker.GetSourceFileFromCache( fileName );
- if( srcCache.data != nullptr )
- {
- m_data = srcCache.data;
- sz = srcCache.len;
- }
- else
- {
- FILE* f = fopen( view.SourceSubstitution( fileName ), "rb" );
- if( f )
- {
- fseek( f, 0, SEEK_END );
- sz = ftell( f );
- fseek( f, 0, SEEK_SET );
- if( sz > m_dataSize )
- {
- delete[] m_dataBuf;
- m_dataBuf = new char[sz];
- m_dataSize = sz;
- }
- fread( m_dataBuf, 1, sz, f );
- m_data = m_dataBuf;
- fclose( f );
- }
- else
- {
- m_file = nullptr;
- }
- }
-
- if( m_file )
- {
- m_tokenizer.Reset();
- auto txt = m_data;
- for(;;)
- {
- auto end = txt;
- while( *end != '\n' && *end != '\r' && end - m_data < sz ) end++;
- m_lines.emplace_back( Tokenizer::Line { txt, end, m_tokenizer.Tokenize( txt, end ) } );
- if( end - m_data == sz ) break;
- if( *end == '\n' )
- {
- end++;
- if( end - m_data < sz && *end == '\r' ) end++;
- }
- else if( *end == '\r' )
- {
- end++;
- if( end - m_data < sz && *end == '\n' ) end++;
- }
- if( end - m_data == sz ) break;
- txt = end;
- }
- }
- }
+ m_source.Parse( fileName, worker, view );
}
}
@@ -890,8 +820,14 @@ void SourceView::Render( const Worker& worker, View& view )
if( m_symAddr == 0 )
{
- if( m_file ) TextFocused( ICON_FA_FILE " File:", m_file );
- if( m_data == m_dataBuf )
+ if( m_source.filename() ) TextFocused( ICON_FA_FILE " File:", m_source.filename() );
+ if( m_source.is_cached() )
+ {
+ TextColoredUnformatted( ImVec4( 0.4f, 0.8f, 0.4f, 1.f ), ICON_FA_DATABASE );
+ ImGui::SameLine();
+ ImGui::TextUnformatted( "Source file cached during profiling run" );
+ }
+ else
{
TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_EXCLAMATION_TRIANGLE );
ImGui::SameLine();
@@ -899,12 +835,6 @@ void SourceView::Render( const Worker& worker, View& view )
ImGui::SameLine();
TextColoredUnformatted( ImVec4( 1.f, 1.f, 0.2f, 1.f ), ICON_FA_EXCLAMATION_TRIANGLE );
}
- else
- {
- TextColoredUnformatted( ImVec4( 0.4f, 0.8f, 0.4f, 1.f ), ICON_FA_DATABASE );
- ImGui::SameLine();
- ImGui::TextUnformatted( "Source file cached during profiling run" );
- }
RenderSimpleSourceView();
}
@@ -920,12 +850,13 @@ void SourceView::RenderSimpleSourceView()
ImGui::BeginChild( "##sourceView", ImVec2( 0, 0 ), true, ImGuiWindowFlags_HorizontalScrollbar );
if( m_font ) ImGui::PushFont( m_font );
+ auto& lines = m_source.get();
auto draw = ImGui::GetWindowDrawList();
const auto wpos = ImGui::GetWindowPos();
const auto wh = ImGui::GetWindowHeight();
const auto ty = ImGui::GetFontSize();
const auto ts = ImGui::CalcTextSize( " " ).x;
- const auto lineCount = m_lines.size();
+ const auto lineCount = lines.size();
const auto tmp = RealToString( lineCount );
const auto maxLine = strlen( tmp );
const auto lx = ts * maxLine + ty + round( ts*0.4f );
@@ -934,7 +865,7 @@ void SourceView::RenderSimpleSourceView()
if( m_targetLine != 0 )
{
int lineNum = 1;
- for( auto& line : m_lines )
+ for( auto& line : lines )
{
if( m_targetLine == lineNum )
{
@@ -949,12 +880,12 @@ void SourceView::RenderSimpleSourceView()
else
{
ImGuiListClipper clipper;
- clipper.Begin( (int)m_lines.size() );
+ clipper.Begin( (int)lines.size() );
while( clipper.Step() )
{
for( auto i=clipper.DisplayStart; iScroll.x, 0 );
const auto wh = ImGui::GetWindowHeight();
const auto ty = ImGui::GetFontSize();
const auto ts = ImGui::CalcTextSize( " " ).x;
- const auto lineCount = m_lines.size();
+ const auto lineCount = lines.size();
const auto tmp = RealToString( lineCount );
const auto maxLine = strlen( tmp );
auto lx = ts * maxLine + ty + round( ts*0.4f );
@@ -1509,7 +1441,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_mapsecond;
- RenderLine( m_lines[i], i+1, ipcnt, iptotal, ipmax, &worker );
+ RenderLine( lines[i], i+1, ipcnt, iptotal, ipmax, &worker );
}
}
}
@@ -1554,23 +1486,23 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_mapAddLine( ImVec2( rect.Min.x, ly ), ImVec2( rect.Max.x, ly ), 0x8899994C, 3 );
}
- if( m_fileStringIdx == m_hoveredSource && m_hoveredLine != 0 )
+ if( m_source.idx() == m_hoveredSource && m_hoveredLine != 0 )
{
- const auto ly = round( rect.Min.y + ( m_hoveredLine - 0.5f ) / m_lines.size() * rect.GetHeight() );
+ const auto ly = round( rect.Min.y + ( m_hoveredLine - 0.5f ) / lines.size() * rect.GetHeight() );
draw->AddLine( ImVec2( rect.Min.x, ly ), ImVec2( rect.Max.x, ly ), 0x88888888, 3 );
}
std::vector> ipData;
ipData.reserve( ipcount.size() );
for( auto& v : ipcount ) ipData.emplace_back( v.first, v.second );
- for( uint32_t lineNum = 1; lineNum <= m_lines.size(); lineNum++ )
+ for( uint32_t lineNum = 1; lineNum <= lines.size(); lineNum++ )
{
if( ipcount.find( lineNum ) == ipcount.end() )
{
- auto addresses = worker.GetAddressesForLocation( m_fileStringIdx, lineNum );
+ auto addresses = worker.GetAddressesForLocation( m_source.idx(), lineNum );
if( addresses )
{
for( auto& addr : *addresses )
@@ -1586,7 +1518,7 @@ void SourceView::RenderSymbolSourceView( uint32_t iptotal, unordered_flat_mapsecond;
++it;
}
- const auto ly = round( rect.Min.y + float( firstLine ) / m_lines.size() * rect.GetHeight() );
+ const auto ly = round( rect.Min.y + float( firstLine ) / lines.size() * rect.GetHeight() );
const uint32_t color = ipSum == 0 ? 0x22FFFFFF : GetHotnessColor( ipSum, ipmax );
draw->AddRectFilled( ImVec2( x14, ly ), ImVec2( x34, ly+3 ), color );
}
@@ -2258,7 +2190,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
auto draw = ImGui::GetWindowDrawList();
const auto w = std::max( m_srcWidth, ImGui::GetWindowWidth() );
const auto wpos = ImGui::GetCursorScreenPos();
- if( m_fileStringIdx == m_hoveredSource && lineNum == m_hoveredLine )
+ if( m_source.idx() == m_hoveredSource && lineNum == m_hoveredLine )
{
draw->AddRectFilled( wpos, wpos + ImVec2( w, ty+1 ), 0x22FFFFFF );
}
@@ -2348,7 +2280,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
ImGui::SameLine( 0, ty );
}
- const auto lineCount = m_lines.size();
+ const auto lineCount = m_source.get().size();
const auto tmp = RealToString( lineCount );
const auto maxLine = strlen( tmp );
const auto lineString = RealToString( lineNum );
@@ -2364,7 +2296,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
{
assert( worker );
const auto stw = ImGui::CalcTextSize( " " ).x;
- auto addresses = worker->GetAddressesForLocation( m_fileStringIdx, lineNum );
+ auto addresses = worker->GetAddressesForLocation( m_source.idx(), lineNum );
if( addresses )
{
for( auto& addr : *addresses )
@@ -2422,7 +2354,7 @@ void SourceView::RenderLine( const Tokenizer::Line& line, int lineNum, uint32_t
}
else
{
- SelectAsmLinesHover( m_fileStringIdx, lineNum, *worker );
+ SelectAsmLinesHover( m_source.idx(), lineNum, *worker );
}
}
@@ -2629,7 +2561,7 @@ void SourceView::RenderAsmLine( AsmLine& line, uint32_t ipcnt, uint32_t iptotal,
if( m_font ) ImGui::PushFont( m_font );
if( ImGui::IsItemClicked( 0 ) || ImGui::IsItemClicked( 1 ) )
{
- if( m_file == fileName )
+ if( m_source.filename() == fileName )
{
if( ImGui::IsMouseClicked( 1 ) ) m_targetLine = srcline;
SelectLine( srcline, &worker, false );
@@ -3117,7 +3049,7 @@ void SourceView::SelectLine( uint32_t line, const Worker* worker, bool changeAsm
m_selectedLine = line;
if( m_symAddr == 0 ) return;
assert( worker );
- SelectAsmLines( m_fileStringIdx, line, *worker, changeAsmLine, targetAddr );
+ SelectAsmLines( m_source.idx(), line, *worker, changeAsmLine, targetAddr );
}
void SourceView::SelectAsmLines( uint32_t file, uint32_t line, const Worker& worker, bool changeAsmLine, uint64_t targetAddr )
@@ -3173,6 +3105,7 @@ void SourceView::SelectAsmLinesHover( uint32_t file, uint32_t line, const Worker
void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& iptotalAsm, unordered_flat_map& ipcountSrc, unordered_flat_map& ipcountAsm, uint32_t& ipmaxSrc, uint32_t& ipmaxAsm, const Worker& worker, bool limitView, const View& view )
{
+ auto filename = m_source.filename();
if( limitView )
{
auto vec = worker.GetSamplesForSymbol( addr );
@@ -3183,13 +3116,13 @@ void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& i
iptotalAsm += end - it;
while( it != end )
{
- if( m_file )
+ if( filename )
{
auto frame = worker.GetCallstackFrame( it->ip );
if( frame )
{
auto ffn = worker.GetString( frame->data[0].file );
- if( strcmp( ffn, m_file ) == 0 )
+ if( strcmp( ffn, filename ) == 0 )
{
const auto line = frame->data[0].line;
if( line != 0 )
@@ -3235,13 +3168,13 @@ void SourceView::GatherIpStats( uint64_t addr, uint32_t& iptotalSrc, uint32_t& i
if( !ipmap ) return;
for( auto& ip : *ipmap )
{
- if( m_file )
+ if( filename )
{
auto frame = worker.GetCallstackFrame( ip.first );
if( frame )
{
auto ffn = worker.GetString( frame->data[0].file );
- if( strcmp( ffn, m_file ) == 0 )
+ if( strcmp( ffn, filename ) == 0 )
{
const auto line = frame->data[0].line;
if( line != 0 )
diff --git a/server/TracySourceView.hpp b/server/TracySourceView.hpp
index 3d666810..3c02085a 100644
--- a/server/TracySourceView.hpp
+++ b/server/TracySourceView.hpp
@@ -8,6 +8,7 @@
#include "tracy_robin_hood.h"
#include "TracyCharUtil.hpp"
#include "TracyDecayValue.hpp"
+#include "TracySourceContents.hpp"
#include "TracySourceTokenizer.hpp"
#include "../common/TracyProtocol.hpp"
@@ -103,7 +104,6 @@ public:
using GetWindowCallback = void*(*)();
SourceView( ImFont* font, GetWindowCallback gwcb );
- ~SourceView();
void SetCpuId( uint32_t cpuid );
@@ -149,14 +149,9 @@ private:
#endif
ImFont* m_font;
- const char* m_file;
- uint32_t m_fileStringIdx;
uint64_t m_symAddr;
uint64_t m_baseAddr;
uint64_t m_targetAddr;
- const char* m_data;
- char* m_dataBuf;
- size_t m_dataSize;
int m_targetLine;
int m_selectedLine;
int m_asmSelected;
@@ -175,7 +170,7 @@ private:
bool m_atnt;
uint64_t m_jumpPopupAddr;
- std::vector m_lines;
+ SourceContents m_source;
std::vector m_asm;
unordered_flat_map m_locMap;