DynamicProfileStorage.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #ifdef DYNAMIC_PROFILE_STORAGE
  7. class DynamicProfileStorage
  8. {
  9. public:
  10. static bool Initialize();
  11. static bool Uninitialize();
  12. static bool IsEnabled() { return enabled; }
  13. static bool DoCollectInfo() { return collectInfo; }
  14. template <typename Fn>
  15. static Js::SourceDynamicProfileManager * Load(__in_z char16 const * filename, Fn loadFn);
  16. static void SaveRecord(__in_z char16 const * filename, __in_ecount(sizeof(DWORD) + *record) char const * record);
  17. static char * AllocRecord(DECLSPEC_GUARD_OVERFLOW DWORD bufferSize);
  18. static void DeleteRecord(__in_ecount(sizeof(DWORD) + *record) char const * record);
  19. static char const * GetRecordBuffer(__in_ecount(sizeof(DWORD) + *record) char const * record);
  20. static char * GetRecordBuffer(__in_ecount(sizeof(DWORD) + *record) char * record);
  21. static DWORD GetRecordSize(__in_ecount(sizeof(DWORD) + *record) char const * record);
  22. private:
  23. static char16 const * GetMessageType();
  24. static void ClearInfoMap(bool deleteFileStorage);
  25. static bool ImportFile(__in_z char16 const * filename, bool allowNonExistingFile);
  26. static bool ExportFile(__in_z char16 const * filename);
  27. static bool SetupCacheDir(__in_z char16 const * dirname);
  28. static void DisableCacheDir();
  29. static bool CreateCacheCatalog();
  30. static void ClearCacheCatalog();
  31. static bool LoadCacheCatalog();
  32. static bool AppendCacheCatalog(__in_z char16 const * url);
  33. static bool AcquireLock();
  34. static bool ReleaseLock();
  35. static bool VerifyHeader();
  36. static bool initialized;
  37. static bool uninitialized;
  38. static bool enabled;
  39. static bool collectInfo;
  40. static bool useCacheDir;
  41. static char16 cacheDrive[_MAX_DRIVE];
  42. static char16 cacheDir[_MAX_DIR];
  43. static char16 catalogFilename[_MAX_PATH];
  44. static DWORD const MagicNumber;
  45. static DWORD const FileFormatVersion;
  46. #ifdef _WIN32
  47. typedef DWORD TimeType;
  48. static inline TimeType GetCreationTime() { return _time32(NULL); }
  49. #else
  50. typedef time_t TimeType;
  51. static inline TimeType GetCreationTime() { return time(NULL); }
  52. #endif
  53. static TimeType creationTime;
  54. static int32 lastOffset;
  55. static HANDLE mutex;
  56. static CriticalSection cs;
  57. static DWORD nextFileId;
  58. static bool locked;
  59. #if DBG_DUMP
  60. static bool DoTrace();
  61. #endif
  62. class StorageInfo
  63. {
  64. public:
  65. void GetFilename(_Out_writes_z_(_MAX_PATH) char16 filename[_MAX_PATH]) const;
  66. char const * ReadRecord() const;
  67. bool WriteRecord(__in_ecount(sizeof(DWORD) + *record) char const * record) const;
  68. bool isFileStorage;
  69. union
  70. {
  71. DWORD fileId;
  72. char const * record;
  73. };
  74. };
  75. typedef JsUtil::BaseDictionary<char16 const *, StorageInfo, NoCheckHeapAllocator, PrimeSizePolicy, DefaultComparer, JsUtil::DictionaryEntry> InfoMap;
  76. static InfoMap infoMap;
  77. };
  78. template <class Fn>
  79. Js::SourceDynamicProfileManager *
  80. DynamicProfileStorage::Load(char16 const * filename, Fn loadFn)
  81. {
  82. Assert(DynamicProfileStorage::IsEnabled());
  83. AutoCriticalSection autocs(&cs);
  84. if (useCacheDir && AcquireLock())
  85. {
  86. LoadCacheCatalog(); // refresh the cache catalog
  87. }
  88. StorageInfo * info;
  89. if (!infoMap.TryGetReference(filename, &info))
  90. {
  91. if (useCacheDir)
  92. {
  93. ReleaseLock();
  94. }
  95. #if !DBG || !defined(_M_AMD64)
  96. char16 const * messageType = GetMessageType();
  97. if (messageType)
  98. {
  99. Output::Print(_u("%s: DynamicProfileStorage: Dynamic Profile Data not found for '%s'\n"), messageType, filename);
  100. Output::Flush();
  101. }
  102. #endif
  103. return nullptr;
  104. }
  105. char const * record;
  106. if (info->isFileStorage)
  107. {
  108. Assert(useCacheDir);
  109. Assert(locked);
  110. record = info->ReadRecord();
  111. ReleaseLock();
  112. if (record == nullptr)
  113. {
  114. #if DBG_DUMP
  115. if (DynamicProfileStorage::DoTrace())
  116. {
  117. Output::Print(_u("TRACE: DynamicProfileStorage: Failed to load from cache dir for '%s'"), filename);
  118. Output::Flush();
  119. }
  120. #endif
  121. return nullptr;
  122. }
  123. }
  124. else
  125. {
  126. record = info->record;
  127. }
  128. DWORD recordSize = GetRecordSize(record);
  129. if (recordSize == 0)
  130. {
  131. return nullptr;
  132. }
  133. Js::SourceDynamicProfileManager * sourceDynamicProfileManager = loadFn(GetRecordBuffer(record), recordSize);
  134. if (info->isFileStorage)
  135. {
  136. // The data is backed by a file, we can delete the memory
  137. Assert(useCacheDir);
  138. DeleteRecord(record);
  139. }
  140. #if DBG_DUMP
  141. if (DynamicProfileStorage::DoTrace() && sourceDynamicProfileManager)
  142. {
  143. Output::Print(_u("TRACE: DynamicProfileStorage: Dynamic Profile Data Loaded: '%s'\n"), filename);
  144. }
  145. #endif
  146. if (sourceDynamicProfileManager == nullptr)
  147. {
  148. char16 const * messageType = GetMessageType();
  149. if (messageType)
  150. {
  151. Output::Print(_u("%s: DynamicProfileStorage: Dynamic Profile Data corrupted: '%s'\n"), messageType, filename);
  152. Output::Flush();
  153. Assert(false);
  154. }
  155. }
  156. return sourceDynamicProfileManager;
  157. }
  158. #endif