@@ -820,129 +820,160 @@ HRESULT PgoManager::getPgoInstrumentationResults(MethodDesc* pMD, BYTE** pAlloca
820
820
//
821
821
if (s_textFormatPgoData.GetCount () > 0 )
822
822
{
823
- COUNT_T methodhash = pMD->GetStableHash ();
824
- int codehash;
825
- unsigned ilSize;
826
- if (GetVersionResilientILCodeHashCode (pMD, &codehash, &ilSize))
823
+ hr = getPgoInstrumentationResultsFromText (pMD, pAllocatedData, ppSchema, pCountSchemaItems, pInstrumentationData, pPgoSource);
824
+ }
825
+
826
+ // If we didn't find any text format data, look for dynamic or static data.
827
+ //
828
+ if (FAILED (hr))
829
+ {
830
+ PgoManager *mgr;
831
+ if (!pMD->IsDynamicMethod ())
827
832
{
828
- Header *found = s_textFormatPgoData.Lookup (CodeAndMethodHash (codehash, methodhash));
829
- if (found != NULL )
830
- {
831
- StackSArray<ICorJitInfo::PgoInstrumentationSchema> schemaArray;
833
+ mgr = pMD->GetLoaderAllocator ()->GetPgoManager ();
834
+ }
835
+ else
836
+ {
837
+ mgr = pMD->AsDynamicMethodDesc ()->GetResolver ()->GetDynamicPgoManager ();
838
+ }
839
+
840
+ if (mgr != NULL )
841
+ {
842
+ hr = mgr->getPgoInstrumentationResultsInstance (pMD, pAllocatedData, ppSchema, pCountSchemaItems, pInstrumentationData, pPgoSource);
843
+ }
844
+ }
845
+
846
+ return hr;
847
+ }
848
+
849
+ HRESULT PgoManager::getPgoInstrumentationResultsFromText (MethodDesc* pMD, BYTE** pAllocatedData, ICorJitInfo::PgoInstrumentationSchema** ppSchema, UINT32* pCountSchemaItems, BYTE** pInstrumentationData, ICorJitInfo::PgoSource* pPgoSource)
850
+ {
851
+ int codehash;
852
+ unsigned ilSize;
853
+ if (!GetVersionResilientILCodeHashCode (pMD, &codehash, &ilSize))
854
+ {
855
+ return E_NOTIMPL;
856
+ }
832
857
833
- if (ReadInstrumentationSchemaWithLayoutIntoSArray (found->GetData (), found->countsOffset , found->countsOffset , &schemaArray))
858
+ COUNT_T methodhash = pMD->GetStableHash ();
859
+ Header* found = s_textFormatPgoData.Lookup (CodeAndMethodHash (codehash, methodhash));
860
+ if (found == NULL )
861
+ {
862
+ return E_NOTIMPL;
863
+ }
864
+
865
+ StackSArray<ICorJitInfo::PgoInstrumentationSchema> schemaArray;
866
+
867
+ if (!ReadInstrumentationSchemaWithLayoutIntoSArray (found->GetData (), found->countsOffset , found->countsOffset , &schemaArray))
868
+ {
869
+ _ASSERTE (!" Unable to parse schema data" );
870
+ return E_NOTIMPL;
871
+ }
872
+
873
+ HRESULT hr = E_NOTIMPL;
874
+ EX_TRY
875
+ {
876
+ for (unsigned iSchema = 0 ; iSchema < schemaArray.GetCount (); iSchema++)
877
+ {
878
+ ICorJitInfo::PgoInstrumentationSchema* schema = &(schemaArray)[iSchema];
879
+ ICorJitInfo::PgoInstrumentationKind kind = schema->InstrumentationKind & ICorJitInfo::PgoInstrumentationKind::MarshalMask;
880
+ if ((kind == ICorJitInfo::PgoInstrumentationKind::TypeHandle) || (kind == ICorJitInfo::PgoInstrumentationKind::MethodHandle))
881
+ {
882
+ for (int iEntry = 0 ; iEntry < schema->Count ; iEntry++)
834
883
{
835
- EX_TRY
884
+ INT_PTR* handleValueAddress = (INT_PTR*)(found->GetData () + schema->Offset + iEntry * InstrumentationKindToSize (schema->InstrumentationKind ));
885
+ INT_PTR initialHandleValue = VolatileLoad (handleValueAddress);
886
+
887
+ // TypeHandles can't reliably be loaded at ReadPGO time
888
+ // Instead, translate them before leaving this method.
889
+ // The ReadPgo method will place pointers to C style null
890
+ // terminated strings in the TypeHandle slots, and this will
891
+ // translate any of those into loaded TypeHandles as appropriate
892
+ if (((initialHandleValue & 1 ) == 1 ) && !ICorJitInfo::IsUnknownHandle (initialHandleValue))
836
893
{
837
- // TypeHandles can't reliably be loaded at ReadPGO time
838
- // Instead, translate them before leaving this method.
839
- // The ReadPgo method will place pointers to C style null
840
- // terminated strings in the TypeHandle slots, and this will
841
- // translate any of those into loaded TypeHandles as appropriate
894
+ INT_PTR newPtr = 0 ;
895
+ char * string = ((char *)initialHandleValue) - 1 ;
896
+
897
+ // Resolving types and methods here can invoke managed code where the
898
+ // JIT may recursively ask for PGO data. We do not support textual PGO
899
+ // for those cases.
900
+ static thread_local bool t_resolvingTypeOrMethod;
842
901
843
- for ( unsigned iSchema = 0 ; iSchema < schemaArray. GetCount (); iSchema++)
902
+ struct ResolveScope
844
903
{
845
- ICorJitInfo::PgoInstrumentationSchema *schema = &(schemaArray)[iSchema];
846
- ICorJitInfo::PgoInstrumentationKind kind = schema->InstrumentationKind & ICorJitInfo::PgoInstrumentationKind::MarshalMask;
847
- if ((kind == ICorJitInfo::PgoInstrumentationKind::TypeHandle) || (kind == ICorJitInfo::PgoInstrumentationKind::MethodHandle))
904
+ ResolveScope ()
848
905
{
849
- for (int iEntry = 0 ; iEntry < schema->Count ; iEntry++)
850
- {
851
- INT_PTR* handleValueAddress = (INT_PTR*)(found->GetData () + schema->Offset + iEntry * InstrumentationKindToSize (schema->InstrumentationKind ));
852
- INT_PTR initialHandleValue = VolatileLoad (handleValueAddress);
853
- if (((initialHandleValue & 1 ) == 1 ) && !ICorJitInfo::IsUnknownHandle (initialHandleValue))
854
- {
855
- INT_PTR newPtr = 0 ;
856
- char * string = ((char *)initialHandleValue) - 1 ;
906
+ t_resolvingTypeOrMethod = true ;
907
+ }
857
908
858
- // Don't attempt to load any types or methods until the EE is started
859
- if (g_fEEStarted)
860
- {
861
- if (kind == ICorJitInfo::PgoInstrumentationKind::TypeHandle)
862
- {
863
- StackSString ts (SString::Utf8, string);
864
- TypeHandle th = TypeName::GetTypeManaged (ts.GetUnicode (), NULL , FALSE , FALSE , FALSE , NULL , NULL );
865
- newPtr = (INT_PTR)th.AsPtr ();
866
- }
867
- else
868
- {
869
- assert (kind == ICorJitInfo::PgoInstrumentationKind::MethodHandle);
870
- // Format is:
871
- // MethodName|@|fully_qualified_type_name
872
- char * sep = strstr (string, " |@|" );
873
- if (sep != nullptr )
874
- {
875
- StackSString typeString (SString::Utf8, sep + 3 );
876
- StackSString methodString (SString::Utf8, string, (COUNT_T)(sep - string));
877
- TypeHandle th = TypeName::GetTypeManaged (typeString.GetUnicode (), NULL , FALSE , FALSE , FALSE , NULL , NULL );
878
- if (!th.IsNull ())
879
- {
880
- MethodDesc* pMD = MemberLoader::FindMethodByName (th.GetMethodTable (), methodString.GetUTF8 ());
881
- if (pMD != nullptr && !pMD->IsGenericMethodDefinition ())
882
- {
883
- newPtr = (INT_PTR)pMD;
884
- }
885
- }
886
- }
887
- }
888
- }
909
+ ~ResolveScope ()
910
+ {
911
+ t_resolvingTypeOrMethod = false ;
912
+ }
913
+ };
889
914
890
- if (newPtr == 0 )
915
+ // Don't attempt to load any types or methods until the EE is started
916
+ if (g_fEEStarted && !t_resolvingTypeOrMethod)
917
+ {
918
+ ResolveScope resolve;
919
+
920
+ if (kind == ICorJitInfo::PgoInstrumentationKind::TypeHandle)
921
+ {
922
+ StackSString ts (SString::Utf8, string);
923
+ TypeHandle th = TypeName::GetTypeManaged (ts.GetUnicode (), NULL , FALSE , FALSE , FALSE , NULL , NULL );
924
+ newPtr = (INT_PTR)th.AsPtr ();
925
+ }
926
+ else
927
+ {
928
+ assert (kind == ICorJitInfo::PgoInstrumentationKind::MethodHandle);
929
+ // Format is:
930
+ // MethodName|@|fully_qualified_type_name
931
+ char * sep = strstr (string, " |@|" );
932
+ if (sep != nullptr )
933
+ {
934
+ StackSString typeString (SString::Utf8, sep + 3 );
935
+ StackSString methodString (SString::Utf8, string, (COUNT_T)(sep - string));
936
+ TypeHandle th = TypeName::GetTypeManaged (typeString.GetUnicode (), NULL , FALSE , FALSE , FALSE , NULL , NULL );
937
+
938
+ if (!th.IsNull ())
939
+ {
940
+ MethodDesc* pMD = MemberLoader::FindMethodByName (th.GetMethodTable (), methodString.GetUTF8 ());
941
+ if (pMD != nullptr && !pMD->IsGenericMethodDefinition ())
891
942
{
892
- newPtr = HashToPgoUnknownHandle ( HashStringA (string)) ;
943
+ newPtr = (INT_PTR)pMD ;
893
944
}
894
-
895
- InterlockedCompareExchangeT (handleValueAddress, newPtr, initialHandleValue);
896
945
}
897
946
}
898
947
}
899
948
}
900
949
901
- *pAllocatedData = new BYTE[schemaArray.GetCount () * sizeof (ICorJitInfo::PgoInstrumentationSchema)];
902
- memcpy (*pAllocatedData, schemaArray.OpenRawBuffer (), schemaArray.GetCount () * sizeof (ICorJitInfo::PgoInstrumentationSchema));
903
- schemaArray.CloseRawBuffer ();
904
- *ppSchema = (ICorJitInfo::PgoInstrumentationSchema*)*pAllocatedData;
905
-
906
- *pCountSchemaItems = schemaArray.GetCount ();
907
- *pInstrumentationData = found->GetData ();
908
- *pPgoSource = ICorJitInfo::PgoSource::Text;
950
+ if (newPtr == 0 )
951
+ {
952
+ newPtr = HashToPgoUnknownHandle (HashStringA (string));
953
+ }
909
954
910
- hr = S_OK;
911
- }
912
- EX_CATCH
913
- {
914
- hr = E_FAIL;
955
+ InterlockedCompareExchangeT (handleValueAddress, newPtr, initialHandleValue);
915
956
}
916
- EX_END_CATCH (RethrowTerminalExceptions)
917
- }
918
- else
919
- {
920
- _ASSERTE (!" Unable to parse schema data" );
921
- hr = E_NOTIMPL;
922
957
}
923
958
}
924
959
}
925
- }
926
960
927
- // If we didn't find any text format data, look for dynamic or static data.
928
- //
929
- if (FAILED (hr))
930
- {
931
- PgoManager *mgr;
932
- if (!pMD->IsDynamicMethod ())
933
- {
934
- mgr = pMD->GetLoaderAllocator ()->GetPgoManager ();
935
- }
936
- else
937
- {
938
- mgr = pMD->AsDynamicMethodDesc ()->GetResolver ()->GetDynamicPgoManager ();
939
- }
961
+ *pAllocatedData = new BYTE[schemaArray.GetCount () * sizeof (ICorJitInfo::PgoInstrumentationSchema)];
962
+ memcpy (*pAllocatedData, schemaArray.OpenRawBuffer (), schemaArray.GetCount () * sizeof (ICorJitInfo::PgoInstrumentationSchema));
963
+ schemaArray.CloseRawBuffer ();
964
+ *ppSchema = (ICorJitInfo::PgoInstrumentationSchema*)*pAllocatedData;
940
965
941
- if (mgr != NULL )
942
- {
943
- hr = mgr->getPgoInstrumentationResultsInstance (pMD, pAllocatedData, ppSchema, pCountSchemaItems, pInstrumentationData, pPgoSource);
944
- }
966
+ *pCountSchemaItems = schemaArray.GetCount ();
967
+ *pInstrumentationData = found->GetData ();
968
+ *pPgoSource = ICorJitInfo::PgoSource::Text;
969
+
970
+ hr = S_OK;
971
+ }
972
+ EX_CATCH
973
+ {
974
+ hr = E_FAIL;
945
975
}
976
+ EX_END_CATCH (RethrowTerminalExceptions)
946
977
947
978
return hr;
948
979
}
0 commit comments