1- //
1+ //
22// Copyright (c) .NET Foundation and Contributors
33// Portions Copyright (c) Microsoft Corporation. All rights reserved.
44// See LICENSE file in the project root for full license information.
1010#include < stdint.h>
1111#endif
1212
13+ #if defined(VIRTUAL_DEVICE)
14+ #include " nanoCLR_native.h"
15+ #include < format>
16+ #endif
17+
1318#if defined(NANOCLR_PROFILE_NEW)
1419
1520CLR_PRF_Profiler g_CLR_PRF_Profiler;
@@ -30,6 +35,11 @@ HRESULT CLR_PRF_Profiler::CreateInstance()
3035
3136 g_CLR_PRF_Profiler.m_initialized = true ;
3237
38+ #if defined(VIRTUAL_DEVICE)
39+ // need to do the here to send the memory layout in the first packet
40+ g_CLR_PRF_Profiler.SendMemoryLayout ();
41+ #endif
42+
3343 NANOCLR_NOCLEANUP ();
3444}
3545
@@ -55,10 +65,28 @@ void CLR_PRF_Profiler::SendMemoryLayout()
5565
5666 // Send Memory Layout
5767 m_stream->WriteBits (CLR_PRF_CMDS::c_Profiling_Memory_Layout, CLR_PRF_CMDS::Bits::CommandHeader);
68+
69+ #if defined(_WIN64)
70+ PackAndWriteBits ((CLR_UINT32)((CLR_UINT64)s_CLR_RT_Heap.m_location >> 32 ));
71+ #endif
5872 PackAndWriteBits ((CLR_UINT32)s_CLR_RT_Heap.m_location );
73+
5974 PackAndWriteBits (s_CLR_RT_Heap.m_size );
6075
6176 Stream_Send ();
77+
78+ #if defined(VIRTUAL_DEVICE)
79+ if (g_ProfilerMessageCallback != NULL )
80+ {
81+ std::string memoryLayout = std::format (
82+ " ** Memory layout **\r\n start:0x{:X}\r\n end:0x{:X}\r\n size:0x{:X}\r\n " ,
83+ (unsigned long long )s_CLR_RT_Heap.m_location ,
84+ (unsigned long long )s_CLR_RT_Heap.m_location + s_CLR_RT_Heap.m_size ,
85+ s_CLR_RT_Heap.m_size );
86+
87+ g_ProfilerMessageCallback (memoryLayout.c_str ());
88+ }
89+ #endif
6290}
6391
6492HRESULT CLR_PRF_Profiler::DumpHeap ()
@@ -507,7 +535,14 @@ void CLR_PRF_Profiler::DumpEndOfRefsList()
507535void CLR_PRF_Profiler::DumpPointer (void *ptr)
508536{
509537 NATIVE_PROFILE_CLR_DIAGNOSTICS ();
538+
539+ #ifdef _WIN64
540+ CLR_UINT64 ptrVAlue = ((CLR_UINT8 *)ptr - s_CLR_RT_Heap.m_location );
541+ PackAndWriteBits ((CLR_UINT32)(ptrVAlue >> 32 ));
542+ PackAndWriteBits ((CLR_UINT32)ptrVAlue);
543+ #else
510544 PackAndWriteBits ((CLR_UINT32)((CLR_UINT8 *)ptr - s_CLR_RT_Heap.m_location ));
545+ #endif
511546}
512547
513548void CLR_PRF_Profiler::DumpSingleReference (CLR_RT_HeapBlock *ptr)
@@ -701,6 +736,29 @@ void CLR_PRF_Profiler::TrackObjectCreation(CLR_RT_HeapBlock *ptr)
701736 CLR_RT_TypeDef_Index idx = ptr->ObjectCls ();
702737 PackAndWriteBits (idx);
703738
739+ #if defined(VIRTUAL_DEVICE)
740+ if (g_ProfilerMessageCallback != NULL )
741+ {
742+ // build type name
743+ char fullTypeName[1024 ] = {0 };
744+ char *szBuffer = fullTypeName;
745+ size_t iBuffer = MAXSTRLEN (fullTypeName);
746+
747+ g_CLR_RT_TypeSystem.BuildTypeName (idx, szBuffer, iBuffer);
748+
749+ // compose output message
750+ std::string objectCreation = std::format (
751+ " New {} {} @ 0x{:X} [{:08x}] {} bytes\r\n " ,
752+ c_CLR_RT_DataTypeLookup[dt].m_name ,
753+ fullTypeName,
754+ (CLR_UINT64)((CLR_UINT8 *)ptr),
755+ idx.m_data ,
756+ (dataSize * sizeof (struct CLR_RT_HeapBlock )));
757+
758+ g_ProfilerMessageCallback (objectCreation.c_str ());
759+ }
760+ #endif
761+
704762#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
705763
706764#ifdef _WIN64
@@ -731,6 +789,34 @@ void CLR_PRF_Profiler::TrackObjectCreation(CLR_RT_HeapBlock *ptr)
731789 PackAndWriteBits (array->ReflectionDataConst ().m_data .m_type );
732790 PackAndWriteBits (array->ReflectionDataConst ().m_levels );
733791
792+ #if defined(VIRTUAL_DEVICE)
793+ if (g_ProfilerMessageCallback != NULL )
794+ {
795+ // build type name
796+ char fullTypeName[1024 ] = {0 };
797+ char *szBuffer = fullTypeName;
798+ size_t iBuffer = MAXSTRLEN (fullTypeName);
799+
800+ CLR_RT_TypeDef_Instance arrayTypeDef{};
801+ CLR_UINT32 levels;
802+ arrayTypeDef.InitializeFromReflection (array->ReflectionData (), &levels);
803+
804+ g_CLR_RT_TypeSystem.BuildTypeName (arrayTypeDef, szBuffer, iBuffer);
805+
806+ // compose output message
807+ std::string objectCreation = std::format (
808+ " New {}[] @ 0x{:X} {} bytes [{:08x}] {} elements {} level(s)\r\n " ,
809+ fullTypeName,
810+ (CLR_UINT64)((CLR_UINT8 *)ptr),
811+ (dataSize * sizeof (struct CLR_RT_HeapBlock )),
812+ elementIdx.m_data ,
813+ array->m_numOfElements ,
814+ levels);
815+
816+ g_ProfilerMessageCallback (objectCreation.c_str ());
817+ }
818+ #endif
819+
734820#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
735821
736822#ifdef _WIN64
@@ -753,6 +839,17 @@ void CLR_PRF_Profiler::TrackObjectCreation(CLR_RT_HeapBlock *ptr)
753839#endif
754840#endif // NANOCLR_TRACE_PROFILER_MESSAGES
755841 }
842+ else
843+ {
844+ // compose output message
845+ std::string objectCreation = std::format (
846+ " New {} @ 0x{:X} {} bytes\r\n " ,
847+ c_CLR_RT_DataTypeLookup[dt].m_name ,
848+ (CLR_UINT64)((CLR_UINT8 *)ptr),
849+ (dataSize * sizeof (struct CLR_RT_HeapBlock )));
850+
851+ g_ProfilerMessageCallback (objectCreation.c_str ());
852+ }
756853#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
757854 else
758855 {
@@ -800,6 +897,74 @@ void CLR_PRF_Profiler::TrackObjectDeletion(CLR_RT_HeapBlock *ptr)
800897 m_stream->WriteBits (CLR_PRF_CMDS::c_Profiling_Allocs_Delete, CLR_PRF_CMDS::Bits::CommandHeader);
801898 DumpPointer (ptr);
802899 Stream_Send ();
900+
901+ #if defined(VIRTUAL_DEVICE)
902+ if (g_ProfilerMessageCallback != NULL )
903+ {
904+ if (dt == DATATYPE_SZARRAY)
905+ {
906+ CLR_RT_HeapBlock_Array *array = (CLR_RT_HeapBlock_Array *)ptr;
907+ CLR_RT_TypeDef_Index elementIdx = array->ReflectionDataConst ().m_data .m_type ;
908+
909+ // build type name
910+ char fullTypeName[1024 ] = {0 };
911+ char *szBuffer = fullTypeName;
912+ size_t iBuffer = MAXSTRLEN (fullTypeName);
913+
914+ CLR_RT_TypeDef_Instance arrayTypeDef{};
915+ CLR_UINT32 levels;
916+ arrayTypeDef.InitializeFromReflection (array->ReflectionData (), &levels);
917+
918+ g_CLR_RT_TypeSystem.BuildTypeName (arrayTypeDef, szBuffer, iBuffer);
919+
920+ // compose output message
921+ std::string objectCreation = std::format (
922+ " Delete {}[] @ 0x{:X} {} bytes [{:08x}] {} elements {} level(s)\r\n " ,
923+ fullTypeName,
924+ (CLR_UINT64)((CLR_UINT8 *)ptr),
925+ (ptr->DataSize () * sizeof (struct CLR_RT_HeapBlock )),
926+ elementIdx.m_data ,
927+ array->m_numOfElements ,
928+ levels);
929+
930+ g_ProfilerMessageCallback (objectCreation.c_str ());
931+ }
932+ else if (dt == DATATYPE_CLASS || dt == DATATYPE_VALUETYPE)
933+ {
934+ CLR_RT_TypeDef_Index idx = ptr->ObjectCls ();
935+
936+ // build type name
937+ char fullTypeName[1024 ] = {0 };
938+ char *szBuffer = fullTypeName;
939+ size_t iBuffer = MAXSTRLEN (fullTypeName);
940+
941+ g_CLR_RT_TypeSystem.BuildTypeName (idx, szBuffer, iBuffer);
942+
943+ // compose output message
944+ std::string objectCreation = std::format (
945+ " Delete {} {} @ 0x{:X} [{:08x}] {} bytes\r\n " ,
946+ c_CLR_RT_DataTypeLookup[dt].m_name ,
947+ fullTypeName,
948+ (CLR_UINT64)((CLR_UINT8 *)ptr),
949+ idx.m_data ,
950+ (ptr->DataSize () * sizeof (struct CLR_RT_HeapBlock )));
951+
952+ g_ProfilerMessageCallback (objectCreation.c_str ());
953+ }
954+ else
955+ {
956+ CLR_UINT16 dataSize = ptr->DataSize ();
957+
958+ std::string objectDeletion = std::format (
959+ " Delete {} @ 0x{:X} {} bytes\r\n " ,
960+ c_CLR_RT_DataTypeLookup[dt].m_name ,
961+ (CLR_UINT64)((CLR_UINT8 *)ptr),
962+ (dataSize * sizeof (struct CLR_RT_HeapBlock )));
963+
964+ g_ProfilerMessageCallback (objectDeletion.c_str ());
965+ }
966+ }
967+ #endif
803968 }
804969
805970#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
@@ -849,6 +1014,19 @@ void CLR_PRF_Profiler::TrackObjectRelocation()
8491014 DumpPointer (relocBlocks[i].m_end );
8501015 PackAndWriteBits (relocBlocks[i].m_offset );
8511016
1017+ #if defined(VIRTUAL_DEVICE)
1018+ if (g_ProfilerMessageCallback != NULL )
1019+ {
1020+ std::string objectRelocation = std::format (
1021+ " Relocate 0x{:X} to 0x{:X} offset 0x{:X}\r\n " ,
1022+ (CLR_UINT64)relocBlocks[i].m_start ,
1023+ (CLR_UINT64)relocBlocks[i].m_destination ,
1024+ relocBlocks[i].m_offset );
1025+
1026+ g_ProfilerMessageCallback (objectRelocation.c_str ());
1027+ }
1028+ #endif
1029+
8521030#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
8531031
8541032#ifdef _WIN64
@@ -888,6 +1066,15 @@ void CLR_PRF_Profiler::RecordGarbageCollectionBegin()
8881066 PackAndWriteBits (g_CLR_RT_GarbageCollector.m_freeBytes );
8891067 Stream_Send ();
8901068
1069+ #if defined(VIRTUAL_DEVICE)
1070+ if (g_ProfilerMessageCallback != NULL )
1071+ {
1072+ std::string garbageCollection =
1073+ std::format (" GC: Starting run #{}\r\n " , g_CLR_RT_GarbageCollector.m_numberOfGarbageCollections );
1074+ g_ProfilerMessageCallback (garbageCollection.c_str ());
1075+ }
1076+ #endif
1077+
8911078#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
8921079
8931080#ifdef _WIN64
@@ -926,6 +1113,18 @@ void CLR_PRF_Profiler::RecordGarbageCollectionEnd()
9261113 PackAndWriteBits (g_CLR_RT_GarbageCollector.m_freeBytes );
9271114 Stream_Send ();
9281115
1116+ #if defined(VIRTUAL_DEVICE)
1117+ if (g_ProfilerMessageCallback != NULL )
1118+ {
1119+ std::string garbageCollection = std::format (
1120+ " GC: Finished run #{} - {} bytes free\r\n " ,
1121+ g_CLR_RT_GarbageCollector.m_numberOfGarbageCollections ,
1122+ g_CLR_RT_GarbageCollector.m_freeBytes );
1123+
1124+ g_ProfilerMessageCallback (garbageCollection.c_str ());
1125+ }
1126+ #endif
1127+
9291128#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
9301129
9311130#ifdef _WIN64
@@ -976,6 +1175,16 @@ void CLR_PRF_Profiler::RecordHeapCompactionBegin()
9761175 PackAndWriteBits (g_CLR_RT_GarbageCollector.m_freeBytes );
9771176 Stream_Send ();
9781177
1178+ #if defined(VIRTUAL_DEVICE)
1179+ if (g_ProfilerMessageCallback != NULL )
1180+ {
1181+ std::string heapCompaction =
1182+ std::format (" Heap compaction: Starting run #{} \r\n " , g_CLR_RT_GarbageCollector.m_numberOfCompactions );
1183+
1184+ g_ProfilerMessageCallback (heapCompaction.c_str ());
1185+ }
1186+ #endif
1187+
9791188#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
9801189
9811190#ifdef _WIN64
@@ -1014,6 +1223,17 @@ void CLR_PRF_Profiler::RecordHeapCompactionEnd()
10141223 PackAndWriteBits (g_CLR_RT_GarbageCollector.m_freeBytes );
10151224 Stream_Send ();
10161225
1226+ #if defined(VIRTUAL_DEVICE)
1227+ if (g_ProfilerMessageCallback != NULL )
1228+ {
1229+ std::string heapCompaction = std::format (
1230+ " Heap compaction: Finished run #{}\r\n " ,
1231+ g_CLR_RT_GarbageCollector.m_numberOfGarbageCollections );
1232+
1233+ g_ProfilerMessageCallback (heapCompaction.c_str ());
1234+ }
1235+ #endif
1236+
10171237#ifdef NANOCLR_TRACE_PROFILER_MESSAGES
10181238
10191239#ifdef _WIN64
@@ -1163,6 +1383,13 @@ HRESULT CLR_PRF_Profiler::Stream_Flush()
11631383 _ASSERTE (false );
11641384 NANOCLR_SET_AND_LEAVE (CLR_E_FAIL);
11651385 }
1386+
1387+ #if defined(VIRTUAL_DEVICE)
1388+ if (g_ProfilerDataCallback != NULL )
1389+ {
1390+ g_ProfilerDataCallback (ptr->m_payload , payloadLength);
1391+ }
1392+ #endif
11661393 }
11671394
11681395 // Don't go past the cursor.
0 commit comments