@@ -1372,6 +1372,17 @@ UINT TransitionFrame::CbStackPopUsingGCRefMap(PTR_BYTE pGCRefMap)
13721372}
13731373#endif
13741374
1375+ static UINT OffsetFromGCRefMapPos (int pos)
1376+ {
1377+ #ifdef TARGET_X86
1378+ return (pos < NUM_ARGUMENT_REGISTERS) ?
1379+ (TransitionBlock::GetOffsetOfArgumentRegisters () + ARGUMENTREGISTERS_SIZE - (pos + 1 ) * sizeof (TADDR)) :
1380+ (TransitionBlock::GetOffsetOfArgs () + (pos - NUM_ARGUMENT_REGISTERS) * sizeof (TADDR));
1381+ #else
1382+ return TransitionBlock::GetOffsetOfFirstGCRefMapSlot () + pos * sizeof (TADDR);
1383+ #endif
1384+ }
1385+
13751386void TransitionFrame::PromoteCallerStackUsingGCRefMap (promote_func* fn, ScanContext* sc, PTR_BYTE pGCRefMap)
13761387{
13771388 WRAPPER_NO_CONTRACT;
@@ -1389,16 +1400,7 @@ void TransitionFrame::PromoteCallerStackUsingGCRefMap(promote_func* fn, ScanCont
13891400 {
13901401 int pos = decoder.CurrentPos ();
13911402 int token = decoder.ReadToken ();
1392-
1393- int ofs;
1394-
1395- #ifdef TARGET_X86
1396- ofs = (pos < NUM_ARGUMENT_REGISTERS) ?
1397- (TransitionBlock::GetOffsetOfArgumentRegisters () + ARGUMENTREGISTERS_SIZE - (pos + 1 ) * sizeof (TADDR)) :
1398- (TransitionBlock::GetOffsetOfArgs () + (pos - NUM_ARGUMENT_REGISTERS) * sizeof (TADDR));
1399- #else
1400- ofs = TransitionBlock::GetOffsetOfFirstGCRefMapSlot () + pos * sizeof (TADDR);
1401- #endif
1403+ int ofs = OffsetFromGCRefMapPos (pos);
14021404
14031405 PTR_TADDR ppObj = dac_cast<PTR_TADDR>(pTransitionBlock + ofs);
14041406
@@ -2060,6 +2062,76 @@ void FakeGcScanRoots(MetaSig& msig, ArgIterator& argit, MethodDesc * pMD, BYTE *
20602062 }
20612063}
20622064
2065+ #ifdef _DEBUG
2066+ static void DumpGCRefMap (const char *name, BYTE *address)
2067+ {
2068+ GCRefMapDecoder decoder (address);
2069+
2070+ printf (" %s GC ref map: " , name);
2071+ #if TARGET_X86
2072+ uint32_t stackPop = decoder.ReadStackPop ();
2073+ printf (" POP(0x%x)" , stackPop);
2074+ #endif
2075+
2076+ int previousToken = GCREFMAP_SKIP;
2077+ while (!decoder.AtEnd ())
2078+ {
2079+ int pos = decoder.CurrentPos ();
2080+ int token = decoder.ReadToken ();
2081+ if (token != previousToken)
2082+ {
2083+ if (previousToken != GCREFMAP_SKIP)
2084+ {
2085+ printf (" ) " );
2086+ }
2087+ switch (token)
2088+ {
2089+ case GCREFMAP_SKIP:
2090+ break ;
2091+
2092+ case GCREFMAP_REF:
2093+ printf (" R(" );
2094+ break ;
2095+
2096+ case GCREFMAP_INTERIOR:
2097+ printf (" I(" );
2098+ break ;
2099+
2100+ case GCREFMAP_METHOD_PARAM:
2101+ printf (" M(" );
2102+ break ;
2103+
2104+ case GCREFMAP_TYPE_PARAM:
2105+ printf (" T(" );
2106+ break ;
2107+
2108+ case GCREFMAP_VASIG_COOKIE:
2109+ printf (" V(" );
2110+ break ;
2111+
2112+ default :
2113+ // Not implemented
2114+ _ASSERTE (false );
2115+ }
2116+ }
2117+ else if (token != GCREFMAP_SKIP)
2118+ {
2119+ printf (" " );
2120+ }
2121+ if (token != GCREFMAP_SKIP)
2122+ {
2123+ printf (" %02x" , OffsetFromGCRefMapPos (pos));
2124+ }
2125+ previousToken = token;
2126+ }
2127+ if (previousToken != GCREFMAP_SKIP)
2128+ {
2129+ printf (" )" );
2130+ }
2131+ printf (" \n " );
2132+ }
2133+ #endif
2134+
20632135bool CheckGCRefMapEqual (PTR_BYTE pGCRefMap, MethodDesc* pMD, bool isDispatchCell)
20642136{
20652137#ifdef _DEBUG
@@ -2074,16 +2146,29 @@ bool CheckGCRefMapEqual(PTR_BYTE pGCRefMap, MethodDesc* pMD, bool isDispatchCell
20742146 GCRefMapDecoder decoderNew ((BYTE *)pBlob);
20752147 GCRefMapDecoder decoderExisting (pGCRefMap);
20762148
2149+ bool invalidGCRefMap = false ;
2150+
20772151#ifdef TARGET_X86
2078- _ASSERTE (decoderNew.ReadStackPop () == decoderExisting.ReadStackPop ());
2152+ if (decoderNew.ReadStackPop () != decoderExisting.ReadStackPop ())
2153+ {
2154+ invalidGCRefMap = true ;
2155+ }
20792156#endif
2080-
2081- _ASSERTE (decoderNew.AtEnd () == decoderExisting.AtEnd ());
2082- while (!decoderNew.AtEnd ())
2157+ while (!invalidGCRefMap && !(decoderNew.AtEnd () && decoderExisting.AtEnd ()))
2158+ {
2159+ if (decoderNew.AtEnd () != decoderExisting.AtEnd () ||
2160+ decoderNew.CurrentPos () != decoderExisting.CurrentPos () ||
2161+ decoderNew.ReadToken () != decoderExisting.ReadToken ())
2162+ {
2163+ invalidGCRefMap = true ;
2164+ }
2165+ }
2166+ if (invalidGCRefMap)
20832167 {
2084- _ASSERTE (decoderNew.CurrentPos () == decoderExisting.CurrentPos ());
2085- _ASSERTE (decoderNew.ReadToken () == decoderExisting.ReadToken ());
2086- _ASSERTE (decoderNew.AtEnd () == decoderExisting.AtEnd ());
2168+ printf (" GC ref map mismatch detected for method: %s::%s\n " , pMD->GetMethodTable ()->GetDebugClassName (), pMD->GetName ());
2169+ DumpGCRefMap (" Runtime" , (BYTE *)pBlob);
2170+ DumpGCRefMap (" Crossgen2" , pGCRefMap);
2171+ _ASSERTE (false );
20872172 }
20882173#endif
20892174 return true ;
0 commit comments