NativeCodeData.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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. #define NativeCodeDataNew(alloc, T, ...) AllocatorNew(NativeCodeData::AllocatorT<T>, alloc, T, __VA_ARGS__)
  7. #define NativeCodeDataNewZ(alloc, T, ...) AllocatorNewZ(NativeCodeData::AllocatorT<T>, alloc, T, __VA_ARGS__)
  8. #define NativeCodeDataNewArray(alloc, T, count) AllocatorNewArray(NativeCodeData::AllocatorT<NativeCodeData::Array<T>>, alloc, T, count)
  9. #define NativeCodeDataNewArrayZ(alloc, T, count) AllocatorNewArrayZ(NativeCodeData::AllocatorT<NativeCodeData::Array<T>>, alloc, T, count)
  10. #define NativeCodeDataNewPlusZ(size, alloc, T, ...) AllocatorNewPlusZ(NativeCodeData::AllocatorT<T>, alloc, size, T, __VA_ARGS__)
  11. #define NativeCodeDataNewNoFixup(alloc, T, ...) AllocatorNew(NativeCodeData::AllocatorNoFixup<T>, alloc, T, __VA_ARGS__)
  12. #define NativeCodeDataNewZNoFixup(alloc, T, ...) AllocatorNewZ(NativeCodeData::AllocatorNoFixup<T>, alloc, T, __VA_ARGS__)
  13. #define NativeCodeDataNewArrayNoFixup(alloc, T, count) AllocatorNewArray(NativeCodeData::AllocatorNoFixup<NativeCodeData::Array<T>>, alloc, T, count)
  14. #define NativeCodeDataNewArrayZNoFixup(alloc, T, count) AllocatorNewArrayZ(NativeCodeData::AllocatorNoFixup<NativeCodeData::Array<T>>, alloc, T, count)
  15. #define NativeCodeDataNewPlusZNoFixup(size, alloc, T, ...) AllocatorNewPlusZ(NativeCodeData::AllocatorNoFixup<T>, alloc, size, T, __VA_ARGS__)
  16. #define FixupNativeDataPointer(field, chunkList) NativeCodeData::AddFixupEntry(this->field, &this->field, this, chunkList)
  17. class NativeCodeData
  18. {
  19. public:
  20. struct DataChunk
  21. {
  22. unsigned int len;
  23. unsigned int allocIndex;
  24. unsigned int offset; // offset to the aggregated buffer
  25. #if DBG
  26. const char* dataType;
  27. #endif
  28. // todo: use union?
  29. void(*fixupFunc)(void* _this, NativeCodeData::DataChunk*);
  30. NativeDataFixupEntry *fixupList;
  31. DataChunk * next;
  32. char data[0];
  33. };
  34. struct DataChunkNoFixup
  35. {
  36. unsigned int len; // only used for memory management purposes.
  37. DataChunkNoFixup * next;
  38. char data[0];
  39. };
  40. static DataChunk* GetDataChunk(void* data)
  41. {
  42. Assert(JITManager::GetJITManager()->IsJITServer());
  43. return (NativeCodeData::DataChunk*)((char*)data - offsetof(NativeCodeData::DataChunk, data));
  44. }
  45. static char16* GetDataDescription(void* data, JitArenaAllocator * alloc);
  46. static unsigned int GetDataTotalOffset(void* data)
  47. {
  48. Assert(JITManager::GetJITManager()->IsJITServer());
  49. return GetDataChunk(data)->offset;
  50. }
  51. NativeCodeData(DataChunk * chunkList);
  52. union
  53. {
  54. DataChunk * chunkList;
  55. DataChunkNoFixup * noFixupChunkList;
  56. };
  57. #ifdef PERF_COUNTERS
  58. size_t size;
  59. #endif
  60. public:
  61. static void VerifyExistFixupEntry(void* targetAddr, void* addrToFixup, void* startAddress);
  62. static void AddFixupEntry(void* targetAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList);
  63. static void AddFixupEntry(void* targetAddr, void* targetStartAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList);
  64. static void AddFixupEntryForPointerArray(void* startAddress, DataChunk * chunkList);
  65. template<class DataChunkT>
  66. static void DeleteChunkList(DataChunkT * chunkList);
  67. public:
  68. class Allocator
  69. {
  70. public:
  71. static const bool FakeZeroLengthArray = false;
  72. Allocator();
  73. ~Allocator();
  74. char * Alloc(DECLSPEC_GUARD_OVERFLOW size_t requestedBytes);
  75. char * AllocZero(DECLSPEC_GUARD_OVERFLOW size_t requestedBytes);
  76. char * AllocLeaf(DECLSPEC_GUARD_OVERFLOW size_t requestedBytes);
  77. NativeCodeData * Finalize();
  78. void Free(void * buffer, size_t byteSize);
  79. union
  80. {
  81. DataChunk * chunkList;
  82. DataChunkNoFixup* noFixupChunkList;
  83. };
  84. DataChunk * lastChunkList; // used to maintain the allocation order in the list
  85. unsigned int totalSize;
  86. unsigned int allocCount;
  87. #ifdef TRACK_ALLOC
  88. // Doesn't support tracking information, dummy implementation
  89. Allocator * TrackAllocInfo(TrackAllocData const& data) { return this; }
  90. void ClearTrackAllocInfo(TrackAllocData* data = NULL) {}
  91. #endif
  92. protected:
  93. bool isOOPJIT;
  94. private:
  95. #if DBG
  96. bool finalized;
  97. #endif
  98. #ifdef PERF_COUNTERS
  99. size_t size;
  100. #endif
  101. };
  102. template<typename T>
  103. class Array
  104. {
  105. public:
  106. void Fixup(NativeCodeData::DataChunk* chunkList)
  107. {
  108. int count = NativeCodeData::GetDataChunk(this)->len / sizeof(T);
  109. while (count-- > 0)
  110. {
  111. (((T*)this) + count)->Fixup(chunkList);
  112. }
  113. }
  114. };
  115. template<typename T>
  116. class AllocatorNoFixup : public Allocator
  117. {
  118. public:
  119. char * Alloc(size_t requestedBytes)
  120. {
  121. char* dataBlock = __super::Alloc(requestedBytes);
  122. #if DBG
  123. if (JITManager::GetJITManager()->IsJITServer())
  124. {
  125. DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
  126. chunk->dataType = typeid(T).name();
  127. if (PHASE_TRACE1(Js::NativeCodeDataPhase))
  128. {
  129. Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
  130. chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
  131. }
  132. }
  133. #endif
  134. return dataBlock;
  135. }
  136. char * AllocZero(size_t requestedBytes)
  137. {
  138. char* dataBlock = __super::AllocZero(requestedBytes);
  139. #if DBG
  140. if (JITManager::GetJITManager()->IsJITServer())
  141. {
  142. DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
  143. chunk->dataType = typeid(T).name();
  144. if (PHASE_TRACE1(Js::NativeCodeDataPhase))
  145. {
  146. Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
  147. chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
  148. }
  149. }
  150. #endif
  151. return dataBlock;
  152. }
  153. char * AllocLeaf(size_t requestedBytes)
  154. {
  155. return Alloc(requestedBytes);
  156. }
  157. };
  158. template<typename T>
  159. class AllocatorT : public Allocator
  160. {
  161. char* AddFixup(char* dataBlock)
  162. {
  163. if (isOOPJIT)
  164. {
  165. DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
  166. chunk->fixupFunc = &Fixup;
  167. #if DBG
  168. chunk->dataType = typeid(T).name();
  169. if (PHASE_TRACE1(Js::NativeCodeDataPhase))
  170. {
  171. Output::Print(_u("NativeCodeData Alloc: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
  172. chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
  173. }
  174. #endif
  175. }
  176. return dataBlock;
  177. }
  178. public:
  179. char * Alloc(size_t requestedBytes)
  180. {
  181. return AddFixup(__super::Alloc(requestedBytes));
  182. }
  183. char * AllocZero(size_t requestedBytes)
  184. {
  185. return AddFixup(__super::AllocZero(requestedBytes));
  186. }
  187. static void Fixup(void* pThis, NativeCodeData::DataChunk* chunkList)
  188. {
  189. ((T*)pThis)->Fixup(chunkList);
  190. }
  191. };
  192. ~NativeCodeData();
  193. };
  194. enum DataDesc
  195. {
  196. DataDesc_None,
  197. DataDesc_InlineeFrameRecord_ArgOffsets,
  198. DataDesc_InlineeFrameRecord_Constants,
  199. DataDesc_BailoutInfo_CotalOutParamCount,
  200. DataDesc_ArgOutOffsetInfo_StartCallOutParamCounts,
  201. DataDesc_ArgOutOffsetInfo_StartCallArgRestoreAdjustCounts,
  202. DataDesc_LowererMD_LoadFloatValue_Float,
  203. DataDesc_LowererMD_LoadFloatValue_Double,
  204. DataDesc_LowererMD_EmitLoadFloatCommon_Double,
  205. DataDesc_LowererMD_Simd128LoadConst,
  206. };
  207. template<DataDesc desc = DataDesc_None>
  208. struct IntType
  209. {
  210. int data;
  211. };
  212. template<DataDesc desc = DataDesc_None>
  213. struct UIntType
  214. {
  215. uint data;
  216. };
  217. template<DataDesc desc = DataDesc_None>
  218. struct FloatType
  219. {
  220. FloatType(float val) :data(val) {}
  221. float data;
  222. };
  223. template<DataDesc desc = DataDesc_None>
  224. struct DoubleType
  225. {
  226. DoubleType() {}
  227. DoubleType(double val) :data(val) {}
  228. double data;
  229. };
  230. template<DataDesc desc = DataDesc_None>
  231. struct SIMDType
  232. {
  233. SIMDType() {}
  234. SIMDType(AsmJsSIMDValue val) :data(val) {}
  235. AsmJsSIMDValue data;
  236. };
  237. template<DataDesc desc = DataDesc_None>
  238. struct VarType
  239. {
  240. Js::Var data;
  241. void Fixup(NativeCodeData::DataChunk* chunkList)
  242. {
  243. AssertMsg(false, "Please specialize Fixup method for this Var type or use no-fixup allocator");
  244. }
  245. };
  246. template<>
  247. inline void VarType<DataDesc_InlineeFrameRecord_Constants>::Fixup(NativeCodeData::DataChunk* chunkList)
  248. {
  249. AssertMsg(false, "InlineeFrameRecord::constants contains Var from main process, should not fixup");
  250. }
  251. struct GlobalBailOutRecordDataTable;
  252. template<>
  253. inline void NativeCodeData::Array<GlobalBailOutRecordDataTable *>::Fixup(NativeCodeData::DataChunk* chunkList)
  254. {
  255. NativeCodeData::AddFixupEntryForPointerArray(this, chunkList);
  256. }