text: //
  // Copyright (c) Microsoft. All rights reserved.
  // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  //
  
  //----------------------------------------------------------
  // MethodContext.cpp - Primary structure to store all the EE-JIT details required to replay creation of a method
  //                     CompileResult contains the stuff generated by a compilation
  //----------------------------------------------------------
  
  #include "standardpch.h"
  #include "methodcontext.h"
  #include "compileresult.h"
  #include "lightweightmap.h"
  #include "callutils.h"
  #include "spmirecordhelper.h"
  #include "spmidumphelper.h"
  
  #define sparseMC // Support filling in details where guesses are okay and will still generate good code. (i.e. helper
                   // function addresses)
  
  #if 0
  // Enable these to get verbose logging during record or playback.
  #define DEBUG_REC(x)                                                                                                   \
      printf("rec");                                                                                                     \
      x;                                                                                                                 \
      printf("\n");
  
  #define DEBUG_REP(x)                                                                                                   \
      printf("rep");                                                                                                     \
      x;                                                                                                                 \
      printf("\n");
  #else
  #define DEBUG_REC(x)
  #define DEBUG_REP(x)
  #endif
  
  // static variable initialization
  Hash MethodContext::m_hash;
  
  MethodContext::MethodContext()
  {
      methodSize = 0;
  
  #define LWM(map, key, value) map = nullptr;
  #include "lwmlist.h"
  
      cr    = new CompileResult();
      index = -1;
  }
  
  MethodContext::~MethodContext()
  {
      Destroy();
  }
  
  void MethodContext::Destroy()
  {
  #define LWM(map, key, value)                                                                                           \
      if (map != nullptr)                                                                                                \
          delete map;
  #include "lwmlist.h"
  
      delete cr;
  }
  
  #define sparseAddLen(target)                                                                                           \
      if (target != nullptr)                                                                                             \
      {                                                                                                                  \
          if (target->GetCount() != 0)                                                                                   \
              totalLen += target->CalculateArraySize() + 6; /* packet canary from lightweightmap + packet marker */      \
      }
  
  #define sparseWriteFile(target)                                                                                        \
      if (target != nullptr)                                                                                             \
      {                                                                                                                  \
          if (target->GetCount() != 0)                                                                                   \
          {                                                                                                              \
              buff2[buffIndex++] = (unsigned char)Packet_##target;                                                       \
              unsigned int loc   = target->DumpToArray(&buff2[buffIndex + 4]);                                           \
              memcpy(&buff2[buffIndex], &loc, sizeof(unsigned int));                                                     \
              buffIndex += 4 + loc;                                                                                      \
              buff2[buffIndex++] = 0x42;                                                                                 \
          }                                                                                                              \
      }
  
  #define sparseWriteFileCR(target)                                                                                      \
      if (cr != nullptr)                                                                                                 \
      {                                                                                                                  \
          if (cr->target != nullptr)                                                                                     \
          {                                                                                                              \
              if (cr->target->GetCount() != 0)                                                                           \
              {                                                                                                          \
                  buff2[buffIndex++] = (unsigned char)PacketCR_##target;                                                 \
                  unsigned int loc   = cr->target->DumpToArray(&buff2[buffIndex + 4]);                                   \
                  memcpy(&buff2[buffIndex], &loc, sizeof(unsigned int));                                                 \
                  buffIndex += 4 + loc;                                                                                  \
                  buff2[buffIndex++] = 0x42;                                                                             \
              }                                                                                                          \
          }                                                                                                              \
      }
  
  #define sparseReadFile(target, key, value)                                                                             \
      case Packet_##target:                                                                                              \
      {                                                                                                                  \
          target = new LightWeightMap<key, value>();                                                                     \
          target->ReadFromArray(&buff2[buffIndex], localsize);                                                           \
          break;                                                                                                         \
      }
  
  #define sparseReadFileCR(target, key, value)                                                                           \
      case PacketCR_##target:                                                                                            \
      {                                                                                                                  \
          cr->target = new LightWeightMap<key, value>();                                                                 \
          cr->target->ReadFromArray(&buff2[buffIndex], localsize);                                                       \
          break;                                                                                                         \
      }
  
  #define sparseReadFileDense(target, value)                                                                             \
      case Packet_##target:                                                                                              \
      {                                                                                                                  \
          target = new DenseLightWeightMap<value>();                                                                     \
          target->ReadFromArray(&buff2[buffIndex], localsize);                                                           \
          break;                                                                                                         \
      }
  
  #define sparseReadFileCRDense(target, value)                                                                           \
      case PacketCR_##target:                                                                                            \
      {                                                                                                                  \
          cr->target = new DenseLightWeightMap<value>();                                                                 \
          cr->target->ReadFromArray(&buff2[buffIndex], localsize);                                                       \
          break;                                                                                                         \
      }
  
  unsigned int MethodContext::calculateFileSize()
  {
      // Calculate file size
      unsigned int totalLen = 0;
  
  #define LWM(map, key, value) sparseAddLen(map)
  #include "lwmlist.h"
  
      // Compile Result members
      if (cr != nullptr)
      {
  #define LWM(map, key, value) sparseAddLen(cr->map);
  #include "crlwmlist.h"
      }
  
      return totalLen;
  }
  
  unsigned int MethodContext::calculateRawFileSize()
  {
      return 2 /* leading magic cookie 'm', 'c' */ + 4 /* 4-byte data length */ + calculateFileSize() +
             2 /* end canary '4', '2' */;
  }
  
  unsigned int MethodContext::saveToFile(HANDLE hFile)
  {
      unsigned int totalLen = calculateFileSize();
      unsigned int totalFileSize =
          2 /* leading magic cookie 'm', 'c' */ + 4 /* 4-byte data length */ + totalLen + 2 /* end canary '4', '2' */;
  
      DWORD          bytesWritten = 0;
      unsigned int   buffIndex    = 0;
      unsigned char* buff2        = new unsigned char[totalFileSize];
      buff2[buffIndex++]          = 'm';
      buff2[buffIndex++]          = 'c';
      memcpy(&buff2[buffIndex], &totalLen, sizeof(unsigned int));
      buffIndex += 4;
  
  #define LWM(map, key, value) sparseWriteFile(map)
  #include "lwmlist.h"
  
  // Compile Result members
  #define LWM(map, key, value) sparseWriteFileCR(map);
  #include "crlwmlist.h"
  
      // Write the end canary
      buff2[buffIndex++] = '4';
      buff2[buffIndex++] = '2';
  
      Assert(buffIndex == totalFileSize);
  
      WriteFile(hFile, buff2, totalFileSize, &bytesWritten, NULL);
      delete[] buff2;
      return bytesWritten;
  }
  
  // This code can't exist in a function with C++ objects needing destruction. Returns true on success
  // (and sets *ppmc with new MethodContext), false on failure.
  //
  // static
  bool MethodContext::Initialize(int loadedCount, unsigned char* buff, DWORD size, /* OUT */ MethodContext** ppmc)
  {
      MethodContext* mc = new MethodContext();
      mc->index         = loadedCount;
      *ppmc             = mc;
      return mc->Initialize(loadedCount, buff, size);
  }
  
  // static
  bool MethodContext::Initialize(int loadedCount, HANDLE hFile, /* OUT */ MethodContext** ppmc)
  {
      MethodContext* mc = new MethodContext();
      mc->index         = loadedCount;
      *ppmc             = mc;
      return mc->Initialize(loadedCount, hFile);
  }
  
  bool MethodContext::Initialize(int loadedCount, unsigned char* buff, DWORD size)
  {
      bool result = true;
  
      struct Param
      {
          unsigned char* buff;
          DWORD          size;
          MethodContext* pThis;
      } param;
      param.buff  = buff;
      param.size  = size;
      param.pThis = this;
  
      PAL_TRY(Param*, pParam, &param)
      {
          pParam->pThis->MethodInitHelper(pParam->buff, pParam->size);
      }
      PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CatchMC)
      {
          LogError("Method %d is of low integrity.", loadedCount);
          result = false;
      }
      PAL_ENDTRY
  
      return result;
  }
  
  bool MethodContext::Initialize(int loadedCount, HANDLE hFile)
  {
      bool result = true;
  
      struct Param
      {
          HANDLE         hFile;
          MethodContext* pThis;
      } param;
      param.hFile = hFile;
      param.pThis = this;
  
      PAL_TRY(Param*, pParam, &param)
      {
          pParam->pThis->MethodInitHelperFile(pParam->hFile);
      }
      PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CatchMC)
      {
          LogError("Method %d is of low integrity.", loadedCount);
          result = false;
      }
      PAL_ENDTRY
  
      return result;
  }
  
  void MethodContext::MethodInitHelperFile(HANDLE hFile)
  {
      DWORD        bytesRead;
      char         buff[512];
      unsigned int totalLen = 0;
  
      AssertCode(ReadFile(hFile, buff, 2 + sizeof(unsigned int), &bytesRead, NULL) == TRUE,
                 EXCEPTIONCODE_MC); // Read Magic number and totalLen
      AssertCodeMsg((buff[0] == 'm') && (buff[1] == 'c'), EXCEPTIONCODE_MC, "Didn't find magic number");
      memcpy(&totalLen, &buff[2], sizeof(unsigned int));
      unsigned char* buff2 = new unsigned char[totalLen + 2]; // total + End Canary
      AssertCode(ReadFile(hFile, buff2, totalLen + 2, &bytesRead, NULL) == TRUE, EXCEPTIONCODE_MC);
      AssertCodeMsg((buff2[totalLen] == '4') && (buff2[totalLen + 1] == '2'), EXCEPTIONCODE_MC, "Didn't find end canary");
      MethodInitHelper(buff2, totalLen);
  }
  
  void MethodContext::MethodInitHelper(unsigned char* buff2, unsigned int totalLen)
  {
      unsigned int   buffIndex = 0;
      unsigned int   localsize = 0;
      unsigned char  canary    = 0xff;
      unsigned char* buff3     = nullptr;
  
      while (buffIndex < totalLen)
      {
          mcPackets packetType = (mcPackets)buff2[buffIndex++];
          memcpy(&localsize, &buff2[buffIndex], sizeof(unsigned int));
          buffIndex += sizeof(unsigned int);
  
          switch (packetType)
          {
  #define LWM(map, key, value) sparseReadFile(map, key, value)
  #define DENSELWM(map, value) sparseReadFileDense(map, value)
  #include "lwmlist.h"
  
  #define LWM(map, key, value) sparseReadFileCR(map, key, value)
  #define DENSELWM(map, value) sparseReadFileCRDense(map, value)
  #include "crlwmlist.h"
  
              default:
                  LogException(EXCEPTIONCODE_MC, "Read ran into unknown packet type %u. Are you using a newer recorder?",
                               packetType);
                  // break;
          }
          buffIndex += localsize;
          canary = buff2[buffIndex++];
          AssertCodeMsg(canary == 0x42, EXCEPTIONCODE_MC, "Didn't find trailing canary for map");
      }
      AssertCodeMsg((buff2[buffIndex++] == '4') && (buff2[buffIndex++] == '2'), EXCEPTIONCODE_MC,
                    "Didn't find trailing canary for map");
      delete[] buff2;
  }
  
  #define dumpStat(target)                                                                                               \
      if (target != nullptr)                                                                                             \
      {                                                                                                                  \
          if (target->GetCount() > 0)                                                                                    \
          {                                                                                                              \
              int t = sprintf_s(buff, len, "%u", target->GetCount());                                                    \
              buff += t;                                                                                                 \
              len -= t;                                                                                                  \
          }                                                                                                              \
      }                                                                                                                  \
      {                                                                                                                  \
          *buff++ = ',';                                                                                                 \
          len--;                                                                                                         \
      }                                                                                                                  \
      if (target != nullptr)                                                                                             \
      {                                                                                                                  \
          int t = sprintf_s(buff, len, "%u", target->CalculateArraySize());                                              \
          buff += t;                                                                                                     \
          len -= t;                                                                                                      \
      }                                                                                                                  \
      {                                                                                                                  \
          *buff++ = ',';                                                                                                 \
          len--;                                                                                                         \
      }
  
  // Dump statistics about each LightWeightMap to the buffer: count of elements, and total size in bytes of map.
  int MethodContext::dumpStatToBuffer(char* buff, int len)
  {
      char* obuff = buff;
  // assumption of enough buffer.. :-|
  
  #define LWM(map, key, value) dumpStat(map)
  #include "lwmlist.h"
  
  // Compile Result members
  #define LWM(map, key, value) dumpStat(cr->map);
  #include "crlwmlist.h"
  
      return (int)(buff - obuff);
  }
  int MethodContext::dumpStatTitleToBuffer(char* buff, int len)
  {
      const char* title =
  
  #define LWM(map, key, value) #map "," #map " SZ,"
  #include "lwmlist.h"
  
  #define LWM(map, key, value) "CR_" #map ",CR_" #map " SZ,"
  #include "crlwmlist.h"
  
          ;
  
      int titleLen = (int)strlen(title);
      if ((titleLen + 1) > len)
      {
          LogError("titleLen is larger than given len");
          return 0;
      }
      strcpy_s(buff, len, title);
      return titleLen;
  }
  
  #define softMapEqual(a)                                                                                                \
      if (a != nullptr)                                                                                                  \
      {                                                                                                                  \
          if (other->a == nullptr)                                                                                       \
              return false;                                                                                              \
          if (a->GetCount() != other->a->GetCount())                                                                     \
              return false;                                                                                              \
      }                                                                                                                  \
      else if (other->a != nullptr)                                                                                      \
          return false;
  
  bool MethodContext::Equal(MethodContext* other)
  {
      // returns true if equal.  Note this is permissive, that is to say that we may reason that too many things are
      // equal. Adding more detailed checks would cause us to reason more things as unique;
  
      // Compare MethodInfo's first.
      CORINFO_METHOD_INFO otherInfo;
      unsigned            otherFlags = 0;
      other->repCompileMethod(&otherInfo, &otherFlags);
  
      CORINFO_METHOD_INFO ourInfo;
      unsigned            ourFlags = 0;
      repCompileMethod(&ourInfo, &ourFlags);
  
      if (otherInfo.ILCodeSize != ourInfo.ILCodeSize)
          return false;
      if (otherInfo.args.numArgs != ourInfo.args.numArgs)
          return false;
      if (otherInfo.args.retType != ourInfo.args.retType)
          return false;
      if (otherInfo.locals.numArgs != ourInfo.locals.numArgs)
          return false;
      if (otherInfo.EHcount != ourInfo.EHcount)
          return false;
      if (otherInfo.options != ourInfo.options)
          return false;
      for (unsigned int j = 0; j < otherInfo.ILCodeSize; j++)
          if (otherInfo.ILCode[j] != ourInfo.ILCode[j])
              return false;
      if (otherInfo.maxStack != ourInfo.maxStack)
          return false;
      if (otherInfo.regionKind != ourInfo.regionKind)
          return false;
      if (otherInfo.args.callConv != ourInfo.args.callConv)
          return false;
      if (otherInfo.args.cbSig != ourInfo.args.cbSig)
          return false;
      if (otherInfo.args.flags != ourInfo.args.flags)
          return false;
      if (otherInfo.locals.cbSig != ourInfo.locals.cbSig)
          return false;
      if (otherFlags != ourFlags)
          return false;
  
  // Now compare the other maps to "estimate" equality.
  
  #define LWM(map, key, value) softMapEqual(map)
  #include "lwmlist.h"
  
  // Compile Result members
  #define LWM(map, key, value) softMapEqual(cr->map)
  #include "crlwmlist.h"
  
      // Base case is we "match"
      return true;
  }
  
  //------------------------------------------------------------------------------
  // MethodContext::recGlobalContext
  //    This method copies any relevant global (i.e. per-JIT-instance) data from
  //    the given method context. Currently this is limited to configuration
  //    values, but may grow to encompass other information in the future (e.g.
  //    any information that is exposed by the ICorJitHost interface and is
  //    therefore accessible outside the context of a call to
  //    `ICJI::compileMethod`).
  //
  //    This method is intended to be called as part of initializing a method
  //    during collection.
  void MethodContext::recGlobalContext(const MethodContext& other)
  {
      Assert(GetIntConfigValue == nullptr);
      Assert(GetStringConfigValue == nullptr);
  
      if (other.GetIntConfigValue != nullptr)
      {
          GetIntConfigValue = new LightWeightMap<Agnostic_ConfigIntInfo, DWORD>(*other.GetIntConfigValue);
      }
  
      if (other.GetStringConfigValue != nullptr)
      {
          GetStringConfigValue = new LightWeightMap<DWORD, DWORD>(*other.GetStringConfigValue);
      }
  }
  
  void MethodContext::dumpToConsole(int mcNumber)
  {
      printf("*****************************************");
      if (mcNumber != -1)
      {
          printf(" method context #%d", mcNumber);
      }
  
      // Dump method name, etc., to output.
      char bufferIdentityInfo[METHOD_IDENTITY_INFO_SIZE];
      int cbLen = dumpMethodIdentityInfoToBuffer(bufferIdentityInfo, METHOD_IDENTITY_INFO_SIZE);
      if (cbLen >= 0)
      {
          printf(" %s", bufferIdentityInfo);
      }
  
      printf("\n");
  
  #define LWM(map, key, value) dumpLWM(this, map)
  #define DENSELWM(map, value) dumpLWMDense(this, map)
  #include "lwmlist.h"
  
  // Compile Result members
  #define LWM(map, key, value) dumpLWM(this->cr, map)
  #define DENSELWM(map, value) dumpLWMDense(this->cr, map)
  #include "crlwmlist.h"
  }
  
  const char* toString(CorInfoType cit)
  {
      switch (cit)
      {
          case CORINFO_TYPE_UNDEF:
              return "undef";
          case CORINFO_TYPE_VOID:
              return "void";
          case CORINFO_TYPE_BOOL:
              return "bool";
          case CORINFO_TYPE_CHAR:
              return "char";
          case CORINFO_TYPE_BYTE:
              return "byte";
          case CORINFO_TYPE_UBYTE:
              return "ubyte";
          case CORINFO_TYPE_SHORT:
              return "short";
          case CORINFO_TYPE_USHORT:
              return "ushort";
          case CORINFO_TYPE_INT:
              return "int";
          case CORINFO_TYPE_UINT:
              return "uint";
          case CORINFO_TYPE_LONG:
              return "long";
          case CORINFO_TYPE_ULONG:
              return "ulong";
          case CORINFO_TYPE_NATIVEINT:
              return "nativeint";
          case CORINFO_TYPE_NATIVEUINT:
              return "nativeuint";
          case CORINFO_TYPE_FLOAT:
              return "float";
          case CORINFO_TYPE_DOUBLE:
              return "double";
          case CORINFO_TYPE_STRING:
              return "string";
          case CORINFO_TYPE_PTR:
              return "ptr";
          case CORINFO_TYPE_BYREF:
              return "byref";
          case CORINFO_TYPE_VALUECLASS:
              return "valueclass";
          case CORINFO_TYPE_CLASS:
              return "class";
          case CORINFO_TYPE_REFANY:
              return "refany";
          case CORINFO_TYPE_VAR:
              return "var";
          default:
              return "UNKNOWN";
      }
  }
  
  unsigned int toCorInfoSize(CorInfoType cit)
  {
      switch (cit)
      {
          case CORINFO_TYPE_BOOL:
          case CORINFO_TYPE_BYTE:
          case CORINFO_TYPE_UBYTE:
              return 1;
  
          case CORINFO_TYPE_CHAR:
          case CORINFO_TYPE_SHORT:
          case CORINFO_TYPE_USHORT:
              return 2;
  
          case CORINFO_TYPE_FLOAT:
          case CORINFO_TYPE_INT:
          case CORINFO_TYPE_UINT:
              return 4;
  
          case CORINFO_TYPE_DOUBLE:
          case CORINFO_TYPE_LONG:
          case CORINFO_TYPE_ULONG:
              return 8;
  
          case CORINFO_TYPE_NATIVEINT:
          case CORINFO_TYPE_NATIVEUINT:
          case CORINFO_TYPE_PTR:
          case CORINFO_TYPE_BYREF:
          case CORINFO_TYPE_CLASS:
              return sizeof(void*);
  
          case CORINFO_TYPE_STRING:
          case CORINFO_TYPE_VALUECLASS:
          case CORINFO_TYPE_REFANY:
          case CORINFO_TYPE_UNDEF:
          case CORINFO_TYPE_VOID:
          default:
              __debugbreak();
              return 0;
      }
      return -1;
  }
  
  void MethodContext::recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags)
  {
      if (CompileMethod == nullptr)
          CompileMethod = new LightWeightMap<DWORD, Agnostic_CompileMethod>();
  
      Agnostic_CompileMethod value;
  
      value.info.ftn                         = (DWORDLONG)info->ftn;
      value.info.scope                       = (DWORDLONG)info->scope;
      value.info.ILCode_offset               = (DWORD)CompileMethod->AddBuffer(info->ILCode, info->ILCodeSize);
      value.info.ILCodeSize                  = (DWORD)info->ILCodeSize;
      value.info.maxStack                    = (DWORD)info->maxStack;
      value.info.EHcount                     = (DWORD)info->EHcount;
      value.info.options                     = (DWORD)info->options;
      value.info.regionKind                  = (DWORD)info->regionKind;
      value.info.args.callConv               = (DWORD)info->args.callConv;
      value.info.args.retTypeClass           = (DWORDLONG)info->args.retTypeClass;
      value.info.args.retTypeSigClass        = (DWORDLONG)info->args.retTypeSigClass;
      value.info.args.retType                = (DWORD)info->args.retType;
      value.info.args.flags                  = (DWORD)info->args.flags;
      value.info.args.numArgs                = (DWORD)info->args.numArgs;
      value.info.args.sigInst_classInstCount = (DWORD)info->args.sigInst.classInstCount;
      value.info.args.sigInst_classInst_Index =
          CompileMethod->AddBuffer((unsigned char*)info->args.sigInst.classInst,
                                   info->args.sigInst.classInstCount * 8); // porting issue
      value.info.args.sigInst_methInstCount = (DWORD)info->args.sigInst.methInstCount;
      value.info.args.sigInst_methInst_Index =
          CompileMethod->AddBuffer((unsigned char*)info->args.sigInst.methInst,
                                   info->args.sigInst.methInstCount * 8); // porting issue
      value.info.args.args           = (DWORDLONG)info->args.args;
      value.info.args.cbSig          = (DWORD)info->args.cbSig;
      value.info.args.pSig_Index     = (DWORD)CompileMethod->AddBuffer((unsigned char*)info->args.pSig, info->args.cbSig);
      value.info.args.scope          = (DWORDLONG)info->args.scope;
      value.info.args.token          = (DWORD)info->args.token;
      value.info.locals.callConv     = (DWORD)info->locals.callConv;
      value.info.locals.retTypeClass = (DWORDLONG)info->locals.retTypeClass;
      value.info.locals.retTypeSigClass        = (DWORDLONG)info->locals.retTypeSigClass;
      value.info.locals.retType                = (DWORD)info->locals.retType;
      value.info.locals.flags                  = (DWORD)info->locals.flags;
      value.info.locals.numArgs                = (DWORD)info->locals.numArgs;
      value.info.locals.sigInst_classInstCount = (DWORD)info->locals.sigInst.classInstCount;
      value.info.locals.sigInst_classInst_Index =
          CompileMethod->AddBuffer((unsigned char*)info->locals.sigInst.classInst,
                                   info->locals.sigInst.classInstCount * 8); // porting issue
      value.info.locals.sigInst_methInstCount = (DWORD)info->locals.sigInst.methInstCount;
      value.info.locals.sigInst_methInst_Index =
          CompileMethod->AddBuffer((unsigned char*)info->locals.sigInst.methInst,
                                   info->locals.sigInst.methInstCount * 8); // porting issue
      value.info.locals.args  = (DWORDLONG)info->locals.args;
      value.info.locals.cbSig = (DWORD)info->locals.cbSig;
      value.info.locals.pSig_Index =
          (DWORD)CompileMethod->AddBuffer((unsigned char*)info->locals.pSig, info->locals.cbSig);
      value.info.locals.scope = (DWORDLONG)info->locals.scope;
      value.info.locals.token = (DWORD)info->locals.token;
      value.flags             = (DWORD)flags;
  
      CompileMethod->Add(0, value);
      DEBUG_REC(dmpCompileMethod(0, value));
  }
  void MethodContext::dmpCompileMethod(DWORD key, const Agnostic_CompileMethod& value)
  {
      printf("CompiledMethod key %u, value ftn-%016llX scp-%016llX ilo-%u ils-%u ms-%u ehc-%u opt-%u rk-%u "
             "args{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u "
             "pSig_Index-%u scp-%016llX tok-%08X} "
             "locals{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u "
             "pSig_Index-%u scp-%016llX tok-%08X} "
             "flg-%08X",
             key, value.info.ftn, value.info.scope, value.info.ILCode_offset, value.info.ILCodeSize, value.info.maxStack,
             value.info.EHcount, value.info.options, value.info.regionKind, value.info.args.callConv,
             value.info.args.retTypeClass, value.info.args.retTypeSigClass, value.info.args.retType,
             toString((CorInfoType)value.info.args.retType), value.info.args.flags, value.info.args.numArgs,
             value.info.args.sigInst_classInstCount, value.info.args.sigInst_classInst_Index,
             value.info.args.sigInst_methInstCount, value.info.args.sigInst_methInst_Index, value.info.args.args,
             value.info.args.cbSig, value.info.args.pSig_Index, value.info.args.scope, value.info.args.token,
             value.info.locals.callConv, value.info.locals.retTypeClass, value.info.locals.retTypeSigClass,
             value.info.locals.retType, toString((CorInfoType)value.info.locals.retType), value.info.locals.flags,
             value.info.locals.numArgs, value.info.locals.sigInst_classInstCount,
             value.info.locals.sigInst_classInst_Index, value.info.locals.sigInst_methInstCount,
             value.info.locals.sigInst_methInst_Index, value.info.locals.args, value.info.locals.cbSig,
             value.info.locals.pSig_Index, value.info.locals.scope, value.info.locals.token, value.flags);
  }
  void MethodContext::repCompileMethod(CORINFO_METHOD_INFO* info, unsigned* flags)
  {
      Agnostic_CompileMethod value;
  
      value = CompileMethod->Get((DWORD)0); // The only item in this set is a single group of inputs to CompileMethod
  
      info->ftn                         = (CORINFO_METHOD_HANDLE)value.info.ftn;
      info->scope                       = (CORINFO_MODULE_HANDLE)value.info.scope;
      info->ILCode                      = CompileMethod->GetBuffer(value.info.ILCode_offset);
      info->ILCodeSize                  = (unsigned)value.info.ILCodeSize;
      methodSize                        = info->ILCodeSize;
      info->maxStack                    = (unsigned)value.info.maxStack;
      info->EHcount                     = (unsigned)value.info.EHcount;
      info->options                     = (CorInfoOptions)value.info.options;
      info->regionKind                  = (CorInfoRegionKind)value.info.regionKind;
      info->args.callConv               = (CorInfoCallConv)value.info.args.callConv;
      info->args.retTypeClass           = (CORINFO_CLASS_HANDLE)value.info.args.retTypeClass;
      info->args.retTypeSigClass        = (CORINFO_CLASS_HANDLE)value.info.args.retTypeSigClass;
      info->args.retType                = (CorInfoType)value.info.args.retType;
      info->args.flags                  = (unsigned)value.info.args.flags;
      info->args.numArgs                = (unsigned)value.info.args.numArgs;
      info->args.sigInst.classInstCount = (unsigned)value.info.args.sigInst_classInstCount;
      info->args.sigInst.classInst =
          (CORINFO_CLASS_HANDLE*)CompileMethod->GetBuffer(value.info.args.sigInst_classInst_Index);
      info->args.sigInst.methInstCount = (unsigned)value.info.args.sigInst_methInstCount;
      info->args.sigInst.methInst =
          (CORINFO_CLASS_HANDLE*)CompileMethod->GetBuffer(value.info.args.sigInst_methInst_Index);
      info->args.args                     = (CORINFO_ARG_LIST_HANDLE)value.info.args.args;
      info->args.cbSig                    = (unsigned int)value.info.args.cbSig;
      info->args.pSig                     = (PCCOR_SIGNATURE)CompileMethod->GetBuffer(value.info.args.pSig_Index);
      info->args.scope                    = (CORINFO_MODULE_HANDLE)value.info.args.scope;
      info->args.token                    = (mdToken)value.info.args.token;
      info->locals.callConv               = (CorInfoCallConv)value.info.locals.callConv;
      info->locals.retTypeClass           = (CORINFO_CLASS_HANDLE)value.info.locals.retTypeClass;
      info->locals.retTypeSigClass        = (CORINFO_CLASS_HANDLE)value.info.locals.retTypeSigClass;
      info->locals.retType                = (CorInfoType)value.info.locals.retType;
      info->locals.flags                  = (unsigned)value.info.locals.flags;
      info->locals.numArgs                = (unsigned)value.info.locals.numArgs;
      info->locals.sigInst.classInstCount = (unsigned)value.info.locals.sigInst_classInstCount;
      info->locals.sigInst.classInst =
          (CORINFO_CLASS_HANDLE*)CompileMethod->GetBuffer(value.info.locals.sigInst_classInst_Index);
      info->locals.sigInst.methInstCount = (unsigned)value.info.locals.sigInst_methInstCount;
      info->locals.sigInst.methInst =
          (CORINFO_CLASS_HANDLE*)CompileMethod->GetBuffer(value.info.locals.sigInst_methInst_Index);
      info->locals.args  = (CORINFO_ARG_LIST_HANDLE)value.info.locals.args;
      info->locals.cbSig = (unsigned int)value.info.locals.cbSig;
      info->locals.pSig  = (PCCOR_SIGNATURE)CompileMethod->GetBuffer(value.info.locals.pSig_Index);
      info->locals.scope = (CORINFO_MODULE_HANDLE)value.info.locals.scope;
      info->locals.token = (mdToken)value.info.locals.token;
  
      *flags             = (unsigned)value.flags;
      DEBUG_REP(dmpCompileMethod(0, value));
  }
  
  void MethodContext::recGetMethodClass(CORINFO_METHOD_HANDLE methodHandle, CORINFO_CLASS_HANDLE classHandle)
  {
      if (GetMethodClass == nullptr)
          GetMethodClass = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      GetMethodClass->Add((DWORDLONG)methodHandle, (DWORDLONG)classHandle);
      DEBUG_REC(dmpGetMethodClass((DWORDLONG)methodHandle, (DWORDLONG)classHandle));
  }
  void MethodContext::dmpGetMethodClass(DWORDLONG key, DWORDLONG value)
  {
      printf("GetMethodClass key %016llX, value %016llX", key, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetMethodClass(CORINFO_METHOD_HANDLE methodHandle)
  {
      AssertCodeMsg(GetMethodClass != nullptr, EXCEPTIONCODE_MC,
                    "Found a null GetMethodClass.  Probably missing a fatTrigger for %016llX.", (DWORDLONG)methodHandle);
      int index = GetMethodClass->GetIndex((DWORDLONG)methodHandle);
      AssertCodeMsg(index != -1, EXCEPTIONCODE_MC, "Didn't find %016llX.  Probably missing a fatTrigger",
                    (DWORDLONG)methodHandle);
      CORINFO_CLASS_HANDLE value = (CORINFO_CLASS_HANDLE)GetMethodClass->Get((DWORDLONG)methodHandle);
      DEBUG_REP(dmpGetMethodClass((DWORDLONG)methodHandle, (DWORDLONG)value));
      return value;
  }
  
  void MethodContext::recGetClassAttribs(CORINFO_CLASS_HANDLE classHandle, DWORD attribs)
  {
      if (GetClassAttribs == nullptr)
          GetClassAttribs = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetClassAttribs->Add((DWORDLONG)classHandle, (DWORD)attribs);
      DEBUG_REC(dmpGetClassAttribs((DWORDLONG)classHandle, attribs));
  }
  void MethodContext::dmpGetClassAttribs(DWORDLONG key, DWORD value)
  {
      printf("GetClassAttribs key %016llX, value %08X (%s)", key, value, SpmiDumpHelper::DumpCorInfoFlag((CorInfoFlag)value).c_str());
  }
  DWORD MethodContext::repGetClassAttribs(CORINFO_CLASS_HANDLE classHandle)
  {
      AssertCodeMsg(GetClassAttribs != nullptr, EXCEPTIONCODE_MC,
                    "Found a null GetMethodClass.  Probably missing a fatTrigger for %016llX.", (DWORDLONG)classHandle);
      int index = GetClassAttribs->GetIndex((DWORDLONG)classHandle);
      AssertCodeMsg(index != -1, EXCEPTIONCODE_MC, "Didn't find %016llX.  Probably missing a fatTrigger",
                    (DWORDLONG)classHandle);
      DWORD value = (DWORD)GetClassAttribs->Get((DWORDLONG)classHandle);
      DEBUG_REP(dmpGetClassAttribs((DWORDLONG)classHandle, value));
      return value;
  }
  
  void MethodContext::recGetMethodAttribs(CORINFO_METHOD_HANDLE methodHandle, DWORD attribs)
  {
      if (GetMethodAttribs == nullptr)
          GetMethodAttribs = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetMethodAttribs->Add((DWORDLONG)methodHandle, attribs);
      DEBUG_REC(dmpGetMethodAttribs((DWORDLONG)methodHandle, attribs));
  }
  void MethodContext::dmpGetMethodAttribs(DWORDLONG key, DWORD value)
  {
      printf("GetMethodAttribs key %016llX, value %08X (%s)", key, value, SpmiDumpHelper::DumpCorInfoFlag((CorInfoFlag)value).c_str());
  }
  DWORD MethodContext::repGetMethodAttribs(CORINFO_METHOD_HANDLE methodHandle)
  {
      AssertCodeMsg(GetMethodAttribs != nullptr, EXCEPTIONCODE_MC,
                    "Found a null GetMethodAttribs.  Probably missing a fatTrigger for %016llX.",
                    (DWORDLONG)methodHandle);
      int index = GetMethodAttribs->GetIndex((DWORDLONG)methodHandle);
      AssertCodeMsg(index != -1, EXCEPTIONCODE_MC, "Didn't find %016llX.  Probably missing a fatTrigger",
                    (DWORDLONG)methodHandle);
      DWORD value = (DWORD)GetMethodAttribs->Get((DWORDLONG)methodHandle);
      DEBUG_REP(dmpGetMethodAttribs((DWORDLONG)methodHandle, value));
      if (cr->repSetMethodAttribs(methodHandle) == CORINFO_FLG_BAD_INLINEE)
          value ^= CORINFO_FLG_DONT_INLINE;
      return value;
  }
  
  // Note - the jit will call freearray on the array we give back....
  void MethodContext::recGetVars(CORINFO_METHOD_HANDLE      ftn,
                                 ULONG32*                   cVars,
                                 ICorDebugInfo::ILVarInfo** vars_in,
                                 bool*                      extendOthers)
  {
      if (GetVars == nullptr)
          GetVars = new LightWeightMap<DWORDLONG, Agnostic_GetVars>();
  
      Agnostic_GetVars value;
  
      value.cVars = (DWORD)*cVars;
      value.vars_offset =
          (DWORD)GetVars->AddBuffer((unsigned char*)*vars_in, sizeof(ICorDebugInfo::ILVarInfo) * (*cVars));
  
      value.extendOthers = (DWORD)*extendOthers;
      GetVars->Add((DWORDLONG)ftn, value);
      DEBUG_REC(dmpGetVars((DWORDLONG)ftn, value));
  }
  void MethodContext::dmpGetVars(DWORDLONG key, const Agnostic_GetVars& value)
  {
      ICorDebugInfo::ILVarInfo* vars = (ICorDebugInfo::ILVarInfo*)GetVars->GetBuffer(value.vars_offset);
      printf("GetVars key ftn-%016llX, value cVars-%u extendOthers-%u (", key, value.cVars, value.extendOthers);
      for (unsigned int i = 0; i < value.cVars; i++)
          printf("(%u %u %u %u)", i, vars[i].startOffset, vars[i].endOffset, vars[i].varNumber);
      printf(")");
      GetVars->Unlock();
  }
  void MethodContext::repGetVars(CORINFO_METHOD_HANDLE      ftn,
                                 ULONG32*                   cVars,
                                 ICorDebugInfo::ILVarInfo** vars_in,
                                 bool*                      extendOthers)
  {
      Agnostic_GetVars value;
      if (GetVars == nullptr)
      {
          *cVars = 0;
          return;
      }
      value  = GetVars->Get((DWORDLONG)ftn);
      *cVars = (ULONG32)value.cVars;
      if (*cVars > 0)
          *vars_in  = (ICorDebugInfo::ILVarInfo*)GetVars->GetBuffer(value.vars_offset);
      *extendOthers = value.extendOthers != 0;
      DEBUG_REP(dmpGetVars((DWORDLONG)ftn, value));
  }
  
  // Note - the jit will call freearray on the array we give back....
  void MethodContext::recGetBoundaries(CORINFO_METHOD_HANDLE         ftn,
                                       unsigned int*                 cILOffsets,
                                       DWORD**                       pILOffsets,
                                       ICorDebugInfo::BoundaryTypes* implictBoundaries)
  {
      if (GetBoundaries == nullptr)
          GetBoundaries = new LightWeightMap<DWORDLONG, Agnostic_GetBoundaries>();
  
      Agnostic_GetBoundaries value;
  
      value.cILOffsets = (DWORD)*cILOffsets;
      value.pILOffset_offset =
          (DWORD)GetBoundaries->AddBuffer((unsigned char*)*pILOffsets, sizeof(DWORD) * (*cILOffsets));
      value.implicitBoundaries = *implictBoundaries;
  
      GetBoundaries->Add((DWORDLONG)ftn, value);
      DEBUG_REC(dmpGetBoundaries((DWORDLONG)ftn, value));
  }
  void MethodContext::dmpGetBoundaries(DWORDLONG key, const Agnostic_GetBoundaries& value)
  {
      printf("GetBoundaries key ftn-%016llX, value cnt-%u imp-%u{", key, value.cILOffsets, value.implicitBoundaries);
      DWORD* bnd = (DWORD*)GetBoundaries->GetBuffer(value.pILOffset_offset);
      for (unsigned int i = 0; i < value.cILOffsets; i++)
      {
          printf("%u", bnd[i]);
          if (i < (value.cILOffsets + 1))
              printf(",");
      }
      GetBoundaries->Unlock();
      printf("}");
  }
  void MethodContext::repGetBoundaries(CORINFO_METHOD_HANDLE         ftn,
                                       unsigned int*                 cILOffsets,
                                       DWORD**                       pILOffsets,
                                       ICorDebugInfo::BoundaryTypes* implictBoundaries)
  {
      Agnostic_GetBoundaries value;
  
      value = GetBoundaries->Get((DWORDLONG)ftn);
  
      *cILOffsets = (unsigned int)value.cILOffsets;
      if (*cILOffsets > 0)
          *pILOffsets    = (DWORD*)GetBoundaries->GetBuffer(value.pILOffset_offset);
      *implictBoundaries = (ICorDebugInfo::BoundaryTypes)value.implicitBoundaries;
  
      DEBUG_REP(dmpGetBoundaries((DWORDLONG)ftn, value));
  }
  
  void MethodContext::recInitClass(CORINFO_FIELD_HANDLE   field,
                                   CORINFO_METHOD_HANDLE  method,
                                   CORINFO_CONTEXT_HANDLE context,
                                   CorInfoInitClassResult result)
  {
      if (InitClass == nullptr)
          InitClass = new LightWeightMap<Agnostic_InitClass, DWORD>();
  
      Agnostic_InitClass key;
      ZeroMemory(&key, sizeof(Agnostic_InitClass)); // We use the input structs as a key and use memcmp to compare.. so we
                                                    // need to zero out padding too
      key.field       = (DWORDLONG)field;
      key.method      = (DWORDLONG)method;
      key.context     = (DWORDLONG)context;
  
      InitClass->Add(key, (DWORD)result);
      DEBUG_REC(dmpInitClass(key, (DWORD)result));
  }
  void MethodContext::dmpInitClass(const Agnostic_InitClass& key, DWORD value)
  {
      printf("InitClass key fld-%016llX meth-%016llX con-%016llX, value res-%u", key.field, key.method,
             key.context, value);
  }
  CorInfoInitClassResult MethodContext::repInitClass(CORINFO_FIELD_HANDLE   field,
                                                     CORINFO_METHOD_HANDLE  method,
                                                     CORINFO_CONTEXT_HANDLE context)
  {
      Agnostic_InitClass key;
      ZeroMemory(&key, sizeof(Agnostic_InitClass)); // We use the input structs as a key and use memcmp to compare.. so we
                                                    // need to zero out padding too
  
      key.field       = (DWORDLONG)field;
      key.method      = (DWORDLONG)method;
      key.context     = (DWORDLONG)context;
  
      AssertCodeMsg(InitClass != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)key.method);
      AssertCodeMsg(InitClass->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)key.method);
      CorInfoInitClassResult result = (CorInfoInitClassResult)InitClass->Get(key);
  
      DEBUG_REP(dmpInitClass(key, result));
      return result;
  }
  
  void MethodContext::recGetMethodName(CORINFO_METHOD_HANDLE ftn, char* methodname, const char** moduleName)
  {
      if (GetMethodName == nullptr)
          GetMethodName = new LightWeightMap<DLD, DD>();
      DD  value;
      DLD key;
      key.A = (DWORDLONG)ftn;
      key.B = (moduleName != nullptr);
  
      if (methodname != nullptr)
          value.A = GetMethodName->AddBuffer((unsigned char*)methodname, (DWORD)strlen(methodname) + 1);
      else
          value.A = (DWORD)-1;
  
      if ((moduleName != nullptr) && (*moduleName != nullptr))
          value.B = GetMethodName->AddBuffer((unsigned char*)*moduleName, (DWORD)strlen(*moduleName) + 1);
      else
          value.B = (DWORD)-1;
  
      GetMethodName->Add(key, value);
      DEBUG_REC(dmpGetMethodName(key, value));
  }
  void MethodContext::dmpGetMethodName(DLD key, DD value)
  {
      unsigned char* methodName = (unsigned char*)GetMethodName->GetBuffer(value.A);
      unsigned char* moduleName = (unsigned char*)GetMethodName->GetBuffer(value.B);
      printf("GetMethodName key - ftn-%016llX modNonNull-%u, value meth-'%s', mod-'%s'", key.A, key.B, methodName,
             moduleName);
      GetMethodName->Unlock();
  }
  
  const char* MethodContext::repGetMethodName(CORINFO_METHOD_HANDLE ftn, const char** moduleName)
  {
      const char* result = "hackishMethodName";
      DD          value;
      DLD         key;
      key.A = (DWORDLONG)ftn;
      key.B = (moduleName != nullptr);
  
      int itemIndex = -1;
      if (GetMethodName != nullptr)
          itemIndex = GetMethodName->GetIndex(key);
      if (itemIndex < 0)
      {
          if (moduleName != nullptr)
              *moduleName = "hackishModuleName";
      }
      else
      {
          value = GetMethodName->Get(key);
          if (moduleName != nullptr)
              *moduleName = (const char*)GetMethodName->GetBuffer(value.B);
          result          = (const char*)GetMethodName->GetBuffer(value.A);
      }
      DEBUG_REP(dmpGetMethodName(key, value));
      return result;
  }
  
  void MethodContext::recGetMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn,
                                                   char*                 methodName,
                                                   const char**          className,
                                                   const char**          namespaceName,
                                                   const char**          enclosingClassName)
  {
      if (GetMethodNameFromMetadata == nullptr)
          GetMethodNameFromMetadata = new LightWeightMap<Agnostic_CORINFO_METHODNAME_TOKENin, Agnostic_CORINFO_METHODNAME_TOKENout>();
      Agnostic_CORINFO_METHODNAME_TOKENout  value;
      Agnostic_CORINFO_METHODNAME_TOKENin key;
      key.ftn = (DWORDLONG)ftn;
      key.className = (className != nullptr);
      key.namespaceName = (namespaceName != nullptr);
      key.enclosingClassName = (enclosingClassName != nullptr);
  
      if (methodName != nullptr)
          value.methodName = GetMethodNameFromMetadata->AddBuffer((unsigned char*)methodName, (DWORD)strlen(methodName) + 1);
      else
          value.methodName = (DWORD)-1;
  
      if ((className != nullptr) && (*className != nullptr))
          value.className = GetMethodNameFromMetadata->AddBuffer((unsigned char*)*className, (DWORD)strlen(*className) + 1);
      else
          value.className = (DWORD)-1;
  
      if ((namespaceName != nullptr) && (*namespaceName != nullptr))
          value.namespaceName =
              GetMethodNameFromMetadata->AddBuffer((unsigned char*)*namespaceName, (DWORD)strlen(*namespaceName) + 1);
      else
          value.namespaceName = (DWORD)-1;
  
      if ((enclosingClassName != nullptr) && (*enclosingClassName != nullptr))
          value.enclosingClassName =
              GetMethodNameFromMetadata->AddBuffer((unsigned char*)*enclosingClassName, (DWORD)strlen(*enclosingClassName) + 1);
      else
          value.enclosingClassName = (DWORD)-1;
  
      GetMethodNameFromMetadata->Add(key, value);
      DEBUG_REC(dmpGetMethodNameFromMetadata(key, value));
  }
  
  void MethodContext::dmpGetMethodNameFromMetadata(Agnostic_CORINFO_METHODNAME_TOKENin key, Agnostic_CORINFO_METHODNAME_TOKENout value)
  {
      unsigned char* methodName    = (unsigned char*)GetMethodNameFromMetadata->GetBuffer(value.methodName);
      unsigned char* className     = (unsigned char*)GetMethodNameFromMetadata->GetBuffer(value.className);
      unsigned char* namespaceName = (unsigned char*)GetMethodNameFromMetadata->GetBuffer(value.namespaceName);
      unsigned char* enclosingClassName = (unsigned char*)GetMethodNameFromMetadata->GetBuffer(value.enclosingClassName);
      printf("GetMethodNameFromMetadata key - ftn-%016llX classNonNull-%u namespaceNonNull-%u enclosingClassNonNull-%u, value meth-'%s', "
             "class-'%s', namespace-'%s' enclosingClass-'%s'",
             key.ftn, key.className, key.namespaceName, key.enclosingClassName, methodName, className, namespaceName, enclosingClassName);
      GetMethodNameFromMetadata->Unlock();
  }
  
  const char* MethodContext::repGetMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn,
                                                          const char**          moduleName,
                                                          const char**          namespaceName,
                                                          const char**          enclosingClassName)
  {
      const char* result = nullptr;
      Agnostic_CORINFO_METHODNAME_TOKENout value;
      Agnostic_CORINFO_METHODNAME_TOKENin key;
      key.ftn = (DWORDLONG)ftn;
      key.className = (moduleName != nullptr);
      key.namespaceName = (namespaceName != nullptr);
      key.enclosingClassName = (enclosingClassName != nullptr);
  
      int itemIndex = -1;
      if (GetMethodNameFromMetadata != nullptr)
          itemIndex = GetMethodNameFromMetadata->GetIndex(key);
      if (itemIndex < 0)
      {
          if (moduleName != nullptr)
          {
              *moduleName = nullptr;
          }
      }
      else
      {
          value  = GetMethodNameFromMetadata->Get(key);
          result = (const char*)GetMethodNameFromMetadata->GetBuffer(value.methodName);
  
          if (moduleName != nullptr)
          {
              *moduleName = (const char*)GetMethodNameFromMetadata->GetBuffer(value.className);
          }
  
          if (namespaceName != nullptr)
          {
              *namespaceName = (const char*)GetMethodNameFromMetadata->GetBuffer(value.namespaceName);
          }
  
          if (enclosingClassName != nullptr)
          {
              *enclosingClassName = (const char*)GetMethodNameFromMetadata->GetBuffer(value.enclosingClassName);
          }
      }
      DEBUG_REP(dmpGetMethodNameFromMetadata(key, value));
      return result;
  }
  
  void MethodContext::recGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes, DWORD result)
  {
      if (GetJitFlags == nullptr)
          GetJitFlags = new LightWeightMap<DWORD, DD>();
  
      DD value;
      value.A = (DWORD)GetJitFlags->AddBuffer((unsigned char*)jitFlags, sizeInBytes);
      value.B = result;
  
      // NOTE: getJitFlags() is expected to be idempotent per method, so the mapping key is always
      //       zero.
      GetJitFlags->Add((DWORD)0, value);
      DEBUG_REC(dmpGetJitFlags((DWORD)0, value));
  }
  void MethodContext::dmpGetJitFlags(DWORD key, DD value)
  {
      CORJIT_FLAGS* jitflags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A);
      printf("GetJitFlags key %u sizeInBytes-%u jitFlags-%016llX instructionSetFlags-%016llX", key, value.B, jitflags->GetFlagsRaw(), jitflags->GetInstructionSetFlagsRaw());
      GetJitFlags->Unlock();
  }
  DWORD MethodContext::repGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
  {
      DD            value       = GetJitFlags->Get((DWORD)0);
      CORJIT_FLAGS* resultFlags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A);
      memcpy(jitFlags, resultFlags, value.B);
      DEBUG_REP(dmpGetJitFlags((DWORD)0, value));
      return value.B;
  }
  
  void MethodContext::recGetJitTimeLogFilename(LPCWSTR tempFileName)
  {
      if (GetJitTimeLogFilename == nullptr)
          GetJitTimeLogFilename = new LightWeightMap<DWORD, DWORD>();
  
      DWORD name_index = -1;
      if (tempFileName != nullptr)
      {
          name_index =
              (DWORD)GetJitTimeLogFilename->AddBuffer((unsigned char*)tempFileName, (DWORD)wcslen(tempFileName) + 2);
      }
      GetJitTimeLogFilename->Add((DWORD)0, name_index);
      DEBUG_REC(dmpGetJitTimeLogFilename((DWORD)0, name_index));
  }
  void MethodContext::dmpGetJitTimeLogFilename(DWORD key, DWORD value)
  {
      unsigned char* fileName = nullptr;
      if (value != 0)
          fileName = (unsigned char*)GetJitTimeLogFilename->GetBuffer(value);
      printf("GetJitTimeLogFilename key %u, value '%s'", key, fileName);
      GetJitTimeLogFilename->Unlock();
  }
  LPCWSTR MethodContext::repGetJitTimeLogFilename()
  {
      DWORD   offset = GetJitTimeLogFilename->Get((DWORD)0);
      LPCWSTR value  = nullptr;
      if (offset != 0)
          value = (LPCWSTR)GetJitTimeLogFilename->GetBuffer(offset);
      DEBUG_REP(dmpGetJitTimeLogFilename((DWORD)0, offset));
      return value;
  }
  
  void MethodContext::recCanInline(CORINFO_METHOD_HANDLE callerHnd,
                                   CORINFO_METHOD_HANDLE calleeHnd,
                                   DWORD*                pRestrictions,
                                   CorInfoInline         response,
                                   DWORD                 exceptionCode)
  {
      if (CanInline == nullptr)
          CanInline = new LightWeightMap<DLDL, Agnostic_CanInline>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      Agnostic_CanInline value;
  
      key.A = (DWORDLONG)callerHnd;
      key.B = (DWORDLONG)calleeHnd;
  
      if (pRestrictions != nullptr)
          value.Restrictions = (DWORD)*pRestrictions;
      else
          value.Restrictions = (DWORD)0;
      value.result           = (DWORD)response;
      value.exceptionCode    = (DWORD)exceptionCode;
  
      CanInline->Add(key, value);
      DEBUG_REC(dmpCanInline(key, value));
  }
  void MethodContext::dmpCanInline(DLDL key, const Agnostic_CanInline& value)
  {
      printf("CanInline key - callerHnd-%016llX calleeHnd-%016llX, value pRestrictions-%u result-%u exceptionCode-%08X",
             key.A, key.B, value.Restrictions, value.result, value.exceptionCode);
  }
  CorInfoInline MethodContext::repCanInline(CORINFO_METHOD_HANDLE callerHnd,
                                            CORINFO_METHOD_HANDLE calleeHnd,
                                            DWORD*                pRestrictions,
                                            DWORD*                exceptionCode)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      Agnostic_CanInline value;
  
      key.A = (DWORDLONG)callerHnd;
      key.B = (DWORDLONG)calleeHnd;
  
      if ((CanInline == nullptr) || (CanInline->GetIndex(key) == -1))
      {
  #ifdef sparseMC
          LogDebug("Sparse - repCanInline saying INLINE_FAIL");
          return INLINE_FAIL; // if we have no info, its pretty safe to say we can't inline it.
  #else
          LogException(EXCEPTIONCODE_MC, "Didn't find %016llx, %016llx.  probably a missing exception in canInline",
                       key.A, key.B);
  #endif
      }
  
      value = CanInline->Get(key);
  
      *exceptionCode = value.exceptionCode;
  
      if (pRestrictions != nullptr)
          *pRestrictions     = (DWORD)value.Restrictions;
      CorInfoInline response = (CorInfoInline)value.result;
      DEBUG_REP(dmpCanInline(key, value));
      return response;
  }
  
  void MethodContext::recResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, DWORD exceptionCode)
  {
      if (ResolveToken == nullptr)
          ResolveToken = new LightWeightMap<Agnostic_CORINFO_RESOLVED_TOKENin, ResolveTokenValue>();
  
      Agnostic_CORINFO_RESOLVED_TOKENin key;
      ZeroMemory(&key, sizeof(Agnostic_CORINFO_RESOLVED_TOKENin)); // We use the input structs as a key and use memcmp to
                                                                   // compare.. so we need to zero out padding too
      key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken);
  
      ResolveTokenValue value;
      value.tokenOut      = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKENout(pResolvedToken, ResolveToken);
      value.exceptionCode = (DWORD)exceptionCode;
  
      ResolveToken->Add(key, value);
      DEBUG_REC(dmpResolveToken(key, value));
  }
  void MethodContext::dmpResolveToken(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const ResolveTokenValue& value)
  {
      printf("ResolveToken key: %s\n", SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENin(key).c_str());
      printf(", value: %s excp-%08X", SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENout(value.tokenOut).c_str(),
             value.exceptionCode);
  }
  void MethodContext::repResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, DWORD* exceptionCode)
  {
      Agnostic_CORINFO_RESOLVED_TOKENin key;
      ZeroMemory(&key, sizeof(Agnostic_CORINFO_RESOLVED_TOKENin)); // We use the input structs as a key and use memcmp to
                                                                   // compare.. so we need to zero out padding too
      key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken);
  
      AssertCodeMsg(ResolveToken->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %x", pResolvedToken->token);
  
      ResolveTokenValue value = ResolveToken->Get(key);
  
      SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKENout(pResolvedToken, value.tokenOut, ResolveToken);
      *exceptionCode = (DWORD)value.exceptionCode;
      DEBUG_REP(dmpResolveToken(key, value));
  }
  
  void MethodContext::recTryResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool success)
  {
      if (TryResolveToken == nullptr)
          TryResolveToken = new LightWeightMap<Agnostic_CORINFO_RESOLVED_TOKENin, TryResolveTokenValue>();
  
      Agnostic_CORINFO_RESOLVED_TOKENin key;
      ZeroMemory(&key, sizeof(Agnostic_CORINFO_RESOLVED_TOKENin)); // We use the input structs as a key and use memcmp to
                                                                   // compare.. so we need to zero out padding too
      key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken);
  
      TryResolveTokenValue value;
  
      value.tokenOut = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKENout(pResolvedToken, ResolveToken);
      value.success  = success ? 0 : 1;
  
      TryResolveToken->Add(key, value);
      DEBUG_REC(dmpTryResolveToken(key, value));
  }
  void MethodContext::dmpTryResolveToken(const Agnostic_CORINFO_RESOLVED_TOKENin& key, const TryResolveTokenValue& value)
  {
      printf("TryResolveToken key: %s\n", SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENin(key).c_str());
      printf(", value: %s failed-%u", SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKENout(value.tokenOut).c_str(),
             value.success);
  }
  bool MethodContext::repTryResolveToken(CORINFO_RESOLVED_TOKEN* pResolvedToken)
  {
      Agnostic_CORINFO_RESOLVED_TOKENin key;
      ZeroMemory(&key, sizeof(Agnostic_CORINFO_RESOLVED_TOKENin)); // We use the input structs as a key and use memcmp to
                                                                   // compare.. so we need to zero out padding too
  
      key = SpmiRecordsHelper::CreateAgnostic_CORINFO_RESOLVED_TOKENin(pResolvedToken);
  
      TryResolveTokenValue value = TryResolveToken->Get(key);
  
      SpmiRecordsHelper::Restore_CORINFO_RESOLVED_TOKENout(pResolvedToken, value.tokenOut, ResolveToken);
  
      DEBUG_REP(dmpTryResolveToken(key, value));
      return (DWORD)value.success == 0;
  }
  
  void MethodContext::recGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                     CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
                                     CORINFO_METHOD_HANDLE   callerHandle,
                                     CORINFO_CALLINFO_FLAGS  flags,
                                     CORINFO_CALL_INFO*      pResult,
                                     DWORD                   exceptionCode)
  {
      if (GetCallInfo == nullptr)
          GetCallInfo = new LightWeightMap<Agnostic_GetCallInfo, Agnostic_CORINFO_CALL_INFO>();
  
      Agnostic_GetCallInfo key;
      ZeroMemory(&key, sizeof(Agnostic_GetCallInfo)); // We use the input structs as a key and use memcmp to compare.. so
                                                      // we need to zero out padding too
      key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetCallInfo);
  
      if (pConstrainedResolvedToken != nullptr)
      {
          key.ConstrainedResolvedToken =
              SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pConstrainedResolvedToken, GetCallInfo);
      }
  
      key.callerHandle = (DWORDLONG)callerHandle;
      key.flags        = (DWORD)flags;
  
      Agnostic_CORINFO_CALL_INFO value;
      ZeroMemory(&value, sizeof(Agnostic_CORINFO_CALL_INFO)); // init verSig with 0.
  
      if (exceptionCode == 0)
      {
          value.hMethod     = (DWORDLONG)pResult->hMethod;
          value.methodFlags = (DWORD)pResult->methodFlags;
          value.classFlags  = (DWORD)pResult->classFlags;
          value.sig         = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(pResult->sig, GetCallInfo);
          if (flags & CORINFO_CALLINFO_VERIFICATION)
          {
              value.verMethodFlags = (DWORD)pResult->verMethodFlags;
              value.verSig         = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(pResult->verSig, GetCallInfo);
          }
  
          value.accessAllowed                   = (DWORD)pResult->accessAllowed;
          value.callsiteCalloutHelper.helperNum = (DWORD)pResult->callsiteCalloutHelper.helperNum;
          value.callsiteCalloutHelper.numArgs   = (DWORD)pResult->callsiteCalloutHelper.numArgs;
          for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
          {
              value.callsiteCalloutHelper.args[i].constant = (DWORDLONG)pResult->callsiteCalloutHelper.args[i].constant;
              value.callsiteCalloutHelper.args[i].argType  = (DWORD)pResult->callsiteCalloutHelper.args[i].argType;
          }
          value.thisTransform = (DWORD)pResult->thisTransform;
  
          value.kind                           = (DWORD)pResult->kind;
          value.nullInstanceCheck              = (DWORD)pResult->nullInstanceCheck;
          value.contextHandle                  = (DWORDLONG)pResult->contextHandle;
          value.exactContextNeedsRuntimeLookup = (DWORD)pResult->exactContextNeedsRuntimeLookup;
  
          value.stubLookup = SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(&pResult->stubLookup);
  
          value.instParamLookup.accessType = (DWORD)pResult->instParamLookup.accessType;
          value.instParamLookup.handle     = (DWORDLONG)pResult->instParamLookup.handle;
          value.wrapperDelegateInvoke       = (DWORD)pResult->wrapperDelegateInvoke;
      }
      else
          ZeroMemory(&value, sizeof(Agnostic_CORINFO_CALL_INFO));
      value.exceptionCode = (DWORD)exceptionCode;
  
      GetCallInfo->Add(key, value);
      DEBUG_REC(dmpGetCallInfo(key, value));
  }
  void MethodContext::dmpGetCallInfo(const Agnostic_GetCallInfo& key, const Agnostic_CORINFO_CALL_INFO& value)
  {
      printf("GetCallInfo key rt{%s} crt{%s} ch-%016llX flg-%08X\n",
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ResolvedToken).c_str(),
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ConstrainedResolvedToken).c_str(), key.callerHandle,
             key.flags);
      printf(", value mth-%016llX, mf-%08X cf-%08X"
             " sig%s"
             " vsig%s"
             " ipl{at-%08X hnd-%016llX}"
             " sdi-%08X"
             " excp-%08X"
             " stubLookup{%s}",
             value.hMethod, value.methodFlags, value.classFlags,
             SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(value.sig).c_str(),
             SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(value.verSig).c_str(), value.instParamLookup.accessType,
             value.instParamLookup.handle, value.wrapperDelegateInvoke, value.exceptionCode,
             SpmiDumpHelper::DumpAgnostic_CORINFO_LOOKUP(value.stubLookup).c_str());
  }
  void MethodContext::repGetCallInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                     CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
                                     CORINFO_METHOD_HANDLE   callerHandle,
                                     CORINFO_CALLINFO_FLAGS  flags,
                                     CORINFO_CALL_INFO*      pResult,
                                     DWORD*                  exceptionCode)
  {
      Agnostic_GetCallInfo key;
      ZeroMemory(&key, sizeof(Agnostic_GetCallInfo)); // We use the input structs as a key and use memcmp to compare.. so
                                                      // we need to zero out padding too
      key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetCallInfo);
      if (pConstrainedResolvedToken != nullptr)
      {
          key.ConstrainedResolvedToken =
              SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pConstrainedResolvedToken, GetCallInfo);
      }
      key.callerHandle = (DWORDLONG)callerHandle;
      key.flags        = (DWORD)flags;
  
      AssertCodeMsg(GetCallInfo->GetIndex(key) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %08x, %016llx. Probably a missing exception in GetCallInfo",
                    key.ResolvedToken.inValue.token, key.ResolvedToken.outValue.hClass);
  
      Agnostic_CORINFO_CALL_INFO value;
  
      value = GetCallInfo->Get(key);
  
      pResult->hMethod     = (CORINFO_METHOD_HANDLE)value.hMethod;
      pResult->methodFlags = (unsigned)value.methodFlags;
      pResult->classFlags  = (unsigned)value.classFlags;
      pResult->sig         = SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(value.sig, GetCallInfo);
      if (flags & CORINFO_CALLINFO_VERIFICATION)
      {
          pResult->verMethodFlags = (unsigned)value.verMethodFlags;
          pResult->verSig         = SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(value.verSig, GetCallInfo);
      }
      pResult->accessAllowed                   = (CorInfoIsAccessAllowedResult)value.accessAllowed;
      pResult->callsiteCalloutHelper.helperNum = (CorInfoHelpFunc)value.callsiteCalloutHelper.helperNum;
      pResult->callsiteCalloutHelper.numArgs   = (unsigned)value.callsiteCalloutHelper.numArgs;
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          pResult->callsiteCalloutHelper.args[i].constant = (size_t)value.callsiteCalloutHelper.args[i].constant;
          pResult->callsiteCalloutHelper.args[i].argType =
              (CorInfoAccessAllowedHelperArgType)value.callsiteCalloutHelper.args[i].argType;
      }
      pResult->thisTransform                            = (CORINFO_THIS_TRANSFORM)value.thisTransform;
      pResult->kind                                     = (CORINFO_CALL_KIND)value.kind;
      pResult->nullInstanceCheck                        = (BOOL)value.nullInstanceCheck;
      pResult->contextHandle                            = (CORINFO_CONTEXT_HANDLE)value.contextHandle;
      pResult->exactContextNeedsRuntimeLookup           = (BOOL)value.exactContextNeedsRuntimeLookup;
      pResult->stubLookup.lookupKind.needsRuntimeLookup = value.stubLookup.lookupKind.needsRuntimeLookup != 0;
      pResult->stubLookup.lookupKind.runtimeLookupKind =
          (CORINFO_RUNTIME_LOOKUP_KIND)value.stubLookup.lookupKind.runtimeLookupKind;
      if (pResult->stubLookup.lookupKind.needsRuntimeLookup)
      {
          pResult->stubLookup.runtimeLookup = SpmiRecordsHelper::RestoreCORINFO_RUNTIME_LOOKUP(value.stubLookup.runtimeLookup);
      }
      else
      {
          pResult->stubLookup.constLookup.accessType = (InfoAccessType)value.stubLookup.constLookup.accessType;
          pResult->stubLookup.constLookup.handle     = (CORINFO_GENERIC_HANDLE)value.stubLookup.constLookup.handle;
      }
      if (pResult->kind == CORINFO_VIRTUALCALL_STUB)
      {
          cr->CallTargetTypes->Add((DWORDLONG)pResult->codePointerLookup.constLookup.addr,
                                   (DWORD)CORINFO_VIRTUALCALL_STUB);
      }
      pResult->instParamLookup.accessType = (InfoAccessType)value.instParamLookup.accessType;
      pResult->instParamLookup.handle     = (CORINFO_GENERIC_HANDLE)value.instParamLookup.handle;
      pResult->wrapperDelegateInvoke       = (BOOL)value.wrapperDelegateInvoke;
      *exceptionCode                      = (DWORD)value.exceptionCode;
  
      DEBUG_REP(dmpGetCallInfo(key, value));
  }
  
  //
  // Variant of repGetCallInfo that only requires a method handle, i.e. it performs a reverse lookup to find the
  // resolved token info that, along with the given method handle, was passed into getCallInfo.
  //
  // Arguments:
  //    methodHandle - The method handle to find call info for.
  //    pResult      - [out] The call info for the given method.
  //
  // Notes:
  //    If this fails to find a recorded call to getCallInfo with the given method handle, this will throw an
  //    exception.
  //
  void MethodContext::repGetCallInfoFromMethodHandle(CORINFO_METHOD_HANDLE methodHandle, CORINFO_CALL_INFO* pResult)
  {
      if (GetCallInfo != nullptr)
      {
          for (unsigned int i = 0; i < GetCallInfo->GetCount(); i++)
          {
              Agnostic_GetCallInfo       key = GetCallInfo->GetKey(i);
              Agnostic_CORINFO_CALL_INFO val = GetCallInfo->GetItem(i);
  
              if ((CORINFO_METHOD_HANDLE)val.hMethod == methodHandle)
              {
                  CORINFO_RESOLVED_TOKEN resolvedToken;
                  DWORD                  exceptionCode;
  
                  resolvedToken.tokenContext = (CORINFO_CONTEXT_HANDLE)key.ResolvedToken.inValue.tokenContext;
                  resolvedToken.tokenScope   = (CORINFO_MODULE_HANDLE)key.ResolvedToken.inValue.tokenScope;
                  resolvedToken.token        = (mdToken)key.ResolvedToken.inValue.token;
                  resolvedToken.tokenType    = (CorInfoTokenKind)key.ResolvedToken.inValue.tokenType;
  
                  repResolveToken(&resolvedToken, &exceptionCode);
  
                  // If the original call to getCallInfo passed in a null constrainedResolvedToken pointer,
                  // then we won't be able to replay it. In that case, we'll need to pass a null pointer into
                  // repGetCallInfo for constrainedResolvedToken, instead of just passing the address of our
                  // local (but meaningless) constrainedResolvedToken struct.
                  CORINFO_RESOLVED_TOKEN  constrainedResolvedToken;
                  CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken = nullptr;
  
                  if (key.ConstrainedResolvedToken.inValue.tokenContext != 0 &&
                      key.ConstrainedResolvedToken.inValue.tokenScope != 0)
                  {
                      constrainedResolvedToken.tokenContext =
                          (CORINFO_CONTEXT_HANDLE)key.ConstrainedResolvedToken.inValue.tokenContext;
                      constrainedResolvedToken.tokenScope =
                          (CORINFO_MODULE_HANDLE)key.ConstrainedResolvedToken.inValue.tokenScope;
                      constrainedResolvedToken.token = (mdToken)key.ConstrainedResolvedToken.inValue.token;
                      constrainedResolvedToken.tokenType =
                          (CorInfoTokenKind)key.ConstrainedResolvedToken.inValue.tokenType;
                      pConstrainedResolvedToken = &constrainedResolvedToken;
  
                      repResolveToken(pConstrainedResolvedToken, &exceptionCode);
                  }
  
                  repGetCallInfo(&resolvedToken, pConstrainedResolvedToken, (CORINFO_METHOD_HANDLE)key.callerHandle,
                                 (CORINFO_CALLINFO_FLAGS)key.flags, pResult, &exceptionCode);
                  return;
              }
          }
      }
  
      // If we reached here, we didn't find a key associated with the given method handle
      LogException(EXCEPTIONCODE_MC, "Didn't find key %016llX.", methodHandle);
  }
  
  void MethodContext::recGetIntrinsicID(CORINFO_METHOD_HANDLE method, bool* pMustExpand, CorInfoIntrinsics result)
  {
      if (GetIntrinsicID == nullptr)
          GetIntrinsicID = new LightWeightMap<DWORDLONG, DD>();
  
      DD value;
      value.A = (pMustExpand != nullptr) ? (DWORD)(*pMustExpand ? 1 : 0) : (DWORD)0;
      value.B = (DWORD)result;
  
      GetIntrinsicID->Add((DWORDLONG)method, value);
      DEBUG_REC(dmpGetIntrinsicID((DWORDLONG)method, value));
  }
  void MethodContext::dmpGetIntrinsicID(DWORDLONG key, DD value)
  {
      printf("GetIntrinsicID key mth-%016llX, mustExpand-%u, value intr-%u", key, value.A, value.B);
  }
  CorInfoIntrinsics MethodContext::repGetIntrinsicID(CORINFO_METHOD_HANDLE method, bool* pMustExpand)
  {
      AssertCodeMsg(GetIntrinsicID != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)method);
      AssertCodeMsg(GetIntrinsicID->GetIndex((DWORDLONG)method) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)method);
  
      DD value;
      value = GetIntrinsicID->Get((DWORDLONG)method);
      if (pMustExpand != nullptr)
      {
          *pMustExpand = (value.A == 0) ? false : true;
      }
      CorInfoIntrinsics result = (CorInfoIntrinsics)value.B;
  
      DEBUG_REP(dmpGetIntrinsicID((DWORDLONG)method, value));
      return result;
  }
  
  void MethodContext::recIsIntrinsicType(CORINFO_CLASS_HANDLE cls, BOOL result)
  {
      if (IsIntrinsicType == nullptr)
          IsIntrinsicType = new LightWeightMap<DWORDLONG, DWORD>();
  
      IsIntrinsicType->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpIsIntrinsicType((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpIsIntrinsicType(DWORDLONG key, DWORD value)
  {
      printf("IsIntrinsicType key mth-%016llX, value intr-%u", key, value);
  }
  BOOL MethodContext::repIsIntrinsicType(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(IsIntrinsicType != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)cls);
      AssertCodeMsg(IsIntrinsicType->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
      BOOL result = (BOOL)IsIntrinsicType->Get((DWORDLONG)cls);
      DEBUG_REP(dmpIsIntrinsicType((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetUnmanagedCallConv(CORINFO_METHOD_HANDLE method, CorInfoUnmanagedCallConv result)
  {
      if (GetUnmanagedCallConv == nullptr)
          GetUnmanagedCallConv = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetUnmanagedCallConv->Add((DWORDLONG)method, result);
      DEBUG_REC(dmpGetUnmanagedCallConv((DWORDLONG)method, (DWORD)result));
  }
  void MethodContext::dmpGetUnmanagedCallConv(DWORDLONG key, DWORD result)
  {
      printf("GetUnmanagedCallConv key ftn-%016llX, value res-%u", key, result);
  }
  CorInfoUnmanagedCallConv MethodContext::repGetUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
  {
      if ((GetUnmanagedCallConv == nullptr) || (GetUnmanagedCallConv->GetIndex((DWORDLONG)method) == -1))
      {
  #ifdef sparseMC
          LogDebug("Sparse - repGetUnmanagedCallConv returning CORINFO_UNMANAGED_CALLCONV_STDCALL");
          return CORINFO_UNMANAGED_CALLCONV_STDCALL;
  #else
          LogException(EXCEPTIONCODE_MC, "Found a null GetUnmanagedCallConv.  Probably missing a fatTrigger for %016llX.",
                       (DWORDLONG)method);
  #endif
      }
      CorInfoUnmanagedCallConv result = (CorInfoUnmanagedCallConv)GetUnmanagedCallConv->Get((DWORDLONG)method);
      DEBUG_REP(dmpGetUnmanagedCallConv((DWORDLONG)method, (DWORD)result));
      return result;
  }
  
  void MethodContext::recAsCorInfoType(CORINFO_CLASS_HANDLE cls, CorInfoType result)
  {
      if (AsCorInfoType == nullptr)
          AsCorInfoType = new LightWeightMap<DWORDLONG, DWORD>();
  
      AsCorInfoType->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpAsCorInfoType((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpAsCorInfoType(DWORDLONG key, DWORD value)
  {
      printf("AsCorInfoType key cls-%016llX, value cit-%u(%s)", key, value, toString((CorInfoType)value));
  }
  CorInfoType MethodContext::repAsCorInfoType(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg((AsCorInfoType != nullptr) && (AsCorInfoType->GetIndex((DWORDLONG)cls) != -1), EXCEPTIONCODE_MC,
                    "Didn't find %016llX.  Probable cached value in JIT issue", (DWORDLONG)cls);
      CorInfoType result = (CorInfoType)AsCorInfoType->Get((DWORDLONG)cls);
      DEBUG_REP(dmpAsCorInfoType((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recIsValueClass(CORINFO_CLASS_HANDLE cls, BOOL result)
  {
      if (IsValueClass == nullptr)
          IsValueClass = new LightWeightMap<DWORDLONG, DWORD>();
  
      IsValueClass->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpIsValueClass((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpIsValueClass(DWORDLONG key, DWORD value)
  {
      printf("IsValueClass key cls-%016llX, value res-%u", key, value);
  }
  BOOL MethodContext::repIsValueClass(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg((IsValueClass != nullptr) && (IsValueClass->GetIndex((DWORDLONG)cls) != -1), EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)cls);
  
      BOOL result = (BOOL)IsValueClass->Get((DWORDLONG)cls);
      DEBUG_REP(dmpIsValueClass((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recIsStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls, BOOL result)
  {
      if (IsStructRequiringStackAllocRetBuf == nullptr)
          IsStructRequiringStackAllocRetBuf = new LightWeightMap<DWORDLONG, DWORD>();
  
      IsStructRequiringStackAllocRetBuf->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpIsStructRequiringStackAllocRetBuf((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpIsStructRequiringStackAllocRetBuf(DWORDLONG key, DWORD value)
  {
      printf("IsStructRequiringStackAllocRetBuf key cls-%016llX, value res-%u", key, value);
  }
  BOOL MethodContext::repIsStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(IsStructRequiringStackAllocRetBuf != nullptr, EXCEPTIONCODE_MC,
                    "Found a null IsStructRequiringStackAllocRetBuf.  Probably missing a fatTrigger for %016llX.",
                    (DWORDLONG)cls);
      AssertCodeMsg(IsStructRequiringStackAllocRetBuf->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)cls);
      BOOL result = (BOOL)IsStructRequiringStackAllocRetBuf->Get((DWORDLONG)cls);
      DEBUG_REP(dmpIsStructRequiringStackAllocRetBuf((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetClassSize(CORINFO_CLASS_HANDLE cls, unsigned result)
  {
      if (GetClassSize == nullptr)
          GetClassSize = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetClassSize->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpGetClassSize((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpGetClassSize(DWORDLONG key, DWORD val)
  {
      printf("GetClassSize key %016llX, value %u", key, val);
  }
  unsigned MethodContext::repGetClassSize(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(GetClassSize != nullptr, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)cls);
      AssertCodeMsg(GetClassSize->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
      unsigned result = (unsigned)GetClassSize->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetClassSize((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetHeapClassSize(CORINFO_CLASS_HANDLE cls, unsigned result)
  {
      if (GetHeapClassSize == nullptr)
          GetHeapClassSize = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetHeapClassSize->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpGetHeapClassSize((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpGetHeapClassSize(DWORDLONG key, DWORD val)
  {
      printf("GetHeapClassSize key %016llX, value %u", key, val);
  }
  unsigned MethodContext::repGetHeapClassSize(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(GetHeapClassSize != nullptr, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)cls);
      AssertCodeMsg(GetHeapClassSize->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
      unsigned result = (unsigned)GetHeapClassSize->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetHeapClassSize((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recCanAllocateOnStack(CORINFO_CLASS_HANDLE cls, BOOL result)
  {
      if (CanAllocateOnStack == nullptr)
          CanAllocateOnStack = new LightWeightMap<DWORDLONG, DWORD>();
  
      CanAllocateOnStack->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpCanAllocateOnStack((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpCanAllocateOnStack(DWORDLONG key, DWORD val)
  {
      printf("CanAllocateOnStack key %016llX, value %u", key, val);
  }
  BOOL MethodContext::repCanAllocateOnStack(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(CanAllocateOnStack != nullptr, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)cls);
      AssertCodeMsg(CanAllocateOnStack->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
      BOOL result = (BOOL)CanAllocateOnStack->Get((DWORDLONG)cls);
      DEBUG_REP(dmpCanAllocateOnStack((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetClassNumInstanceFields(CORINFO_CLASS_HANDLE cls, unsigned result)
  {
      if (GetClassNumInstanceFields == nullptr)
          GetClassNumInstanceFields = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetClassNumInstanceFields->Add((DWORDLONG)cls, (DWORD)result);
      DEBUG_REC(dmpGetClassNumInstanceFields((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpGetClassNumInstanceFields(DWORDLONG key, DWORD value)
  {
      printf("GetClassNumInstanceFields key cls-%016llX, value res-%u", key, value);
  }
  unsigned MethodContext::repGetClassNumInstanceFields(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(GetClassNumInstanceFields != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)cls);
      AssertCodeMsg(GetClassNumInstanceFields->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
  
      unsigned result = (unsigned)GetClassNumInstanceFields->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetClassNumInstanceFields((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetNewArrHelper(CORINFO_CLASS_HANDLE arrayCls, CorInfoHelpFunc result)
  {
      if (GetNewArrHelper == nullptr)
          GetNewArrHelper = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetNewArrHelper->Add((DWORDLONG)arrayCls, result);
      DEBUG_REC(dmpGetNewArrHelper((DWORDLONG)arrayCls, (DWORD)result));
  }
  void MethodContext::dmpGetNewArrHelper(DWORDLONG key, DWORD value)
  {
      printf("GetNewArrHelper key cls-%016llX, value res-%u", key, value);
  }
  CorInfoHelpFunc MethodContext::repGetNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
  {
      CorInfoHelpFunc result = (CorInfoHelpFunc)GetNewArrHelper->Get((DWORDLONG)arrayCls);
      DEBUG_REP(dmpGetNewArrHelper((DWORDLONG)arrayCls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd, CorInfoHelpFunc result)
  {
      if (GetSharedCCtorHelper == nullptr)
          GetSharedCCtorHelper = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetSharedCCtorHelper->Add((DWORDLONG)clsHnd, result);
      DEBUG_REC(dmpGetSharedCCtorHelper((DWORDLONG)clsHnd, (DWORD)result));
  }
  void MethodContext::dmpGetSharedCCtorHelper(DWORDLONG key, DWORD value)
  {
      printf("GetSharedCCtorHelper key cls-%016llX, value res-%u", key, value);
  }
  CorInfoHelpFunc MethodContext::repGetSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
  {
      CorInfoHelpFunc result = (CorInfoHelpFunc)GetSharedCCtorHelper->Get((DWORDLONG)clsHnd);
      DEBUG_REP(dmpGetSharedCCtorHelper((DWORDLONG)clsHnd, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetTypeForBox(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result)
  {
      if (GetTypeForBox == nullptr)
          GetTypeForBox = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      GetTypeForBox->Add((DWORDLONG)cls, (DWORDLONG)result);
      DEBUG_REC(dmpGetTypeForBox((DWORDLONG)cls, (DWORDLONG)result));
  }
  void MethodContext::dmpGetTypeForBox(DWORDLONG key, DWORDLONG value)
  {
      printf("GetTypeForBox key cls-%016llX, value res-%016llX", key, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetTypeForBox(CORINFO_CLASS_HANDLE cls)
  {
      CORINFO_CLASS_HANDLE result = (CORINFO_CLASS_HANDLE)GetTypeForBox->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetTypeForBox((DWORDLONG)cls, (DWORDLONG)result));
      return result;
  }
  
  void MethodContext::recGetBoxHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc result)
  {
      if (GetBoxHelper == nullptr)
          GetBoxHelper = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetBoxHelper->Add((DWORDLONG)cls, result);
      DEBUG_REC(dmpGetBoxHelper((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpGetBoxHelper(DWORDLONG key, DWORD value)
  {
      printf("GetBoxHelper key cls-%016llX, value res-%u", key, value);
  }
  CorInfoHelpFunc MethodContext::repGetBoxHelper(CORINFO_CLASS_HANDLE cls)
  {
      CorInfoHelpFunc result = (CorInfoHelpFunc)GetBoxHelper->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetBoxHelper((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetBuiltinClass(CorInfoClassId classId, CORINFO_CLASS_HANDLE result)
  {
      if (GetBuiltinClass == nullptr)
          GetBuiltinClass = new LightWeightMap<DWORD, DWORDLONG>();
  
      GetBuiltinClass->Add((DWORD)classId, (DWORDLONG)result);
      DEBUG_REC(dmpGetBuiltinClass((DWORDLONG)classId, (DWORDLONG)result));
  }
  void MethodContext::dmpGetBuiltinClass(DWORD key, DWORDLONG value)
  {
      printf("GetBuiltinClass key cls-%08X, value cls-%016llX", key, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetBuiltinClass(CorInfoClassId classId)
  {
      AssertCodeMsg(GetBuiltinClass != nullptr, EXCEPTIONCODE_MC, "Encountered an empty LWM while looking for %016llX",
                    (DWORDLONG)classId);
      AssertCodeMsg(GetBuiltinClass->GetIndex((DWORDLONG)classId) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)classId);
      CORINFO_CLASS_HANDLE value = (CORINFO_CLASS_HANDLE)GetBuiltinClass->Get((DWORD)classId);
      DEBUG_REP(dmpGetBuiltinClass((DWORDLONG)classId, (DWORDLONG)value));
      return value;
  }
  
  void MethodContext::recGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls, CorInfoType result)
  {
      if (GetTypeForPrimitiveValueClass == nullptr)
          GetTypeForPrimitiveValueClass = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetTypeForPrimitiveValueClass->Add((DWORDLONG)cls, result);
      DEBUG_REC(dmpGetTypeForPrimitiveValueClass((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpGetTypeForPrimitiveValueClass(DWORDLONG key, DWORD value)
  {
      printf("GetTypeForPrimitiveValueClass key cls-%016llX, value cit-%u(%s)", key, value, toString((CorInfoType)value));
  }
  CorInfoType MethodContext::repGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(GetTypeForPrimitiveValueClass != nullptr, EXCEPTIONCODE_MC,
                    "Encountered an empty LWM while looking for %016llX", (DWORDLONG)cls);
      AssertCodeMsg(GetTypeForPrimitiveValueClass->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)cls);
      CorInfoType result = (CorInfoType)GetTypeForPrimitiveValueClass->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetTypeForPrimitiveValueClass((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls, CorInfoType result)
  {
      if (GetTypeForPrimitiveNumericClass == nullptr)
          GetTypeForPrimitiveNumericClass = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetTypeForPrimitiveNumericClass->Add((DWORDLONG)cls, result);
      DEBUG_REC(dmpGetTypeForPrimitiveNumericClass((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpGetTypeForPrimitiveNumericClass(DWORDLONG key, DWORD value)
  {
      printf("GetTypeForPrimitiveNumericClass key cls-%016llX, value cit-%u(%s)", key, value,
             toString((CorInfoType)value));
  }
  CorInfoType MethodContext::repGetTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(GetTypeForPrimitiveNumericClass != nullptr, EXCEPTIONCODE_MC,
                    "Encountered an empty LWM while looking for %016llX", (DWORDLONG)cls);
      AssertCodeMsg(GetTypeForPrimitiveNumericClass->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)cls);
      CorInfoType result = (CorInfoType)GetTypeForPrimitiveNumericClass->Get((DWORDLONG)cls);
      DEBUG_REP(dmpGetTypeForPrimitiveNumericClass((DWORDLONG)cls, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetParentType(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result)
  {
      if (GetParentType == nullptr)
          GetParentType = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      GetParentType->Add((DWORDLONG)cls, (DWORDLONG)result);
  }
  void MethodContext::dmpGetParentType(DWORDLONG key, DWORDLONG value)
  {
      printf("GetParentType key cls-%016llX, value cls-%016llX", key, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetParentType(CORINFO_CLASS_HANDLE cls)
  {
      CORINFO_CLASS_HANDLE result = (CORINFO_CLASS_HANDLE)GetParentType->Get((DWORDLONG)cls);
      return result;
  }
  
  void MethodContext::recIsSDArray(CORINFO_CLASS_HANDLE cls, BOOL result)
  {
      if (IsSDArray == nullptr)
          IsSDArray = new LightWeightMap<DWORDLONG, DWORD>();
  
      IsSDArray->Add((DWORDLONG)cls, result);
      DEBUG_REC(dmpIsSDArray((DWORDLONG)cls, (DWORD)result));
  }
  void MethodContext::dmpIsSDArray(DWORDLONG key, DWORD value)
  {
      printf("IsSDArray key cls-%016llX, value res-%u", key, value);
  }
  BOOL MethodContext::repIsSDArray(CORINFO_CLASS_HANDLE cls)
  {
      AssertCodeMsg(IsSDArray != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)cls);
      AssertCodeMsg(IsSDArray->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)cls);
      BOOL temp = (BOOL)IsSDArray->Get((DWORDLONG)cls);
      DEBUG_REP(dmpIsSDArray((DWORDLONG)cls, (DWORD)temp));
      return temp;
  }
  
  void MethodContext::recGetFieldClass(CORINFO_FIELD_HANDLE field, CORINFO_CLASS_HANDLE result)
  {
      if (GetFieldClass == nullptr)
          GetFieldClass = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      GetFieldClass->Add((DWORDLONG)field, (DWORDLONG)result);
      DEBUG_REC(dmpGetFieldClass((DWORDLONG)field, (DWORDLONG)result));
  }
  void MethodContext::dmpGetFieldClass(DWORDLONG key, DWORDLONG value)
  {
      printf("GetFieldClass key %016llX, value %016llX", key, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetFieldClass(CORINFO_FIELD_HANDLE field)
  {
      AssertCodeMsg(GetFieldClass != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)field);
      AssertCodeMsg(GetFieldClass->GetIndex((DWORDLONG)field) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)field);
      CORINFO_CLASS_HANDLE temp = (CORINFO_CLASS_HANDLE)GetFieldClass->Get((DWORDLONG)field);
      DEBUG_REP(dmpGetFieldClass((DWORDLONG)field, (DWORDLONG)temp));
      return temp;
  }
  
  void MethodContext::recGetFieldOffset(CORINFO_FIELD_HANDLE field, unsigned result)
  {
      if (GetFieldOffset == nullptr)
          GetFieldOffset = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetFieldOffset->Add((DWORDLONG)field, result);
      DEBUG_REC(dmpGetFieldOffset((DWORDLONG)field, (DWORD)result));
  }
  void MethodContext::dmpGetFieldOffset(DWORDLONG key, DWORD value)
  {
      printf("GetFieldOffset key FLD-%016llX, value %08X", key, value);
  }
  unsigned MethodContext::repGetFieldOffset(CORINFO_FIELD_HANDLE field)
  {
      AssertCodeMsg((GetFieldOffset != nullptr) && (GetFieldOffset->GetIndex((DWORDLONG)field) != -1), EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)field);
  
      unsigned temp = (unsigned)GetFieldOffset->Get((DWORDLONG)field);
      DEBUG_REP(dmpGetFieldOffset((DWORDLONG)field, (DWORD)temp));
      return temp;
  }
  
  void MethodContext::recGetLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle, CorInfoHelpFunc result)
  {
      if (GetLazyStringLiteralHelper == nullptr)
          GetLazyStringLiteralHelper = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetLazyStringLiteralHelper->Add((DWORDLONG)handle, result);
      DEBUG_REC(dmpGetLazyStringLiteralHelper((DWORDLONG)handle, result));
  }
  
  void MethodContext::dmpGetLazyStringLiteralHelper(DWORDLONG key, DWORD value)
  {
      printf("GetLazyStringLiteralHelper key mod-%016llX, value res-%u", key, value);
  }
  
  CorInfoHelpFunc MethodContext::repGetLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
  {
      AssertCodeMsg(GetLazyStringLiteralHelper != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)handle);
      AssertCodeMsg(GetLazyStringLiteralHelper->GetIndex((DWORDLONG)handle) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)handle);
      CorInfoHelpFunc temp = (CorInfoHelpFunc)GetLazyStringLiteralHelper->Get((DWORDLONG)handle);
      DEBUG_REP(dmpGetLazyStringLiteralHelper((DWORDLONG)handle, temp));
      return temp;
  }
  
  void MethodContext::recGetUnBoxHelper(CORINFO_CLASS_HANDLE cls, CorInfoHelpFunc result)
  {
      if (GetUnBoxHelper == nullptr)
          GetUnBoxHelper = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetUnBoxHelper->Add((DWORDLONG)cls, result);
  }
  void MethodContext::dmpGetUnBoxHelper(DWORDLONG key, DWORD value)
  {
      printf("GetUnBoxHelper key cls-%016llX, value res-%u", key, value);
  }
  CorInfoHelpFunc MethodContext::repGetUnBoxHelper(CORINFO_CLASS_HANDLE cls)
  {
      CorInfoHelpFunc temp = (CorInfoHelpFunc)GetUnBoxHelper->Get((DWORDLONG)cls);
      return temp;
  }
  
  void MethodContext::recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                             CORINFO_LOOKUP_KIND*    pGenericLookupKind,
                                             CorInfoHelpFunc         id,
                                             CORINFO_CONST_LOOKUP*   pLookup,
                                             bool                    result)
  {
      if (GetReadyToRunHelper == nullptr)
          GetReadyToRunHelper = new LightWeightMap<GetReadyToRunHelper_TOKENin, GetReadyToRunHelper_TOKENout>();
  
      GetReadyToRunHelper_TOKENin key;
      ZeroMemory(&key, sizeof(key));
      key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetReadyToRunHelper);
      key.GenericLookupKind = SpmiRecordsHelper::CreateAgnostic_CORINFO_LOOKUP_KIND(pGenericLookupKind);
      key.id                = (DWORD)id;
      GetReadyToRunHelper_TOKENout value;
      value.Lookup = SpmiRecordsHelper::StoreAgnostic_CORINFO_CONST_LOOKUP(pLookup);
      value.result = result;
  
      GetReadyToRunHelper->Add(key, value);
      DEBUG_REP(dmpGetReadyToRunHelper(key, value));
  }
  
  void MethodContext::dmpGetReadyToRunHelper(GetReadyToRunHelper_TOKENin key, GetReadyToRunHelper_TOKENout value)
  {
      printf("GetReadyToRunHelper key: tk{%s} kind{%s} id-%u",
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ResolvedToken).c_str(),
             SpmiDumpHelper::DumpAgnostic_CORINFO_LOOKUP_KIND(key.GenericLookupKind).c_str(), key.id);
      printf(", value: lk{ %s } %u", SpmiDumpHelper::DumpAgnostic_CORINFO_CONST_LOOKUP(value.Lookup).c_str(),
             value.result);
  }
  
  bool MethodContext::repGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                             CORINFO_LOOKUP_KIND*    pGenericLookupKind,
                                             CorInfoHelpFunc         id,
                                             CORINFO_CONST_LOOKUP*   pLookup)
  {
      AssertCodeMsg(GetReadyToRunHelper != nullptr, EXCEPTIONCODE_MC, "No GetReadyToRunHelper records");
  
      GetReadyToRunHelper_TOKENin key;
      ZeroMemory(&key, sizeof(key));
      key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetReadyToRunHelper);
      key.GenericLookupKind = SpmiRecordsHelper::CreateAgnostic_CORINFO_LOOKUP_KIND(pGenericLookupKind);
      key.id                = (DWORD)id;
  
      AssertCodeMsg(GetReadyToRunHelper->GetIndex(key) != -1, EXCEPTIONCODE_MC,
                    "Didn't find a key for GetReadyToRunHelper");
  
      GetReadyToRunHelper_TOKENout value = GetReadyToRunHelper->Get(key);
      *pLookup                           = SpmiRecordsHelper::RestoreCORINFO_CONST_LOOKUP(value.Lookup);
      return value.result;
  }
  
  void MethodContext::recGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod,
                                                         CORINFO_CLASS_HANDLE    delegateType,
                                                         CORINFO_LOOKUP*         pLookup)
  {
      if (GetReadyToRunDelegateCtorHelper == nullptr)
          GetReadyToRunDelegateCtorHelper =
              new LightWeightMap<GetReadyToRunDelegateCtorHelper_TOKENIn, Agnostic_CORINFO_LOOKUP>();
  
      GetReadyToRunDelegateCtorHelper_TOKENIn key;
      ZeroMemory(&key, sizeof(key));
      key.TargetMethod =
          SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pTargetMethod, GetReadyToRunDelegateCtorHelper);
      key.delegateType              = (DWORDLONG)delegateType;
      Agnostic_CORINFO_LOOKUP value = SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(pLookup);
      GetReadyToRunDelegateCtorHelper->Add(key, value);
      DEBUG_REP(dmpGetReadyToRunDelegateCtorHelper(key, value));
  }
  
  void MethodContext::dmpGetReadyToRunDelegateCtorHelper(GetReadyToRunDelegateCtorHelper_TOKENIn key,
                                                         Agnostic_CORINFO_LOOKUP                 value)
  {
      printf("GetReadyToRunDelegateCtorHelper key: method tk{%s} type-%016llX",
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.TargetMethod).c_str(), key.delegateType);
      printf(", value: %s", SpmiDumpHelper::DumpAgnostic_CORINFO_LOOKUP(value).c_str());
  }
  
  void MethodContext::repGetReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod,
                                                         CORINFO_CLASS_HANDLE    delegateType,
                                                         CORINFO_LOOKUP*         pLookup)
  {
      AssertCodeMsg(GetReadyToRunDelegateCtorHelper != nullptr, EXCEPTIONCODE_MC,
                    "No GetReadyToRunDelegateCtorHelper records");
      GetReadyToRunDelegateCtorHelper_TOKENIn key;
      ZeroMemory(&key, sizeof(key));
      key.TargetMethod =
          SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pTargetMethod, GetReadyToRunDelegateCtorHelper);
      key.delegateType = (DWORDLONG)delegateType;
  
      AssertCodeMsg(GetReadyToRunDelegateCtorHelper->GetIndex(key) != -1, EXCEPTIONCODE_MC,
                    "Didn't find a key for GetReadyToRunDelegateCtorHelper");
      Agnostic_CORINFO_LOOKUP value = GetReadyToRunDelegateCtorHelper->Get(key);
      *pLookup                      = SpmiRecordsHelper::RestoreCORINFO_LOOKUP(value);
  }
  
  void MethodContext::recGetHelperFtn(CorInfoHelpFunc ftnNum, void** ppIndirection, void* result)
  {
      if (GetHelperFtn == nullptr)
          GetHelperFtn = new LightWeightMap<DWORD, DLDL>();
  
      DLDL value;
      value.A = (DWORDLONG)*ppIndirection;
      value.B = (DWORDLONG)result;
  
      if (GetHelperFtn->GetIndex((DWORD)ftnNum) != -1)
      {
          DLDL oldValue = GetHelperFtn->Get((DWORD)ftnNum);
  
          AssertCodeMsg(oldValue.A == value.A && oldValue.B == oldValue.B, EXCEPTIONCODE_MC,
                        "collision! old: %016llX %016llX, new: %016llX %016llX \n", oldValue.A, oldValue.B, value.A,
                        value.B);
      }
  
      GetHelperFtn->Add((DWORD)ftnNum, value);
      DEBUG_REC(dmpGetHelperFtn((DWORD)ftnNum, value));
  }
  void MethodContext::dmpGetHelperFtn(DWORD key, DLDL value)
  {
      printf("GetHelperFtn key ftn-%u, value ppi-%016llX res-%016llX", key, value.A, value.B);
  }
  void* MethodContext::repGetHelperFtn(CorInfoHelpFunc ftnNum, void** ppIndirection)
  {
      if ((GetHelperFtn == nullptr) || (GetHelperFtn->GetIndex((DWORD)ftnNum) == -1))
      {
  #ifdef sparseMC
          LogDebug("Sparse - repGetHelperFtn returning nullptr and 0XCAFE0003");
          *ppIndirection = nullptr;
          return (void*)(size_t)0xCAFE0003;
  #else
          LogException(EXCEPTIONCODE_MC, "Encountered an empty LWM while looking for %08X", (DWORD)ftnNum);
  #endif
      }
  
      DLDL value     = (DLDL)GetHelperFtn->Get((DWORD)ftnNum);
      *ppIndirection = (void*)value.A;
      DEBUG_REP(dmpGetHelperFtn((DWORD)ftnNum, value));
      return (void*)value.B;
  }
  
  //
  // Finds the identifier (i.e. the CorInfoHelpFunc enum) of a helper function, based on the address where it
  // is located in memory.
  //
  // Arguments:
  //    functionAddress - The starting address of the helper function in memory.
  //    pResult         - [out] Pointer to write out the identifier of the helper function located at the given
  //                      address.
  //
  // Return Value:
  //    True if there is a helper function associated with the given target address; false otherwise.
  //
  // Assumptions:
  //    Only the lower 32 bits of the method address are necessary to identify the method.
  //
  // Notes:
  //    - See notes for fndGetFunctionEntryPoint for a more in-depth discussion of why we only match on the
  //      lower 32 bits of the target address.
  //    - This might not work correctly with method contexts recorded via NGen compilation.
  //
  bool MethodContext::fndGetHelperFtn(void* functionAddress, CorInfoHelpFunc* pResult)
  {
      if (GetHelperFtn != nullptr)
      {
          for (unsigned int i = 0; i < GetHelperFtn->GetCount(); i++)
          {
              DWORD key = GetHelperFtn->GetKey(i);
              DLDL  val = GetHelperFtn->GetItem(i);
  
              // TODO-Cleanup: this only compares the function addresses, and doesn't account for
              // ppIndirection, which will break if the helper is a dynamic helper function.
              if (val.B == (DWORDLONG)functionAddress)
              {
                  *pResult = (CorInfoHelpFunc)key;
                  return true;
              }
          }
      }
  
      LogDebug("fndGetHelperFtn - didn't find value %p", functionAddress);
      return false;
  }
  
  void MethodContext::recGetJustMyCodeHandle(CORINFO_METHOD_HANDLE         method,
                                             CORINFO_JUST_MY_CODE_HANDLE** ppIndirection,
                                             CORINFO_JUST_MY_CODE_HANDLE   result)
  {
      if (GetJustMyCodeHandle == nullptr)
          GetJustMyCodeHandle = new LightWeightMap<DWORDLONG, DLDL>();
      DLDL temp;
      temp.A = (DWORDLONG)*ppIndirection;
      temp.B = (DWORDLONG)result;
      GetJustMyCodeHandle->Add((DWORDLONG)method, temp);
      DEBUG_REC(dmpGetJustMyCodeHandle((DWORDLONG)method, temp));
  }
  void MethodContext::dmpGetJustMyCodeHandle(DWORDLONG key, DLDL value)
  {
      printf("GetJustMyCodeHandle key ftn-%016llX, value pp-%016llX, res-%016llX", key, value.A, value.B);
  }
  CORINFO_JUST_MY_CODE_HANDLE MethodContext::repGetJustMyCodeHandle(CORINFO_METHOD_HANDLE         method,
                                                                    CORINFO_JUST_MY_CODE_HANDLE** ppIndirection)
  {
      DLDL temp                          = (DLDL)GetJustMyCodeHandle->Get((DWORDLONG)method);
      *ppIndirection                     = (CORINFO_JUST_MY_CODE_HANDLE*)temp.A;
      CORINFO_JUST_MY_CODE_HANDLE result = (CORINFO_JUST_MY_CODE_HANDLE)temp.B;
      DEBUG_REP(dmpGetJustMyCodeHandle((DWORDLONG)method, temp));
      return result;
  }
  
  void MethodContext::recGetFunctionEntryPoint(CORINFO_METHOD_HANDLE ftn,
                                               CORINFO_CONST_LOOKUP* pResult,
                                               CORINFO_ACCESS_FLAGS  accessFlags)
  {
      if (GetFunctionEntryPoint == nullptr)
          GetFunctionEntryPoint = new LightWeightMap<DLD, DLD>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      DLD value;
      key.A   = (DWORDLONG)ftn;
      key.B   = (DWORD)accessFlags;
      value.A = (DWORDLONG)pResult->addr; // First union member
      value.B = (DWORD)pResult->accessType;
      GetFunctionEntryPoint->Add(key, value);
      DEBUG_REC(dmpGetFunctionEntryPoint(key, value));
  }
  void MethodContext::dmpGetFunctionEntryPoint(DLD key, DLD value)
  {
      printf("GetFunctionEntryPoint key ftn-%016llX af-%08X, value add-%016llX at-%u", key.A, key.B, value.A, value.B);
  }
  void MethodContext::repGetFunctionEntryPoint(CORINFO_METHOD_HANDLE ftn,
                                               CORINFO_CONST_LOOKUP* pResult,
                                               CORINFO_ACCESS_FLAGS  accessFlags)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      DLD value;
      key.A = (DWORDLONG)ftn;
      key.B = (DWORD)accessFlags;
  
      if (GetFunctionEntryPoint == nullptr)
      {
  #ifdef sparseMC
          LogDebug("Sparse - repGetFunctionEntryPoint fabricated result for request.");
          pResult->accessType = (InfoAccessType)IAT_PVALUE;
          pResult->addr       = (void*)((DWORDLONG)ftn + 0x1c);
          return;
  #else
          LogException(EXCEPTIONCODE_MC, "Didn't find %016llX, %8x", (DWORDLONG)ftn, accessFlags);
  #endif
      }
      if (GetFunctionEntryPoint->GetIndex(key) == -1)
      {
  #ifdef sparseMC
          key.B ^= (DWORD)CORINFO_ACCESS_NONNULL;
          if (GetFunctionEntryPoint->GetIndex(key) != -1)
          {
              LogDebug("Sparse - repGetFunctionEntryPoint found result with inverted CORINFO_ACCESS_NONNULL");
          }
          else
          {
              LogDebug("Sparse - repGetFunctionEntryPoint fabricated result for request.");
              pResult->accessType = (InfoAccessType)IAT_PVALUE;
              pResult->addr       = (void*)((DWORDLONG)ftn + 0x1c);
              return;
          }
  #else
          LogException(EXCEPTIONCODE_MC, "Didn't find %016llX, %8x", (DWORDLONG)ftn, accessFlags);
  #endif
      }
      value = GetFunctionEntryPoint->Get(key);
  
      pResult->accessType = (InfoAccessType)value.B;
      pResult->addr       = (void*)value.A;
      DEBUG_REP(dmpGetFunctionEntryPoint(key, value));
  }
  
  //
  // Finds the method handle associated with a method, based on the address where its generated code is located
  // in memory.
  //
  // Arguments:
  //    methodAddress - The starting address of the generated code for the method.
  //    pResult       - [out] Pointer to a method handle to write into. If this successfully finds a method
  //                    handle associated with the given target address, it will be written to here.
  //
  // Return Value:
  //    True if there is a helper function associated with the given target address; false otherwise.
  //
  // Assumptions:
  //    - The given method address does not point to a jump stub.
  //    - The given method is not a generic method.
  //    - Only the lower 32 bits of the method address are necessary to identify the method.
  //
  // Notes:
  //    On 64-bit platforms, this only checks if the lower 32 bits of the method address match a recorded
  //    function entry point because, on AMD64, this only supports reverse lookups for near calls, which
  //    encode their target address as a 32-bit PC-relative displacement.
  //
  //    Practically speaking, there are two concrete reasons why we ignore the upper 64 bits. First, on
  //    AMD64, when the JIT emits a near call, it records the displacement it encodes into the call with
  //    the EE as a 32-bit relative "relocation". Consequently, this leads to the second reason why we
  //    ignore the upper 64 bits: when SuperPMI is replaying method compilation, it patches up addresses
  //    based on the "relocations" the JIT had previously recorded with the EE. Since these relocations
  //    are only 32-bit deltas, what you'll usually end up seeing is that, after SuperPMI has applied
  //    these fixups, the lower 32 bits of method addresses will match, but the upper 32 bits will differ.
  //
  bool MethodContext::fndGetFunctionEntryPoint(DLD value, CORINFO_METHOD_HANDLE* pResult)
  {
      if (GetFunctionEntryPoint != nullptr)
      {
          for (unsigned int i = 0; i < GetFunctionEntryPoint->GetCount(); i++)
          {
              DLD key = GetFunctionEntryPoint->GetKey(i);
              DLD val = GetFunctionEntryPoint->GetItem(i);
  
              // TODO-Cleanup: we should be more conscious of the rest of the information in CORINFO_CONST_LOOKUP
              if ((DWORD)val.A == (DWORD)value.A)
              {
                  *pResult = (CORINFO_METHOD_HANDLE)key.A;
                  return true;
              }
          }
      }
  
      LogDebug("fndGetFunctionEntryPoint - didn't find value %016llX", value.A);
      return false;
  }
  
  void MethodContext::recConstructStringLiteral(CORINFO_MODULE_HANDLE module,
                                                mdToken               metaTok,
                                                void*                 pValue,
                                                InfoAccessType        result)
  {
      if (ConstructStringLiteral == nullptr)
          ConstructStringLiteral = new LightWeightMap<DLD, DLD>();
      DLD temp;
      ZeroMemory(&temp, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      DLD temp2;
      temp.A  = (DWORDLONG)module;
      temp.B  = (DWORD)metaTok;
      temp2.A = (DWORDLONG)pValue;
      temp2.B = (DWORD)result;
  
      ConstructStringLiteral->Add(temp, temp2);
      DEBUG_REC(dmpConstructStringLiteral(temp, temp2));
  }
  void MethodContext::dmpConstructStringLiteral(DLD key, DLD value)
  {
      printf("ConstructStringLiteral key mod-%016llX tok-%08X, value pp-%016llX iat-%u", key.A, key.B, value.A, value.B);
  }
  InfoAccessType MethodContext::repConstructStringLiteral(CORINFO_MODULE_HANDLE module, mdToken metaTok, void** ppValue)
  {
      DLD temp;
      ZeroMemory(&temp, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      DLD temp2;
      temp.A = (DWORDLONG)module;
      temp.B = (DWORD)metaTok;
      AssertCodeMsg(ConstructStringLiteral != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)module);
      AssertCodeMsg(ConstructStringLiteral->GetIndex(temp) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)module);
      temp2    = ConstructStringLiteral->Get(temp);
      *ppValue = (void*)temp2.A;
      DEBUG_REP(dmpConstructStringLiteral(temp, temp2));
      return (InfoAccessType)temp2.B;
  }
  
  void MethodContext::recConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert, bool result)
  {
      if (ConvertPInvokeCalliToCall == nullptr)
          ConvertPInvokeCalliToCall = new LightWeightMap<DLD, DWORDLONG>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      key.A = (DWORDLONG)pResolvedToken->tokenScope;
      key.B = (DWORD)pResolvedToken->token;
  
      DWORDLONG value = (DWORDLONG)(result ? pResolvedToken->hMethod : 0);
  
      ConvertPInvokeCalliToCall->Add(key, value);
      DEBUG_REC(dmpConvertPInvokeCalliToCall(key, value));
  }
  void MethodContext::dmpConvertPInvokeCalliToCall(DLD key, DWORDLONG value)
  {
      printf("ConvertPInvokeCalliToCall key mod-%016llX tok-%08X, value %016llX", key.A, key.B, value);
  }
  bool MethodContext::repConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      key.A = (DWORDLONG)pResolvedToken->tokenScope;
      key.B = (DWORD)pResolvedToken->token;
  
      DWORDLONG value = ConvertPInvokeCalliToCall->Get(key);
      DEBUG_REP(dmpGetArgType(key, value));
  
      pResolvedToken->hMethod = (CORINFO_METHOD_HANDLE)value;
      return value != 0;
  }
  
  void MethodContext::recEmptyStringLiteral(void** pValue, InfoAccessType result)
  {
      if (EmptyStringLiteral == nullptr)
          EmptyStringLiteral = new DenseLightWeightMap<DLD>();
      DLD temp2;
      temp2.A = (DWORDLONG)*pValue;
      temp2.B = (DWORD)result;
  
      EmptyStringLiteral->Append(temp2);
  }
  void MethodContext::dmpEmptyStringLiteral(DWORD key, DLD value)
  {
      printf("EmptyStringLiteral key %u, value pVal-%016llX res-%u", key, value.A, value.B);
  }
  InfoAccessType MethodContext::repEmptyStringLiteral(void** ppValue)
  {
      // TODO-Cleanup: sketchy if someone calls this twice
      DLD temp2;
      temp2    = EmptyStringLiteral->Get((DWORD)0);
      *ppValue = (void*)temp2.A;
      return (InfoAccessType)temp2.B;
  }
  
  void MethodContext::recGetArgType(CORINFO_SIG_INFO*       sig,
                                    CORINFO_ARG_LIST_HANDLE args,
                                    CORINFO_CLASS_HANDLE*   vcTypeRet,
                                    CorInfoTypeWithMod      result,
                                    DWORD                   exceptionCode)
  {
      if (GetArgType == nullptr)
          GetArgType = new LightWeightMap<GetArgTypeValue, Agnostic_GetArgType_Value>();
  
      GetArgTypeValue key;
      ZeroMemory(&key, sizeof(key)); // We use the input structs as a key and use memcmp to compare.. so
                                     // we need to zero out padding too
      // Only setting values for things the EE seems to pay attention to... this is necessary since some of the values
      // are unset and fail our precise comparisons ...
      key.flags                  = (DWORD)sig->flags;
      key.numArgs                = (DWORD)sig->numArgs;
      key.sigInst_classInstCount = (DWORD)sig->sigInst.classInstCount;
      key.sigInst_classInst_Index =
          (DWORD)GetArgType->AddBuffer((unsigned char*)sig->sigInst.classInst, sig->sigInst.classInstCount * 8);
      key.sigInst_methInstCount = (DWORD)sig->sigInst.methInstCount;
      key.sigInst_methInst_Index =
          (DWORD)GetArgType->AddBuffer((unsigned char*)sig->sigInst.methInst, sig->sigInst.methInstCount * 8);
      key.scope = (DWORDLONG)sig->scope;
      key.args  = (DWORDLONG)args;
  
      Agnostic_GetArgType_Value value;
      value.vcTypeRet     = (DWORDLONG)*vcTypeRet;
      value.result        = (DWORD)result;
      value.exceptionCode = (DWORD)exceptionCode;
  
      GetArgType->Add(key, value);
      DEBUG_REC(dmpGetArgType(key, value));
  }
  void MethodContext::dmpGetArgType(const GetArgTypeValue& key, const Agnostic_GetArgType_Value& value)
  {
      printf("GetArgType key flg-%08X na-%u cc-%u ci-%u mc-%u mi-%u scp-%016llX arg-%016llX", key.flags, key.numArgs,
             key.sigInst_classInstCount, key.sigInst_classInst_Index, key.sigInst_methInstCount,
             key.sigInst_methInst_Index, key.scope, key.args);
      printf(", value rt-%016llX ci-%u excp-%08X", value.vcTypeRet, value.result, value.exceptionCode);
  }
  CorInfoTypeWithMod MethodContext::repGetArgType(CORINFO_SIG_INFO*       sig,
                                                  CORINFO_ARG_LIST_HANDLE args,
                                                  CORINFO_CLASS_HANDLE*   vcTypeRet,
                                                  DWORD*                  exceptionCode)
  {
      GetArgTypeValue key;
      ZeroMemory(&key, sizeof(GetArgTypeValue)); // We use the input structs as a key and use memcmp to compare.. so
                                                 // we need to zero out padding too
  
      AssertCodeMsg(GetArgType != nullptr, EXCEPTIONCODE_MC,
                    "Didn't find %016llx, %016llx.  probably a missing exception in getArgType", key.scope, key.args);
      key.flags                  = (DWORD)sig->flags;
      key.numArgs                = (DWORD)sig->numArgs;
      key.sigInst_classInstCount = (DWORD)sig->sigInst.classInstCount;
      key.sigInst_classInst_Index =
          (DWORD)GetArgType->Contains((unsigned char*)sig->sigInst.classInst, sig->sigInst.classInstCount * 8);
      key.sigInst_methInstCount = (DWORD)sig->sigInst.methInstCount;
      key.sigInst_methInst_Index =
          (DWORD)GetArgType->Contains((unsigned char*)sig->sigInst.methInst, sig->sigInst.methInstCount * 8);
      key.scope = (DWORDLONG)sig->scope;
      key.args  = (DWORDLONG)args;
  
      AssertCodeMsg(GetArgType->GetIndex(key) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llx, %016llx.  probably a missing exception in getArgType", key.scope, key.args);
  
      Agnostic_GetArgType_Value value = GetArgType->Get(key);
      *vcTypeRet                      = (CORINFO_CLASS_HANDLE)value.vcTypeRet;
      CorInfoTypeWithMod temp         = (CorInfoTypeWithMod)value.result;
      *exceptionCode                  = (DWORD)value.exceptionCode;
  
      DEBUG_REP(dmpGetArgType(key, value));
      return temp;
  }
  
  void MethodContext::recGetArgNext(CORINFO_ARG_LIST_HANDLE args, CORINFO_ARG_LIST_HANDLE result)
  {
      if (GetArgNext == nullptr)
          GetArgNext = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      GetArgNext->Add((DWORDLONG)args, (DWORDLONG)result);
      DEBUG_REC(dmpGetArgNext((DWORDLONG)args, (DWORDLONG)result));
  }
  void MethodContext::dmpGetArgNext(DWORDLONG key, DWORDLONG value)
  {
      printf("GetArgNext key %016llX, value %016llX", key, value);
  }
  CORINFO_ARG_LIST_HANDLE MethodContext::repGetArgNext(CORINFO_ARG_LIST_HANDLE args)
  {
      CORINFO_ARG_LIST_HANDLE temp = (CORINFO_ARG_LIST_HANDLE)GetArgNext->Get((DWORDLONG)args);
      DEBUG_REP(dmpGetArgNext((DWORDLONG)args, (DWORDLONG)temp));
      return temp;
  }
  void MethodContext::recGetMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO* sig, CORINFO_CLASS_HANDLE memberParent)
  {
      if (GetMethodSig == nullptr)
          GetMethodSig = new LightWeightMap<DLDL, Agnostic_CORINFO_SIG_INFO>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      key.A = (DWORDLONG)ftn;
      key.B = (DWORDLONG)memberParent;
  
      Agnostic_CORINFO_SIG_INFO value = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(*sig, GetMethodSig);
  
      GetMethodSig->Add(key, value);
      DEBUG_REC(dmpGetMethodSig(key, value));
  }
  void MethodContext::dmpGetMethodSig(DLDL key, const Agnostic_CORINFO_SIG_INFO& value)
  {
      printf("GetMethodSig key ftn-%016llX prt-%016llX, value %s", key.A, key.B,
             SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(value).c_str());
  }
  void MethodContext::repGetMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO* sig, CORINFO_CLASS_HANDLE memberParent)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      Agnostic_CORINFO_SIG_INFO value;
  
      key.A = (DWORDLONG)ftn;
      key.B = (DWORDLONG)memberParent;
  
      value = GetMethodSig->Get(key);
  
      *sig = SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(value, GetMethodSig);
  
      DEBUG_REP(dmpGetMethodSig(key, value));
  }
  
  void MethodContext::recGetArgClass(CORINFO_SIG_INFO*       sig,
                                     CORINFO_ARG_LIST_HANDLE args,
                                     CORINFO_CLASS_HANDLE    result,
                                     DWORD                   exceptionCode)
  {
      if (GetArgClass == nullptr)
          GetArgClass = new LightWeightMap<GetArgClassValue, Agnostic_GetArgClass_Value>();
  
      GetArgClassValue key;
      ZeroMemory(&key, sizeof(GetArgClassValue)); // We use the input structs as a key and use memcmp to compare.. so
                                                  // we need to zero out padding too
      // Only setting values for things the EE seems to pay attention to... this is necessary since some of the values
      // are unset and fail our precise comparisions...
      key.sigInst_classInstCount = (DWORD)sig->sigInst.classInstCount;
      key.sigInst_classInst_Index =
          (DWORD)GetArgClass->AddBuffer((unsigned char*)sig->sigInst.classInst, sig->sigInst.classInstCount * 8);
      key.sigInst_methInstCount = (DWORD)sig->sigInst.methInstCount;
      key.sigInst_methInst_Index =
          (DWORD)GetArgClass->AddBuffer((unsigned char*)sig->sigInst.methInst, sig->sigInst.methInstCount * 8);
      key.scope = (DWORDLONG)sig->scope;
      key.args  = (DWORDLONG)args;
  
      Agnostic_GetArgClass_Value value;
      value.result        = (DWORDLONG)result;
      value.exceptionCode = exceptionCode;
  
      GetArgClass->Add(key, value);
      DEBUG_REC(dmpGetArgClass(key, value));
  }
  void MethodContext::dmpGetArgClass(const GetArgClassValue& key, const Agnostic_GetArgClass_Value& value)
  {
      printf("GetArgClass key cc-%u ci-%u mc-%u mi-%u scp-%016llX args-%016llX", key.sigInst_classInstCount,
             key.sigInst_classInst_Index, key.sigInst_methInstCount, key.sigInst_methInst_Index, key.scope, key.args);
      printf(", value %016llX excp-%08X", value.result, value.exceptionCode);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetArgClass(CORINFO_SIG_INFO*       sig,
                                                     CORINFO_ARG_LIST_HANDLE args,
                                                     DWORD*                  exceptionCode)
  {
      GetArgClassValue key;
      ZeroMemory(&key, sizeof(GetArgClassValue)); // We use the input structs as a key and use memcmp to compare.. so
                                                  // we need to zero out padding too
  
      AssertCodeMsg(GetArgClass != nullptr, EXCEPTIONCODE_MC,
                    "Didn't find %016llx, %016llx.  probably a missing exception in getArgClass", key.scope, key.args);
      key.sigInst_classInstCount = (DWORD)sig->sigInst.classInstCount;
      key.sigInst_classInst_Index =
          (DWORD)GetArgClass->Contains((unsigned char*)sig->sigInst.classInst, sig->sigInst.classInstCount * 8);
      key.sigInst_methInstCount = (DWORD)sig->sigInst.methInstCount;
      key.sigInst_methInst_Index =
          (DWORD)GetArgClass->Contains((unsigned char*)sig->sigInst.methInst, sig->sigInst.methInstCount * 8);
      key.scope = (DWORDLONG)sig->scope;
      key.args  = (DWORDLONG)args;
  
      AssertCodeMsg(GetArgClass->GetIndex(key) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llx, %016llx.  probably a missing exception in getArgClass", key.scope, key.args);
  
      Agnostic_GetArgClass_Value value = GetArgClass->Get(key);
      *exceptionCode                   = value.exceptionCode;
      DEBUG_REP(dmpGetArgClass(key, value));
  
      return (CORINFO_CLASS_HANDLE)value.result;
  }
  
  void MethodContext::recGetHFAType(CORINFO_CLASS_HANDLE clsHnd, CorInfoHFAElemType result)
  {
      if (GetHFAType == nullptr)
          GetHFAType = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetHFAType->Add((DWORDLONG)clsHnd, (DWORD)result);
      DEBUG_REC(dmpGetHFAType((DWORDLONG)clsHnd, (DWORD)result));
      return;
  }
  
  void MethodContext::dmpGetHFAType(DWORDLONG key, DWORD value)
  {
      printf("GetHFAType key %016llX, value %u ", key, value);
      return;
  }
  
  CorInfoHFAElemType MethodContext::repGetHFAType(CORINFO_CLASS_HANDLE clsHnd)
  {
      DWORD value;
  
      AssertCodeMsg(GetHFAType != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)clsHnd);
      AssertCodeMsg(GetHFAType->GetIndex((DWORDLONG)clsHnd) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)clsHnd);
  
      value = GetHFAType->Get((DWORDLONG)clsHnd);
      DEBUG_REP(dmpGetHFAType((DWORDLONG)clsHnd, value));
      return (CorInfoHFAElemType)value;
  }
  
  void MethodContext::recGetMethodInfo(CORINFO_METHOD_HANDLE ftn,
                                       CORINFO_METHOD_INFO*  info,
                                       bool                  result,
                                       DWORD                 exceptionCode)
  {
      if (GetMethodInfo == nullptr)
          GetMethodInfo = new LightWeightMap<DWORDLONG, Agnostic_GetMethodInfo>();
  
      Agnostic_GetMethodInfo value;
      ZeroMemory(&value, sizeof(Agnostic_GetMethodInfo));
  
      if (result)
      {
          value.info.ftn                         = (DWORDLONG)info->ftn;
          value.info.scope                       = (DWORDLONG)info->scope;
          value.info.ILCode_offset               = (DWORD)GetMethodInfo->AddBuffer(info->ILCode, info->ILCodeSize);
          value.info.ILCodeSize                  = (DWORD)info->ILCodeSize;
          value.info.maxStack                    = (DWORD)info->maxStack;
          value.info.EHcount                     = (DWORD)info->EHcount;
          value.info.options                     = (DWORD)info->options;
          value.info.regionKind                  = (DWORD)info->regionKind;
          value.info.args.callConv               = (DWORD)info->args.callConv;
          value.info.args.retTypeClass           = (DWORDLONG)info->args.retTypeClass;
          value.info.args.retTypeSigClass        = (DWORDLONG)info->args.retTypeSigClass;
          value.info.args.retType                = (DWORD)info->args.retType;
          value.info.args.flags                  = (DWORD)info->args.flags;
          value.info.args.numArgs                = (DWORD)info->args.numArgs;
          value.info.args.sigInst_classInstCount = (DWORD)info->args.sigInst.classInstCount;
          value.info.args.sigInst_classInst_Index =
              (DWORD)GetMethodInfo->AddBuffer((unsigned char*)info->args.sigInst.classInst,
                                              info->args.sigInst.classInstCount * 8); // porting issue
          value.info.args.sigInst_methInstCount = (DWORD)info->args.sigInst.methInstCount;
          value.info.args.sigInst_methInst_Index =
              (DWORD)GetMethodInfo->AddBuffer((unsigned char*)info->args.sigInst.methInst,
                                              info->args.sigInst.methInstCount * 8); // porting issue
          value.info.args.args       = (DWORDLONG)info->args.args;
          value.info.args.cbSig      = (DWORD)info->args.cbSig;
          value.info.args.pSig_Index = (DWORD)GetMethodInfo->AddBuffer((unsigned char*)info->args.pSig, info->args.cbSig);
          value.info.args.scope      = (DWORDLONG)info->args.scope;
          value.info.args.token      = (DWORD)info->args.token;
          value.info.locals.callConv = (DWORD)info->locals.callConv;
          value.info.locals.retTypeClass           = (DWORDLONG)info->locals.retTypeClass;
          value.info.locals.retTypeSigClass        = (DWORDLONG)info->locals.retTypeSigClass;
          value.info.locals.retType                = (DWORD)info->locals.retType;
          value.info.locals.flags                  = (DWORD)info->locals.flags;
          value.info.locals.numArgs                = (DWORD)info->locals.numArgs;
          value.info.locals.sigInst_classInstCount = (DWORD)info->locals.sigInst.classInstCount;
          value.info.locals.sigInst_classInst_Index =
              (DWORD)GetMethodInfo->AddBuffer((unsigned char*)info->locals.sigInst.classInst,
                                              info->locals.sigInst.classInstCount * 8); // porting issue
          value.info.locals.sigInst_methInstCount = (DWORD)info->locals.sigInst.methInstCount;
          value.info.locals.sigInst_methInst_Index =
              (DWORD)GetMethodInfo->AddBuffer((unsigned char*)info->locals.sigInst.methInst,
                                              info->locals.sigInst.methInstCount * 8); // porting issue
          value.info.locals.args  = (DWORDLONG)info->locals.args;
          value.info.locals.cbSig = (DWORD)info->locals.cbSig;
          value.info.locals.pSig_Index =
              (DWORD)GetMethodInfo->AddBuffer((unsigned char*)info->locals.pSig, info->locals.cbSig);
          value.info.locals.scope = (DWORDLONG)info->locals.scope;
          value.info.locals.token = (DWORD)info->locals.token;
      }
      value.result        = result;
      value.exceptionCode = (DWORD)exceptionCode;
  
      GetMethodInfo->Add((DWORDLONG)ftn, value);
      DEBUG_REC(dmpGetMethodInfo((DWORDLONG)ftn, value));
  }
  void MethodContext::dmpGetMethodInfo(DWORDLONG key, const Agnostic_GetMethodInfo& value)
  {
      printf("GetMethodInfo key ftn-%016llX", key);
      printf(", value res-%u ftn-%016llX scp-%016llX ilo-%u ils-%u ms-%u ehc-%u opt-%08X rk-%u "
             "args{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u "
             "pSig_Index-%u scp-%016llX tok-%08X} "
             "locals{cc-%u rc-%016llX rts-%016llX rt-%u(%s) flg-%08X nA-%u cc-%u ci-%u mc-%u mi-%u arg-%016llX cb-%u "
             "pSig_Index-%u scp-%016llX tok-%08X} "
             "excp-%08X",
             value.result, value.info.ftn, value.info.scope, value.info.ILCode_offset, value.info.ILCodeSize,
             value.info.maxStack, value.info.EHcount, value.info.options, value.info.regionKind, value.info.args.callConv,
             value.info.args.retTypeClass, value.info.args.retTypeSigClass, value.info.args.retType,
             toString((CorInfoType)value.info.args.retType), value.info.args.flags, value.info.args.numArgs,
             value.info.args.sigInst_classInstCount, value.info.args.sigInst_classInst_Index,
             value.info.args.sigInst_methInstCount, value.info.args.sigInst_methInst_Index, value.info.args.args,
             value.info.args.cbSig, value.info.args.pSig_Index, value.info.args.scope, value.info.args.token,
             value.info.locals.callConv, value.info.locals.retTypeClass, value.info.locals.retTypeSigClass,
             value.info.locals.retType, toString((CorInfoType)value.info.locals.retType), value.info.locals.flags,
             value.info.locals.numArgs, value.info.locals.sigInst_classInstCount,
             value.info.locals.sigInst_classInst_Index, value.info.locals.sigInst_methInstCount,
             value.info.locals.sigInst_methInst_Index, value.info.locals.args, value.info.locals.cbSig,
             value.info.locals.pSig_Index, value.info.locals.scope, value.info.locals.token, value.exceptionCode);
  }
  bool MethodContext::repGetMethodInfo(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info, DWORD* exceptionCode)
  {
      Agnostic_GetMethodInfo value;
      AssertCodeMsg(GetMethodInfo != nullptr, EXCEPTIONCODE_MC,
                    "Didn't find %016llx.  probably a missing exception in getMethodInfo", (DWORDLONG)ftn);
      AssertCodeMsg(GetMethodInfo->GetIndex((DWORDLONG)ftn) != -1, EXCEPTIONCODE_MC,
                    "Didn't find %016llx.  probably a missing exception in getMethodInfo", (DWORDLONG)ftn);
  
      value = GetMethodInfo->Get((DWORDLONG)ftn);
      if (value.result)
      {
          info->ftn                         = (CORINFO_METHOD_HANDLE)value.info.ftn;
          info->scope                       = (CORINFO_MODULE_HANDLE)value.info.scope;
          info->ILCode                      = GetMethodInfo->GetBuffer(value.info.ILCode_offset);
          info->ILCodeSize                  = (unsigned)value.info.ILCodeSize;
          info->maxStack                    = (unsigned)value.info.maxStack;
          info->EHcount                     = (unsigned)value.info.EHcount;
          info->options                     = (CorInfoOptions)value.info.options;
          info->regionKind                  = (CorInfoRegionKind)value.info.regionKind;
          info->args.callConv               = (CorInfoCallConv)value.info.args.callConv;
          info->args.retTypeClass           = (CORINFO_CLASS_HANDLE)value.info.args.retTypeClass;
          info->args.retTypeSigClass        = (CORINFO_CLASS_HANDLE)value.info.args.retTypeSigClass;
          info->args.retType                = (CorInfoType)value.info.args.retType;
          info->args.flags                  = (unsigned)value.info.args.flags;
          info->args.numArgs                = (unsigned)value.info.args.numArgs;
          info->args.sigInst.classInstCount = (unsigned)value.info.args.sigInst_classInstCount;
          info->args.sigInst.classInst =
              (CORINFO_CLASS_HANDLE*)GetMethodInfo->GetBuffer(value.info.args.sigInst_classInst_Index);
          info->args.sigInst.methInstCount = (unsigned)value.info.args.sigInst_methInstCount;
          info->args.sigInst.methInst =
              (CORINFO_CLASS_HANDLE*)GetMethodInfo->GetBuffer(value.info.args.sigInst_methInst_Index);
          info->args.args                     = (CORINFO_ARG_LIST_HANDLE)value.info.args.args;
          info->args.cbSig                    = (unsigned int)value.info.args.cbSig;
          info->args.pSig                     = (PCCOR_SIGNATURE)GetMethodInfo->GetBuffer(value.info.args.pSig_Index);
          info->args.scope                    = (CORINFO_MODULE_HANDLE)value.info.args.scope;
          info->args.token                    = (mdToken)value.info.args.token;
          info->locals.callConv               = (CorInfoCallConv)value.info.locals.callConv;
          info->locals.retTypeClass           = (CORINFO_CLASS_HANDLE)value.info.locals.retTypeClass;
          info->locals.retTypeSigClass        = (CORINFO_CLASS_HANDLE)value.info.locals.retTypeSigClass;
          info->locals.retType                = (CorInfoType)value.info.locals.retType;
          info->locals.flags                  = (unsigned)value.info.locals.flags;
          info->locals.numArgs                = (unsigned)value.info.locals.numArgs;
          info->locals.sigInst.classInstCount = (unsigned)value.info.locals.sigInst_classInstCount;
          info->locals.sigInst.classInst =
              (CORINFO_CLASS_HANDLE*)GetMethodInfo->GetBuffer(value.info.locals.sigInst_classInst_Index);
          info->locals.sigInst.methInstCount = (unsigned)value.info.locals.sigInst_methInstCount;
          info->locals.sigInst.methInst =
              (CORINFO_CLASS_HANDLE*)GetMethodInfo->GetBuffer(value.info.locals.sigInst_methInst_Index);
          info->locals.args  = (CORINFO_ARG_LIST_HANDLE)value.info.locals.args;
          info->locals.cbSig = (unsigned int)value.info.locals.cbSig;
          info->locals.pSig  = (PCCOR_SIGNATURE)GetMethodInfo->GetBuffer(value.info.locals.pSig_Index);
          info->locals.scope = (CORINFO_MODULE_HANDLE)value.info.locals.scope;
          info->locals.token = (mdToken)value.info.locals.token;
      }
      bool result    = value.result;
      *exceptionCode = (DWORD)value.exceptionCode;
      DEBUG_REP(dmpGetMethodInfo((DWORDLONG)ftn, value));
      return result;
  }
  
  void MethodContext::recGetNewHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                      CORINFO_METHOD_HANDLE   callerHandle,
                                      bool* pHasSideEffects,
                                      CorInfoHelpFunc         result)
  {
      if (GetNewHelper == nullptr)
          GetNewHelper = new LightWeightMap<Agnostic_GetNewHelper, DD>();
  
      Agnostic_GetNewHelper key;
      ZeroMemory(&key, sizeof(Agnostic_GetNewHelper)); // We use the input structs as a key and use memcmp to compare.. so
                                                       // we need to zero out padding too
      key.hClass       = (DWORDLONG)pResolvedToken->hClass;
      key.callerHandle = (DWORDLONG)callerHandle;
  
      DD value;
      value.A = (pHasSideEffects != nullptr) ? (DWORD)(*pHasSideEffects ? 1 : 0) : (DWORD)0;
      value.B = (DWORD)result;
  
      GetNewHelper->Add(key, value);
      DEBUG_REC(dmpGetNewHelper(key, value));
  }
  void MethodContext::dmpGetNewHelper(const Agnostic_GetNewHelper& key, DD value)
  {
      printf("GetNewHelper key cls-%016llX chan-%016llX, hasSideEffects-%u, value res-%u", key.hClass, key.callerHandle, value.A, value.B);
  }
  CorInfoHelpFunc MethodContext::repGetNewHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                                 CORINFO_METHOD_HANDLE   callerHandle,
                                                 bool* pHasSideEffects)
  {
      Agnostic_GetNewHelper key;
      ZeroMemory(&key, sizeof(Agnostic_GetNewHelper)); // We use the input structs as a key and use memcmp to compare.. so
                                                       // we need to zero out padding too
      key.hClass       = (DWORDLONG)pResolvedToken->hClass;
      key.callerHandle = (DWORDLONG)callerHandle;
  
      AssertCodeMsg(GetNewHelper != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)key.hClass);
      AssertCodeMsg(GetNewHelper->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)key.hClass);
  
      DD value;
      value = GetNewHelper->Get(key);
      if (pHasSideEffects != nullptr)
      {
          *pHasSideEffects = (value.A == 0) ? false : true;
      }
      CorInfoHelpFunc result = (CorInfoHelpFunc)value.B;
  
      DEBUG_REP(dmpGetNewHelper(key, value));
      return result;
  }
  
  void MethodContext::recEmbedGenericHandle(CORINFO_RESOLVED_TOKEN*       pResolvedToken,
                                            BOOL                          fEmbedParent,
                                            CORINFO_GENERICHANDLE_RESULT* pResult)
  {
      if (EmbedGenericHandle == nullptr)
          EmbedGenericHandle = new LightWeightMap<Agnostic_EmbedGenericHandle, Agnostic_CORINFO_GENERICHANDLE_RESULT>();
  
      Agnostic_EmbedGenericHandle key;
      ZeroMemory(&key, sizeof(Agnostic_EmbedGenericHandle)); // We use the input structs as a key and use memcmp to
                                                             // compare.. so we need to zero out padding too
      key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, EmbedGenericHandle);
      key.fEmbedParent  = (DWORD)fEmbedParent;
  
      Agnostic_CORINFO_GENERICHANDLE_RESULT value;
      value.lookup            = SpmiRecordsHelper::StoreAgnostic_CORINFO_LOOKUP(&pResult->lookup);
      value.compileTimeHandle = (DWORDLONG)pResult->compileTimeHandle;
      value.handleType        = (DWORD)pResult->handleType;
  
      EmbedGenericHandle->Add(key, value);
      DEBUG_REC(dmpEmbedGenericHandle(key, value));
  }
  void MethodContext::dmpEmbedGenericHandle(const Agnostic_EmbedGenericHandle&           key,
                                            const Agnostic_CORINFO_GENERICHANDLE_RESULT& value)
  {
      printf("EmbedGenericHandle key rt{%s} emb-%u\n",
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ResolvedToken).c_str(), key.fEmbedParent);
      printf(", value %s", SpmiDumpHelper::DumpAgnostic_CORINFO_LOOKUP(value.lookup).c_str());
      printf(" cth-%016llX ht-%u", value.compileTimeHandle, value.handleType);
  }
  void MethodContext::repEmbedGenericHandle(CORINFO_RESOLVED_TOKEN*       pResolvedToken,
                                            BOOL                          fEmbedParent,
                                            CORINFO_GENERICHANDLE_RESULT* pResult)
  {
      Agnostic_EmbedGenericHandle key;
      ZeroMemory(&key, sizeof(Agnostic_EmbedGenericHandle)); // We use the input structs as a key and use memcmp to
                                                             // compare.. so we need to zero out padding too
  
      AssertCodeMsg(EmbedGenericHandle != nullptr, EXCEPTIONCODE_MC, "Encountered an empty LWM while looking for ...");
      key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, EmbedGenericHandle);
      key.fEmbedParent  = (DWORD)fEmbedParent;
  
      AssertCodeMsg(EmbedGenericHandle->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find ...");
  
      Agnostic_CORINFO_GENERICHANDLE_RESULT value;
      value = EmbedGenericHandle->Get(key);
  
      pResult->lookup            = SpmiRecordsHelper::RestoreCORINFO_LOOKUP(value.lookup);
      pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)value.compileTimeHandle;
      pResult->handleType        = (CorInfoGenericHandleType)value.handleType;
  
      DEBUG_REP(dmpEmbedGenericHandle(key, value));
  }
  
  void MethodContext::recGetEHinfo(CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
  {
      if (GetEHinfo == nullptr)
          GetEHinfo = new LightWeightMap<DLD, Agnostic_CORINFO_EH_CLAUSE>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      Agnostic_CORINFO_EH_CLAUSE value;
  
      key.A = (DWORDLONG)ftn;
      key.B = (DWORD)EHnumber;
  
      value.Flags         = (DWORD)clause->Flags;
      value.TryOffset     = (DWORD)clause->TryOffset;
      value.TryLength     = (DWORD)clause->TryLength;
      value.HandlerOffset = (DWORD)clause->HandlerOffset;
      value.HandlerLength = (DWORD)clause->HandlerLength;
      value.ClassToken    = (DWORD)clause->ClassToken;
  
      GetEHinfo->Add(key, value);
      DEBUG_REC(dmpGetEHinfo(key, value));
  }
  void MethodContext::dmpGetEHinfo(DLD key, const Agnostic_CORINFO_EH_CLAUSE& value)
  {
      printf("GetEHinfo key ftn-%016llX ehn-%u, value flg-%u to-%u tl-%u ho-%u hl-%u ct-%u", key.A, key.B, value.Flags,
             value.TryOffset, value.TryLength, value.HandlerOffset, value.HandlerLength, value.ClassToken);
  }
  void MethodContext::repGetEHinfo(CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      Agnostic_CORINFO_EH_CLAUSE value;
  
      key.A = (DWORDLONG)ftn;
      key.B = (DWORD)EHnumber;
  
      value = GetEHinfo->Get(key);
  
      clause->Flags         = (CORINFO_EH_CLAUSE_FLAGS)value.Flags;
      clause->TryOffset     = (DWORD)value.TryOffset;
      clause->TryLength     = (DWORD)value.TryLength;
      clause->HandlerOffset = (DWORD)value.HandlerOffset;
      clause->HandlerLength = (DWORD)value.HandlerLength;
      clause->ClassToken    = (DWORD)value.ClassToken;
      DEBUG_REP(dmpGetEHinfo(key, value));
  }
  
  void MethodContext::recGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
                                               unsigned*             offsetOfIndirection,
                                               unsigned*             offsetAfterIndirection,
                                               bool*                 isRelative)
  {
      if (GetMethodVTableOffset == nullptr)
          GetMethodVTableOffset = new LightWeightMap<DWORDLONG, DDD>();
  
      DDD value;
      value.A = (DWORD)*offsetOfIndirection;
      value.B = (DWORD)*offsetAfterIndirection;
      value.C = *isRelative ? 1 : 0;
      GetMethodVTableOffset->Add((DWORDLONG)method, value);
      DEBUG_REC(dmpGetMethodVTableOffset((DWORDLONG)method, value));
  }
  void MethodContext::dmpGetMethodVTableOffset(DWORDLONG key, DDD value)
  {
      printf("GetMethodVTableOffset key ftn-%016llX, value offi-%u, offa-%u. offr-%d", key, value.A, value.B, value.C);
  }
  void MethodContext::repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
                                               unsigned*             offsetOfIndirection,
                                               unsigned*             offsetAfterIndirection,
                                               bool*                 isRelative)
  {
      DDD value;
  
      AssertCodeMsg(GetMethodVTableOffset != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)method);
      AssertCodeMsg(GetMethodVTableOffset->GetIndex((DWORDLONG)method) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)method);
      value = GetMethodVTableOffset->Get((DWORDLONG)method);
  
      *offsetOfIndirection    = (unsigned)value.A;
      *offsetAfterIndirection = (unsigned)value.B;
      *isRelative             = (value.C != 0);
      DEBUG_REP(dmpGetMethodVTableOffset((DWORDLONG)method, value));
  }
  
  void MethodContext::recResolveVirtualMethod(CORINFO_METHOD_HANDLE  virtMethod,
                                              CORINFO_CLASS_HANDLE   implClass,
                                              CORINFO_CONTEXT_HANDLE ownerType,
                                              CORINFO_METHOD_HANDLE  result)
  {
      if (ResolveVirtualMethod == nullptr)
      {
          ResolveVirtualMethod = new LightWeightMap<Agnostic_ResolveVirtualMethod, DWORDLONG>();
      }
  
      Agnostic_ResolveVirtualMethod key;
      key.virtualMethod     = (DWORDLONG)virtMethod;
      key.implementingClass = (DWORDLONG)implClass;
      key.ownerType         = (DWORDLONG)ownerType;
      ResolveVirtualMethod->Add(key, (DWORDLONG)result);
      DEBUG_REC(dmpResolveVirtualMethod(key, result));
  }
  
  void MethodContext::dmpResolveVirtualMethod(const Agnostic_ResolveVirtualMethod& key, DWORDLONG value)
  {
      printf("ResolveVirtualMethod virtMethod-%016llX, implClass-%016llX, ownerType--%016llX, result-%016llX",
             key.virtualMethod, key.implementingClass, key.ownerType, value);
  }
  
  CORINFO_METHOD_HANDLE MethodContext::repResolveVirtualMethod(CORINFO_METHOD_HANDLE  virtMethod,
                                                               CORINFO_CLASS_HANDLE   implClass,
                                                               CORINFO_CONTEXT_HANDLE ownerType)
  {
      Agnostic_ResolveVirtualMethod key;
      key.virtualMethod     = (DWORDLONG)virtMethod;
      key.implementingClass = (DWORDLONG)implClass;
      key.ownerType         = (DWORDLONG)ownerType;
  
      AssertCodeMsg(ResolveVirtualMethod != nullptr, EXCEPTIONCODE_MC,
                    "No ResolveVirtualMap map for %016llX-%016llX-%016llX", key.virtualMethod, key.implementingClass,
                    key.ownerType);
      AssertCodeMsg(ResolveVirtualMethod->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX-%016llx-%016llX",
                    key.virtualMethod, key.implementingClass, key.ownerType);
      DWORDLONG result = ResolveVirtualMethod->Get(key);
  
      DEBUG_REP(dmpResolveVirtualMethod(key, result));
  
      return (CORINFO_METHOD_HANDLE)result;
  }
  
  void MethodContext::recGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn,
                                         bool*                 requiresInstMethodTableArg,
                                         CORINFO_METHOD_HANDLE result)
  {
      if (GetUnboxedEntry == nullptr)
      {
          GetUnboxedEntry = new LightWeightMap<DWORDLONG, DLD>();
      }
  
      DWORDLONG key = (DWORDLONG)ftn;
      DLD       value;
      value.A = (DWORDLONG)result;
      if (requiresInstMethodTableArg != nullptr)
      {
          value.B = (DWORD)*requiresInstMethodTableArg ? 1 : 0;
      }
      else
      {
          value.B = 0;
      }
      GetUnboxedEntry->Add(key, value);
      DEBUG_REC(dmpGetUnboxedEntry(key, value));
  }
  
  void MethodContext::dmpGetUnboxedEntry(DWORDLONG key, DLD value)
  {
      printf("GetUnboxedEntry ftn-%016llX, result-%016llX, requires-inst-%u", key, value.A, value.B);
  }
  
  CORINFO_METHOD_HANDLE MethodContext::repGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg)
  {
      DWORDLONG key = (DWORDLONG)ftn;
  
      AssertCodeMsg(GetUnboxedEntry != nullptr, EXCEPTIONCODE_MC, "No GetUnboxedEntry map for %016llX", key);
      AssertCodeMsg(GetUnboxedEntry->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", key);
      DLD result = GetUnboxedEntry->Get(key);
  
      DEBUG_REP(dmpGetUnboxedEntry(key, result));
  
      if (requiresInstMethodTableArg != nullptr)
      {
          *requiresInstMethodTableArg = (result.B == 1);
      }
  
      return (CORINFO_METHOD_HANDLE)(result.A);
  }
  
  void MethodContext::recGetDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result)
  {
      if (GetDefaultEqualityComparerClass == nullptr)
          GetDefaultEqualityComparerClass = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      GetDefaultEqualityComparerClass->Add((DWORDLONG)cls, (DWORDLONG)result);
  }
  void MethodContext::dmpGetDefaultEqualityComparerClass(DWORDLONG key, DWORDLONG value)
  {
      printf("GetDefaultEqualityComparerClass key cls-%016llX, value cls-%016llX", key, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls)
  {
      CORINFO_CLASS_HANDLE result = (CORINFO_CLASS_HANDLE)GetDefaultEqualityComparerClass->Get((DWORDLONG)cls);
      return result;
  }
  
  void MethodContext::recGetTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_CLASS_HANDLE result)
  {
      if (GetTokenTypeAsHandle == nullptr)
          GetTokenTypeAsHandle = new LightWeightMap<GetTokenTypeAsHandleValue, DWORDLONG>();
  
      GetTokenTypeAsHandleValue key;
      ZeroMemory(&key, sizeof(GetTokenTypeAsHandleValue)); // We use the input structs as a key and use memcmp to
                                                           // compare.. so we need to zero out padding too
  
      key.hMethod = (DWORDLONG)pResolvedToken->hMethod;
      key.hField  = (DWORDLONG)pResolvedToken->hField;
  
      GetTokenTypeAsHandle->Add(key, (DWORDLONG)result);
  }
  void MethodContext::dmpGetTokenTypeAsHandle(const GetTokenTypeAsHandleValue& key, DWORDLONG value)
  {
      printf("GetTokenTypeAsHandle key ftn-%016llX fld-%016llX, value cls-%016llX", key.hMethod, key.hField, value);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken)
  {
      GetTokenTypeAsHandleValue key;
      ZeroMemory(&key, sizeof(GetTokenTypeAsHandleValue)); // We use the input structs as a key and use memcmp to
                                                           // compare.. so we need to zero out padding too
  
      key.hMethod = (DWORDLONG)pResolvedToken->hMethod;
      key.hField  = (DWORDLONG)pResolvedToken->hField;
  
      CORINFO_CLASS_HANDLE value = (CORINFO_CLASS_HANDLE)GetTokenTypeAsHandle->Get(key);
      return value;
  }
  
  void MethodContext::recGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                      CORINFO_METHOD_HANDLE   callerHandle,
                                      CORINFO_ACCESS_FLAGS    flags,
                                      CORINFO_FIELD_INFO*     pResult)
  {
      if (GetFieldInfo == nullptr)
          GetFieldInfo = new LightWeightMap<Agnostic_GetFieldInfo, Agnostic_CORINFO_FIELD_INFO>();
      Agnostic_GetFieldInfo key;
      ZeroMemory(&key, sizeof(Agnostic_GetFieldInfo)); // Since dd has nested structs, and we use memcmp to compare, we
                                                       // need to zero out the padding bytes too
      key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetFieldInfo);
      key.callerHandle  = (DWORDLONG)callerHandle;
      key.flags         = (DWORD)flags;
  
      Agnostic_CORINFO_FIELD_INFO value;
      value.fieldAccessor                 = (DWORD)pResult->fieldAccessor;
      value.fieldFlags                    = (DWORD)pResult->fieldFlags;
      value.helper                        = (DWORD)pResult->helper;
      value.offset                        = (DWORD)pResult->offset;
      value.fieldType                     = (DWORD)pResult->fieldType;
      value.structType                    = (DWORDLONG)pResult->structType;
      value.accessAllowed                 = (DWORD)pResult->accessAllowed;
      value.accessCalloutHelper.helperNum = (DWORD)pResult->accessCalloutHelper.helperNum;
      value.accessCalloutHelper.numArgs   = (DWORD)pResult->accessCalloutHelper.numArgs;
      value.fieldLookup                   = SpmiRecordsHelper::StoreAgnostic_CORINFO_CONST_LOOKUP(&pResult->fieldLookup);
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          value.accessCalloutHelper.args[i].constant = (DWORDLONG)pResult->accessCalloutHelper.args[i].constant;
          value.accessCalloutHelper.args[i].argType  = (DWORD)pResult->accessCalloutHelper.args[i].argType;
      }
      GetFieldInfo->Add(key, value);
      DEBUG_REC(dmpGetFieldInfo(key, value));
  }
  void MethodContext::dmpGetFieldInfo(const Agnostic_GetFieldInfo& key, const Agnostic_CORINFO_FIELD_INFO& value)
  {
      printf("GetFieldInfo key ch-%016llX flg-%08X rt{%s}\n", key.callerHandle, key.flags,
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ResolvedToken).c_str());
  
      printf(", value fa-%u fflg-%08X hlp-%u off-%u fT-%u(%s) sT-%016llX aa-%u hnum-%u na-%u {", value.fieldAccessor,
             value.fieldFlags, value.helper, value.offset, value.fieldType, toString((CorInfoType)value.fieldType),
             value.structType, value.accessAllowed, value.accessCalloutHelper.helperNum,
             value.accessCalloutHelper.numArgs);
  
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          switch ((CorInfoAccessAllowedHelperArgType)value.accessCalloutHelper.args[i].argType)
          {
              default:
                  printf("{%u: illegal}", i);
                  break;
              case CORINFO_HELPER_ARG_TYPE_Field:
                  printf("{%u: fld-%016llX}", i, value.accessCalloutHelper.args[i].constant);
                  break;
              case CORINFO_HELPER_ARG_TYPE_Method:
                  printf("{%u: mth-%016llX}", i, value.accessCalloutHelper.args[i].constant);
                  break;
              case CORINFO_HELPER_ARG_TYPE_Class:
                  printf("{%u: cls-%016llX}", i, value.accessCalloutHelper.args[i].constant);
                  break;
              case CORINFO_HELPER_ARG_TYPE_Module:
                  printf("{%u: mod-%016llX}", i, value.accessCalloutHelper.args[i].constant);
                  break;
              case CORINFO_HELPER_ARG_TYPE_Const:
                  printf("{%u: const-%016llX}", i, value.accessCalloutHelper.args[i].constant);
                  break;
          }
      }
      printf(" fl %s}", SpmiDumpHelper::DumpAgnostic_CORINFO_CONST_LOOKUP(value.fieldLookup).c_str());
  }
  void MethodContext::repGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                      CORINFO_METHOD_HANDLE   callerHandle,
                                      CORINFO_ACCESS_FLAGS    flags,
                                      CORINFO_FIELD_INFO*     pResult)
  {
      AssertCodeMsg(GetFieldInfo != nullptr, EXCEPTIONCODE_MC, "Didn't find %x", pResolvedToken->token);
  
      Agnostic_GetFieldInfo key;
      ZeroMemory(&key, sizeof(Agnostic_GetFieldInfo)); // Since dd has nested structs, and we use memcmp to compare, we
                                                       // need to zero out the padding bytes too
      key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, GetFieldInfo);
      key.callerHandle  = (DWORDLONG)callerHandle;
      key.flags         = (DWORD)flags;
  
      DWORD origFlag = key.flags;
  
      if (GetFieldInfo->GetIndex(key) == -1)
      {
  #ifdef sparseMC
          key.flags = origFlag ^ ((DWORD)CORINFO_ACCESS_THIS);
          if (GetFieldInfo->GetIndex(key) != -1)
          {
              LogDebug(
                  "Sparse - repGetFieldInfo found value with inverted CORINFO_ACCESS_THIS");
          }
          else
          {
              key.flags = origFlag ^ (DWORD)CORINFO_ACCESS_INLINECHECK;
              if (GetFieldInfo->GetIndex(key) != -1)
              {
                  LogDebug("Sparse - repGetFieldInfo found value with inverted CORINFO_ACCESS_INLINECHECK");
              }
              else
              {
                  LogException(EXCEPTIONCODE_MC, "Didn't find %x", pResolvedToken->token);
              }
          }
  #else
          LogException(EXCEPTIONCODE_MC, "Didn't find %x", pResolvedToken->token);
  #endif
      }
  
      Agnostic_CORINFO_FIELD_INFO value = GetFieldInfo->Get(key);
  
      pResult->fieldAccessor                 = (CORINFO_FIELD_ACCESSOR)value.fieldAccessor;
      pResult->fieldFlags                    = (unsigned)value.fieldFlags;
      pResult->helper                        = (CorInfoHelpFunc)value.helper;
      pResult->offset                        = (DWORD)value.offset;
      pResult->fieldType                     = (CorInfoType)value.fieldType;
      pResult->structType                    = (CORINFO_CLASS_HANDLE)value.structType;
      pResult->accessAllowed                 = (CorInfoIsAccessAllowedResult)value.accessAllowed;
      pResult->accessCalloutHelper.helperNum = (CorInfoHelpFunc)value.accessCalloutHelper.helperNum;
      pResult->accessCalloutHelper.numArgs   = (unsigned)value.accessCalloutHelper.numArgs;
      pResult->fieldLookup                   = SpmiRecordsHelper::RestoreCORINFO_CONST_LOOKUP(value.fieldLookup);
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          pResult->accessCalloutHelper.args[i].constant = (size_t)value.accessCalloutHelper.args[i].constant;
          pResult->accessCalloutHelper.args[i].argType =
              (CorInfoAccessAllowedHelperArgType)value.accessCalloutHelper.args[i].argType;
      }
      DEBUG_REP(dmpGetFieldInfo(key, value));
  }
  
  void MethodContext::recEmbedMethodHandle(CORINFO_METHOD_HANDLE handle,
                                           void**                ppIndirection,
                                           CORINFO_METHOD_HANDLE result)
  {
      if (EmbedMethodHandle == nullptr)
          EmbedMethodHandle = new LightWeightMap<DWORDLONG, DLDL>();
  
      DLDL value;
      if (ppIndirection == nullptr)
          value.A = (DWORDLONG)0;
      else
          value.A = (DWORDLONG)*ppIndirection;
      value.B     = (DWORDLONG)result;
  
      EmbedMethodHandle->Add((DWORDLONG)handle, value);
      DEBUG_REC(dmpEmbedMethodHandle((DWORDLONG)handle, value));
  }
  void MethodContext::dmpEmbedMethodHandle(DWORDLONG key, DLDL value)
  {
      printf("EmbedMethodHandle key ftn-%016llX, value pp-%016llX res-%016llX", key, value.A, value.B);
  }
  CORINFO_METHOD_HANDLE MethodContext::repEmbedMethodHandle(CORINFO_METHOD_HANDLE handle, void** ppIndirection)
  {
      DLDL value;
  
      AssertCodeMsg(EmbedMethodHandle != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)handle);
      AssertCodeMsg(EmbedMethodHandle->GetIndex((DWORDLONG)handle) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)handle);
      value = EmbedMethodHandle->Get((DWORDLONG)handle);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      DEBUG_REP(dmpEmbedMethodHandle((DWORDLONG)handle, value));
      return (CORINFO_METHOD_HANDLE)value.B;
  }
  
  void MethodContext::recGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection, void* result, CorInfoType cit)
  {
      if (GetFieldAddress == nullptr)
          GetFieldAddress = new LightWeightMap<DWORDLONG, Agnostic_GetFieldAddress>();
  
      Agnostic_GetFieldAddress value;
      if (ppIndirection == nullptr)
          value.ppIndirection = (DWORDLONG)0;
      else
          value.ppIndirection = (DWORDLONG)*ppIndirection;
      value.fieldAddress      = (DWORDLONG)result;
  
      value.fieldValue = (DWORD)-1;
  
      // Make an attempt at stashing a copy of the value
      if (result > (void*)0xffff) // TODO-Cleanup: sometimes there is a field offset?
      {
          DWORDLONG scratch = 0x4242424242424242;
          switch (cit)
          {
              case CORINFO_TYPE_BOOL:
              case CORINFO_TYPE_BYTE:
              case CORINFO_TYPE_UBYTE:
                  value.fieldValue =
                      (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(BYTE),
                                                        true); // important to not merge two fields into one address
                  break;
              case CORINFO_TYPE_CHAR:
              case CORINFO_TYPE_SHORT:
              case CORINFO_TYPE_USHORT:
                  value.fieldValue =
                      (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(WORD),
                                                        true); // important to not merge two fields into one address
                  break;
              case CORINFO_TYPE_INT:
              case CORINFO_TYPE_UINT:
              case CORINFO_TYPE_FLOAT:
                  value.fieldValue =
                      (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(DWORD),
                                                        true); // important to not merge two fields into one address
                  break;
              case CORINFO_TYPE_LONG:
              case CORINFO_TYPE_ULONG:
              case CORINFO_TYPE_DOUBLE:
                  value.fieldValue =
                      (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(DWORDLONG),
                                                        true); // important to not merge two fields into one address
                  break;
              case CORINFO_TYPE_NATIVEINT:
              case CORINFO_TYPE_NATIVEUINT:
              case CORINFO_TYPE_PTR:
                  value.fieldValue =
                      (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(size_t),
                                                        true); // important to not merge two fields into one address
                  GetFieldAddress->AddBuffer((unsigned char*)&scratch, sizeof(DWORD)); // Padding out the data so we can
                                                                                       // read it back "safetly" on x64
                  break;
              default:
                  break;
          }
      }
      GetFieldAddress->Add((DWORDLONG)field, value);
      DEBUG_REC(dmpGetFieldAddress((DWORDLONG)field, value));
  }
  void MethodContext::dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value)
  {
      printf("GetFieldAddress key fld-%016llX, value ppi-%016llX addr-%016llX val-%u", key, value.ppIndirection,
             value.fieldAddress, value.fieldValue);
  }
  void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection)
  {
      Agnostic_GetFieldAddress value;
  
      value = GetFieldAddress->Get((DWORDLONG)field);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.ppIndirection;
      void* temp;
  
      if (value.fieldValue != (DWORD)-1)
      {
          temp = (void*)GetFieldAddress->GetBuffer(value.fieldValue);
          cr->recAddressMap((void*)value.fieldAddress, temp, toCorInfoSize(repGetFieldType(field, nullptr, nullptr)));
      }
      else
          temp = (void*)value.fieldAddress;
  
      DEBUG_REP(dmpGetFieldAddress((DWORDLONG)field, value));
      return temp;
  }
  
  void MethodContext::recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field,
                                                    bool                 isSpeculative,
                                                    CORINFO_CLASS_HANDLE result)
  {
      if (GetStaticFieldCurrentClass == nullptr)
          GetStaticFieldCurrentClass = new LightWeightMap<DWORDLONG, Agnostic_GetStaticFieldCurrentClass>();
  
      Agnostic_GetStaticFieldCurrentClass value;
  
      value.classHandle   = (DWORDLONG)result;
      value.isSpeculative = isSpeculative;
  
      GetStaticFieldCurrentClass->Add((DWORDLONG)field, value);
      DEBUG_REC(dmpGetFieldAddress((DWORDLONG)field, value));
  }
  void MethodContext::dmpGetStaticFieldCurrentClass(DWORDLONG key, const Agnostic_GetStaticFieldCurrentClass& value)
  {
      printf("GetStaticFieldCurrentClass key fld-%016llX, value clsHnd-%016llX isSpeculative-%u", key, value.classHandle,
             value.isSpeculative);
  }
  CORINFO_CLASS_HANDLE MethodContext::repGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative)
  {
      Agnostic_GetStaticFieldCurrentClass value = GetStaticFieldCurrentClass->Get((DWORDLONG)field);
  
      if (pIsSpeculative != nullptr)
      {
          *pIsSpeculative = value.isSpeculative;
      }
  
      CORINFO_CLASS_HANDLE result = (CORINFO_CLASS_HANDLE)value.classHandle;
      DEBUG_REP(dmpGetStaticFieldCurrentValue((DWORDLONG)field, value));
      return result;
  }
  
  void MethodContext::recGetClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE* gcPtrs, unsigned len, unsigned result)
  {
      if (GetClassGClayout == nullptr)
          GetClassGClayout = new LightWeightMap<DWORDLONG, Agnostic_GetClassGClayout>();
  
      Agnostic_GetClassGClayout value;
  
      value.gcPtrs_Index = (DWORD)GetClassGClayout->AddBuffer((unsigned char*)gcPtrs, len * sizeof(BYTE));
      value.len          = (DWORD)len;
      value.valCount     = (DWORD)result;
  
      GetClassGClayout->Add((DWORDLONG)cls, value);
      DEBUG_REC(dmpGetClassGClayout((DWORDLONG)cls, value));
  }
  void MethodContext::dmpGetClassGClayout(DWORDLONG key, const Agnostic_GetClassGClayout& value)
  {
      printf("GetClassGCLayout key %016llX, value len %u cnt %u {", key, value.len, value.valCount);
      if (value.gcPtrs_Index != (DWORD)-1)
      {
          BYTE* ptr = (BYTE*)GetClassGClayout->GetBuffer(value.gcPtrs_Index);
          for (unsigned int i = 0; i < value.len; i++)
          {
              printf("0x%02x", ptr[i]);
              if (i + 1 < value.len)
                  printf(",");
          }
          GetClassGClayout->Unlock();
      }
      printf("}");
  }
  unsigned MethodContext::repGetClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE* gcPtrs)
  {
      Agnostic_GetClassGClayout value;
  
      AssertCodeMsg(GetClassGClayout != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)cls);
      AssertCodeMsg(GetClassGClayout->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
      value = GetClassGClayout->Get((DWORDLONG)cls);
  
      unsigned int len   = (unsigned int)value.len;
      unsigned int index = (unsigned int)value.gcPtrs_Index;
  
      if (index != (unsigned int)-1)
      {
          BYTE* ptr = (BYTE*)GetClassGClayout->GetBuffer(index);
          for (unsigned int i = 0; i < len; i++)
              gcPtrs[i]       = ptr[i];
      }
      DEBUG_REP(dmpGetClassGClayout((DWORDLONG)cls, value));
      return (unsigned)value.valCount;
  }
  
  void MethodContext::recGetClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint, unsigned result)
  {
      if (GetClassAlignmentRequirement == nullptr)
          GetClassAlignmentRequirement = new LightWeightMap<DLD, DWORD>();
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)cls;
      key.B = (DWORD)fDoubleAlignHint;
  
      GetClassAlignmentRequirement->Add(key, (DWORD)result);
      DEBUG_REC(dmpGetClassAlignmentRequirement(key, result));
  }
  void MethodContext::dmpGetClassAlignmentRequirement(DLD key, DWORD value)
  {
      printf("GetClassAlignmentRequirement key %016llX %u, value %u", key.A, key.B, value);
  }
  unsigned MethodContext::repGetClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      key.A = (DWORDLONG)cls;
      key.B = (DWORD)fDoubleAlignHint;
  
      unsigned result = (unsigned)GetClassAlignmentRequirement->Get(key);
      DEBUG_REP(dmpGetClassAlignmentRequirement(key, result));
      return result;
  }
  
  void MethodContext::recCanAccessClass(CORINFO_RESOLVED_TOKEN*      pResolvedToken,
                                        CORINFO_METHOD_HANDLE        callerHandle,
                                        CORINFO_HELPER_DESC*         pAccessHelper,
                                        CorInfoIsAccessAllowedResult result)
  {
      if (CanAccessClass == nullptr)
          CanAccessClass = new LightWeightMap<Agnostic_CanAccessClassIn, Agnostic_CanAccessClassOut>();
  
      Agnostic_CanAccessClassIn key;
      ZeroMemory(&key, sizeof(Agnostic_CanAccessClassIn)); // We use the input structs as a key and use memcmp to
                                                           // compare.. so we need to zero out padding too
      key.ResolvedToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, CanAccessClass);
      key.callerHandle  = (DWORDLONG)callerHandle;
  
      Agnostic_CanAccessClassOut value;
      value.AccessHelper.helperNum = (DWORD)pAccessHelper->helperNum;
      value.AccessHelper.numArgs   = (DWORD)pAccessHelper->numArgs;
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          value.AccessHelper.args[i].constant = (DWORDLONG)pAccessHelper->args[i].constant;
          value.AccessHelper.args[i].argType  = (DWORD)pAccessHelper->args[i].argType;
      }
      value.result = (DWORD)result;
  
      CanAccessClass->Add(key, value);
      DEBUG_REC(dmpCanAccessClass(key, value));
  }
  void MethodContext::dmpCanAccessClass(const Agnostic_CanAccessClassIn& key, const Agnostic_CanAccessClassOut& value)
  {
      printf("CanAccessClass key rt{%s}, callerHandle %016llX\n",
             SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.ResolvedToken).c_str(), key.callerHandle);
      printf(", value hnum-%u na-%u {", value.AccessHelper.helperNum, value.AccessHelper.numArgs);
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          printf("{%016llX %u}", value.AccessHelper.args[i].constant, value.AccessHelper.args[i].argType);
      }
      printf("} res-%u", value.result);
  }
  CorInfoIsAccessAllowedResult MethodContext::repCanAccessClass(CORINFO_RESOLVED_TOKEN* pResolvedToken,
                                                                CORINFO_METHOD_HANDLE   callerHandle,
                                                                CORINFO_HELPER_DESC*    pAccessHelper)
  {
      AssertCodeMsg(CanAccessClass != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)pResolvedToken->hClass);
  
      Agnostic_CanAccessClassIn key;
      ZeroMemory(&key, sizeof(Agnostic_CanAccessClassIn)); // We use the input structs as a key and use memcmp to
                                                           // compare.. so we need to zero out padding too
      key.ResolvedToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(pResolvedToken, CanAccessClass);
      key.callerHandle  = (DWORDLONG)callerHandle;
  
      AssertCodeMsg(CanAccessClass->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)pResolvedToken->hClass);
      Agnostic_CanAccessClassOut value = CanAccessClass->Get(key);
  
      pAccessHelper->helperNum = (CorInfoHelpFunc)value.AccessHelper.helperNum;
      pAccessHelper->numArgs   = (unsigned)value.AccessHelper.numArgs;
      for (int i = 0; i < CORINFO_ACCESS_ALLOWED_MAX_ARGS; i++)
      {
          pAccessHelper->args[i].constant = (size_t)value.AccessHelper.args[i].constant;
          pAccessHelper->args[i].argType  = (CorInfoAccessAllowedHelperArgType)value.AccessHelper.args[i].argType;
      }
      CorInfoIsAccessAllowedResult temp = (CorInfoIsAccessAllowedResult)value.result;
      DEBUG_REP(dmpCanAccessClass(key, value));
      return temp;
  }
  
  void MethodContext::recGetCastingHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fThrowing, CorInfoHelpFunc result)
  {
      if (GetCastingHelper == nullptr)
          GetCastingHelper = new LightWeightMap<Agnostic_GetCastingHelper, DWORD>();
  
      Agnostic_GetCastingHelper key;
      ZeroMemory(&key, sizeof(Agnostic_GetCastingHelper)); // We use the input structs as a key and use memcmp to
                                                           // compare.. so we need to zero out padding too
  
      key.hClass    = (DWORDLONG)pResolvedToken->hClass;
      key.fThrowing = (DWORD)fThrowing;
  
      GetCastingHelper->Add(key, (DWORD)result);
  }
  void MethodContext::dmpGetCastingHelper(const Agnostic_GetCastingHelper& key, DWORD value)
  {
      printf("GetCastingHelper key cls-%016llX, thw-%u, value res-%u", key.hClass, key.fThrowing, value);
  }
  CorInfoHelpFunc MethodContext::repGetCastingHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fThrowing)
  {
      Agnostic_GetCastingHelper key;
      ZeroMemory(&key, sizeof(Agnostic_GetCastingHelper)); // We use the input structs as a key and use memcmp to
                                                           // compare.. so we need to zero out padding too
  
      key.hClass    = (DWORDLONG)pResolvedToken->hClass;
      key.fThrowing = (DWORD)fThrowing;
  
      CorInfoHelpFunc value = (CorInfoHelpFunc)GetCastingHelper->Get(key);
      return value;
  }
  
  void MethodContext::recEmbedModuleHandle(CORINFO_MODULE_HANDLE handle,
                                           void**                ppIndirection,
                                           CORINFO_MODULE_HANDLE result)
  {
      if (EmbedModuleHandle == nullptr)
          EmbedModuleHandle = new LightWeightMap<DWORDLONG, DLDL>();
  
      DLDL value;
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      EmbedModuleHandle->Add((DWORDLONG)handle, value);
  }
  void MethodContext::dmpEmbedModuleHandle(DWORDLONG key, DLDL value)
  {
      printf("EmbedModuleHandle key mod-%016llX, value pp-%016llX res-%016llX", key, value.A, value.B);
  }
  CORINFO_MODULE_HANDLE MethodContext::repEmbedModuleHandle(CORINFO_MODULE_HANDLE handle, void** ppIndirection)
  {
      DLDL value;
  
      value = EmbedModuleHandle->Get((DWORDLONG)handle);
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      return (CORINFO_MODULE_HANDLE)value.B;
  }
  
  void MethodContext::recEmbedClassHandle(CORINFO_CLASS_HANDLE handle, void** ppIndirection, CORINFO_CLASS_HANDLE result)
  {
      if (EmbedClassHandle == nullptr)
          EmbedClassHandle = new LightWeightMap<DWORDLONG, DLDL>();
  
      DLDL value;
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      EmbedClassHandle->Add((DWORDLONG)handle, value);
      DEBUG_REC(dmpEmbedClassHandle((DWORDLONG)handle, value));
  }
  void MethodContext::dmpEmbedClassHandle(DWORDLONG key, DLDL value)
  {
      printf("EmbedClassHandle key cls-%016llX, value pp-%016llX res-%016llX", key, value.A, value.B);
  }
  CORINFO_CLASS_HANDLE MethodContext::repEmbedClassHandle(CORINFO_CLASS_HANDLE handle, void** ppIndirection)
  {
      DLDL value;
  
      AssertCodeMsg(EmbedClassHandle != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)handle);
      AssertCodeMsg(EmbedClassHandle->GetIndex((DWORDLONG)handle) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)handle);
      value = EmbedClassHandle->Get((DWORDLONG)handle);
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      DEBUG_REP(dmpEmbedClassHandle((DWORDLONG)handle, value));
      return (CORINFO_CLASS_HANDLE)value.B;
  }
  
  void MethodContext::recPInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method,
                                                   CORINFO_SIG_INFO*     callSiteSig,
                                                   BOOL                  result)
  {
      if (PInvokeMarshalingRequired == nullptr)
          PInvokeMarshalingRequired = new LightWeightMap<PInvokeMarshalingRequiredValue, DWORD>();
  
      PInvokeMarshalingRequiredValue key;
      ZeroMemory(&key, sizeof(PInvokeMarshalingRequiredValue)); // We use the input structs as a key and use memcmp to
                                                                // compare.. so we need to zero out padding too
  
      key.method     = (DWORDLONG)method;
      key.pSig_Index = (DWORD)PInvokeMarshalingRequired->AddBuffer((unsigned char*)callSiteSig->pSig, callSiteSig->cbSig);
      key.cbSig      = (DWORD)callSiteSig->cbSig;
      key.scope      = (DWORDLONG)callSiteSig->scope;
  
      PInvokeMarshalingRequired->Add(key, (DWORD)result);
      DEBUG_REC(dmpPInvokeMarshalingRequired(key, (DWORD)result));
  }
  void MethodContext::dmpPInvokeMarshalingRequired(const PInvokeMarshalingRequiredValue& key, DWORD value)
  {
      printf("PInvokeMarshalingRequired key mth-%016llX scp-%016llX sig-%u, value res-%u", key.method, key.scope,
             key.pSig_Index, value);
  }
  // Note the jit interface implementation seems to only care about scope and pSig from callSiteSig
  BOOL MethodContext::repPInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig)
  {
      if (PInvokeMarshalingRequired == nullptr) // so when we replay checked on free, we throw from lwm
          return TRUE;                          // TODO-Cleanup: hackish...
  
      PInvokeMarshalingRequiredValue key;
      ZeroMemory(&key, sizeof(PInvokeMarshalingRequiredValue)); // We use the input structs as a key and use memcmp to
                                                                // compare.. so we need to zero out padding too
  
      key.method     = (DWORDLONG)method;
      key.pSig_Index = (DWORD)PInvokeMarshalingRequired->Contains((unsigned char*)callSiteSig->pSig, callSiteSig->cbSig);
      key.cbSig      = (DWORD)callSiteSig->cbSig;
      key.scope      = (DWORDLONG)callSiteSig->scope;
  
      DWORD value = PInvokeMarshalingRequired->Get(key);
      DEBUG_REP(dmpPInvokeMarshalingRequired(key, value));
      return value;
  }
  
  void MethodContext::recFindSig(CORINFO_MODULE_HANDLE  module,
                                 unsigned               sigTOK,
                                 CORINFO_CONTEXT_HANDLE context,
                                 CORINFO_SIG_INFO*      sig)
  {
      if (FindSig == nullptr)
          FindSig = new LightWeightMap<Agnostic_FindSig, Agnostic_CORINFO_SIG_INFO>();
  
      Agnostic_FindSig key;
      ZeroMemory(&key, sizeof(Agnostic_FindSig)); // We use the input structs as a key and use memcmp to compare.. so we
                                                  // need to zero out padding too
      key.module  = (DWORDLONG)module;
      key.sigTOK  = (DWORD)sigTOK;
      key.context = (DWORDLONG)context;
  
      Agnostic_CORINFO_SIG_INFO value = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(*sig, FindSig);
  
      FindSig->Add(key, value);
      DEBUG_REC(dmpFindSig(key, value));
  }
  void MethodContext::dmpFindSig(const Agnostic_FindSig& key, const Agnostic_CORINFO_SIG_INFO& value)
  {
      printf("FindSig key module-%016llX sigTOK-%08X context-%016llX", key.module, key.sigTOK, key.context);
      printf(", value callConv-%08X retTypeClass-%016llX retTypeSigClass-%016llX retType-%u(%s) flags-%08X numArgs-%08X "
             "classInstCount-%08X classInd-%08X "
             "methInstCount-%08X methInd-%08X args-%016llX cbSig-%08X pSig_Index-%08X scope-%016llX token-%08X",
             value.callConv, value.retTypeClass, value.retTypeSigClass, value.retType,
             toString((CorInfoType)value.retType), value.flags, value.numArgs, value.sigInst_classInstCount,
             value.sigInst_classInst_Index, value.sigInst_methInstCount, value.sigInst_methInst_Index, value.args,
             value.cbSig, value.pSig_Index, value.scope, value.token);
  }
  void MethodContext::repFindSig(CORINFO_MODULE_HANDLE  module,
                                 unsigned               sigTOK,
                                 CORINFO_CONTEXT_HANDLE context,
                                 CORINFO_SIG_INFO*      sig)
  {
      Agnostic_FindSig key;
      ZeroMemory(&key, sizeof(Agnostic_FindSig)); // We use the input structs as a key and use memcmp to compare.. so we
                                                  // need to zero out padding too
      Agnostic_CORINFO_SIG_INFO value;
  
      key.module  = (DWORDLONG)module;
      key.sigTOK  = (DWORD)sigTOK;
      key.context = (DWORDLONG)context;
  
      value = FindSig->Get(key);
  
      *sig = SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(value, FindSig);
      DEBUG_REP(dmpFindSig(key, value));
  }
  
  void MethodContext::recGetEEInfo(CORINFO_EE_INFO* pEEInfoOut)
  {
      if (GetEEInfo == nullptr)
          GetEEInfo = new LightWeightMap<DWORD, Agnostic_CORINFO_EE_INFO>();
  
      Agnostic_CORINFO_EE_INFO value;
  
      value.inlinedCallFrameInfo.size                  = (DWORD)pEEInfoOut->inlinedCallFrameInfo.size;
      value.inlinedCallFrameInfo.offsetOfGSCookie      = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie;
      value.inlinedCallFrameInfo.offsetOfFrameVptr     = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr;
      value.inlinedCallFrameInfo.offsetOfFrameLink     = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink;
      value.inlinedCallFrameInfo.offsetOfCallSiteSP    = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP;
      value.inlinedCallFrameInfo.offsetOfCalleeSavedFP = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP;
      value.inlinedCallFrameInfo.offsetOfCallTarget    = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget;
      value.inlinedCallFrameInfo.offsetOfReturnAddress = (DWORD)pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress;
      value.offsetOfThreadFrame                        = (DWORD)pEEInfoOut->offsetOfThreadFrame;
      value.offsetOfGCState                            = (DWORD)pEEInfoOut->offsetOfGCState;
      value.offsetOfDelegateInstance                   = (DWORD)pEEInfoOut->offsetOfDelegateInstance;
      value.offsetOfDelegateFirstTarget                = (DWORD)pEEInfoOut->offsetOfDelegateFirstTarget;
      value.offsetOfWrapperDelegateIndirectCell        = (DWORD)pEEInfoOut->offsetOfWrapperDelegateIndirectCell;
      value.sizeOfReversePInvokeFrame                  = (DWORD)pEEInfoOut->sizeOfReversePInvokeFrame;
      value.osPageSize                                 = (DWORD)pEEInfoOut->osPageSize;
      value.maxUncheckedOffsetForNullObject            = (DWORD)pEEInfoOut->maxUncheckedOffsetForNullObject;
      value.targetAbi                                  = (DWORD)pEEInfoOut->targetAbi;
      value.osType                                     = (DWORD)pEEInfoOut->osType;
  
      GetEEInfo->Add((DWORD)0, value);
      DEBUG_REC(dmpGetEEInfo((DWORD)0, value));
  }
  void MethodContext::dmpGetEEInfo(DWORD key, const Agnostic_CORINFO_EE_INFO& value)
  {
      printf("GetEEInfo key %u, value icfi{sz-%u ogs-%u ofv-%u ofl-%u ocsp-%u ocsfp-%u oct-%u ora-%u} "
             "otf-%u ogcs-%u odi-%u odft-%u osdic-%u srpf-%u osps-%u muono-%u tabi-%u osType-%u",
             key, value.inlinedCallFrameInfo.size, value.inlinedCallFrameInfo.offsetOfGSCookie,
             value.inlinedCallFrameInfo.offsetOfFrameVptr, value.inlinedCallFrameInfo.offsetOfFrameLink,
             value.inlinedCallFrameInfo.offsetOfCallSiteSP, value.inlinedCallFrameInfo.offsetOfCalleeSavedFP,
             value.inlinedCallFrameInfo.offsetOfCallTarget, value.inlinedCallFrameInfo.offsetOfReturnAddress,
             value.offsetOfThreadFrame, value.offsetOfGCState, value.offsetOfDelegateInstance,
             value.offsetOfDelegateFirstTarget, value.offsetOfWrapperDelegateIndirectCell,
             value.sizeOfReversePInvokeFrame, value.osPageSize, value.maxUncheckedOffsetForNullObject, value.targetAbi,
             value.osType);
  }
  void MethodContext::repGetEEInfo(CORINFO_EE_INFO* pEEInfoOut)
  {
      Agnostic_CORINFO_EE_INFO value;
  
      int index = -1;
      if (GetEEInfo != nullptr)
          index = GetEEInfo->GetIndex((DWORD)0);
      if (index >= 0)
      {
          value                                               = GetEEInfo->Get((DWORD)0);
          pEEInfoOut->inlinedCallFrameInfo.size               = (unsigned)value.inlinedCallFrameInfo.size;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie   = (unsigned)value.inlinedCallFrameInfo.offsetOfGSCookie;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr  = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameVptr;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink  = (unsigned)value.inlinedCallFrameInfo.offsetOfFrameLink;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP = (unsigned)value.inlinedCallFrameInfo.offsetOfCallSiteSP;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP =
              (unsigned)value.inlinedCallFrameInfo.offsetOfCalleeSavedFP;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget = (unsigned)value.inlinedCallFrameInfo.offsetOfCallTarget;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress =
              (unsigned)value.inlinedCallFrameInfo.offsetOfReturnAddress;
          pEEInfoOut->offsetOfThreadFrame                = (unsigned)value.offsetOfThreadFrame;
          pEEInfoOut->offsetOfGCState                    = (unsigned)value.offsetOfGCState;
          pEEInfoOut->offsetOfDelegateInstance           = (unsigned)value.offsetOfDelegateInstance;
          pEEInfoOut->offsetOfDelegateFirstTarget        = (unsigned)value.offsetOfDelegateFirstTarget;
          pEEInfoOut->offsetOfWrapperDelegateIndirectCell= (unsigned)value.offsetOfWrapperDelegateIndirectCell;
          pEEInfoOut->sizeOfReversePInvokeFrame          = (unsigned)value.sizeOfReversePInvokeFrame;
          pEEInfoOut->osPageSize                         = (size_t)value.osPageSize;
          pEEInfoOut->maxUncheckedOffsetForNullObject    = (size_t)value.maxUncheckedOffsetForNullObject;
          pEEInfoOut->targetAbi                          = (CORINFO_RUNTIME_ABI)value.targetAbi;
          pEEInfoOut->osType                             = (CORINFO_OS)value.osType;
          DEBUG_REP(dmpGetEEInfo((DWORD)0, value));
      }
      else
      {
          pEEInfoOut->inlinedCallFrameInfo.size                  = (unsigned)0x40;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfGSCookie      = (unsigned)0;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameVptr     = (unsigned)0x8;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfFrameLink     = (unsigned)0x10;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfCallSiteSP    = (unsigned)0x28;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfCalleeSavedFP = (unsigned)0x38;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfCallTarget    = (unsigned)0x18;
          pEEInfoOut->inlinedCallFrameInfo.offsetOfReturnAddress = (unsigned)0x30;
          pEEInfoOut->offsetOfThreadFrame                        = (unsigned)0x10;
          pEEInfoOut->offsetOfGCState                            = (unsigned)0xc;
          pEEInfoOut->offsetOfDelegateInstance                   = (unsigned)0x8;
          pEEInfoOut->offsetOfDelegateFirstTarget                = (unsigned)0x18;
          pEEInfoOut->offsetOfWrapperDelegateIndirectCell        = (unsigned)0x40;
          pEEInfoOut->sizeOfReversePInvokeFrame                  = (unsigned)0x8;
          pEEInfoOut->osPageSize                                 = (size_t)0x1000;
          pEEInfoOut->maxUncheckedOffsetForNullObject            = (size_t)((32 * 1024) - 1);
          pEEInfoOut->targetAbi                                  = CORINFO_DESKTOP_ABI;
  #ifdef TARGET_UNIX
          pEEInfoOut->osType                                     = CORINFO_UNIX;
  #else
          pEEInfoOut->osType                                     = CORINFO_WINNT;
  #endif
      }
  }
  
  void MethodContext::recGetGSCookie(GSCookie* pCookieVal, GSCookie** ppCookieVal)
  {
      if (GetGSCookie == nullptr)
          GetGSCookie = new LightWeightMap<DWORD, DLDL>();
  
      DLDL value;
  
      if (pCookieVal != nullptr)
          value.A = (DWORDLONG)*pCookieVal;
      else
          value.A = (DWORDLONG)0;
  
      if (ppCookieVal != nullptr)
          value.B = (DWORDLONG)*ppCookieVal;
      else
          value.B = (DWORDLONG)0;
      GetGSCookie->Add((DWORD)0, value);
  }
  void MethodContext::dmpGetGSCookie(DWORD key, DLDL value)
  {
      printf("GetGSCookie key 0, value pCookieVal-%016llX ppCookieVal-%016llX", value.A, value.B);
  }
  void MethodContext::repGetGSCookie(GSCookie* pCookieVal, GSCookie** ppCookieVal)
  {
      DLDL value;
  
      value = GetGSCookie->Get((DWORD)0);
  
      if (pCookieVal != nullptr)
          *pCookieVal = (GSCookie)value.A;
      if (ppCookieVal != nullptr)
          *ppCookieVal = (GSCookie*)value.B;
  }
  
  void MethodContext::recGetOSRInfo(PatchpointInfo* patchpointInfo, unsigned* ilOffset)
  {
      if (GetOSRInfo == nullptr)
      {
          GetOSRInfo = new LightWeightMap<DWORD, Agnostic_GetOSRInfo>();
      }
  
      Agnostic_GetOSRInfo value;
  
      value.index = (DWORD)GetOSRInfo->AddBuffer((const unsigned char*) patchpointInfo, patchpointInfo->PatchpointInfoSize());
      value.ilOffset = *ilOffset;
  
      // use 0 for key
      DWORD key = 0;
      GetOSRInfo->Add(key, value);
      DEBUG_REC(dmpGetOSRInfo(key, value));
  }
  
  void MethodContext::dmpGetOSRInfo(DWORD key, const Agnostic_GetOSRInfo& value)
  {
      // todo - dump patchpoint info?
      printf("GetOSRInfo key %u, value patchpointInfo-%u {...} iloffset-%u\n",
          key, value.index, value.ilOffset);
  }
  
  PatchpointInfo* MethodContext::repGetOSRInfo(unsigned* ilOffset)
  {
      DWORD key = 0;
      Agnostic_GetOSRInfo value = GetOSRInfo->Get(key);
      *ilOffset = value.ilOffset;
      return (PatchpointInfo*)GetOSRInfo->GetBuffer(value.index);
  }
  
  void MethodContext::recGetClassModuleIdForStatics(CORINFO_CLASS_HANDLE   cls,
                                                    CORINFO_MODULE_HANDLE* pModule,
                                                    void**                 ppIndirection,
                                                    size_t                 result)
  {
      if (GetClassModuleIdForStatics == nullptr)
          GetClassModuleIdForStatics = new LightWeightMap<DWORDLONG, Agnostic_GetClassModuleIdForStatics>();
  
      Agnostic_GetClassModuleIdForStatics value;
  
      if (pModule != nullptr)
          value.Module = (DWORDLONG)*pModule;
      else
          value.Module = (DWORDLONG)0;
      if (ppIndirection != nullptr)
          value.pIndirection = (DWORDLONG)*ppIndirection;
      else
          value.pIndirection = (DWORDLONG)0;
      value.result           = (DWORDLONG)result;
      GetClassModuleIdForStatics->Add((DWORDLONG)cls, value);
  }
  void MethodContext::dmpGetClassModuleIdForStatics(DWORDLONG key, const Agnostic_GetClassModuleIdForStatics& value)
  {
      printf("GetClassModuleIdForStatics key cls-%016llX, value mod-%016llX pp-%016llX res-%016llX", key, value.Module,
             value.pIndirection, value.result);
  }
  size_t MethodContext::repGetClassModuleIdForStatics(CORINFO_CLASS_HANDLE   cls,
                                                      CORINFO_MODULE_HANDLE* pModule,
                                                      void**                 ppIndirection)
  {
      Agnostic_GetClassModuleIdForStatics value;
  
      value = GetClassModuleIdForStatics->Get((DWORDLONG)cls);
  
      if (pModule != nullptr)
          *pModule = (CORINFO_MODULE_HANDLE)value.Module;
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.pIndirection;
  
      return (size_t)value.result;
  }
  
  void MethodContext::recGetThreadTLSIndex(void** ppIndirection, DWORD result)
  {
      if (GetThreadTLSIndex == nullptr)
          GetThreadTLSIndex = new LightWeightMap<DWORD, DLD>();
  
      DLD value;
  
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORD)result;
  
      GetThreadTLSIndex->Add((DWORD)0, value);
  }
  void MethodContext::dmpGetThreadTLSIndex(DWORD key, DLD value)
  {
      printf("GetThreadTLSIndex key 0, value ppIndirection-%016llX result-%08X", value.A, value.B);
  }
  DWORD MethodContext::repGetThreadTLSIndex(void** ppIndirection)
  {
      DLD value;
  
      value = GetThreadTLSIndex->Get((DWORD)0);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      return (DWORD)value.B;
  }
  
  void MethodContext::recGetInlinedCallFrameVptr(void** ppIndirection, const void* result)
  {
      if (GetInlinedCallFrameVptr == nullptr)
          GetInlinedCallFrameVptr = new LightWeightMap<DWORD, DLDL>();
  
      DLDL value;
  
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      GetInlinedCallFrameVptr->Add((DWORD)0, value);
  }
  void MethodContext::dmpGetInlinedCallFrameVptr(DWORD key, DLDL value)
  {
      printf("GetInlinedCallFrameVptr key 0, value ppIndirection-%016llX result-%016llX", value.A, value.B);
  }
  const void* MethodContext::repGetInlinedCallFrameVptr(void** ppIndirection)
  {
      DLDL value;
  
      value = GetInlinedCallFrameVptr->Get((DWORD)0);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      return (const void*)value.B;
  }
  
  void MethodContext::recGetAddrOfCaptureThreadGlobal(void** ppIndirection, LONG* result)
  {
      if (GetAddrOfCaptureThreadGlobal == nullptr)
          GetAddrOfCaptureThreadGlobal = new LightWeightMap<DWORD, DLDL>();
  
      DLDL value;
  
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      GetAddrOfCaptureThreadGlobal->Add((DWORD)0, value);
      DEBUG_REC(dmpGetAddrOfCaptureThreadGlobal((DWORD)0, value));
  }
  void MethodContext::dmpGetAddrOfCaptureThreadGlobal(DWORD key, DLDL value)
  {
      printf("GetAddrOfCaptureThreadGlobal key %u, value ppi-%016llX res-%016llX", key, value.A, value.B);
  }
  LONG* MethodContext::repGetAddrOfCaptureThreadGlobal(void** ppIndirection)
  {
      DLDL value;
  
      if ((GetAddrOfCaptureThreadGlobal == nullptr) || (GetAddrOfCaptureThreadGlobal->GetIndex((DWORD)0) == -1))
      {
  #ifdef sparseMC
          LogDebug("Sparse - repGetAddrOfCaptureThreadGlobal returning 0xCAFE0001");
          return (LONG*)(size_t)0xCAFE0001;
  #else
          LogException(EXCEPTIONCODE_MC, "Didn't find anything for GetAddrOfCaptureThreadGlobal", "");
  #endif
      }
      value = GetAddrOfCaptureThreadGlobal->Get((DWORD)0);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      DEBUG_REP(dmpGetAddrOfCaptureThreadGlobal((DWORD)0, value));
      return (LONG*)value.B;
  }
  
  void MethodContext::recGetClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection, unsigned result)
  {
      if (GetClassDomainID == nullptr)
          GetClassDomainID = new LightWeightMap<DWORDLONG, DLD>();
  
      DLD value;
  
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORD)result;
  
      GetClassDomainID->Add((DWORDLONG)cls, value);
      DEBUG_REC(dmpGetClassDomainID((DWORDLONG)cls, value));
  }
  void MethodContext::dmpGetClassDomainID(DWORDLONG key, DLD value)
  {
      printf("GetClassDomainID key cls-%016llX, value pp-%016llX res-%u", key, value.A, value.B);
  }
  unsigned MethodContext::repGetClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection)
  {
      DLD value;
  
      AssertCodeMsg(GetClassDomainID != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)cls);
      AssertCodeMsg(GetClassDomainID->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)cls);
      value = GetClassDomainID->Get((DWORDLONG)cls);
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      DEBUG_REP(dmpGetClassDomainID((DWORDLONG)cls, value));
      return (unsigned)value.B;
  }
  
  void MethodContext::recGetLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* result)
  {
      if (GetLocationOfThisType == nullptr)
          GetLocationOfThisType = new LightWeightMap<DWORDLONG, Agnostic_CORINFO_LOOKUP_KIND>();
  
      Agnostic_CORINFO_LOOKUP_KIND value = SpmiRecordsHelper::CreateAgnostic_CORINFO_LOOKUP_KIND(result);
      GetLocationOfThisType->Add((DWORDLONG)context, value);
  }
  void MethodContext::dmpGetLocationOfThisType(DWORDLONG key, const Agnostic_CORINFO_LOOKUP_KIND& value)
  {
      printf("GetLocationOfThisType key ftn-%016llX, value %s", key,
             SpmiDumpHelper::DumpAgnostic_CORINFO_LOOKUP_KIND(value).c_str());
  }
  void MethodContext::repGetLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* pLookupKind)
  {
      Agnostic_CORINFO_LOOKUP_KIND value = GetLocationOfThisType->Get((DWORDLONG)context);
      *pLookupKind = SpmiRecordsHelper::RestoreCORINFO_LOOKUP_KIND(value);
  }
  
  void MethodContext::recGetDelegateCtor(CORINFO_METHOD_HANDLE methHnd,
                                         CORINFO_CLASS_HANDLE  clsHnd,
                                         CORINFO_METHOD_HANDLE targetMethodHnd,
                                         DelegateCtorArgs*     pCtorData,
                                         CORINFO_METHOD_HANDLE result)
  {
      if (GetDelegateCtor == nullptr)
          GetDelegateCtor = new LightWeightMap<Agnostic_GetDelegateCtorIn, Agnostic_GetDelegateCtorOut>();
  
      Agnostic_GetDelegateCtorIn key;
      ZeroMemory(&key, sizeof(Agnostic_GetDelegateCtorIn)); // We use the input structs as a key and use memcmp to
                                                            // compare.. so we need to zero out padding too
      Agnostic_GetDelegateCtorOut value;
  
      key.methHnd         = (DWORDLONG)methHnd;
      key.clsHnd          = (DWORDLONG)clsHnd;
      key.targetMethodHnd = (DWORDLONG)targetMethodHnd;
  
      value.CtorData.pMethod = (DWORDLONG)pCtorData->pMethod;
      value.CtorData.pArg3   = (DWORDLONG)pCtorData->pArg3;
      value.CtorData.pArg4   = (DWORDLONG)pCtorData->pArg4;
      value.CtorData.pArg5   = (DWORDLONG)pCtorData->pArg5;
      value.result           = (DWORDLONG)result;
  
      GetDelegateCtor->Add(key, value);
      DEBUG_REC(dmpGetDelegateCtor(key, value));
  }
  void MethodContext::dmpGetDelegateCtor(const Agnostic_GetDelegateCtorIn& key, const Agnostic_GetDelegateCtorOut& value)
  {
      printf("GetDelegateCtor key ftn-%016llX cls-%016llX tftn-%016llX, value pm-%016llX a3-%016llX a4-%016llX "
             "a5-%016llX res-%016llX",
             key.methHnd, key.clsHnd, key.targetMethodHnd, value.CtorData.pMethod, value.CtorData.pArg3,
             value.CtorData.pArg4, value.CtorData.pArg5, value.result);
  }
  CORINFO_METHOD_HANDLE MethodContext::repGetDelegateCtor(CORINFO_METHOD_HANDLE methHnd,
                                                          CORINFO_CLASS_HANDLE  clsHnd,
                                                          CORINFO_METHOD_HANDLE targetMethodHnd,
                                                          DelegateCtorArgs*     pCtorData)
  {
      Agnostic_GetDelegateCtorIn key;
      ZeroMemory(&key, sizeof(Agnostic_GetDelegateCtorIn)); // We use the input structs as a key and use memcmp to
                                                            // compare.. so we need to zero out padding too
      Agnostic_GetDelegateCtorOut value;
  
      key.methHnd         = (DWORDLONG)methHnd;
      key.clsHnd          = (DWORDLONG)clsHnd;
      key.targetMethodHnd = (DWORDLONG)targetMethodHnd;
  
      AssertCodeMsg(GetDelegateCtor != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)key.methHnd);
      AssertCodeMsg(GetDelegateCtor->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)key.methHnd);
      value = GetDelegateCtor->Get(key);
  
      pCtorData->pMethod = (void*)value.CtorData.pMethod;
      pCtorData->pArg3   = (void*)value.CtorData.pArg3;
      pCtorData->pArg4   = (void*)value.CtorData.pArg4;
      pCtorData->pArg5   = (void*)value.CtorData.pArg5;
      DEBUG_REP(dmpGetDelegateCtor(key, value));
      return (CORINFO_METHOD_HANDLE)value.result;
  }
  
  void MethodContext::recGetFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP* pResult)
  {
      if (GetFunctionFixedEntryPoint == nullptr)
          GetFunctionFixedEntryPoint = new LightWeightMap<DWORDLONG, Agnostic_CORINFO_CONST_LOOKUP>();
  
      Agnostic_CORINFO_CONST_LOOKUP value = SpmiRecordsHelper::StoreAgnostic_CORINFO_CONST_LOOKUP(pResult);
  
      GetFunctionFixedEntryPoint->Add((DWORDLONG)ftn, value);
  }
  void MethodContext::dmpGetFunctionFixedEntryPoint(DWORDLONG key, const Agnostic_CORINFO_CONST_LOOKUP& value)
  {
      printf("GetFunctionFixedEntryPoint key ftn-%016llX, value %s", key,
             SpmiDumpHelper::DumpAgnostic_CORINFO_CONST_LOOKUP(value).c_str());
  }
  void MethodContext::repGetFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP* pResult)
  {
      Agnostic_CORINFO_CONST_LOOKUP value;
  
      value = GetFunctionFixedEntryPoint->Get((DWORDLONG)ftn);
  
      *pResult = SpmiRecordsHelper::RestoreCORINFO_CONST_LOOKUP(value);
  }
  
  void MethodContext::recGetFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num, CORINFO_FIELD_HANDLE result)
  {
      if (GetFieldInClass == nullptr)
          GetFieldInClass = new LightWeightMap<DLD, DWORDLONG>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)clsHnd;
      key.B = (DWORD)num;
  
      GetFieldInClass->Add(key, (DWORDLONG)result);
      DEBUG_REC(dmpGetFieldInClass(key, (DWORDLONG)result));
  }
  void MethodContext::dmpGetFieldInClass(DLD key, DWORDLONG value)
  {
      printf("GetFieldInClass key cls-%016llX ind-%u, value %016llX", key.A, key.B, value);
  }
  CORINFO_FIELD_HANDLE MethodContext::repGetFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)clsHnd;
      key.B = (DWORD)num;
  
      AssertCodeMsg((GetFieldInClass != nullptr) && (GetFieldInClass->GetIndex(key) != -1), EXCEPTIONCODE_MC,
                    "Didn't find %016llX", (DWORDLONG)key.A);
      CORINFO_FIELD_HANDLE temp = (CORINFO_FIELD_HANDLE)GetFieldInClass->Get(key);
  
      DEBUG_REP(dmpGetFieldInClass(key, (DWORDLONG)temp));
      return temp;
  }
  
  void MethodContext::recGetFieldType(CORINFO_FIELD_HANDLE  field,
                                      CORINFO_CLASS_HANDLE* structType,
                                      CORINFO_CLASS_HANDLE  memberParent,
                                      CorInfoType           result)
  {
      if (GetFieldType == nullptr)
          GetFieldType = new LightWeightMap<DLDL, DLD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      DLD value;
  
      key.A = (DWORDLONG)field;
      key.B = (DWORDLONG)memberParent;
  
      value.B = (DWORD)result;
      if (structType == nullptr)
      {
          value.A = 0;
      }
      else
      {
          value.A = (DWORDLONG)*structType;
  
          // If we had a previous call with null 'structType', we will not have captured the
          // class handle (we use only 'field' and 'memberParent' as keys).
          // Update the value in that case.
          unsigned index = GetFieldType->GetIndex(key);
          if ((index != (unsigned)-1) && (GetFieldType->GetItem(index).A == 0))
          {
              GetFieldType->Update(index, value);
              DEBUG_REC(dmpGetFieldType(key, value));
              return;
          }
      }
      GetFieldType->Add(key, value);
      DEBUG_REC(dmpGetFieldType(key, value));
  }
  void MethodContext::dmpGetFieldType(DLDL key, DLD value)
  {
      printf("GetFieldType key fld-%016llX cls-%016llX, value ch-%016llX cit-%u(%s)", key.A, key.B, value.A, value.B,
             toString((CorInfoType)value.B));
  }
  CorInfoType MethodContext::repGetFieldType(CORINFO_FIELD_HANDLE  field,
                                             CORINFO_CLASS_HANDLE* structType,
                                             CORINFO_CLASS_HANDLE  memberParent)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      DLD value;
  
      key.A = (DWORDLONG)field;
      key.B = (DWORDLONG)memberParent;
  
      AssertCodeMsg(GetFieldType != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)key.A);
      AssertCodeMsg(GetFieldType->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)key.A);
      value = GetFieldType->Get(key);
  
      if (structType != nullptr)
          *structType = (CORINFO_CLASS_HANDLE)value.A;
  
      DEBUG_REP(dmpGetFieldType(key, value));
      return (CorInfoType)value.B;
  }
  
  void MethodContext::recGetFieldName(CORINFO_FIELD_HANDLE ftn, const char** moduleName, const char* result)
  {
      if (GetFieldName == nullptr)
          GetFieldName = new LightWeightMap<DWORDLONG, DD>();
  
      DD value;
  
      if (result != nullptr)
          value.A = GetFieldName->AddBuffer((unsigned char*)result, (DWORD)strlen(result) + 1);
      else
          value.A = (DWORD)-1;
  
      if ((moduleName != nullptr) && (*moduleName != nullptr)) // protect strlen
          value.B = (DWORD)GetFieldName->AddBuffer((unsigned char*)*moduleName, (DWORD)strlen(*moduleName) + 1);
      else
          value.B = (DWORD)-1;
  
      GetFieldName->Add((DWORDLONG)ftn, value);
  }
  void MethodContext::dmpGetFieldName(DWORDLONG key, DD value)
  {
      unsigned char* fieldName  = (unsigned char*)GetFieldName->GetBuffer(value.A);
      unsigned char* moduleName = (unsigned char*)GetFieldName->GetBuffer(value.B);
      printf("GetFieldName key - ftn-%016llX, value fld-'%s', mod-'%s'", key, fieldName, moduleName);
      GetFieldName->Unlock();
  }
  const char* MethodContext::repGetFieldName(CORINFO_FIELD_HANDLE ftn, const char** moduleName)
  {
      DD value;
      if (GetFieldName == nullptr)
      {
          if (moduleName != nullptr)
              *moduleName = "hackishModuleName";
          return "hackishFieldName";
      }
      value = GetFieldName->Get((DWORDLONG)ftn);
      if (moduleName != nullptr)
          *moduleName = (const char*)GetFieldName->GetBuffer(value.B);
      return (const char*)GetFieldName->GetBuffer(value.A);
  }
  
  void MethodContext::recCanInlineTypeCheck(CORINFO_CLASS_HANDLE         cls,
                                            CorInfoInlineTypeCheckSource source,
                                            CorInfoInlineTypeCheck       result)
  {
      if (CanInlineTypeCheck == nullptr)
          CanInlineTypeCheck = new LightWeightMap<DLD, DWORD>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)cls;
      key.B = (DWORD)source;
  
      CanInlineTypeCheck->Add(key, (DWORD)result);
  }
  void MethodContext::dmpCanInlineTypeCheck(DLD key, DWORD value)
  {
      printf("CanInlineTypeCheck key cls-%016llX src-%08X, value res-%u", key.A, key.B, value);
  }
  CorInfoInlineTypeCheck MethodContext::repCanInlineTypeCheck(CORINFO_CLASS_HANDLE         cls,
                                                              CorInfoInlineTypeCheckSource source)
  {
      AssertCodeMsg(CanInlineTypeCheck != nullptr, EXCEPTIONCODE_MC, "No map for CanInlineTypeCheck");
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)cls;
      key.B = (DWORD)source;
  
      return (CorInfoInlineTypeCheck)CanInlineTypeCheck->Get(key);
  }
  
  void MethodContext::recSatisfiesMethodConstraints(CORINFO_CLASS_HANDLE  parent,
                                                    CORINFO_METHOD_HANDLE method,
                                                    BOOL                  result)
  {
      if (SatisfiesMethodConstraints == nullptr)
          SatisfiesMethodConstraints = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)parent;
      key.B = (DWORDLONG)method;
  
      SatisfiesMethodConstraints->Add(key, (DWORD)result);
  }
  void MethodContext::dmpSatisfiesMethodConstraints(DLDL key, DWORD value)
  {
      printf("SatisfiesMethodConstraints key cls-%016llX ftn-%016llX, value res-%u", key.A, key.B, value);
  }
  BOOL MethodContext::repSatisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, CORINFO_METHOD_HANDLE method)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)parent;
      key.B = (DWORDLONG)method;
  
      BOOL value = (BOOL)SatisfiesMethodConstraints->Get(key);
      return value;
  }
  
  void MethodContext::recIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK, BOOL result)
  {
      if (IsValidStringRef == nullptr)
          IsValidStringRef = new LightWeightMap<DLD, DWORD>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
  
      IsValidStringRef->Add(key, (DWORD)result);
  }
  void MethodContext::dmpIsValidStringRef(DLD key, DWORD value)
  {
      printf("IsValidStringRef key mod-%016llX tok-%08X, value res-%u", key.A, key.B, value);
  }
  BOOL MethodContext::repIsValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
  
      BOOL value = (BOOL)IsValidStringRef->Get(key);
      return value;
  }
  
  
  void MethodContext::recGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int length, LPCWSTR result)
  {
      if (GetStringLiteral == nullptr)
          GetStringLiteral = new LightWeightMap<DLD, DD>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
  
      DWORD strBuf = (DWORD)-1;
      if (result != nullptr)
          strBuf = (DWORD)GetStringLiteral->AddBuffer((unsigned char*)result, (unsigned int)((wcslen(result) * 2) + 2));
  
      DD value;
      value.A = (DWORD)length;
      value.B = (DWORD)strBuf;
  
      GetStringLiteral->Add(key, value);
  }
  
  void MethodContext::dmpGetStringLiteral(DLD key, DD value)
  {
      printf("GetStringLiteral key mod-%016llX tok-%08X, result-%s, len-%u", key.A, key.B,
          GetStringLiteral->GetBuffer(value.B), value.A);
  }
  
  LPCWSTR MethodContext::repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* length)
  {
      if (GetStringLiteral == nullptr)
      {
          *length = -1;
          return nullptr;
      }
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
  
      int itemIndex = GetStringLiteral->GetIndex(key);
      if (itemIndex < 0)
      {
          *length = -1;
          return nullptr;
      }
      else
      {
          DD result = GetStringLiteral->Get(key);
          *length = (int)result.A;
          return (LPCWSTR)GetStringLiteral->GetBuffer(itemIndex);
      }
  }
  
  void MethodContext::recGetHelperName(CorInfoHelpFunc funcNum, const char* result)
  {
      if (GetHelperName == nullptr)
          GetHelperName = new LightWeightMap<DWORD, DWORD>();
  
      DWORD value = (DWORD)-1;
      if (result != nullptr)
          value = (DWORD)GetHelperName->AddBuffer((unsigned char*)result, (DWORD)strlen(result) + 1);
  
      GetHelperName->Add((DWORD)funcNum, value);
      DEBUG_REC(dmpGetHelperName((DWORD)funcNum, value));
  }
  void MethodContext::dmpGetHelperName(DWORD key, DWORD value)
  {
      printf("GetHelperName key ftn-%u, value '%s'", key, (const char*)GetHelperName->GetBuffer(value));
      GetHelperName->Unlock();
  }
  const char* MethodContext::repGetHelperName(CorInfoHelpFunc funcNum)
  {
      if (GetHelperName == nullptr)
          return "Yickish helper name";
  
      int itemIndex = GetHelperName->GetIndex((DWORD)funcNum);
      if (itemIndex < 0)
      {
          return "hackishHelperName";
      }
      else
      {
          unsigned int buffIndex = GetHelperName->Get((DWORD)funcNum);
          DEBUG_REP(dmpGetHelperName((DWORD)funcNum, buffIndex));
          return (const char*)GetHelperName->GetBuffer(buffIndex);
      }
  }
  
  void MethodContext::recCanCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent, BOOL result)
  {
      if (CanCast == nullptr)
          CanCast = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)child;
      key.B = (DWORDLONG)parent;
  
      CanCast->Add(key, (DWORD)result);
      DEBUG_REC(dmpCanCast(key, (DWORD)result));
  }
  void MethodContext::dmpCanCast(DLDL key, DWORD value)
  {
      printf("CanCast key chd-%016llX par-%016llX, value res-%u", key.A, key.B, value);
  }
  BOOL MethodContext::repCanCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)child;
      key.B = (DWORDLONG)parent;
  
      AssertCodeMsg(CanCast != nullptr, EXCEPTIONCODE_MC, "Didn't find anything %016llX, %016llX in map",
                    (DWORDLONG)child, (DWORDLONG)parent);
      AssertCodeMsg(CanCast->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX, %016llX %u in map",
                    (DWORDLONG)child, (DWORDLONG)parent, CanCast->GetCount());
      BOOL value = (BOOL)CanCast->Get(key);
      DEBUG_REP(dmpCanCast(key, (DWORD)value));
      return value;
  }
  
  void MethodContext::recGetChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet, CorInfoType result)
  {
      if (GetChildType == nullptr)
          GetChildType = new LightWeightMap<DWORDLONG, DLD>();
  
      DLD value;
  
      value.A = (DWORDLONG)*clsRet;
      value.B = (DWORD)result;
  
      GetChildType->Add((DWORDLONG)clsHnd, value);
      DEBUG_REC(dmpGetChildType((DWORDLONG)clsHnd, value));
  }
  void MethodContext::dmpGetChildType(DWORDLONG key, DLD value)
  {
      printf("GetChildType key cls-%016llX, value clsr-%016llX cit-%u(%s)", key, value.A, value.B,
             toString((CorInfoType)value.B));
  }
  CorInfoType MethodContext::repGetChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet)
  {
      DLD value;
  
      AssertCodeMsg(GetChildType != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)clsHnd);
      AssertCodeMsg(GetChildType->GetIndex((DWORDLONG)clsHnd) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)clsHnd);
      value = GetChildType->Get((DWORDLONG)clsHnd);
  
      *clsRet = (CORINFO_CLASS_HANDLE)value.A;
      DEBUG_REP(dmpGetChildType((DWORDLONG)clsHnd, value));
      return (CorInfoType)value.B;
  }
  
  void MethodContext::recGetArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size, void* result)
  {
      if (GetArrayInitializationData == nullptr)
          GetArrayInitializationData = new LightWeightMap<DLD, DWORDLONG>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)field;
      key.B = (DWORD)size;
  
      GetArrayInitializationData->Add(key, (DWORDLONG)result);
  }
  void MethodContext::dmpGetArrayInitializationData(DLD key, DWORDLONG value)
  {
      printf("GetArrayInitializationData key field-%016llX size-%08X, value result-%016llX", key.A, key.B, value);
  }
  void* MethodContext::repGetArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A = (DWORDLONG)field;
      key.B = (DWORD)size;
  
      void* value = (void*)GetArrayInitializationData->Get(key);
      return value;
  }
  
  void MethodContext::recFilterException(struct _EXCEPTION_POINTERS* pExceptionPointers, int result)
  {
      if (FilterException == nullptr)
          FilterException = new LightWeightMap<DWORD, DWORD>();
  
      FilterException->Add((DWORD)pExceptionPointers->ExceptionRecord->ExceptionCode, (DWORD)result);
  }
  void MethodContext::dmpFilterException(DWORD key, DWORD value)
  {
      printf("FilterException key %u, value %u", key, value);
  }
  int MethodContext::repFilterException(struct _EXCEPTION_POINTERS* pExceptionPointers)
  {
      if (FilterException == nullptr)
          return EXCEPTION_CONTINUE_SEARCH;
      if (FilterException->GetIndex((DWORD)pExceptionPointers->ExceptionRecord->ExceptionCode) < 0)
          return EXCEPTION_CONTINUE_SEARCH;
      else
      {
          int result = FilterException->Get((DWORD)pExceptionPointers->ExceptionRecord->ExceptionCode);
          return result;
      }
  }
  
  void MethodContext::recHandleException(struct _EXCEPTION_POINTERS* pExceptionPointers)
  {
      if (HandleException == nullptr)
          HandleException = new DenseLightWeightMap<DWORD>();
  
      HandleException->Append(pExceptionPointers->ExceptionRecord->ExceptionCode);
  }
  void MethodContext::dmpHandleException(DWORD key, DWORD value)
  {
      printf("HandleException key %u, value %u", key, value);
  }
  
  void MethodContext::recGetAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup)
  {
      if (GetAddressOfPInvokeTarget == nullptr)
          GetAddressOfPInvokeTarget = new LightWeightMap<DWORDLONG, DLD>();
  
      DLD value;
  
      value.A = (DWORDLONG)pLookup->addr;
      value.B = (DWORD)pLookup->accessType;
  
      GetAddressOfPInvokeTarget->Add((DWORDLONG)method, value);
  }
  void MethodContext::dmpGetAddressOfPInvokeTarget(DWORDLONG key, DLD value)
  {
      printf("GetAddressOfPInvokeTarget key ftn-%016llX, value addr-%016llX at-%u", key, value.A, value.B);
  }
  void MethodContext::repGetAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup)
  {
      DLD value = GetAddressOfPInvokeTarget->Get((DWORDLONG)method);
  
      pLookup->addr       = (void*)value.A;
      pLookup->accessType = (InfoAccessType)value.B;
  }
  
  void MethodContext::recSatisfiesClassConstraints(CORINFO_CLASS_HANDLE cls, BOOL result)
  {
      if (SatisfiesClassConstraints == nullptr)
          SatisfiesClassConstraints = new LightWeightMap<DWORDLONG, DWORD>();
  
      SatisfiesClassConstraints->Add((DWORDLONG)cls, (DWORD)result);
  }
  void MethodContext::dmpSatisfiesClassConstraints(DWORDLONG key, DWORD value)
  {
      printf("SatisfiesClassConstraints key cls-%016llX, value res-%u", key, value);
  }
  BOOL MethodContext::repSatisfiesClassConstraints(CORINFO_CLASS_HANDLE cls)
  {
      return (BOOL)SatisfiesClassConstraints->Get((DWORDLONG)cls);
  }
  
  void MethodContext::recGetMethodHash(CORINFO_METHOD_HANDLE ftn, unsigned result)
  {
      if (GetMethodHash == nullptr)
          GetMethodHash = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetMethodHash->Add((DWORDLONG)ftn, (DWORD)result);
      DEBUG_REC(dmpGetMethodHash((DWORDLONG)ftn, (DWORD)result));
  }
  void MethodContext::dmpGetMethodHash(DWORDLONG key, DWORD value)
  {
      printf("GetMethodHash key %016llX, value %u", key, value);
  }
  unsigned MethodContext::repGetMethodHash(CORINFO_METHOD_HANDLE ftn)
  {
      unsigned result = 0x43;
      if (GetMethodHash != nullptr)
          if (GetMethodHash->GetIndex((DWORDLONG)ftn) >= 0)
              result = GetMethodHash->Get((DWORDLONG)ftn);
      DEBUG_REP(dmpGetMethodHash((DWORDLONG)ftn, (DWORD)result));
      return result;
  }
  
  void MethodContext::recCanTailCall(CORINFO_METHOD_HANDLE callerHnd,
                                     CORINFO_METHOD_HANDLE declaredCalleeHnd,
                                     CORINFO_METHOD_HANDLE exactCalleeHnd,
                                     bool                  fIsTailPrefix,
                                     bool                  result)
  {
      if (CanTailCall == nullptr)
          CanTailCall = new LightWeightMap<Agnostic_CanTailCall, DWORD>();
  
      Agnostic_CanTailCall key;
      ZeroMemory(&key, sizeof(Agnostic_CanTailCall)); // We use the input structs as a key and use memcmp to compare.. so
                                                      // we need to zero out padding too
  
      key.callerHnd         = (DWORDLONG)callerHnd;
      key.declaredCalleeHnd = (DWORDLONG)declaredCalleeHnd;
      key.exactCalleeHnd    = (DWORDLONG)exactCalleeHnd;
      key.fIsTailPrefix     = (DWORD)fIsTailPrefix;
  
      CanTailCall->Add(key, (DWORD)result);
      DEBUG_REC(dmpCanTailCall(key, (DWORD)result));
  }
  void MethodContext::dmpCanTailCall(const Agnostic_CanTailCall& key, DWORD value)
  {
      printf("CanTailCall key clr-%016llX dcle-%016llX ecle-%016llX pfx-%u, value res-%u", key.callerHnd,
             key.declaredCalleeHnd, key.exactCalleeHnd, key.fIsTailPrefix, value);
  }
  bool MethodContext::repCanTailCall(CORINFO_METHOD_HANDLE callerHnd,
                                     CORINFO_METHOD_HANDLE declaredCalleeHnd,
                                     CORINFO_METHOD_HANDLE exactCalleeHnd,
                                     bool                  fIsTailPrefix)
  {
      Agnostic_CanTailCall key;
      ZeroMemory(&key, sizeof(Agnostic_CanTailCall)); // We use the input structs as a key and use memcmp to compare.. so
                                                      // we need to zero out padding too
  
      key.callerHnd         = (DWORDLONG)callerHnd;
      key.declaredCalleeHnd = (DWORDLONG)declaredCalleeHnd;
      key.exactCalleeHnd    = (DWORDLONG)exactCalleeHnd;
      key.fIsTailPrefix     = (DWORD)fIsTailPrefix;
  
      AssertCodeMsg(CanTailCall != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)key.callerHnd);
      AssertCodeMsg(CanTailCall->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)key.callerHnd);
      bool temp = CanTailCall->Get(key) != 0;
      DEBUG_REP(dmpCanTailCall(key, (DWORD)temp));
      return temp;
  }
  
  void MethodContext::recIsCompatibleDelegate(CORINFO_CLASS_HANDLE  objCls,
                                              CORINFO_CLASS_HANDLE  methodParentCls,
                                              CORINFO_METHOD_HANDLE method,
                                              CORINFO_CLASS_HANDLE  delegateCls,
                                              BOOL*                 pfIsOpenDelegate,
                                              BOOL                  result)
  {
      if (IsCompatibleDelegate == nullptr)
          IsCompatibleDelegate = new LightWeightMap<Agnostic_IsCompatibleDelegate, DD>();
      Agnostic_IsCompatibleDelegate key;
      ZeroMemory(&key, sizeof(Agnostic_IsCompatibleDelegate)); // We use the input structs as a key and use memcmp to
                                                               // compare.. so we need to zero out padding too
      DD value;
  
      key.objCls          = (DWORDLONG)objCls;
      key.methodParentCls = (DWORDLONG)methodParentCls;
      key.method          = (DWORDLONG)method;
      key.delegateCls     = (DWORDLONG)delegateCls;
  
      value.A = (DWORD)*pfIsOpenDelegate;
      value.B = (DWORD)result;
  
      IsCompatibleDelegate->Add(key, value);
  }
  void MethodContext::dmpIsCompatibleDelegate(const Agnostic_IsCompatibleDelegate& key, DD value)
  {
      printf("IsCompatibleDelegate key objCls-%016llX methodParentCls-%016llX method-%016llX delegateCls-%016llX, value  "
             "pfIsOpenDelegate-%08X result-%08X",
             key.objCls, key.methodParentCls, key.method, key.delegateCls, value.A, value.B);
  }
  BOOL MethodContext::repIsCompatibleDelegate(CORINFO_CLASS_HANDLE  objCls,
                                              CORINFO_CLASS_HANDLE  methodParentCls,
                                              CORINFO_METHOD_HANDLE method,
                                              CORINFO_CLASS_HANDLE  delegateCls,
                                              BOOL*                 pfIsOpenDelegate)
  {
      Agnostic_IsCompatibleDelegate key;
      ZeroMemory(&key, sizeof(Agnostic_IsCompatibleDelegate)); // We use the input structs as a key and use memcmp to
                                                               // compare.. so we need to zero out padding too
      DD value;
  
      key.objCls          = (DWORDLONG)objCls;
      key.methodParentCls = (DWORDLONG)methodParentCls;
      key.method          = (DWORDLONG)method;
      key.delegateCls     = (DWORDLONG)delegateCls;
  
      value = IsCompatibleDelegate->Get(key);
  
      *pfIsOpenDelegate = (BOOL)value.A;
      return (BOOL)value.B;
  }
  
  void MethodContext::recIsDelegateCreationAllowed(CORINFO_CLASS_HANDLE  delegateHnd,
                                                   CORINFO_METHOD_HANDLE calleeHnd,
                                                   BOOL                  result)
  {
      if (IsDelegateCreationAllowed == nullptr)
          IsDelegateCreationAllowed = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(key));
      DWORD value;
  
      key.A = (DWORDLONG)delegateHnd;
      key.B = (DWORDLONG)calleeHnd;
  
      value = (DWORD)result;
  
      IsDelegateCreationAllowed->Add(key, value);
  }
  void MethodContext::dmpIsDelegateCreationAllowed(DLDL key, DWORD value)
  {
      printf("IsDelegateCreationAllowed key delegateHnd-%016llX calleeHnd-%016llX result-%08X", key.A, key.B, value);
  }
  BOOL MethodContext::repIsDelegateCreationAllowed(CORINFO_CLASS_HANDLE delegateHnd, CORINFO_METHOD_HANDLE calleeHnd)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(key));
      DWORD value;
  
      key.A = (DWORDLONG)delegateHnd;
      key.B = (DWORDLONG)calleeHnd;
  
      value = IsDelegateCreationAllowed->Get(key);
  
      return (BOOL)value;
  }
  
  void MethodContext::recFindCallSiteSig(CORINFO_MODULE_HANDLE  module,
                                         unsigned               methTOK,
                                         CORINFO_CONTEXT_HANDLE context,
                                         CORINFO_SIG_INFO*      sig)
  {
      if (FindCallSiteSig == nullptr)
          FindCallSiteSig = new LightWeightMap<Agnostic_FindCallSiteSig, Agnostic_CORINFO_SIG_INFO>();
  
      Agnostic_FindCallSiteSig key;
      ZeroMemory(&key, sizeof(Agnostic_FindCallSiteSig)); // We use the input structs as a key and use memcmp to compare..
                                                          // so we need to zero out padding too
      key.module  = (DWORDLONG)module;
      key.methTok = (DWORD)methTOK;
      key.context = (DWORDLONG)context;
  
      Agnostic_CORINFO_SIG_INFO value = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(*sig, FindCallSiteSig);
  
      FindCallSiteSig->Add(key, value);
      DEBUG_REC(dmpFindCallSiteSig(key, value));
  }
  void MethodContext::dmpFindCallSiteSig(const Agnostic_FindCallSiteSig& key, const Agnostic_CORINFO_SIG_INFO& value)
  {
      printf("dmpFindCallSiteSig key module-%016llX methTok-%08X context-%016llX", key.module, key.methTok, key.context);
      printf(", value callConv-%08X retTypeClass-%016llX retTypeSigClass-%016llX retType-%u(%s) flags-%08X numArgs-%08X "
             "classInstCount-%08X classInd-%08X "
             "methInstCount-%08X methInd-%08X args-%016llX cbSig-%08X pSig_Index-%08X scope-%016llX token-%08X",
             value.callConv, value.retTypeClass, value.retTypeSigClass, value.retType,
             toString((CorInfoType)value.retType), value.flags, value.numArgs, value.sigInst_classInstCount,
             value.sigInst_classInst_Index, value.sigInst_methInstCount, value.sigInst_methInst_Index, value.args,
             value.cbSig, value.pSig_Index, value.scope, value.token);
  }
  void MethodContext::repFindCallSiteSig(CORINFO_MODULE_HANDLE  module,
                                         unsigned               methTOK,
                                         CORINFO_CONTEXT_HANDLE context,
                                         CORINFO_SIG_INFO*      sig)
  {
      Agnostic_FindCallSiteSig key;
      ZeroMemory(&key, sizeof(Agnostic_FindCallSiteSig)); // We use the input structs as a key and use memcmp to compare..
                                                          // so we need to zero out padding too
      Agnostic_CORINFO_SIG_INFO value;
  
      key.module  = (DWORDLONG)module;
      key.methTok = (DWORD)methTOK;
      key.context = (DWORDLONG)context;
  
      AssertCodeMsg(FindCallSiteSig != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %08X", (DWORD)key.methTok);
      AssertCodeMsg(FindCallSiteSig->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %08X", (DWORD)key.methTok);
      value = FindCallSiteSig->Get(key);
  
      *sig = SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(value, FindCallSiteSig);
  
      DEBUG_REP(dmpFindCallSiteSig(key, value));
  }
  
  void MethodContext::recGetMethodSync(CORINFO_METHOD_HANDLE ftn, void** ppIndirection, void* result)
  {
      if (GetMethodSync == nullptr)
          GetMethodSync = new LightWeightMap<DWORDLONG, DLDL>();
      DLDL value;
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      GetMethodSync->Add((DWORDLONG)ftn, value);
  }
  void MethodContext::dmpGetMethodSync(DWORDLONG key, DLDL value)
  {
      printf("GetMethodSync key %016llX, value pp-%016llX res-%016llX", key, value.A, value.B);
  }
  void* MethodContext::repGetMethodSync(CORINFO_METHOD_HANDLE ftn, void** ppIndirection)
  {
      DLDL value;
  
      value = (DLDL)GetMethodSync->Get((DWORDLONG)ftn);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
  
      return (void*)value.B;
  }
  
  void MethodContext::recGetVarArgsHandle(CORINFO_SIG_INFO* pSig, void** ppIndirection, CORINFO_VARARGS_HANDLE result)
  {
      if (GetVarArgsHandle == nullptr)
          GetVarArgsHandle = new LightWeightMap<GetVarArgsHandleValue, DLDL>();
  
      GetVarArgsHandleValue key;
      ZeroMemory(&key, sizeof(GetVarArgsHandleValue)); // We use the input structs as a key and use memcmp to
                                                       // compare.. so we need to zero out padding too
      key.cbSig      = (DWORD)pSig->cbSig;
      key.pSig_Index = (DWORD)GetVarArgsHandle->AddBuffer((unsigned char*)pSig->pSig, pSig->cbSig);
      key.scope      = (DWORDLONG)pSig->scope;
      key.token      = (DWORD)pSig->token;
  
      DLDL value;
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      GetVarArgsHandle->Add(key, value);
  }
  void MethodContext::dmpGetVarArgsHandle(const GetVarArgsHandleValue& key, DLDL value)
  {
      printf("GetVarArgsHandle key cbSig-%08X pSig_Index-%08X scope-%016llX token-%08X", key.cbSig, key.pSig_Index,
             key.scope, key.token);
      printf(", value ppIndirection-%016llX result-%016llX", value.A, value.B);
  }
  CORINFO_VARARGS_HANDLE MethodContext::repGetVarArgsHandle(CORINFO_SIG_INFO* pSig, void** ppIndirection)
  {
      GetVarArgsHandleValue key;
      ZeroMemory(&key, sizeof(GetVarArgsHandleValue)); // We use the input structs as a key and use memcmp to
                                                       // compare.. so we need to zero out padding too
  
      key.cbSig      = (DWORD)pSig->cbSig;
      key.pSig_Index = (DWORD)GetVarArgsHandle->Contains((unsigned char*)pSig->pSig, pSig->cbSig);
      key.scope      = (DWORDLONG)pSig->scope;
      key.token      = (DWORD)pSig->token;
  
      DLDL value = (DLDL)GetVarArgsHandle->Get(key);
  
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
  
      return (CORINFO_VARARGS_HANDLE)value.B;
  }
  
  void MethodContext::recCanGetVarArgsHandle(CORINFO_SIG_INFO* pSig, bool result)
  {
      if (CanGetVarArgsHandle == nullptr)
          CanGetVarArgsHandle = new LightWeightMap<CanGetVarArgsHandleValue, DWORD>();
  
      CanGetVarArgsHandleValue key;
      ZeroMemory(&key, sizeof(CanGetVarArgsHandleValue)); // We use the input structs as a key and use memcmp to
                                                          // compare.. so we need to zero out padding too
      key.scope = (DWORDLONG)pSig->scope;
      key.token = (DWORD)pSig->token;
  
      CanGetVarArgsHandle->Add(key, (DWORD)result);
      DEBUG_REC(dmpCanGetVarArgsHandle(key, (DWORD)result));
  }
  void MethodContext::dmpCanGetVarArgsHandle(const CanGetVarArgsHandleValue& key, DWORD value)
  {
      printf("CanGetVarArgsHandle key scope-%016llX token-%08X, value result-%08X", key.scope, key.token, value);
  }
  bool MethodContext::repCanGetVarArgsHandle(CORINFO_SIG_INFO* pSig)
  {
      CanGetVarArgsHandleValue key;
      ZeroMemory(&key, sizeof(CanGetVarArgsHandleValue)); // We use the input structs as a key and use memcmp to
                                                          // compare.. so we need to zero out padding too
      key.scope = (DWORDLONG)pSig->scope;
      key.token = (DWORD)pSig->token;
  
      AssertCodeMsg(CanGetVarArgsHandle != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
                    (DWORDLONG)key.token);
      AssertCodeMsg(CanGetVarArgsHandle->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)key.token);
      bool value = CanGetVarArgsHandle->Get(key) != 0;
      DEBUG_REP(dmpCanGetVarArgsHandle(key, (DWORD)value));
      return value;
  }
  
  void MethodContext::recGetFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field, void** ppIndirection, DWORD result)
  {
      if (GetFieldThreadLocalStoreID == nullptr)
          GetFieldThreadLocalStoreID = new LightWeightMap<DWORDLONG, DLD>();
      ;
  
      DLD value;
  
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORD)result;
  
      GetFieldThreadLocalStoreID->Add((DWORDLONG)field, value);
  }
  void MethodContext::dmpGetFieldThreadLocalStoreID(DWORDLONG key, DLD value)
  {
      printf("GetFieldThreadLocalStoreID key field-%016llX, value ppIndirection-%016llX result-%08X", key, value.A,
             value.B);
  }
  DWORD MethodContext::repGetFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field, void** ppIndirection)
  {
      DLD value;
      value = (DLD)GetFieldThreadLocalStoreID->Get((DWORDLONG)field);
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      return (DWORD)value.B;
  }
  
  void MethodContext::recGetMethodBlockCounts(CORINFO_METHOD_HANDLE        ftnHnd,
                                              UINT32 *                     pCount,
                                              ICorJitInfo::BlockCounts**   pBlockCounts,
                                              UINT32 *                     pNumRuns,
                                              HRESULT                      result)
  {
      if (GetMethodBlockCounts == nullptr)
          GetMethodBlockCounts = new LightWeightMap<DWORDLONG, Agnostic_GetMethodBlockCounts>();
  
      Agnostic_GetMethodBlockCounts value;
  
      value.count = (DWORD)*pCount;
      value.pBlockCounts_index =
          GetMethodBlockCounts->AddBuffer((unsigned char*)*pBlockCounts, sizeof(ICorJitInfo::BlockCounts) * (*pCount));
      value.numRuns = (DWORD)*pNumRuns;
      value.result  = (DWORD)result;
  
      GetMethodBlockCounts->Add((DWORDLONG)ftnHnd, value);
  }
  void MethodContext::dmpGetMethodBlockCounts(DWORDLONG key, const Agnostic_GetMethodBlockCounts& value)
  {
      printf("GetMethodBlockCounts key ftn-%016llX, value cnt-%u profileBuf-", key, value.count);
      ICorJitInfo::BlockCounts* pBuf =
          (ICorJitInfo::BlockCounts*)GetMethodBlockCounts->GetBuffer(value.pBlockCounts_index);
      for (DWORD i = 0; i < value.count; i++, pBuf++)
      {
          printf("{il-%u,cnt-%u}", pBuf->ILOffset, pBuf->ExecutionCount);
      }
      GetMethodBlockCounts->Unlock();
      printf(" numRuns-%u result-%u", value.numRuns, value.result);
  }
  HRESULT MethodContext::repGetMethodBlockCounts(CORINFO_METHOD_HANDLE        ftnHnd,
                                                 UINT32 *                     pCount,
                                                 ICorJitInfo::BlockCounts**   pBlockCounts,
                                                 UINT32 *                     pNumRuns)
  {
      Agnostic_GetMethodBlockCounts tempValue;
  
      tempValue = GetMethodBlockCounts->Get((DWORDLONG)ftnHnd);
  
      *pCount        = (UINT32)tempValue.count;
      *pBlockCounts  = (ICorJitInfo::BlockCounts*)GetMethodBlockCounts->GetBuffer(tempValue.pBlockCounts_index);
      *pNumRuns      = (UINT32)tempValue.numRuns;
      HRESULT result = (HRESULT)tempValue.result;
      return result;
  }
  
  void MethodContext::recMergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, CORINFO_CLASS_HANDLE result)
  {
      if (MergeClasses == nullptr)
          MergeClasses = new LightWeightMap<DLDL, DWORDLONG>();
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      MergeClasses->Add(key, (DWORDLONG)result);
  }
  void MethodContext::dmpMergeClasses(DLDL key, DWORDLONG value)
  {
      printf("MergeClasses NYI");
  }
  CORINFO_CLASS_HANDLE MethodContext::repMergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      DWORDLONG value;
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      AssertCodeMsg(MergeClasses->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX %016llX", (DWORDLONG)cls1,
                    (DWORDLONG)cls2);
      value = MergeClasses->Get(key);
  
      return (CORINFO_CLASS_HANDLE)value;
  }
  
  void MethodContext::recIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, BOOL result)
  {
      if (IsMoreSpecificType == nullptr)
          IsMoreSpecificType = new LightWeightMap<DLDL, DWORD>();
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      IsMoreSpecificType->Add(key, (DWORD)result);
  }
  void MethodContext::dmpIsMoreSpecificType(DLDL key, DWORD value)
  {
      printf("IsMoreSpecificType key cls1-%016llX cls2-%016llX, value %u", key.A, key.B, value);
  }
  BOOL MethodContext::repIsMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
      DWORD value;
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      AssertCodeMsg(IsMoreSpecificType->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX %016llX", (DWORDLONG)cls1,
                    (DWORDLONG)cls2);
  
      value = IsMoreSpecificType->Get(key);
  
      return (BOOL)value;
  }
  
  void MethodContext::recGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void** ppIndirection, LPVOID result)
  {
      if (GetCookieForPInvokeCalliSig == nullptr)
          GetCookieForPInvokeCalliSig = new LightWeightMap<GetCookieForPInvokeCalliSigValue, DLDL>();
  
      GetCookieForPInvokeCalliSigValue key;
      ZeroMemory(&key, sizeof(GetCookieForPInvokeCalliSigValue)); // We use the input structs as a key and use memcmp to
                                                                  // compare.. so we need to zero out padding too
      key.cbSig      = (DWORD)szMetaSig->cbSig;
      key.pSig_Index = (DWORD)GetCookieForPInvokeCalliSig->AddBuffer((unsigned char*)szMetaSig->pSig, szMetaSig->cbSig);
      key.scope      = (DWORDLONG)szMetaSig->scope;
      key.token      = (DWORD)szMetaSig->token;
  
      DLDL value;
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      GetCookieForPInvokeCalliSig->Add(key, value);
  }
  void MethodContext::dmpGetCookieForPInvokeCalliSig(const GetCookieForPInvokeCalliSigValue& key, DLDL value)
  {
      printf("GetCookieForPInvokeCalliSig NYI");
  }
  LPVOID MethodContext::repGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void** ppIndirection)
  {
      GetCookieForPInvokeCalliSigValue key;
      ZeroMemory(&key, sizeof(GetCookieForPInvokeCalliSigValue)); // We use the input structs as a key and use memcmp to
                                                                  // compare.. so we need to zero out padding too
      key.cbSig      = (DWORD)szMetaSig->cbSig;
      key.pSig_Index = (DWORD)GetCookieForPInvokeCalliSig->Contains((unsigned char*)szMetaSig->pSig, szMetaSig->cbSig);
      key.scope      = (DWORDLONG)szMetaSig->scope;
      key.token      = (DWORD)szMetaSig->token;
  
      DLDL value = (DLDL)GetCookieForPInvokeCalliSig->Get(key);
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
  
      return (CORINFO_VARARGS_HANDLE)value.B;
  }
  
  void MethodContext::recCanGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, bool result)
  {
      if (CanGetCookieForPInvokeCalliSig == nullptr)
          CanGetCookieForPInvokeCalliSig = new LightWeightMap<CanGetCookieForPInvokeCalliSigValue, DWORD>();
  
      CanGetCookieForPInvokeCalliSigValue key;
      ZeroMemory(&key,
                 sizeof(CanGetCookieForPInvokeCalliSigValue)); // We use the input structs as a key and use memcmp to
                                                               // compare.. so we need to zero out padding too
      key.scope = (DWORDLONG)szMetaSig->scope;
      key.token = (DWORD)szMetaSig->token;
  
      CanGetCookieForPInvokeCalliSig->Add(key, (DWORD)result);
  }
  void MethodContext::dmpCanGetCookieForPInvokeCalliSig(const CanGetCookieForPInvokeCalliSigValue& key, DWORD value)
  {
      printf("CanGetCookieForPInvokeCalliSig key scope-%016llX token-%08X, value result-%08X", key.scope, key.token,
             value);
  }
  bool MethodContext::repCanGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
  {
      CanGetCookieForPInvokeCalliSigValue key;
      ZeroMemory(&key,
                 sizeof(CanGetCookieForPInvokeCalliSigValue)); // We use the input structs as a key and use memcmp to
                                                               // compare.. so we need to zero out padding too
      key.scope = (DWORDLONG)szMetaSig->scope;
      key.token = (DWORD)szMetaSig->token;
  
      DWORD temp = CanGetCookieForPInvokeCalliSig->Get(key);
      return temp != 0;
  }
  
  void MethodContext::recCanAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType, BOOL result)
  {
      if (CanAccessFamily == nullptr)
          CanAccessFamily = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)hCaller;
      key.B = (DWORDLONG)hInstanceType;
  
      CanAccessFamily->Add(key, (DWORD)result);
  }
  void MethodContext::dmpCanAccessFamily(DLDL key, DWORD value)
  {
      printf("CanAccessFamily key cal-%016llX inst-%016llX, value %u", key.A, key.B, value);
  }
  BOOL MethodContext::repCanAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)hCaller;
      key.B = (DWORDLONG)hInstanceType;
  
      DWORD temp = CanAccessFamily->Get(key);
      return (BOOL)temp;
  }
  
  void MethodContext::recErrorList(const char* error)
  {
      if (ErrorList == nullptr)
          ErrorList = new DenseLightWeightMap<DWORD>();
  
      DWORD temp = (DWORD)-1;
  
      if (error != nullptr)
          temp = (DWORD)ErrorList->AddBuffer((unsigned char*)error, (DWORD)strlen(error) + 1);
  
      ErrorList->Append(temp);
  }
  void MethodContext::dmpErrorList(DWORD key, DWORD value)
  {
      printf("ErrorList NYI");
  }
  
  void MethodContext::recGetProfilingHandle(BOOL* pbHookFunction, void** pProfilerHandle, BOOL* pbIndirectedHandles)
  {
      if (GetProfilingHandle == nullptr)
          GetProfilingHandle = new LightWeightMap<DWORD, Agnostic_GetProfilingHandle>();
  
      Agnostic_GetProfilingHandle value;
      ZeroMemory(&value, sizeof(Agnostic_GetProfilingHandle)); // We use the input structs as a value and use memcmp to
                                                               // compare.. so we need to zero out padding too
  
      value.bHookFunction      = (DWORD)*pbHookFunction;
      value.ProfilerHandle     = (DWORDLONG)*pProfilerHandle;
      value.bIndirectedHandles = (DWORD)*pbIndirectedHandles;
      GetProfilingHandle->Add((DWORD)0, value);
      DEBUG_REC(dmpGetProfilingHandle(0, value));
  }
  void MethodContext::dmpGetProfilingHandle(DWORD key, const Agnostic_GetProfilingHandle& value)
  {
      printf("GetProfilingHandle key %u, value bHookFtn-%u profHnd-%016llX bIndHnd-%u", key, value.bHookFunction,
             value.ProfilerHandle, value.bIndirectedHandles);
  }
  void MethodContext::repGetProfilingHandle(BOOL* pbHookFunction, void** pProfilerHandle, BOOL* pbIndirectedHandles)
  {
      Agnostic_GetProfilingHandle value;
  
      value = GetProfilingHandle->Get((DWORD)0);
  
      *pbHookFunction      = (BOOL)value.bHookFunction;
      *pProfilerHandle     = (void*)value.ProfilerHandle;
      *pbIndirectedHandles = (BOOL)value.bIndirectedHandles;
      DEBUG_REP(dmpGetProfilingHandle(0, value));
  }
  
  void MethodContext::recEmbedFieldHandle(CORINFO_FIELD_HANDLE handle, void** ppIndirection, CORINFO_FIELD_HANDLE result)
  {
      if (EmbedFieldHandle == nullptr)
          EmbedFieldHandle = new LightWeightMap<DWORDLONG, DLDL>();
  
      DLDL value;
      if (ppIndirection != nullptr)
          value.A = (DWORDLONG)*ppIndirection;
      else
          value.A = (DWORDLONG)0;
      value.B     = (DWORDLONG)result;
  
      EmbedFieldHandle->Add((DWORDLONG)handle, value);
  }
  void MethodContext::dmpEmbedFieldHandle(DWORDLONG key, DLDL value)
  {
      printf("EmbedFieldHandle NYI");
  }
  CORINFO_FIELD_HANDLE MethodContext::repEmbedFieldHandle(CORINFO_FIELD_HANDLE handle, void** ppIndirection)
  {
      DLDL value;
  
      value = EmbedFieldHandle->Get((DWORDLONG)handle);
      if (ppIndirection != nullptr)
          *ppIndirection = (void*)value.A;
      return (CORINFO_FIELD_HANDLE)value.B;
  }
  
  void MethodContext::recAreTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2, BOOL result)
  {
      if (AreTypesEquivalent == nullptr)
          AreTypesEquivalent = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      AreTypesEquivalent->Add(key, (DWORD)result);
  }
  void MethodContext::dmpAreTypesEquivalent(DLDL key, DWORD value)
  {
      printf("AreTypesEquivalent NYI");
  }
  BOOL MethodContext::repAreTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      AssertCodeMsg(AreTypesEquivalent->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX %016llX",
                    (DWORDLONG)cls1, (DWORDLONG)cls2);
      BOOL value = (BOOL)AreTypesEquivalent->Get(key);
      return value;
  }
  
  void MethodContext::recCompareTypesForCast(CORINFO_CLASS_HANDLE fromClass,
                                             CORINFO_CLASS_HANDLE toClass,
                                             TypeCompareState     result)
  {
      if (CompareTypesForCast == nullptr)
          CompareTypesForCast = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)fromClass;
      key.B = (DWORDLONG)toClass;
  
      CompareTypesForCast->Add(key, (DWORD)result);
  }
  void MethodContext::dmpCompareTypesForCast(DLDL key, DWORD value)
  {
      printf("CompareTypesForCast key fromClass=%016llX, toClass=%016llx, result=%d", key.A, key.B, value);
  }
  TypeCompareState MethodContext::repCompareTypesForCast(CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass)
  {
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)fromClass;
      key.B = (DWORDLONG)toClass;
  
      AssertCodeMsg(CompareTypesForCast->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX %016llX",
                    (DWORDLONG)fromClass, (DWORDLONG)toClass);
      TypeCompareState value = (TypeCompareState)CompareTypesForCast->Get(key);
      return value;
  }
  
  void MethodContext::recCompareTypesForEquality(CORINFO_CLASS_HANDLE cls1,
                                                 CORINFO_CLASS_HANDLE cls2,
                                                 TypeCompareState     result)
  {
      if (CompareTypesForEquality == nullptr)
          CompareTypesForEquality = new LightWeightMap<DLDL, DWORD>();
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      CompareTypesForEquality->Add(key, (DWORD)result);
  }
  void MethodContext::dmpCompareTypesForEquality(DLDL key, DWORD value)
  {
      printf("CompareTypesForEquality key cls1=%016llX, cls2=%016llx, result=%d", key.A, key.B, value);
  }
  TypeCompareState MethodContext::repCompareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
  {
      AssertCodeMsg(CompareTypesForEquality != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for CompareTypesForEquality");
  
      DLDL key;
      ZeroMemory(&key, sizeof(DLDL)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                      // out padding too
  
      key.A = (DWORDLONG)cls1;
      key.B = (DWORDLONG)cls2;
  
      AssertCodeMsg(CompareTypesForEquality->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX %016llX",
                    (DWORDLONG)cls1, (DWORDLONG)cls2);
      TypeCompareState value = (TypeCompareState)CompareTypesForEquality->Get(key);
      return value;
  }
  
  void MethodContext::recFindNameOfToken(
      CORINFO_MODULE_HANDLE module, mdToken metaTOK, char* szFQName, size_t FQNameCapacity, size_t result)
  {
      if (FindNameOfToken == nullptr)
          FindNameOfToken = new LightWeightMap<DLD, DLD>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      DLD value;
  
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
  
      value.A = result;
      value.B = FindNameOfToken->AddBuffer((unsigned char*)szFQName, (unsigned int)result);
  
      FindNameOfToken->Add(key, value);
      DEBUG_REC(dmpFindNameOfToken(key, value));
  }
  void MethodContext::dmpFindNameOfToken(DLD key, DLD value)
  {
      // practically the name of a token wont be bigger than 4gb...
      unsigned char* buff = new unsigned char[(unsigned int)value.A + 1];
      ZeroMemory(buff, (unsigned int)value.A + 1);
      memcpy(buff, FindNameOfToken->GetBuffer(value.B), (unsigned int)value.A);
      FindNameOfToken->Unlock();
      printf("FindNameOfToken key mod-%016llX tok-%08X, value '%s'", key.A, key.B, buff);
      delete[] buff;
  }
  size_t MethodContext::repFindNameOfToken(CORINFO_MODULE_HANDLE module,
                                           mdToken               metaTOK,
                                           char*                 szFQName,
                                           size_t                FQNameCapacity)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      DLD value;
  
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
  
      value = FindNameOfToken->Get(key);
  
      unsigned char* temp = nullptr;
      if (value.B != (DWORD)-1)
      {
          temp = FindNameOfToken->GetBuffer(value.B);
          memcpy(szFQName, temp, (size_t)value.A);
      }
  
      DEBUG_REP(dmpFindNameOfToken(key, value));
      return (size_t)value.A;
  }
  
  void MethodContext::recGetSystemVAmd64PassStructInRegisterDescriptor(
      CORINFO_CLASS_HANDLE                                 structHnd,
      SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr,
      bool                                                 result)
  {
      if (GetSystemVAmd64PassStructInRegisterDescriptor == nullptr)
          GetSystemVAmd64PassStructInRegisterDescriptor =
              new LightWeightMap<DWORDLONG, Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor>();
  
      DWORDLONG                                              key;
      Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor value;
  
      key = (DWORDLONG)structHnd;
  
      value.passedInRegisters = (DWORD)structPassInRegDescPtr->passedInRegisters;
      value.eightByteCount    = (DWORD)structPassInRegDescPtr->eightByteCount;
      for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++)
      {
          value.eightByteClassifications[i] = (DWORD)structPassInRegDescPtr->eightByteClassifications[i];
          value.eightByteSizes[i]           = (DWORD)structPassInRegDescPtr->eightByteSizes[i];
          value.eightByteOffsets[i]         = (DWORD)structPassInRegDescPtr->eightByteOffsets[i];
      }
      value.result = result ? 1 : 0;
  
      GetSystemVAmd64PassStructInRegisterDescriptor->Add(key, value);
      DEBUG_REC(dmpGetSystemVAmd64PassStructInRegisterDescriptor(key, value));
  }
  void MethodContext::dmpGetSystemVAmd64PassStructInRegisterDescriptor(
      DWORDLONG key, const Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor& value)
  {
      printf("GetSystemVAmd64PassStructInRegisterDescriptor key structHnd-%016llX, value passInReg-%u 8bCount-%u", key,
             value.passedInRegisters, value.eightByteCount);
      for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++)
      {
          printf(" 8bClass[%u]-%u 8bSz[%u]-%u 8bOff[%u]-%u", i, value.eightByteClassifications[i], i,
                 value.eightByteSizes[i], i, value.eightByteOffsets[i]);
      }
      printf(" result %u", value.result);
  }
  bool MethodContext::repGetSystemVAmd64PassStructInRegisterDescriptor(
      CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
  {
      DWORDLONG                                              key;
      Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor value;
  
      key = (DWORDLONG)structHnd;
  
      value = GetSystemVAmd64PassStructInRegisterDescriptor->Get(key);
  
      structPassInRegDescPtr->passedInRegisters = value.passedInRegisters ? true : false;
      structPassInRegDescPtr->eightByteCount    = (unsigned __int8)value.eightByteCount;
      for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++)
      {
          structPassInRegDescPtr->eightByteClassifications[i] =
              (SystemVClassificationType)value.eightByteClassifications[i];
          structPassInRegDescPtr->eightByteSizes[i]   = (unsigned __int8)value.eightByteSizes[i];
          structPassInRegDescPtr->eightByteOffsets[i] = (unsigned __int8)value.eightByteOffsets[i];
      }
  
      DEBUG_REP(dmpGetSystemVAmd64PassStructInRegisterDescriptor(key, value));
      return value.result ? true : false;
  }
  
  void MethodContext::recGetRelocTypeHint(void* target, WORD result)
  {
      if (GetRelocTypeHint == nullptr)
          GetRelocTypeHint = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetRelocTypeHint->Add((DWORDLONG)target, (DWORD)result);
      DEBUG_REC(dmpGetRelocTypeHint((DWORDLONG)target, (DWORD)result));
  }
  void MethodContext::dmpGetRelocTypeHint(DWORDLONG key, DWORD value)
  {
      printf("GetRelocTypeHint key tgt-%016llX, value hint-%u", key, value);
  }
  WORD MethodContext::repGetRelocTypeHint(void* target)
  {
      if (GetRelocTypeHint == nullptr)
      {
  #ifdef sparseMC
          LogDebug("Sparse - repGetRelocTypeHint yielding fake answer...");
          return 65535;
  #else
          LogException(EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)target);
  #endif
      }
      if (GetRelocTypeHint->GetIndex((DWORDLONG)target) == -1)
      {
          void* origAddr = cr->repAddressMap((void*)target);
          if (origAddr != (void*)-1 && origAddr != nullptr)
          {
              if (GetRelocTypeHint->GetIndex((DWORDLONG)origAddr) == -1)
                  target = origAddr;
          }
          else
          {
  #ifdef sparseMC
              LogDebug("Sparse - repGetRelocTypeHint yielding fake answer...");
              return 65535;
  #else
              LogException(EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)target);
  #endif
          }
      }
  
      int  index  = GetRelocTypeHint->GetIndex((DWORDLONG)target);
      WORD retVal = 0;
      if (index == -1)
      {
          void* subtarget = cr->searchAddressMap(target);
  
          int index2 = GetRelocTypeHint->GetIndex((DWORDLONG)subtarget);
          if (index2 == -1)
          {
              // __debugbreak(); // seems like a source of pain
              retVal = IMAGE_REL_BASED_REL32;
          }
          else
              retVal = (WORD)GetRelocTypeHint->Get((DWORDLONG)subtarget);
      }
      else
          retVal = (WORD)GetRelocTypeHint->Get((DWORDLONG)target);
      DEBUG_REP(dmpGetRelocTypeHint((DWORDLONG)target, retVal));
      return retVal;
  }
  
  void MethodContext::recIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK, BOOL result)
  {
      if (IsValidToken == nullptr)
          IsValidToken = new LightWeightMap<DLD, DWORD>();
  
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
      key.A = (DWORDLONG)module;
      key.B = (DWORD)metaTOK;
      IsValidToken->Add(key, (DWORD)result);
  }
  void MethodContext::dmpIsValidToken(DLD key, DWORD value)
  {
      printf("IsValidToken key mod-%016llX tok-%08X, value res-%u", key.A, key.B, value);
  }
  BOOL MethodContext::repIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK)
  {
      DLD key;
      ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero
                                     // out padding too
  
      key.A      = (DWORDLONG)module;
      key.B      = (DWORD)metaTOK;
      BOOL value = (BOOL)IsValidToken->Get(key);
      return value;
  }
  
  void MethodContext::recGetClassName(CORINFO_CLASS_HANDLE cls, const char* result)
  {
      if (GetClassName == nullptr)
          GetClassName = new LightWeightMap<DWORDLONG, DWORD>();
  
      DWORD temp = (DWORD)-1;
      if (result != nullptr)
          temp = (DWORD)GetClassName->AddBuffer((unsigned char*)result, (unsigned int)strlen(result) + 1);
  
      GetClassName->Add((DWORDLONG)cls, (DWORD)temp);
      DEBUG_REC(dmpGetClassName((DWORDLONG)cls, (DWORD)temp));
  }
  void MethodContext::dmpGetClassName(DWORDLONG key, DWORD value)
  {
      printf("GetClassName key %016llX, value %s", key, GetClassName->GetBuffer(value));
      GetClassName->Unlock();
  }
  const char* MethodContext::repGetClassName(CORINFO_CLASS_HANDLE cls)
  {
      if (GetClassName == nullptr)
          return "hackishClassName";
      int index = GetClassName->GetIndex((DWORDLONG)cls);
      if (index == -1)
          return "hackishClassName";
      int         offset = GetClassName->Get((DWORDLONG)cls);
      const char* name   = (const char*)GetClassName->GetBuffer(offset);
      DEBUG_REC(dmpGetClassName((DWORDLONG)cls, (DWORD)offset));
      return name;
  }
  
  void MethodContext::recGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, char* className, const char** namespaceName)
  {
      if (GetClassNameFromMetadata == nullptr)
          GetClassNameFromMetadata = new LightWeightMap<DLD, DD>();
      DD  value;
      DLD key;
      key.A = (DWORDLONG)cls;
      key.B = (namespaceName != nullptr);
  
      if (className != nullptr)
          value.A = GetClassNameFromMetadata->AddBuffer((unsigned char*)className, (DWORD)strlen(className) + 1);
      else
          value.A = (DWORD)-1;
  
      if ((namespaceName != nullptr) && (*namespaceName != nullptr))
          value.B =
              GetClassNameFromMetadata->AddBuffer((unsigned char*)*namespaceName, (DWORD)strlen(*namespaceName) + 1);
      else
          value.B = (DWORD)-1;
  
      GetClassNameFromMetadata->Add(key, value);
      DEBUG_REC(dmpGetClassNameFromMetadata(key, value));
  }
  
  void MethodContext::dmpGetClassNameFromMetadata(DLD key, DD value)
  {
      unsigned char* className     = (unsigned char*)GetClassNameFromMetadata->GetBuffer(value.A);
      unsigned char* namespaceName = (unsigned char*)GetClassNameFromMetadata->GetBuffer(value.B);
      printf("GetClassNameFromMetadata key - classNonNull-%llu namespaceNonNull-%u, value "
             "class-'%s', namespace-'%s'",
             key.A, key.B, className, namespaceName);
      GetClassNameFromMetadata->Unlock();
  }
  
  const char* MethodContext::repGetClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName)
  {
      const char* result = nullptr;
      DD          value;
      DLD         key;
      key.A = (DWORDLONG)cls;
      key.B = (namespaceName != nullptr);
  
      int itemIndex = -1;
      if (GetClassNameFromMetadata != nullptr)
          itemIndex = GetClassNameFromMetadata->GetIndex(key);
      if (itemIndex < 0)
      {
          if (namespaceName != nullptr)
          {
              *namespaceName = nullptr;
          }
      }
      else
      {
          value  = GetClassNameFromMetadata->Get(key);
          result = (const char*)GetClassNameFromMetadata->GetBuffer(value.A);
  
          if (namespaceName != nullptr)
          {
              *namespaceName = (const char*)GetClassNameFromMetadata->GetBuffer(value.B);
          }
      }
      DEBUG_REP(dmpGetClassNameFromMetadata(key, value));
      return result;
  }
  
  void MethodContext::recGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls,
                                                      CORINFO_CLASS_HANDLE result,
                                                      unsigned             index)
  {
      if (GetTypeInstantiationArgument == nullptr)
          GetTypeInstantiationArgument = new LightWeightMap<DWORDLONG, DWORDLONG>();
  
      DWORDLONG key = (DWORDLONG)cls;
  
      GetTypeInstantiationArgument->Add(key, (DWORDLONG)result);
      DEBUG_REC(dmpGetTypeInstantiationArgument(key, (DWORDLONG)result));
  }
  
  void MethodContext::dmpGetTypeInstantiationArgument(DWORDLONG key, DWORDLONG value)
  {
      printf("GetTypeInstantiationArgument key - classNonNull-%llu, value NonNull-%llu", key, value);
      GetTypeInstantiationArgument->Unlock();
  }
  
  CORINFO_CLASS_HANDLE MethodContext::repGetTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index)
  {
      CORINFO_CLASS_HANDLE result = nullptr;
      DWORDLONG            value;
      DWORDLONG            key;
      key = (DWORDLONG)cls;
  
      int itemIndex = -1;
      if (GetTypeInstantiationArgument != nullptr)
          itemIndex = GetTypeInstantiationArgument->GetIndex(key);
      if (itemIndex >= 0)
      {
          value  = GetTypeInstantiationArgument->Get(key);
          result = (CORINFO_CLASS_HANDLE)value;
      }
  
      DEBUG_REP(dmpGetTypeInstantiationArgument(key, value));
      return result;
  }
  
  void MethodContext::recAppendClassName(
      CORINFO_CLASS_HANDLE cls, BOOL fNamespace, BOOL fFullInst, BOOL fAssembly, const WCHAR* result)
  {
      if (AppendClassName == nullptr)
          AppendClassName = new LightWeightMap<Agnostic_AppendClassName, DWORD>();
  
      Agnostic_AppendClassName key;
      ZeroMemory(&key, sizeof(Agnostic_AppendClassName)); // We use the input structs as a key and use memcmp to compare..
                                                          // so we need to zero out padding too
      key.classHandle = (DWORDLONG)cls;
      key.fNamespace  = fNamespace;
      key.fFullInst   = fFullInst;
      key.fAssembly   = fAssembly;
  
      DWORD temp = (DWORD)-1;
      if (result != nullptr)
          temp = (DWORD)AppendClassName->AddBuffer((unsigned char*)result, (unsigned int)((wcslen(result) * 2) + 2));
  
      AppendClassName->Add(key, (DWORD)temp);
      DEBUG_REC(dmpAppendClassName(key, (DWORD)temp));
  }
  
  void MethodContext::dmpAppendClassName(const Agnostic_AppendClassName& key, DWORD value)
  {
      printf("AppendClassName key cls-%016llX ns-%u fi-%u as-%u, value %s", key.classHandle, key.fNamespace,
             key.fFullInst, key.fAssembly, AppendClassName->GetBuffer(value));
      AppendClassName->Unlock();
  }
  
  const WCHAR* MethodContext::repAppendClassName(CORINFO_CLASS_HANDLE cls,
                                                 BOOL                 fNamespace,
                                                 BOOL                 fFullInst,
                                                 BOOL                 fAssembly)
  {
      if (AppendClassName == nullptr)
          return W("hackishClassName");
  
      Agnostic_AppendClassName key;
      ZeroMemory(&key, sizeof(Agnostic_AppendClassName)); // We use the input structs as a key and use memcmp to compare..
                                                          // so we need to zero out padding too
      key.classHandle = (DWORDLONG)cls;
      key.fNamespace  = fNamespace;
      key.fFullInst   = fFullInst;
      key.fAssembly   = fAssembly;
  
      int index = AppendClassName->GetIndex(key);
      if (index == -1)
          return W("hackishClassName");
      int          offset = AppendClassName->Get(key);
      const WCHAR* name   = (const WCHAR*)AppendClassName->GetBuffer(offset);
      DEBUG_REC(dmpAppendClassName(key, (DWORD)offset));
      return name;
  }
  
  void MethodContext::recGetTailCallHelpers(
      CORINFO_RESOLVED_TOKEN* callToken,
      CORINFO_SIG_INFO* sig,
      CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
      CORINFO_TAILCALL_HELPERS* pResult)
  {
      if (GetTailCallHelpers == nullptr)
          GetTailCallHelpers = new LightWeightMap<Agnostic_GetTailCallHelpers, Agnostic_CORINFO_TAILCALL_HELPERS>();
  
      Agnostic_GetTailCallHelpers key;
      ZeroMemory(&key, sizeof(Agnostic_GetTailCallHelpers));
  
      key.callToken = SpmiRecordsHelper::StoreAgnostic_CORINFO_RESOLVED_TOKEN(callToken, GetTailCallHelpers);
      key.sig = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(*sig, GetTailCallHelpers);
      key.flags = (DWORD)flags;
  
      Agnostic_CORINFO_TAILCALL_HELPERS value;
      ZeroMemory(&value, sizeof(Agnostic_CORINFO_TAILCALL_HELPERS));
  
      value.result = pResult != nullptr;
      if (pResult != nullptr)
      {
          value.flags = (DWORD)pResult->flags;
          value.hStoreArgs = (DWORDLONG)pResult->hStoreArgs;
          value.hCallTarget = (DWORDLONG)pResult->hCallTarget;
          value.hDispatcher = (DWORDLONG)pResult->hDispatcher;
      }
      GetTailCallHelpers->Add(key, value);
      DEBUG_REC(dmpGetTailCallHelpers(key, value));
  }
  
  void MethodContext::dmpGetTailCallHelpers(const Agnostic_GetTailCallHelpers& key, const Agnostic_CORINFO_TAILCALL_HELPERS& value)
  {
      printf("GetTailCallHelpers key callToken-%s sig-%s flg-%08X",
          SpmiDumpHelper::DumpAgnostic_CORINFO_RESOLVED_TOKEN(key.callToken).c_str(),
          SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(key.sig).c_str(),
          key.flags);
      printf(", value result-%s flg-%08X hStoreArgs-%016llX hCallTarget-%016llX hDispatcher-%016llX",
          value.result ? "true" : "false",
          value.flags,
          value.hStoreArgs,
          value.hCallTarget,
          value.hDispatcher);
  }
  
  bool MethodContext::repGetTailCallHelpers(
      CORINFO_RESOLVED_TOKEN* callToken,
      CORINFO_SIG_INFO* sig,
      CORINFO_GET_TAILCALL_HELPERS_FLAGS flags,
      CORINFO_TAILCALL_HELPERS* pResult)
  {
      AssertCodeMsg(GetTailCallHelpers != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for ...");
  
      Agnostic_GetTailCallHelpers key;
      ZeroMemory(&key, sizeof(Agnostic_GetTailCallHelpers));
      key.callToken = SpmiRecordsHelper::RestoreAgnostic_CORINFO_RESOLVED_TOKEN(callToken, GetTailCallHelpers);
      key.sig = SpmiRecordsHelper::RestoreAgnostic_CORINFO_SIG_INFO(*sig, GetTailCallHelpers);
      key.flags = (DWORD)flags;
  
      AssertCodeMsg(GetTailCallHelpers->GetIndex(key) != -1, EXCEPTIONCODE_MC, "Could not find matching tail call helper call");
      Agnostic_CORINFO_TAILCALL_HELPERS value = GetTailCallHelpers->Get(key);
      if (!value.result)
          return false;
  
      pResult->flags = (CORINFO_TAILCALL_HELPERS_FLAGS)value.flags;
      pResult->hStoreArgs = (CORINFO_METHOD_HANDLE)value.hStoreArgs;
      pResult->hCallTarget = (CORINFO_METHOD_HANDLE)value.hCallTarget;
      pResult->hDispatcher = (CORINFO_METHOD_HANDLE)value.hDispatcher;
      DEBUG_REP(dmpGetTailCallHelpers(key, value));
      return true;
  }
  
  void MethodContext::recGetMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod, mdMethodDef result)
  {
      if (GetMethodDefFromMethod == nullptr)
          GetMethodDefFromMethod = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetMethodDefFromMethod->Add((DWORDLONG)hMethod, (DWORD)result);
  }
  void MethodContext::dmpGetMethodDefFromMethod(DWORDLONG key, DWORD value)
  {
      printf("GetMethodDefFromMethod key ftn-%016llX, value res-%u", key, value);
  }
  mdMethodDef MethodContext::repGetMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
  {
      // Since this is diagnostic, fake up a result if one wasn't recorded.
      if (GetMethodDefFromMethod == nullptr)
          return (mdMethodDef)0x06000000;
  
      int index = GetMethodDefFromMethod->GetIndex((DWORDLONG)hMethod);
      if (index < 0)
          return (mdMethodDef)0x06000001;
  
      return (mdMethodDef)GetMethodDefFromMethod->Get((DWORDLONG)hMethod);
  }
  
  void MethodContext::recCheckMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional, BOOL result)
  {
      if (CheckMethodModifier == nullptr)
          CheckMethodModifier = new LightWeightMap<Agnostic_CheckMethodModifier, DWORD>();
  
      Agnostic_CheckMethodModifier key;
      ZeroMemory(&key, sizeof(Agnostic_CheckMethodModifier)); // We use the input structs as a key and use memcmp to
                                                              // compare.. so we need to zero out padding too
  
      key.hMethod = (DWORDLONG)hMethod;
      // If the input matches something already in the buffer, just re-use that slot.. easier than searching for a soft
      // key on rep.
      if (modifier != nullptr)
          key.modifier =
              (DWORD)CheckMethodModifier->AddBuffer((unsigned char*)modifier, (unsigned int)strlen(modifier) + 1);
      else
          key.modifier = (DWORD)-1;
  
      key.fOptional = (DWORD)fOptional;
  
      CheckMethodModifier->Add(key, (DWORD)result);
  }
  void MethodContext::dmpCheckMethodModifier(const Agnostic_CheckMethodModifier& key, DWORD value)
  {
      printf("CheckMethodModifier key, ftn-%016llX mod-'%s' opt-%u, value res-%u", key.hMethod,
             (unsigned char*)CheckMethodModifier->GetBuffer(key.modifier), key.fOptional, value);
      CheckMethodModifier->Unlock();
  }
  BOOL MethodContext::repCheckMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional)
  {
      Agnostic_CheckMethodModifier key;
      ZeroMemory(&key, sizeof(Agnostic_CheckMethodModifier)); // We use the input structs as a key and use memcmp to
                                                              // compare.. so we need to zero out padding too
  
      key.hMethod = (DWORDLONG)hMethod;
      if (modifier != nullptr)
          key.modifier =
              (DWORD)CheckMethodModifier->Contains((unsigned char*)modifier, (unsigned int)strlen(modifier) + 1);
      else
          key.modifier = (DWORD)-1;
  
      key.fOptional = (DWORD)fOptional;
  
      BOOL value = (BOOL)CheckMethodModifier->Get(key);
      return value;
  }
  
  void MethodContext::recGetArrayRank(CORINFO_CLASS_HANDLE cls, unsigned result)
  {
      if (GetArrayRank == nullptr)
          GetArrayRank = new LightWeightMap<DWORDLONG, DWORD>();
  
      GetArrayRank->Add((DWORDLONG)cls, (DWORD)result);
  }
  void MethodContext::dmpGetArrayRank(DWORDLONG key, DWORD value)
  {
      printf("GetArrayRank key %016llX, value %u", key, value);
  }
  unsigned MethodContext::repGetArrayRank(CORINFO_CLASS_HANDLE cls)
  {
      return (unsigned)GetArrayRank->Get((DWORDLONG)cls);
  }
  
  void MethodContext::recIsFieldStatic(CORINFO_FIELD_HANDLE fhld, bool result)
  {
      if (IsFieldStatic == nullptr)
          IsFieldStatic = new LightWeightMap<DWORDLONG, DWORD>();
  
      IsFieldStatic->Add((DWORDLONG)fhld, (DWORD)result);
      DEBUG_REC(dmpIsFieldStatic((DWORDLONG)fhld, (DWORD)result));
  }
  void MethodContext::dmpIsFieldStatic(DWORDLONG key, DWORD value)
  {
      printf("IsFieldStatic key %016llX, value %u", key, value);
  }
  bool MethodContext::repIsFieldStatic(CORINFO_FIELD_HANDLE fhld)
  {
      AssertCodeMsg(IsFieldStatic != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX", (DWORDLONG)fhld);
      AssertCodeMsg(IsFieldStatic->GetIndex((DWORDLONG)fhld) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
                    (DWORDLONG)fhld);
      bool result = (bool)(IsFieldStatic->Get((DWORDLONG)fhld) != 0);
      DEBUG_REP(dmpIsFieldStatic((DWORDLONG)fhld, (DWORD)result));
      return result;
  }
  
  void MethodContext::recGetIntConfigValue(const WCHAR* name, int defaultValue, int result)
  {
      if (GetIntConfigValue == nullptr)
          GetIntConfigValue = new LightWeightMap<Agnostic_ConfigIntInfo, DWORD>();
  
      AssertCodeMsg(name != nullptr, EXCEPTIONCODE_MC, "Name can not be nullptr");
  
      Agnostic_ConfigIntInfo key;
      ZeroMemory(&key, sizeof(Agnostic_ConfigIntInfo));
  
      DWORD index =
          (DWORD)GetIntConfigValue->AddBuffer((unsigned char*)name, sizeof(WCHAR) * ((unsigned int)wcslen(name) + 1));
  
      key.nameIndex    = index;
      key.defaultValue = defaultValue;
  
      GetIntConfigValue->Add(key, result);
      DEBUG_REC(dmpGetIntConfigValue(key, result));
  }
  
  void MethodContext::dmpGetIntConfigValue(const Agnostic_ConfigIntInfo& key, int value)
  {
      const WCHAR* name = (const WCHAR*)GetIntConfigValue->GetBuffer(key.nameIndex);
      printf("GetIntConfigValue name %S, default value %d, value %d", name, key.defaultValue, value);
      GetIntConfigValue->Unlock();
  }
  
  int MethodContext::repGetIntConfigValue(const WCHAR* name, int defaultValue)
  {
      if (GetIntConfigValue == nullptr)
          return defaultValue;
  
      AssertCodeMsg(name != nullptr, EXCEPTIONCODE_MC, "Name can not be nullptr");
  
      Agnostic_ConfigIntInfo key;
      ZeroMemory(&key, sizeof(Agnostic_ConfigIntInfo));
  
      size_t nameLenInBytes = sizeof(WCHAR) * (wcslen(name) + 1);
      int    nameIndex      = GetIntConfigValue->Contains((unsigned char*)name, (unsigned int)nameLenInBytes);
      if (nameIndex == -1) // config name not in map
          return defaultValue;
  
      key.nameIndex    = (DWORD)nameIndex;
      key.defaultValue = defaultValue;
  
      DWORD result = GetIntConfigValue->Get(key);
      DEBUG_REP(dmpGetIntConfigValue(key, result));
      return (int)result;
  }
  
  void MethodContext::recGetStringConfigValue(const WCHAR* name, const WCHAR* result)
  {
      if (GetStringConfigValue == nullptr)
          GetStringConfigValue = new LightWeightMap<DWORD, DWORD>();
  
      AssertCodeMsg(name != nullptr, EXCEPTIONCODE_MC, "Name can not be nullptr");
  
      DWORD nameIndex = (DWORD)GetStringConfigValue->AddBuffer((unsigned char*)name,
                                                               sizeof(WCHAR) * ((unsigned int)wcslen(name) + 1));
  
      DWORD resultIndex = (DWORD)-1;
      if (result != nullptr)
          resultIndex = (DWORD)GetStringConfigValue->AddBuffer((unsigned char*)result,
                                                               sizeof(WCHAR) * ((unsigned int)wcslen(result) + 1));
  
      GetStringConfigValue->Add(nameIndex, resultIndex);
      DEBUG_REC(dmpGetStringConfigValue(nameIndex, resultIndex));
  }
  
  void MethodContext::dmpGetStringConfigValue(DWORD nameIndex, DWORD resultIndex)
  {
      const WCHAR* name   = (const WCHAR*)GetStringConfigValue->GetBuffer(nameIndex);
      const WCHAR* result = (const WCHAR*)GetStringConfigValue->GetBuffer(resultIndex);
      printf("GetStringConfigValue name %S, result %S", name, result);
      GetStringConfigValue->Unlock();
  }
  
  const WCHAR* MethodContext::repGetStringConfigValue(const WCHAR* name)
  {
      if (GetStringConfigValue == nullptr)
          return nullptr;
  
      AssertCodeMsg(name != nullptr, EXCEPTIONCODE_MC, "Name can not be nullptr");
  
      size_t nameLenInBytes = sizeof(WCHAR) * (wcslen(name) + 1);
      int    nameIndex      = GetStringConfigValue->Contains((unsigned char*)name, (unsigned int)nameLenInBytes);
      if (nameIndex == -1) // config name not in map
          return nullptr;
  
      int            resultIndex = GetStringConfigValue->Get(nameIndex);
      const WCHAR* value       = (const WCHAR*)GetStringConfigValue->GetBuffer(resultIndex);
  
      DEBUG_REP(dmpGetStringConfigValue(nameIndex, resultIndex));
  
      return value;
  }
  
  int MethodContext::dumpMethodIdentityInfoToBuffer(char* buff, int len, bool ignoreMethodName /* = false */, CORINFO_METHOD_INFO* optInfo /* = nullptr */, unsigned optFlags /* = 0 */)
  {
      if (len < METHOD_IDENTITY_INFO_SIZE)
          return -1;
  
      // Obtain the Method Info structure for this method
      CORINFO_METHOD_INFO  info;
      CORINFO_METHOD_INFO* pInfo = nullptr;
      unsigned             flags = 0;
  
      if (optInfo != nullptr)
      {
          // Use the info we've already retrieved from repCompileMethod().
          pInfo = optInfo;
          flags = optFlags;
      }
      else
      {
          repCompileMethod(&info, &flags);
          pInfo = &info;
      }
  
      char* obuff = buff;
  
      // Add the Method Signature
      int t = sprintf_s(buff, len, "%s -- ", CallUtils::GetMethodFullName(this, pInfo->ftn, pInfo->args, ignoreMethodName));
      buff += t;
      len -= t;
  
      // Add Calling convention information, CorInfoOptions and CorInfoRegionKind
      t = sprintf_s(buff, len, "CallingConvention: %d, CorInfoOptions: %d, CorInfoRegionKind: %d ", pInfo->args.callConv,
                    pInfo->options, pInfo->regionKind);
      buff += t;
      len -= t;
  
      // Hash the IL Code for this method and append it to the ID info
      char ilHash[MD5_HASH_BUFFER_SIZE];
      dumpMD5HashToBuffer(pInfo->ILCode, pInfo->ILCodeSize, ilHash, MD5_HASH_BUFFER_SIZE);
      t = sprintf_s(buff, len, "ILCode Hash: %s", ilHash);
      buff += t;
      len -= t;
  
      return (int)(buff - obuff);
  }
  
  int MethodContext::dumpMethodMD5HashToBuffer(char* buff, int len, bool ignoreMethodName /* = false */, CORINFO_METHOD_INFO* optInfo /* = nullptr */, unsigned optFlags /* = 0 */)
  {
      char bufferIdentityInfo[METHOD_IDENTITY_INFO_SIZE];
  
      int cbLen = dumpMethodIdentityInfoToBuffer(bufferIdentityInfo, METHOD_IDENTITY_INFO_SIZE, ignoreMethodName, optInfo, optFlags);
  
      if (cbLen < 0)
          return cbLen;
  
      cbLen = dumpMD5HashToBuffer((BYTE*)bufferIdentityInfo, cbLen, buff, len);
  
      return cbLen;
  }
  
  int MethodContext::dumpMD5HashToBuffer(BYTE* pBuffer, int bufLen, char* hash, int hashLen)
  {
      // Lazy initialize the MD5 hasher.
      if (!m_hash.IsInitialized())
      {
          if (!m_hash.Initialize())
          {
              AssertMsg(false, "Failed to initialize the MD5 hasher");
              return -1;
          }
      }
  
      return m_hash.HashBuffer(pBuffer, bufLen, hash, hashLen);
  }
  
  MethodContext::Environment MethodContext::cloneEnvironment()
  {
      MethodContext::Environment env;
      if (GetIntConfigValue != nullptr)
      {
          env.getIntConfigValue = new LightWeightMap<MethodContext::Agnostic_ConfigIntInfo, DWORD>(*GetIntConfigValue);
      }
      if (GetStringConfigValue != nullptr)
      {
          env.getStingConfigValue = new LightWeightMap<DWORD, DWORD>(*GetStringConfigValue);
      }
      return env;
  }
  
  // Check that there is a difference between the current enviroment variables maps and the prevEnv.
  bool MethodContext::WasEnvironmentChanged(const Environment& prevEnv)
  {
      if (!IsEnvironmentHeaderEqual(prevEnv))
      {
          return true;
      }
      if (!IsEnvironmentContentEqual(prevEnv))
      {
          return true;
      }
      return false;
  }
  
  // Check that environment maps headers are equal to the prevEnv maps headers.
  bool MethodContext::IsEnvironmentHeaderEqual(const Environment& prevEnv)
  {
      if (!AreLWMHeadersEqual(prevEnv.getIntConfigValue, GetIntConfigValue))
      {
          return false;
      }
      if (!AreLWMHeadersEqual(prevEnv.getStingConfigValue, GetStringConfigValue))
      {
          return false;
      }
      return true;
  }
  
  // Check that environment maps content is equal to the prevEnv content.
  bool MethodContext::IsEnvironmentContentEqual(const Environment& prevEnv)
  {
      if (!IsIntConfigContentEqual(prevEnv.getIntConfigValue, GetIntConfigValue))
      {
          return false;
      }
      if (!IsStringContentEqual(prevEnv.getStingConfigValue, GetStringConfigValue))
      {
          return false;
      }
      return true;
  }
  
  // Check pointers to be both initizlized or null and number of keys to be equal.
  template <typename key, typename value>
  bool MethodContext::AreLWMHeadersEqual(LightWeightMap<key, value>* prev, LightWeightMap<key, value>* curr)
  {
      if (prev == nullptr && curr == nullptr)
      {
          return true;
      }
      if (prev != nullptr && curr != nullptr)
      {
          if (prev->GetCount() == curr->GetCount())
          {
              return true;
          }
      }
      return false;
  }
  
  bool MethodContext::IsIntConfigContentEqual(LightWeightMap<Agnostic_ConfigIntInfo, DWORD>* prev,
                                              LightWeightMap<Agnostic_ConfigIntInfo, DWORD>* curr)
  {
      if (prev != nullptr && curr != nullptr)
      {
          if (prev->GetCount() != curr->GetCount())
          {
              return false;
          }
  
          for (unsigned i = 0; i < prev->GetCount(); ++i)
          {
              DWORD currValue = curr->GetItem(i);
              DWORD prevValue = prev->GetItem(i);
              if (currValue != prevValue)
              {
                  return false;
              }
  
              Agnostic_ConfigIntInfo currKey = curr->GetKey(i);
              Agnostic_ConfigIntInfo prevKey = prev->GetKey(i);
  
              if (currKey.defaultValue != prevKey.defaultValue)
              {
                  return false;
              }
  
              DWORD  currNameIndex = currKey.nameIndex;
              LPCSTR currName      = (LPCSTR)curr->GetBuffer(currNameIndex);
              DWORD  prevNameIndex = prevKey.nameIndex;
              LPCSTR prevName      = (LPCSTR)prev->GetBuffer(currNameIndex);
              if (strcmp(currName, prevName) != 0)
              {
                  return false;
              }
          }
          return true;
      }
      else
      {
          return (prev == curr);
      }
  }
  
  bool MethodContext::IsStringContentEqual(LightWeightMap<DWORD, DWORD>* prev, LightWeightMap<DWORD, DWORD>* curr)
  {
      if (prev != nullptr && curr != nullptr)
      {
          if (prev->GetCount() != curr->GetCount())
          {
              return false;
          }
  
          for (unsigned i = 0; i < curr->GetCount(); ++i)
          {
              DWORD  currKeyIndex = curr->GetKey(i);
              LPCSTR currKey      = (LPCSTR)curr->GetBuffer(currKeyIndex);
              DWORD  prevKeyIndex = prev->GetKey(i);
              LPCSTR prevKey      = (LPCSTR)prev->GetBuffer(prevKeyIndex);
              if (strcmp(currKey, prevKey) != 0)
              {
                  return false;
              }
  
              DWORD  currValueIndex = curr->GetItem(i);
              LPCSTR currValue      = (LPCSTR)curr->GetBuffer(currValueIndex);
              DWORD  prevValueIndex = prev->GetItem(i);
              LPCSTR prevValue      = (LPCSTR)prev->GetBuffer(prevValueIndex);
              if (strcmp(currValue, prevValue) != 0)
              {
                  return false;
              }
          }
          return true;
      }
      else
      {
          return (prev == curr);
      }
  }
  