NativeCodeData.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. #include "Backend.h"
  6. char DataDesc_None[] = "";
  7. char DataDesc_InlineeFrameRecord_ArgOffsets[] = "";
  8. char DataDesc_InlineeFrameRecord_Constants[] = "";
  9. char DataDesc_BailoutInfo_CotalOutParamCount[] = "";
  10. char DataDesc_ArgOutOffsetInfo_StartCallOutParamCounts[] = "";
  11. char DataDesc_ArgOutOffsetInfo_StartCallArgRestoreAdjustCounts[] = "";
  12. char DataDesc_LowererMD_LoadFloatValue_Float[] = "";
  13. char DataDesc_LowererMD_LoadFloatValue_Double[] = "";
  14. char DataDesc_LowererMD_EmitLoadFloatCommon_Double[] = "";
  15. char DataDesc_LowererMD_Simd128LoadConst[] = "";
  16. NativeCodeData::NativeCodeData(DataChunk * chunkList) : chunkList(chunkList)
  17. {
  18. #ifdef PERF_COUNTERS
  19. this->size = 0;
  20. #endif
  21. }
  22. NativeCodeData::~NativeCodeData()
  23. {
  24. NativeCodeData::DeleteChunkList(this->chunkList);
  25. PERF_COUNTER_SUB(Code, DynamicNativeCodeDataSize, this->size);
  26. PERF_COUNTER_SUB(Code, TotalNativeCodeDataSize, this->size);
  27. }
  28. void
  29. NativeCodeData::AddFixupEntry(void* targetAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList)
  30. {
  31. return NativeCodeData::AddFixupEntry(targetAddr, targetAddr, addrToFixup, startAddress, chunkList);
  32. }
  33. // targetAddr: target address
  34. // targetStartAddr: target start address, some fied might reference to middle of another data chunk, like outParamOffsets
  35. // startAddress: current data start address
  36. // addrToFixup: address that currently pointing to dataAddr, which need to be updated
  37. void
  38. NativeCodeData::AddFixupEntry(void* targetAddr, void* targetStartAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList)
  39. {
  40. Assert(addrToFixup >= startAddress);
  41. Assert(((__int64)addrToFixup) % sizeof(void*) == 0);
  42. if (targetAddr == nullptr)
  43. {
  44. return;
  45. }
  46. Assert(targetStartAddr);
  47. unsigned int inDataOffset = (unsigned int)((char*)targetAddr - (char*)targetStartAddr);
  48. DataChunk* targetChunk = NativeCodeData::GetDataChunk(targetStartAddr);
  49. Assert(targetChunk->len >= inDataOffset);
  50. #if DBG
  51. bool foundTargetChunk = false;
  52. while (chunkList)
  53. {
  54. foundTargetChunk |= (chunkList == targetChunk);
  55. chunkList = chunkList->next;
  56. }
  57. AssertMsg(foundTargetChunk, "current pointer is not allocated with NativeCodeData allocator?"); // change to valid check instead of assertion?
  58. #endif
  59. DataChunk* chunk = NativeCodeData::GetDataChunk(startAddress);
  60. NativeDataFixupEntry* entry = (NativeDataFixupEntry*)midl_user_allocate(sizeof(NativeDataFixupEntry));
  61. if (entry)
  62. {
  63. Js::Throw::OutOfMemory();
  64. }
  65. __analysis_assume(entry);
  66. entry->addrOffset = (unsigned int)((__int64)addrToFixup - (__int64)startAddress);
  67. Assert(entry->addrOffset <= chunk->len - sizeof(void*));
  68. entry->targetTotalOffset = targetChunk->offset + inDataOffset;
  69. entry->next = chunk->fixupList;
  70. chunk->fixupList = entry;
  71. #if DBG
  72. if (PHASE_TRACE1(Js::NativeCodeDataPhase))
  73. {
  74. Output::Print(L"NativeCodeData Add Fixup: %p(%p+%d, chunk:%p) --> %p(chunk:%p) %S\n",
  75. addrToFixup, startAddress, entry->addrOffset, (void*)chunk, targetAddr, (void*)targetChunk, chunk->dataType);
  76. }
  77. #endif
  78. }
  79. void
  80. NativeCodeData::AddFixupEntryForPointerArray(void* startAddress, DataChunk * chunkList)
  81. {
  82. DataChunk* chunk = NativeCodeData::GetDataChunk(startAddress);
  83. Assert(chunk->len % sizeof(void*) == 0);
  84. for (unsigned int i = 0; i < chunk->len / sizeof(void*); i++)
  85. {
  86. size_t offset = i * sizeof(void*);
  87. void* targetAddr = *(void**)((char*)startAddress + offset);
  88. if (targetAddr == nullptr)
  89. {
  90. continue;
  91. }
  92. DataChunk* targetChunk = NativeCodeData::GetDataChunk(targetAddr);
  93. #if DBG
  94. bool foundTargetChunk = false;
  95. DataChunk* chunk1 = chunkList;
  96. while (chunk1 && !foundTargetChunk)
  97. {
  98. foundTargetChunk = (chunk1 == targetChunk);
  99. chunk1 = chunk1->next;
  100. }
  101. AssertMsg(foundTargetChunk, "current pointer is not allocated with NativeCodeData allocator?"); // change to valid check instead of assertion?
  102. #endif
  103. NativeDataFixupEntry* entry = (NativeDataFixupEntry*)midl_user_allocate(sizeof(NativeDataFixupEntry));
  104. if (entry)
  105. {
  106. Js::Throw::OutOfMemory();
  107. }
  108. __analysis_assume(entry);
  109. entry->addrOffset = (unsigned int)offset;
  110. entry->targetTotalOffset = targetChunk->offset;
  111. entry->next = chunk->fixupList;
  112. chunk->fixupList = entry;
  113. #if DBG
  114. if (PHASE_TRACE1(Js::NativeCodeDataPhase))
  115. {
  116. Output::Print(L"NativeCodeData Add Fixup: %p[%d](+%d, chunk:%p) --> %p(chunk:%p) %S\n",
  117. startAddress, i, entry->addrOffset, (void*)chunk, targetAddr, (void*)targetChunk, chunk->dataType);
  118. }
  119. #endif
  120. }
  121. }
  122. wchar_t*
  123. NativeCodeData::GetDataDescription(void* data, JitArenaAllocator * alloc)
  124. {
  125. auto chunk = GetDataChunk(data);
  126. wchar_t buf[1024] = { 0 };
  127. #if DBG
  128. swprintf_s(buf, L"%hs, NativeCodeData: index: %x, len: %x, offset: +%x", chunk->dataType, chunk->allocIndex, chunk->len, chunk->offset);
  129. #else
  130. swprintf_s(buf, L"NativeCodeData: index: %x, len: %x, offset: +%x", chunk->allocIndex, chunk->len, chunk->offset);
  131. #endif
  132. auto len = wcslen(buf) + 1;
  133. auto desc = JitAnewArray(alloc, wchar_t, len);
  134. wcscpy_s(desc, len, buf);
  135. return desc;
  136. }
  137. void
  138. NativeCodeData::VerifyExistFixupEntry(void* targetAddr, void* addrToFixup, void* startAddress)
  139. {
  140. DataChunk* chunk = NativeCodeData::GetDataChunk(startAddress);
  141. DataChunk* targetChunk = NativeCodeData::GetDataChunk(targetAddr);
  142. if (chunk->len == 0)
  143. {
  144. return;
  145. }
  146. unsigned int offset = (unsigned int)((char*)addrToFixup - (char*)startAddress);
  147. Assert(offset <= chunk->len);
  148. NativeDataFixupEntry* entry = chunk->fixupList;
  149. while (entry)
  150. {
  151. if (entry->addrOffset == offset)
  152. {
  153. Assert(entry->targetTotalOffset == targetChunk->offset);
  154. return;
  155. }
  156. entry = entry->next;
  157. }
  158. AssertMsg(false, "Data chunk not found");
  159. }
  160. void
  161. NativeCodeData::DeleteChunkList(DataChunk * chunkList)
  162. {
  163. DataChunk * next = chunkList;
  164. while (next != nullptr)
  165. {
  166. DataChunk * current = next;
  167. next = next->next;
  168. delete current;
  169. }
  170. }
  171. NativeCodeData::Allocator::Allocator() : chunkList(nullptr), lastChunkList(nullptr)
  172. {
  173. this->totalSize = 0;
  174. this->allocCount = 0;
  175. #if DBG
  176. this->finalized = false;
  177. #endif
  178. #ifdef PERF_COUNTERS
  179. this->size = 0;
  180. #endif
  181. }
  182. NativeCodeData::Allocator::~Allocator()
  183. {
  184. Assert(!finalized || this->chunkList == nullptr);
  185. NativeCodeData::DeleteChunkList(this->chunkList);
  186. PERF_COUNTER_SUB(Code, DynamicNativeCodeDataSize, this->size);
  187. PERF_COUNTER_SUB(Code, TotalNativeCodeDataSize, this->size);
  188. }
  189. char *
  190. NativeCodeData::Allocator::Alloc(size_t requestSize)
  191. {
  192. char * data = nullptr;
  193. Assert(!finalized);
  194. requestSize = Math::Align(requestSize, sizeof(void*));
  195. DataChunk * newChunk = HeapNewStructPlus(requestSize, DataChunk);
  196. #if DBG
  197. newChunk->dataType = nullptr;
  198. #endif
  199. newChunk->next = nullptr;
  200. newChunk->allocIndex = this->allocCount++;
  201. newChunk->len = (unsigned int)requestSize;
  202. newChunk->fixupList = nullptr;
  203. newChunk->fixupFunc = nullptr;
  204. newChunk->offset = this->totalSize;
  205. if (this->chunkList == nullptr)
  206. {
  207. this->chunkList = newChunk;
  208. this->lastChunkList = newChunk;
  209. }
  210. else
  211. {
  212. this->lastChunkList->next = newChunk;
  213. this->lastChunkList = newChunk;
  214. }
  215. data = newChunk->data;
  216. this->totalSize += (unsigned int)requestSize;
  217. #ifdef PERF_COUNTERS
  218. this->size += requestSize;
  219. PERF_COUNTER_ADD(Code, DynamicNativeCodeDataSize, requestSize);
  220. #endif
  221. PERF_COUNTER_ADD(Code, TotalNativeCodeDataSize, requestSize);
  222. return data;
  223. }
  224. char *
  225. NativeCodeData::Allocator::AllocZero(size_t requestSize)
  226. {
  227. char * data = Alloc(requestSize);
  228. memset(data, 0, requestSize);
  229. return data;
  230. }
  231. NativeCodeData *
  232. NativeCodeData::Allocator::Finalize()
  233. {
  234. NativeCodeData * data = nullptr;
  235. if (this->chunkList != nullptr)
  236. {
  237. data = HeapNew(NativeCodeData, this->chunkList);
  238. this->chunkList = nullptr;
  239. #ifdef PERF_COUNTERS
  240. data->size = this->size;
  241. this->size = 0;
  242. #endif
  243. }
  244. #if DBG
  245. this->finalized = true;
  246. #endif
  247. return data;
  248. }
  249. //////////////////////////////////////////////////////////////////////////
  250. //NativeCodeData::Allocator::Free
  251. //This function should not be called at all because the life time is active during the run time
  252. //This function is added to enable Dictionary(has calls to Free() Method - which will never be called as it will be
  253. //allocated as a NativeAllocator to be allocated with NativeAllocator)
  254. //////////////////////////////////////////////////////////////////////////
  255. void
  256. NativeCodeData::Allocator::Free(void * buffer, size_t byteSize)
  257. {
  258. }