MetadataCache.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339
  1. #include "il2cpp-config.h"
  2. #include "MetadataCache.h"
  3. #include "GlobalMetadata.h"
  4. #include <map>
  5. #include <limits>
  6. #include "il2cpp-tabledefs.h"
  7. #include "il2cpp-runtime-stats.h"
  8. #include "gc/GarbageCollector.h"
  9. #include "metadata/ArrayMetadata.h"
  10. #include "metadata/GenericMetadata.h"
  11. #include "metadata/GenericMethod.h"
  12. #include "os/Atomic.h"
  13. #include "os/Mutex.h"
  14. #include "utils/CallOnce.h"
  15. #include "utils/Collections.h"
  16. #include "utils/Il2CppHashSet.h"
  17. #include "utils/Memory.h"
  18. #include "utils/PathUtils.h"
  19. #include "vm/Assembly.h"
  20. #include "vm/Class.h"
  21. #include "vm/ClassInlines.h"
  22. #include "vm/GenericClass.h"
  23. #include "vm/MetadataAlloc.h"
  24. #include "vm/MetadataLoader.h"
  25. #include "vm/MetadataLock.h"
  26. #include "vm/Method.h"
  27. #include "vm/Object.h"
  28. #include "vm/Runtime.h"
  29. #include "vm/String.h"
  30. #include "vm/Type.h"
  31. #include "vm-utils/MethodDefinitionKey.h"
  32. #include "vm-utils/NativeSymbol.h"
  33. #include "Baselib.h"
  34. #include "Cpp/ReentrantLock.h"
  35. #include "hybridclr/metadata/Assembly.h"
  36. #include "hybridclr/metadata/MetadataModule.h"
  37. typedef Il2CppReaderWriterLockedHashMap<Il2CppClass*, Il2CppClass*> PointerTypeMap;
  38. typedef Il2CppHashSet<const Il2CppGenericMethod*, il2cpp::metadata::Il2CppGenericMethodHash, il2cpp::metadata::Il2CppGenericMethodCompare> Il2CppGenericMethodSet;
  39. typedef Il2CppGenericMethodSet::const_iterator Il2CppGenericMethodSetIter;
  40. static Il2CppGenericMethodSet s_GenericMethodSet;
  41. struct Il2CppMetadataCache
  42. {
  43. il2cpp::os::FastReaderReaderWriterLock m_CacheLock;
  44. PointerTypeMap m_PointerTypes;
  45. };
  46. static Il2CppMetadataCache s_MetadataCache;
  47. static int32_t s_ImagesCount = 0;
  48. static Il2CppImage* s_ImagesTable = NULL;
  49. static int32_t s_AssembliesCount = 0;
  50. static Il2CppAssembly* s_AssembliesTable = NULL;
  51. typedef Il2CppReaderWriterLockedHashSet<const Il2CppGenericInst*, il2cpp::metadata::Il2CppGenericInstHash, il2cpp::metadata::Il2CppGenericInstCompare> Il2CppGenericInstSet;
  52. static Il2CppGenericInstSet s_GenericInstSet;
  53. typedef il2cpp::vm::Il2CppMethodTableMap::const_iterator Il2CppMethodTableMapIter;
  54. static il2cpp::vm::Il2CppMethodTableMap s_MethodTableMap;
  55. typedef il2cpp::vm::Il2CppUnresolvedSignatureMap::const_iterator Il2CppUnresolvedSignatureMapIter;
  56. static il2cpp::vm::Il2CppUnresolvedSignatureMap *s_pUnresolvedSignatureMap;
  57. typedef Il2CppHashMap<FieldInfo*, int32_t, il2cpp::utils::PointerHash<FieldInfo> > Il2CppThreadLocalStaticOffsetHashMap;
  58. typedef Il2CppThreadLocalStaticOffsetHashMap::iterator Il2CppThreadLocalStaticOffsetHashMapIter;
  59. static Il2CppThreadLocalStaticOffsetHashMap s_ThreadLocalStaticOffsetMap;
  60. static const Il2CppCodeRegistration * s_Il2CppCodeRegistration;
  61. static const Il2CppMetadataRegistration* s_MetadataCache_Il2CppMetadataRegistration;
  62. static const Il2CppCodeGenOptions* s_Il2CppCodeGenOptions;
  63. static il2cpp::vm::WindowsRuntimeTypeNameToClassMap s_WindowsRuntimeTypeNameToClassMap;
  64. static il2cpp::vm::ClassToWindowsRuntimeTypeNameMap s_ClassToWindowsRuntimeTypeNameMap;
  65. struct InteropDataToTypeConverter
  66. {
  67. inline const Il2CppType* operator()(const Il2CppInteropData& interopData) const
  68. {
  69. return interopData.type;
  70. }
  71. };
  72. typedef il2cpp::utils::collections::ArrayValueMap<const Il2CppType*, Il2CppInteropData, InteropDataToTypeConverter, il2cpp::metadata::Il2CppTypeLess, il2cpp::metadata::Il2CppTypeEqualityComparer> InteropDataMap;
  73. static InteropDataMap s_InteropData;
  74. struct WindowsRuntimeFactoryTableEntryToTypeConverter
  75. {
  76. inline const Il2CppType* operator()(const Il2CppWindowsRuntimeFactoryTableEntry& entry) const
  77. {
  78. return entry.type;
  79. }
  80. };
  81. typedef il2cpp::utils::collections::ArrayValueMap<const Il2CppType*, Il2CppWindowsRuntimeFactoryTableEntry, WindowsRuntimeFactoryTableEntryToTypeConverter, il2cpp::metadata::Il2CppTypeLess, il2cpp::metadata::Il2CppTypeEqualityComparer> WindowsRuntimeFactoryTable;
  82. static WindowsRuntimeFactoryTable s_WindowsRuntimeFactories;
  83. template<typename K, typename V>
  84. struct PairToKeyConverter
  85. {
  86. inline const K& operator()(const std::pair<K, V>& pair) const
  87. {
  88. return pair.first;
  89. }
  90. };
  91. typedef il2cpp::utils::collections::ArrayValueMap<const Il2CppGuid*, std::pair<const Il2CppGuid*, Il2CppClass*>, PairToKeyConverter<const Il2CppGuid*, Il2CppClass*> > GuidToClassMap;
  92. static GuidToClassMap s_GuidToNonImportClassMap;
  93. static il2cpp::utils::dynamic_array<Il2CppAssembly*> s_cliAssemblies;
  94. void il2cpp::vm::MetadataCache::Register(const Il2CppCodeRegistration* const codeRegistration, const Il2CppMetadataRegistration* const metadataRegistration, const Il2CppCodeGenOptions* const codeGenOptions)
  95. {
  96. il2cpp::vm::GlobalMetadata::Register(codeRegistration, metadataRegistration, codeGenOptions);
  97. s_Il2CppCodeRegistration = codeRegistration;
  98. s_MetadataCache_Il2CppMetadataRegistration = metadataRegistration;
  99. s_Il2CppCodeGenOptions = codeGenOptions;
  100. }
  101. Il2CppClass* il2cpp::vm::MetadataCache::GetTypeInfoFromTypeIndex(const Il2CppImage *image, TypeIndex index)
  102. {
  103. return il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeIndex(index);
  104. }
  105. const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromMethodDefinitionIndex(const Il2CppImage *image, MethodIndex index)
  106. {
  107. return il2cpp::vm::GlobalMetadata::GetMethodInfoFromMethodDefinitionIndex(index);
  108. }
  109. const MethodInfo* il2cpp::vm::MetadataCache::GetAssemblyEntryPoint(const Il2CppImage* image)
  110. {
  111. return il2cpp::vm::GlobalMetadata::GetAssemblyEntryPoint(image);
  112. }
  113. Il2CppMetadataTypeHandle il2cpp::vm::MetadataCache::GetAssemblyTypeHandle(const Il2CppImage* image, AssemblyTypeIndex index)
  114. {
  115. return il2cpp::vm::GlobalMetadata::GetAssemblyTypeHandle(image, index);
  116. }
  117. Il2CppMetadataTypeHandle il2cpp::vm::MetadataCache::GetAssemblyExportedTypeHandle(const Il2CppImage* image, AssemblyExportedTypeIndex index)
  118. {
  119. return il2cpp::vm::GlobalMetadata::GetAssemblyExportedTypeHandle(image, index);
  120. }
  121. const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromMethodHandle(Il2CppMetadataMethodDefinitionHandle handle)
  122. {
  123. return il2cpp::vm::GlobalMetadata::GetMethodInfoFromMethodHandle(handle);
  124. }
  125. bool il2cpp::vm::MetadataCache::Initialize()
  126. {
  127. if (!il2cpp::vm::GlobalMetadata::Initialize(&s_ImagesCount, &s_AssembliesCount))
  128. {
  129. return false;
  130. }
  131. il2cpp::metadata::GenericMetadata::RegisterGenericClasses(s_MetadataCache_Il2CppMetadataRegistration->genericClasses, s_MetadataCache_Il2CppMetadataRegistration->genericClassesCount);
  132. il2cpp::metadata::GenericMetadata::SetMaximumRuntimeGenericDepth(s_Il2CppCodeGenOptions->maximumRuntimeGenericDepth);
  133. il2cpp::metadata::GenericMetadata::SetGenericVirtualIterations(s_Il2CppCodeGenOptions->recursiveGenericIterations);
  134. s_GenericInstSet.Resize(s_MetadataCache_Il2CppMetadataRegistration->genericInstsCount);
  135. for (int32_t i = 0; i < s_MetadataCache_Il2CppMetadataRegistration->genericInstsCount; i++)
  136. {
  137. bool inserted = s_GenericInstSet.Add(s_MetadataCache_Il2CppMetadataRegistration->genericInsts[i]);
  138. IL2CPP_ASSERT(inserted);
  139. }
  140. s_InteropData.assign_external(s_Il2CppCodeRegistration->interopData, s_Il2CppCodeRegistration->interopDataCount);
  141. s_WindowsRuntimeFactories.assign_external(s_Il2CppCodeRegistration->windowsRuntimeFactoryTable, s_Il2CppCodeRegistration->windowsRuntimeFactoryCount);
  142. // Pre-allocate these arrays so we don't need to lock when reading later.
  143. // These arrays hold the runtime metadata representation for metadata explicitly
  144. // referenced during conversion. There is a corresponding table of same size
  145. // in the converted metadata, giving a description of runtime metadata to construct.
  146. s_ImagesTable = (Il2CppImage*)IL2CPP_CALLOC(s_ImagesCount, sizeof(Il2CppImage));
  147. s_AssembliesTable = (Il2CppAssembly*)IL2CPP_CALLOC(s_AssembliesCount, sizeof(Il2CppAssembly));
  148. // setup all the Il2CppImages. There are not many and it avoid locks later on
  149. for (int32_t imageIndex = 0; imageIndex < s_ImagesCount; imageIndex++)
  150. {
  151. Il2CppImage* image = s_ImagesTable + imageIndex;
  152. AssemblyIndex imageAssemblyIndex;
  153. il2cpp::vm::GlobalMetadata::BuildIl2CppImage(image, imageIndex, &imageAssemblyIndex);
  154. image->assembly = const_cast<Il2CppAssembly*>(GetAssemblyFromIndex(imageAssemblyIndex));
  155. std::string nameNoExt = il2cpp::utils::PathUtils::PathNoExtension(image->name);
  156. image->nameNoExt = (char*)IL2CPP_CALLOC(nameNoExt.size() + 1, sizeof(char));
  157. strcpy(const_cast<char*>(image->nameNoExt), nameNoExt.c_str());
  158. for (uint32_t codeGenModuleIndex = 0; codeGenModuleIndex < s_Il2CppCodeRegistration->codeGenModulesCount; ++codeGenModuleIndex)
  159. {
  160. if (strcmp(image->name, s_Il2CppCodeRegistration->codeGenModules[codeGenModuleIndex]->moduleName) == 0)
  161. image->codeGenModule = s_Il2CppCodeRegistration->codeGenModules[codeGenModuleIndex];
  162. }
  163. IL2CPP_ASSERT(image->codeGenModule);
  164. image->dynamic = false;
  165. }
  166. // setup all the Il2CppAssemblies.
  167. for (int32_t assemblyIndex = 0; assemblyIndex < s_ImagesCount; assemblyIndex++)
  168. {
  169. Il2CppAssembly* assembly = s_AssembliesTable + assemblyIndex;
  170. ImageIndex assemblyImageIndex;
  171. il2cpp::vm::GlobalMetadata::BuildIl2CppAssembly(assembly, assemblyIndex, &assemblyImageIndex);
  172. assembly->image = il2cpp::vm::MetadataCache::GetImageFromIndex(assemblyImageIndex);
  173. Assembly::Register(assembly);
  174. }
  175. InitializeUnresolvedSignatureTable();
  176. #if IL2CPP_ENABLE_NATIVE_STACKTRACES
  177. std::vector<MethodDefinitionKey> managedMethods;
  178. il2cpp::vm::GlobalMetadata::GetAllManagedMethods(managedMethods);
  179. il2cpp::utils::NativeSymbol::RegisterMethods(managedMethods);
  180. #endif
  181. return true;
  182. }
  183. void il2cpp::vm::MetadataCache::ExecuteEagerStaticClassConstructors()
  184. {
  185. for (int32_t i = 0; i < s_AssembliesCount; i++)
  186. {
  187. const Il2CppImage* image = s_AssembliesTable[i].image;
  188. if (image->codeGenModule->staticConstructorTypeIndices != NULL)
  189. {
  190. TypeDefinitionIndex* indexPointer = image->codeGenModule->staticConstructorTypeIndices;
  191. while (*indexPointer) // 0 terminated
  192. {
  193. Il2CppMetadataTypeHandle handle = GetTypeHandleFromIndex(image, *indexPointer);
  194. Il2CppClass* klass = GlobalMetadata::GetTypeInfoFromHandle(handle);
  195. Runtime::ClassInit(klass);
  196. indexPointer++;
  197. }
  198. }
  199. }
  200. }
  201. typedef void(*Il2CppModuleInitializerMethodPointer)(const MethodInfo*);
  202. void il2cpp::vm::MetadataCache::ExecuteModuleInitializers()
  203. {
  204. for (int32_t i = 0; i < s_AssembliesCount; i++)
  205. {
  206. const Il2CppImage* image = s_AssembliesTable[i].image;
  207. if (image->codeGenModule->moduleInitializer != NULL)
  208. {
  209. Il2CppModuleInitializerMethodPointer moduleInitializer = (Il2CppModuleInitializerMethodPointer)image->codeGenModule->moduleInitializer;
  210. moduleInitializer(NULL);
  211. }
  212. }
  213. }
  214. void ClearGenericMethodTable()
  215. {
  216. s_MethodTableMap.clear();
  217. }
  218. void ClearWindowsRuntimeTypeNamesTables()
  219. {
  220. s_ClassToWindowsRuntimeTypeNameMap.clear();
  221. }
  222. void il2cpp::vm::MetadataCache::InitializeGuidToClassTable()
  223. {
  224. Il2CppInteropData* interopData = s_Il2CppCodeRegistration->interopData;
  225. uint32_t interopDataCount = s_Il2CppCodeRegistration->interopDataCount;
  226. std::vector<std::pair<const Il2CppGuid*, Il2CppClass*> > guidToNonImportClassMap;
  227. guidToNonImportClassMap.reserve(interopDataCount);
  228. for (uint32_t i = 0; i < interopDataCount; i++)
  229. {
  230. // It's important to check for non-import types because type projections will have identical GUIDs (e.g. IEnumerable<T> and IIterable<T>)
  231. if (interopData[i].guid != NULL)
  232. {
  233. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(interopData[i].type);
  234. if (!klass->is_import_or_windows_runtime)
  235. guidToNonImportClassMap.push_back(std::make_pair(interopData[i].guid, klass));
  236. }
  237. }
  238. s_GuidToNonImportClassMap.assign(guidToNonImportClassMap);
  239. }
  240. // this is called later in the intialization cycle with more systems setup like GC
  241. void il2cpp::vm::MetadataCache::InitializeGCSafe()
  242. {
  243. il2cpp::vm::GlobalMetadata::InitializeStringLiteralTable();
  244. il2cpp::vm::GlobalMetadata::InitializeGenericMethodTable(s_MethodTableMap);
  245. il2cpp::vm::GlobalMetadata::InitializeWindowsRuntimeTypeNamesTables(s_WindowsRuntimeTypeNameToClassMap, s_ClassToWindowsRuntimeTypeNameMap);
  246. InitializeGuidToClassTable();
  247. }
  248. void ClearImageNames()
  249. {
  250. for (int32_t imageIndex = 0; imageIndex < s_ImagesCount; imageIndex++)
  251. {
  252. Il2CppImage* image = s_ImagesTable + imageIndex;
  253. IL2CPP_FREE((void*)image->nameNoExt);
  254. }
  255. }
  256. void il2cpp::vm::MetadataCache::Clear()
  257. {
  258. ClearGenericMethodTable();
  259. ClearWindowsRuntimeTypeNamesTables();
  260. delete s_pUnresolvedSignatureMap;
  261. Assembly::ClearAllAssemblies();
  262. ClearImageNames();
  263. IL2CPP_FREE(s_ImagesTable);
  264. s_ImagesTable = NULL;
  265. s_ImagesCount = 0;
  266. IL2CPP_FREE(s_AssembliesTable);
  267. s_AssembliesTable = NULL;
  268. s_AssembliesCount = 0;
  269. s_GenericMethodSet.clear();
  270. metadata::ArrayMetadata::Clear();
  271. s_GenericInstSet.Clear();
  272. s_Il2CppCodeRegistration = NULL;
  273. s_Il2CppCodeGenOptions = NULL;
  274. il2cpp::metadata::GenericMetadata::Clear();
  275. il2cpp::metadata::GenericMethod::ClearStatics();
  276. il2cpp::vm::GlobalMetadata::Clear();
  277. }
  278. void il2cpp::vm::MetadataCache::InitializeUnresolvedSignatureTable()
  279. {
  280. s_pUnresolvedSignatureMap = new Il2CppUnresolvedSignatureMap();
  281. il2cpp::vm::GlobalMetadata::InitializeUnresolvedSignatureTable(*s_pUnresolvedSignatureMap);
  282. }
  283. Il2CppClass* il2cpp::vm::MetadataCache::GetGenericInstanceType(Il2CppClass* genericTypeDefinition, const Il2CppType** genericArgumentTypes, uint32_t genericArgumentCount)
  284. {
  285. const Il2CppGenericInst* inst = il2cpp::vm::MetadataCache::GetGenericInst(genericArgumentTypes, genericArgumentCount);
  286. Il2CppGenericClass* genericClass = il2cpp::metadata::GenericMetadata::GetGenericClass(genericTypeDefinition, inst);
  287. return il2cpp::vm::GenericClass::GetClass(genericClass);
  288. }
  289. const MethodInfo* il2cpp::vm::MetadataCache::GetGenericInstanceMethod(const MethodInfo* genericMethodDefinition, const Il2CppType** genericArgumentTypes, uint32_t genericArgumentCount)
  290. {
  291. Il2CppGenericContext context = { NULL, GetGenericInst(genericArgumentTypes, genericArgumentCount) };
  292. return il2cpp::vm::GlobalMetadata::GetGenericInstanceMethod(genericMethodDefinition, &context);
  293. }
  294. const Il2CppGenericContext* il2cpp::vm::MetadataCache::GetMethodGenericContext(const MethodInfo* method)
  295. {
  296. if (!method->is_inflated)
  297. {
  298. IL2CPP_NOT_IMPLEMENTED(Image::GetMethodGenericContext);
  299. return NULL;
  300. }
  301. return &method->genericMethod->context;
  302. }
  303. const MethodInfo* il2cpp::vm::MetadataCache::GetGenericMethodDefinition(const MethodInfo* method)
  304. {
  305. if (!method->is_inflated)
  306. {
  307. IL2CPP_NOT_IMPLEMENTED(Image::GetGenericMethodDefinition);
  308. return NULL;
  309. }
  310. return method->genericMethod->methodDefinition;
  311. }
  312. Il2CppClass* il2cpp::vm::MetadataCache::GetPointerType(Il2CppClass* type)
  313. {
  314. Il2CppClass* pointerClass;
  315. if (s_MetadataCache.m_PointerTypes.TryGet(type, &pointerClass))
  316. return pointerClass;
  317. return NULL;
  318. }
  319. Il2CppClass* il2cpp::vm::MetadataCache::GetWindowsRuntimeClass(const char* fullName)
  320. {
  321. WindowsRuntimeTypeNameToClassMap::iterator it = s_WindowsRuntimeTypeNameToClassMap.find(fullName);
  322. if (it != s_WindowsRuntimeTypeNameToClassMap.end())
  323. return it->second;
  324. return NULL;
  325. }
  326. const char* il2cpp::vm::MetadataCache::GetWindowsRuntimeClassName(const Il2CppClass* klass)
  327. {
  328. ClassToWindowsRuntimeTypeNameMap::iterator it = s_ClassToWindowsRuntimeTypeNameMap.find(klass);
  329. if (it != s_ClassToWindowsRuntimeTypeNameMap.end())
  330. return it->second;
  331. return NULL;
  332. }
  333. Il2CppMethodPointer il2cpp::vm::MetadataCache::GetWindowsRuntimeFactoryCreationFunction(const char* fullName)
  334. {
  335. Il2CppClass* klass = GetWindowsRuntimeClass(fullName);
  336. if (klass == NULL)
  337. return NULL;
  338. WindowsRuntimeFactoryTable::iterator factoryEntry = s_WindowsRuntimeFactories.find_first(&klass->byval_arg);
  339. if (factoryEntry == s_WindowsRuntimeFactories.end())
  340. return NULL;
  341. return factoryEntry->createFactoryFunction;
  342. }
  343. Il2CppClass* il2cpp::vm::MetadataCache::GetClassForGuid(const Il2CppGuid* guid)
  344. {
  345. IL2CPP_ASSERT(guid != NULL);
  346. GuidToClassMap::iterator it = s_GuidToNonImportClassMap.find_first(guid);
  347. if (it != s_GuidToNonImportClassMap.end())
  348. return it->second;
  349. return NULL;
  350. }
  351. void il2cpp::vm::MetadataCache::AddPointerTypeLocked(Il2CppClass* type, Il2CppClass* pointerType, const il2cpp::os::FastAutoLock& lock)
  352. {
  353. // This method must be called while holding the g_MetadataLock to ensure that we don't insert the same pointer type twice
  354. // And WalkPointerTypes assumes this
  355. IL2CPP_ASSERT(lock.IsLock(&g_MetadataLock));
  356. s_MetadataCache.m_PointerTypes.Add(type, pointerType);
  357. }
  358. const Il2CppGenericInst* il2cpp::vm::MetadataCache::GetGenericInst(const Il2CppType* const* types, uint32_t typeCount)
  359. {
  360. // temporary inst to lookup a permanent one that may already exist
  361. Il2CppGenericInst inst;
  362. inst.type_argc = typeCount;
  363. inst.type_argv = (const Il2CppType**)types;
  364. const Il2CppGenericInst* foundInst;
  365. if (s_GenericInstSet.TryGet(&inst, &foundInst))
  366. return foundInst;
  367. il2cpp::os::FastAutoLock lock(&g_MetadataLock);
  368. // Check if instance was added while we were blocked on g_MetadataLock
  369. if (s_GenericInstSet.TryGet(&inst, &foundInst))
  370. return foundInst;
  371. Il2CppGenericInst* newInst = NULL;
  372. newInst = (Il2CppGenericInst*)MetadataMalloc(sizeof(Il2CppGenericInst));
  373. newInst->type_argc = typeCount;
  374. newInst->type_argv = (const Il2CppType**)MetadataMalloc(newInst->type_argc * sizeof(Il2CppType*));
  375. int index = 0;
  376. const Il2CppType* const* typesEnd = types + typeCount;
  377. for (const Il2CppType* const* iter = types; iter != typesEnd; ++iter, ++index)
  378. newInst->type_argv[index] = *iter;
  379. // Do this while still holding the g_MetadataLock to prevent the same instance from being added twice
  380. bool added = s_GenericInstSet.Add(newInst);
  381. IL2CPP_ASSERT(added);
  382. ++il2cpp_runtime_stats.generic_instance_count;
  383. return newInst;
  384. }
  385. static baselib::ReentrantLock s_GenericMethodMutex;
  386. const Il2CppGenericMethod* il2cpp::vm::MetadataCache::GetGenericMethod(const MethodInfo* methodDefinition, const Il2CppGenericInst* classInst, const Il2CppGenericInst* methodInst)
  387. {
  388. Il2CppGenericMethod method = { 0 };
  389. method.methodDefinition = methodDefinition;
  390. method.context.class_inst = classInst;
  391. method.context.method_inst = methodInst;
  392. il2cpp::os::FastAutoLock lock(&s_GenericMethodMutex);
  393. Il2CppGenericMethodSet::const_iterator iter = s_GenericMethodSet.find(&method);
  394. if (iter != s_GenericMethodSet.end())
  395. return *iter;
  396. Il2CppGenericMethod* newMethod = MetadataAllocGenericMethod();
  397. newMethod->methodDefinition = methodDefinition;
  398. newMethod->context.class_inst = classInst;
  399. newMethod->context.method_inst = methodInst;
  400. s_GenericMethodSet.insert(newMethod);
  401. return newMethod;
  402. }
  403. static bool IsShareableEnum(const Il2CppType* type)
  404. {
  405. // Base case for recursion - we've found an enum.
  406. if (il2cpp::vm::Type::IsEnum(type))
  407. return true;
  408. if (il2cpp::vm::Type::IsGenericInstance(type))
  409. {
  410. // Recursive case - look "inside" the generic instance type to see if this is a nested enum.
  411. Il2CppClass* definition = il2cpp::vm::GenericClass::GetTypeDefinition(type->data.generic_class);
  412. return IsShareableEnum(il2cpp::vm::Class::GetType(definition));
  413. }
  414. // Base case for recurion - this is not an enum or a generic instance type.
  415. return false;
  416. }
  417. static il2cpp::vm::GenericParameterRestriction IsReferenceTypeGenericConstraint(const Il2CppType* constraint)
  418. {
  419. // This must match GenericSharingAnalsyis.GetGenericParameterConstraintRestriction()
  420. if (constraint->type == IL2CPP_TYPE_VAR || constraint->type == IL2CPP_TYPE_MVAR)
  421. return il2cpp::vm::GenericParameterRestrictionNone;
  422. if (il2cpp::metadata::Il2CppTypeEqualityComparer::AreEqual(constraint, &il2cpp_defaults.enum_class->byval_arg))
  423. return il2cpp::vm::GenericParameterRestrictionValueType;
  424. if (il2cpp::metadata::Il2CppTypeEqualityComparer::AreEqual(constraint, &il2cpp_defaults.value_type_class->byval_arg))
  425. return il2cpp::vm::GenericParameterRestrictionNone; // Not a valid constraint, so consider it unconstrained
  426. else if (il2cpp::vm::Class::IsInterface(il2cpp::vm::Class::FromIl2CppType(constraint)))
  427. return il2cpp::vm::GenericParameterRestrictionNone; // Interfaces constraints can be satisfied by reference or value types
  428. // Any other type constraint e.g. T : SomeType, SomeType must be a reference type
  429. return il2cpp::vm::GenericParameterRestrictionReferenceType;
  430. }
  431. il2cpp::vm::GenericParameterRestriction il2cpp::vm::MetadataCache::IsReferenceTypeGenericParameter(Il2CppMetadataGenericParameterHandle genericParameter)
  432. {
  433. uint16_t flags = il2cpp::vm::GlobalMetadata::GetGenericParameterFlags(genericParameter);
  434. if ((flags & IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0)
  435. return GenericParameterRestrictionReferenceType;
  436. if ((flags & IL2CPP_GENERIC_PARAMETER_ATTRIBUTE_NOT_NULLABLE_VALUE_TYPE_CONSTRAINT) != 0)
  437. return GenericParameterRestrictionValueType; // Must be a value type
  438. uint32_t count = il2cpp::vm::GlobalMetadata::GetGenericConstraintCount(genericParameter);
  439. for (uint32_t constraintIndex = 0; constraintIndex < count; ++constraintIndex)
  440. {
  441. const Il2CppType* constraint = il2cpp::vm::GlobalMetadata::GetGenericParameterConstraintFromIndex(genericParameter, constraintIndex);
  442. GenericParameterRestriction restriction = IsReferenceTypeGenericConstraint(constraint);
  443. if (restriction != GenericParameterRestrictionNone)
  444. return restriction;
  445. }
  446. return GenericParameterRestrictionNone;
  447. }
  448. static const Il2CppGenericInst* GetFullySharedInst(Il2CppMetadataGenericContainerHandle genericContainer, const Il2CppGenericInst* inst)
  449. {
  450. if (inst == NULL || !il2cpp::vm::Runtime::IsFullGenericSharingEnabled())
  451. return NULL;
  452. const Il2CppType** types = (const Il2CppType**)alloca(inst->type_argc * sizeof(Il2CppType*));
  453. for (uint32_t i = 0; i < inst->type_argc; ++i)
  454. {
  455. const Il2CppType* type;
  456. switch (il2cpp::vm::MetadataCache::IsReferenceTypeGenericParameter(il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(genericContainer, i)))
  457. {
  458. case il2cpp::vm::GenericParameterRestrictionValueType:
  459. type = &il2cpp_defaults.il2cpp_fully_shared_struct_type->byval_arg;
  460. break;
  461. case il2cpp::vm::GenericParameterRestrictionReferenceType:
  462. type = &il2cpp_defaults.object_class->byval_arg;
  463. break;
  464. default:
  465. type = &il2cpp_defaults.il2cpp_fully_shared_type->byval_arg;
  466. break;
  467. }
  468. types[i] = type;
  469. }
  470. const Il2CppGenericInst* sharedInst = il2cpp::vm::MetadataCache::GetGenericInst(types, inst->type_argc);
  471. return sharedInst;
  472. }
  473. // this logic must match the C# logic in GenericSharingAnalysis.GetSharedTypeForGenericParameter
  474. static const Il2CppGenericInst* GetSharedInst(const Il2CppGenericInst* inst)
  475. {
  476. if (inst == NULL)
  477. return NULL;
  478. const Il2CppType** types = (const Il2CppType**)alloca(inst->type_argc * sizeof(Il2CppType*));
  479. for (uint32_t i = 0; i < inst->type_argc; ++i)
  480. {
  481. if (il2cpp::vm::Type::IsReference(inst->type_argv[i]))
  482. types[i] = &il2cpp_defaults.object_class->byval_arg;
  483. else
  484. {
  485. const Il2CppType* type = inst->type_argv[i];
  486. if (s_Il2CppCodeGenOptions->enablePrimitiveValueTypeGenericSharing)
  487. {
  488. if (IsShareableEnum(type))
  489. {
  490. const Il2CppType* underlyingType = il2cpp::vm::Type::GetUnderlyingType(type);
  491. switch (underlyingType->type)
  492. {
  493. case IL2CPP_TYPE_I1:
  494. type = &il2cpp_defaults.sbyte_shared_enum->byval_arg;
  495. break;
  496. case IL2CPP_TYPE_I2:
  497. type = &il2cpp_defaults.int16_shared_enum->byval_arg;
  498. break;
  499. case IL2CPP_TYPE_I4:
  500. type = &il2cpp_defaults.int32_shared_enum->byval_arg;
  501. break;
  502. case IL2CPP_TYPE_I8:
  503. type = &il2cpp_defaults.int64_shared_enum->byval_arg;
  504. break;
  505. case IL2CPP_TYPE_U1:
  506. type = &il2cpp_defaults.byte_shared_enum->byval_arg;
  507. break;
  508. case IL2CPP_TYPE_U2:
  509. type = &il2cpp_defaults.uint16_shared_enum->byval_arg;
  510. break;
  511. case IL2CPP_TYPE_U4:
  512. type = &il2cpp_defaults.uint32_shared_enum->byval_arg;
  513. break;
  514. case IL2CPP_TYPE_U8:
  515. type = &il2cpp_defaults.uint64_shared_enum->byval_arg;
  516. break;
  517. default:
  518. IL2CPP_ASSERT(0 && "Invalid enum underlying type");
  519. break;
  520. }
  521. }
  522. }
  523. if (il2cpp::vm::Type::IsGenericInstance(type))
  524. {
  525. const Il2CppGenericInst* sharedInst = GetSharedInst(type->data.generic_class->context.class_inst);
  526. Il2CppGenericClass* gklass = il2cpp::metadata::GenericMetadata::GetGenericClass(type->data.generic_class->type, sharedInst);
  527. Il2CppClass* klass = il2cpp::vm::GenericClass::GetClass(gklass);
  528. type = &klass->byval_arg;
  529. }
  530. types[i] = type;
  531. }
  532. }
  533. const Il2CppGenericInst* sharedInst = il2cpp::vm::MetadataCache::GetGenericInst(types, inst->type_argc);
  534. return sharedInst;
  535. }
  536. static il2cpp::vm::Il2CppGenericMethodPointers MakeGenericMethodPointers(const Il2CppGenericMethodIndices* methodIndicies, bool isFullyShared)
  537. {
  538. IL2CPP_ASSERT(methodIndicies->methodIndex >= 0 && methodIndicies->invokerIndex >= 0);
  539. if (static_cast<uint32_t>(methodIndicies->methodIndex) < s_Il2CppCodeRegistration->genericMethodPointersCount && static_cast<uint32_t>(methodIndicies->invokerIndex) < s_Il2CppCodeRegistration->invokerPointersCount)
  540. {
  541. Il2CppMethodPointer virtualMethod;
  542. Il2CppMethodPointer method;
  543. method = s_Il2CppCodeRegistration->genericMethodPointers[methodIndicies->methodIndex];
  544. if (methodIndicies->adjustorThunkIndex != -1)
  545. {
  546. virtualMethod = s_Il2CppCodeRegistration->genericAdjustorThunks[methodIndicies->adjustorThunkIndex];
  547. }
  548. else
  549. {
  550. virtualMethod = method;
  551. }
  552. return { method, virtualMethod, s_Il2CppCodeRegistration->invokerPointers[methodIndicies->invokerIndex], isFullyShared };
  553. }
  554. return { NULL, NULL, NULL, false };
  555. }
  556. il2cpp::vm::Il2CppGenericMethodPointers il2cpp::vm::MetadataCache::GetGenericMethodPointers(const MethodInfo* methodDefinition, const Il2CppGenericContext* context)
  557. {
  558. Il2CppGenericMethod method = { 0 };
  559. method.methodDefinition = const_cast<MethodInfo*>(methodDefinition);
  560. method.context.class_inst = context->class_inst;
  561. method.context.method_inst = context->method_inst;
  562. Il2CppMethodTableMapIter iter = s_MethodTableMap.find(&method);
  563. if (iter != s_MethodTableMap.end())
  564. return MakeGenericMethodPointers(iter->second, false);
  565. // get the shared version if it exists
  566. method.context.class_inst = GetSharedInst(context->class_inst);
  567. method.context.method_inst = GetSharedInst(context->method_inst);
  568. iter = s_MethodTableMap.find(&method);
  569. if (iter != s_MethodTableMap.end())
  570. return MakeGenericMethodPointers(iter->second, false);
  571. // get the fully shared version if it exists
  572. method.context.class_inst = GetFullySharedInst(methodDefinition->klass->genericContainerHandle, context->class_inst);
  573. method.context.method_inst = GetFullySharedInst(methodDefinition->genericContainerHandle, context->method_inst);
  574. iter = s_MethodTableMap.find(&method);
  575. if (iter != s_MethodTableMap.end())
  576. return MakeGenericMethodPointers(iter->second, true);
  577. return { NULL, NULL, NULL };
  578. }
  579. const Il2CppType* il2cpp::vm::MetadataCache::GetIl2CppTypeFromIndex(const Il2CppImage* image, TypeIndex index)
  580. {
  581. return il2cpp::vm::GlobalMetadata::GetIl2CppTypeFromIndex(index);
  582. }
  583. const Il2CppType* il2cpp::vm::MetadataCache::GetTypeFromRgctxDefinition(const Il2CppRGCTXDefinition* rgctxDef)
  584. {
  585. return il2cpp::vm::GlobalMetadata::GetTypeFromRgctxDefinition(rgctxDef);
  586. }
  587. const Il2CppGenericMethod* il2cpp::vm::MetadataCache::GetGenericMethodFromRgctxDefinition(const Il2CppRGCTXDefinition* rgctxDef)
  588. {
  589. return il2cpp::vm::GlobalMetadata::GetGenericMethodFromRgctxDefinition(rgctxDef);
  590. }
  591. std::pair<const Il2CppType*, const MethodInfo*> il2cpp::vm::MetadataCache::GetConstrainedCallFromRgctxDefinition(const Il2CppRGCTXDefinition* rgctxDef)
  592. {
  593. return il2cpp::vm::GlobalMetadata::GetConstrainedCallFromRgctxDefinition(rgctxDef);
  594. }
  595. const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromVTableSlot(const Il2CppClass* klass, int32_t vTableSlot)
  596. {
  597. return il2cpp::vm::GlobalMetadata::GetMethodInfoFromVTableSlot(klass, vTableSlot);
  598. }
  599. static int CompareIl2CppTokenAdjustorThunkPair(const void* pkey, const void* pelem)
  600. {
  601. return (int)(((Il2CppTokenAdjustorThunkPair*)pkey)->token - ((Il2CppTokenAdjustorThunkPair*)pelem)->token);
  602. }
  603. Il2CppMethodPointer il2cpp::vm::MetadataCache::GetAdjustorThunk(const Il2CppImage* image, uint32_t token)
  604. {
  605. if (hybridclr::metadata::IsInterpreterIndex(image->token))
  606. {
  607. return hybridclr::metadata::MetadataModule::GetAdjustorThunk(image, token);
  608. }
  609. if (image->codeGenModule->adjustorThunkCount == 0)
  610. return NULL;
  611. Il2CppTokenAdjustorThunkPair key;
  612. memset(&key, 0, sizeof(Il2CppTokenAdjustorThunkPair));
  613. key.token = token;
  614. const Il2CppTokenAdjustorThunkPair* result = (const Il2CppTokenAdjustorThunkPair*)bsearch(&key, image->codeGenModule->adjustorThunks,
  615. image->codeGenModule->adjustorThunkCount, sizeof(Il2CppTokenAdjustorThunkPair), CompareIl2CppTokenAdjustorThunkPair);
  616. if (result == NULL)
  617. return NULL;
  618. return result->adjustorThunk;
  619. }
  620. Il2CppMethodPointer il2cpp::vm::MetadataCache::GetMethodPointer(const Il2CppImage* image, uint32_t token)
  621. {
  622. uint32_t rid = GetTokenRowId(token);
  623. uint32_t table = GetTokenType(token);
  624. if (rid == 0)
  625. return NULL;
  626. if (hybridclr::metadata::IsInterpreterImage(image))
  627. {
  628. return hybridclr::metadata::MetadataModule::GetMethodPointer(image, token);
  629. }
  630. IL2CPP_ASSERT(rid <= image->codeGenModule->methodPointerCount);
  631. return image->codeGenModule->methodPointers[rid - 1];
  632. }
  633. InvokerMethod il2cpp::vm::MetadataCache::GetMethodInvoker(const Il2CppImage* image, uint32_t token)
  634. {
  635. uint32_t rid = GetTokenRowId(token);
  636. uint32_t table = GetTokenType(token);
  637. if (rid == 0)
  638. return Runtime::GetMissingMethodInvoker();
  639. if (hybridclr::metadata::IsInterpreterImage(image))
  640. {
  641. return hybridclr::metadata::MetadataModule::GetMethodInvoker(image, token);
  642. }
  643. int32_t index = image->codeGenModule->invokerIndices[rid - 1];
  644. if (index == kMethodIndexInvalid)
  645. return Runtime::GetMissingMethodInvoker();
  646. IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_Il2CppCodeRegistration->invokerPointersCount);
  647. return s_Il2CppCodeRegistration->invokerPointers[index];
  648. }
  649. const Il2CppInteropData* il2cpp::vm::MetadataCache::GetInteropDataForType(const Il2CppType* type)
  650. {
  651. IL2CPP_ASSERT(type != NULL);
  652. InteropDataMap::iterator interopData = s_InteropData.find_first(type);
  653. if (interopData == s_InteropData.end())
  654. return NULL;
  655. return interopData;
  656. }
  657. static bool MatchTokens(Il2CppTokenIndexMethodTuple key, Il2CppTokenIndexMethodTuple element)
  658. {
  659. return key.token < element.token;
  660. }
  661. static bool GenericInstancesMatch(const MethodInfo* method, const MethodInfo* matchingMethod)
  662. {
  663. if (method->genericMethod->context.class_inst != NULL && matchingMethod->genericMethod->context.class_inst != NULL)
  664. {
  665. if (!il2cpp::metadata::Il2CppGenericInstCompare::AreEqual(method->genericMethod->context.class_inst, matchingMethod->genericMethod->context.class_inst))
  666. return false;
  667. }
  668. if (method->genericMethod->context.method_inst != NULL && matchingMethod->genericMethod->context.method_inst != NULL)
  669. {
  670. if (!il2cpp::metadata::Il2CppGenericInstCompare::AreEqual(method->genericMethod->context.method_inst, matchingMethod->genericMethod->context.method_inst))
  671. return false;
  672. }
  673. return true;
  674. }
  675. Il2CppMethodPointer il2cpp::vm::MetadataCache::GetReversePInvokeWrapper(const Il2CppImage* image, const MethodInfo* method)
  676. {
  677. if (hybridclr::metadata::IsInterpreterImage(image))
  678. {
  679. return hybridclr::metadata::MetadataModule::GetReversePInvokeWrapper(image, method);
  680. }
  681. if (image->codeGenModule->reversePInvokeWrapperCount == 0)
  682. return NULL;
  683. // For each image (i.e. assembly), the reverse pinvoke wrapper indices are in an array sorted by
  684. // metadata token. Each entry also might have the method metadata pointer, which is used to further
  685. // find methods that have a matching metadata token.
  686. Il2CppTokenIndexMethodTuple key;
  687. memset(&key, 0, sizeof(Il2CppTokenIndexMethodTuple));
  688. key.token = method->token;
  689. // Binary search for a range which matches the metadata token.
  690. auto begin = image->codeGenModule->reversePInvokeWrapperIndices;
  691. auto end = image->codeGenModule->reversePInvokeWrapperIndices + image->codeGenModule->reversePInvokeWrapperCount;
  692. auto matchingRange = std::equal_range(begin, end, key, &MatchTokens);
  693. int32_t index = -1;
  694. auto numberOfMatches = std::distance(matchingRange.first, matchingRange.second);
  695. if (numberOfMatches == 1)
  696. {
  697. if (method->genericMethod == NULL)
  698. {
  699. // We found one non-generic method.
  700. index = matchingRange.first->index;
  701. }
  702. else
  703. {
  704. // We found one generic method - let's make sure the class and method generic instances match. This reverse p/invoke
  705. // wrapper might be for a different inflated generic instance.
  706. const MethodInfo* possibleMatch = il2cpp::metadata::GenericMethod::GetMethod(il2cpp::vm::GlobalMetadata::GetGenericMethodFromTokenMethodTuple(matchingRange.first));
  707. if (possibleMatch->genericMethod != NULL && GenericInstancesMatch(method, possibleMatch))
  708. index = matchingRange.first->index;
  709. }
  710. }
  711. else if (numberOfMatches > 1)
  712. {
  713. // Multiple generic instance methods share the same token, since it is from the generic method definition.
  714. // To find the proper method, look for the one with a matching method metadata pointer.
  715. const Il2CppTokenIndexMethodTuple* currentMatch = matchingRange.first;
  716. const Il2CppTokenIndexMethodTuple* lastMatch = matchingRange.second;
  717. while (currentMatch != lastMatch)
  718. {
  719. // First, check the method metadata, and use it if it has been initialized.
  720. // If not, let's fall back to the generic method.
  721. const MethodInfo* possibleMatch = (const MethodInfo*)*currentMatch->method;
  722. if (!il2cpp::vm::GlobalMetadata::IsRuntimeMetadataInitialized(possibleMatch))
  723. possibleMatch = il2cpp::metadata::GenericMethod::GetMethod(il2cpp::vm::GlobalMetadata::GetGenericMethodFromTokenMethodTuple(currentMatch));
  724. if (possibleMatch == method)
  725. {
  726. index = currentMatch->index;
  727. break;
  728. }
  729. currentMatch++;
  730. }
  731. }
  732. if (index == -1)
  733. return NULL;
  734. IL2CPP_ASSERT(index >= 0 && static_cast<uint32_t>(index) < s_Il2CppCodeRegistration->reversePInvokeWrapperCount);
  735. return s_Il2CppCodeRegistration->reversePInvokeWrappers[index];
  736. }
  737. static const Il2CppType* GetReducedType(const Il2CppType* type)
  738. {
  739. if (type->byref)
  740. return &il2cpp_defaults.object_class->byval_arg;
  741. if (il2cpp::vm::Type::IsEnum(type))
  742. type = il2cpp::vm::Type::GetUnderlyingType(type);
  743. switch (type->type)
  744. {
  745. case IL2CPP_TYPE_BOOLEAN:
  746. return &il2cpp_defaults.sbyte_class->byval_arg;
  747. case IL2CPP_TYPE_CHAR:
  748. return &il2cpp_defaults.int16_class->byval_arg;
  749. case IL2CPP_TYPE_BYREF:
  750. case IL2CPP_TYPE_CLASS:
  751. case IL2CPP_TYPE_OBJECT:
  752. case IL2CPP_TYPE_STRING:
  753. case IL2CPP_TYPE_ARRAY:
  754. case IL2CPP_TYPE_SZARRAY:
  755. return &il2cpp_defaults.object_class->byval_arg;
  756. case IL2CPP_TYPE_GENERICINST:
  757. if (il2cpp::vm::Type::GenericInstIsValuetype(type))
  758. return type;
  759. else
  760. return &il2cpp_defaults.object_class->byval_arg;
  761. default:
  762. return type;
  763. }
  764. }
  765. Il2CppMethodPointer il2cpp::vm::MetadataCache::GetUnresolvedVirtualCallStub(const MethodInfo* method)
  766. {
  767. il2cpp::metadata::Il2CppSignature signature;
  768. signature.Count = method->parameters_count + 1;
  769. signature.Types = (const Il2CppType**)alloca(signature.Count * sizeof(Il2CppType*));
  770. signature.Types[0] = GetReducedType(method->return_type);
  771. for (int i = 0; i < method->parameters_count; ++i)
  772. signature.Types[i + 1] = GetReducedType(method->parameters[i]);
  773. Il2CppUnresolvedSignatureMapIter it = s_pUnresolvedSignatureMap->find(signature);
  774. if (it != s_pUnresolvedSignatureMap->end())
  775. return it->second;
  776. return NULL;
  777. }
  778. const Il2CppAssembly* il2cpp::vm::MetadataCache::GetAssemblyFromIndex(AssemblyIndex index)
  779. {
  780. if (index == kGenericContainerIndexInvalid)
  781. return NULL;
  782. IL2CPP_ASSERT(index <= s_AssembliesCount);
  783. return s_AssembliesTable + index;
  784. }
  785. const Il2CppAssembly* il2cpp::vm::MetadataCache::GetAssemblyByName(const char* nameToFind)
  786. {
  787. const char* assemblyName = hybridclr::GetAssemblyNameFromPath(nameToFind);
  788. il2cpp::utils::VmStringUtils::CaseInsensitiveComparer comparer;
  789. for (int i = 0; i < s_AssembliesCount; i++)
  790. {
  791. const Il2CppAssembly* assembly = s_AssembliesTable + i;
  792. if (comparer(assembly->aname.name, assemblyName) || comparer(assembly->image->name, assemblyName))
  793. return assembly;
  794. }
  795. il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
  796. for (auto assembly : s_cliAssemblies)
  797. {
  798. if (comparer(assembly->aname.name, assemblyName) || comparer(assembly->image->name, assemblyName))
  799. return assembly;
  800. }
  801. return nullptr;
  802. }
  803. void il2cpp::vm::MetadataCache::RegisterInterpreterAssembly(Il2CppAssembly* assembly)
  804. {
  805. il2cpp::vm::Assembly::Register(assembly);
  806. s_cliAssemblies.push_back(assembly);
  807. }
  808. const Il2CppAssembly* il2cpp::vm::MetadataCache::LoadAssemblyFromBytes(const char* assemblyBytes, size_t length)
  809. {
  810. il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
  811. Il2CppAssembly* newAssembly = hybridclr::metadata::Assembly::LoadFromBytes(assemblyBytes, length, true);
  812. // avoid register placeholder assembly twicely.
  813. for (Il2CppAssembly* ass : s_cliAssemblies)
  814. {
  815. if (ass == newAssembly)
  816. {
  817. il2cpp::vm::Assembly::InvalidateAssemblyList();
  818. return ass;
  819. }
  820. }
  821. RegisterInterpreterAssembly(newAssembly);
  822. return newAssembly;
  823. }
  824. const Il2CppGenericMethod* il2cpp::vm::MetadataCache::FindGenericMethod(std::function<bool(const Il2CppGenericMethod*)> predic)
  825. {
  826. for (auto e : s_MethodTableMap)
  827. {
  828. if (predic(e.first))
  829. {
  830. return e.first;
  831. }
  832. }
  833. return nullptr;
  834. }
  835. void il2cpp::vm::MetadataCache::FixThreadLocalStaticOffsetForFieldLocked(FieldInfo* field, int32_t offset, const il2cpp::os::FastAutoLock& lock)
  836. {
  837. s_ThreadLocalStaticOffsetMap[field] = offset;
  838. }
  839. Il2CppImage* il2cpp::vm::MetadataCache::GetImageFromIndex(ImageIndex index)
  840. {
  841. if (index == kGenericContainerIndexInvalid)
  842. return NULL;
  843. IL2CPP_ASSERT(index <= s_ImagesCount);
  844. return s_ImagesTable + index;
  845. }
  846. Il2CppClass* il2cpp::vm::MetadataCache::GetTypeInfoFromType(const Il2CppType* type)
  847. {
  848. if (type == NULL)
  849. return NULL;
  850. return il2cpp::vm::GlobalMetadata::GetTypeInfoFromType(type);
  851. }
  852. Il2CppClass* il2cpp::vm::MetadataCache::GetTypeInfoFromHandle(Il2CppMetadataTypeHandle handle)
  853. {
  854. return il2cpp::vm::GlobalMetadata::GetTypeInfoFromHandle(handle);
  855. }
  856. Il2CppMetadataGenericContainerHandle il2cpp::vm::MetadataCache::GetGenericContainerFromGenericClass(const Il2CppImage* image, const Il2CppGenericClass* genericClass)
  857. {
  858. return il2cpp::vm::GlobalMetadata::GetGenericContainerFromGenericClass(genericClass);
  859. }
  860. Il2CppMetadataGenericContainerHandle il2cpp::vm::MetadataCache::GetGenericContainerFromMethod(Il2CppMetadataMethodDefinitionHandle handle)
  861. {
  862. return il2cpp::vm::GlobalMetadata::GetGenericContainerFromMethod(handle);
  863. }
  864. Il2CppMetadataGenericParameterHandle il2cpp::vm::MetadataCache::GetGenericParameterFromType(const Il2CppType* type)
  865. {
  866. return il2cpp::vm::GlobalMetadata::GetGenericParameterFromType(type);
  867. }
  868. Il2CppClass* il2cpp::vm::MetadataCache::GetContainerDeclaringType(Il2CppMetadataGenericContainerHandle handle)
  869. {
  870. return il2cpp::vm::GlobalMetadata::GetContainerDeclaringType(handle);
  871. }
  872. Il2CppClass* il2cpp::vm::MetadataCache::GetParameterDeclaringType(Il2CppMetadataGenericParameterHandle handle)
  873. {
  874. return il2cpp::vm::GlobalMetadata::GetParameterDeclaringType(handle);
  875. }
  876. Il2CppMetadataGenericParameterHandle il2cpp::vm::MetadataCache::GetGenericParameterFromIndex(Il2CppMetadataGenericContainerHandle handle, GenericContainerParameterIndex index)
  877. {
  878. return il2cpp::vm::GlobalMetadata::GetGenericParameterFromIndex(handle, index);
  879. }
  880. const Il2CppType* il2cpp::vm::MetadataCache::GetGenericParameterConstraintFromIndex(Il2CppMetadataGenericParameterHandle handle, GenericParameterConstraintIndex index)
  881. {
  882. return il2cpp::vm::GlobalMetadata::GetGenericParameterConstraintFromIndex(handle, index);
  883. }
  884. Il2CppClass* il2cpp::vm::MetadataCache::GetNestedTypeFromOffset(const Il2CppClass* klass, TypeNestedTypeIndex offset)
  885. {
  886. return il2cpp::vm::GlobalMetadata::GetNestedTypeFromOffset(klass, offset);
  887. }
  888. const Il2CppType* il2cpp::vm::MetadataCache::GetInterfaceFromOffset(const Il2CppClass* klass, TypeInterfaceIndex offset)
  889. {
  890. return il2cpp::vm::GlobalMetadata::GetInterfaceFromOffset(klass, offset);
  891. }
  892. Il2CppInterfaceOffsetInfo il2cpp::vm::MetadataCache::GetInterfaceOffsetInfo(const Il2CppClass* klass, TypeInterfaceOffsetIndex index)
  893. {
  894. return il2cpp::vm::GlobalMetadata::GetInterfaceOffsetInfo(klass, index);
  895. }
  896. static int CompareIl2CppTokenRangePair(const void* pkey, const void* pelem)
  897. {
  898. return (int)(((Il2CppTokenRangePair*)pkey)->token - ((Il2CppTokenRangePair*)pelem)->token);
  899. }
  900. il2cpp::vm::RGCTXCollection il2cpp::vm::MetadataCache::GetRGCTXs(const Il2CppImage* image, uint32_t token)
  901. {
  902. RGCTXCollection collection = { 0, NULL };
  903. if (image->codeGenModule->rgctxRangesCount == 0)
  904. return collection;
  905. Il2CppTokenRangePair key;
  906. memset(&key, 0, sizeof(Il2CppTokenRangePair));
  907. key.token = token;
  908. const Il2CppTokenRangePair* res = (const Il2CppTokenRangePair*)bsearch(&key, image->codeGenModule->rgctxRanges, image->codeGenModule->rgctxRangesCount, sizeof(Il2CppTokenRangePair), CompareIl2CppTokenRangePair);
  909. if (res == NULL)
  910. return collection;
  911. collection.count = res->range.length;
  912. collection.items = image->codeGenModule->rgctxs + res->range.start;
  913. return collection;
  914. }
  915. const uint8_t* il2cpp::vm::MetadataCache::GetFieldDefaultValue(const FieldInfo* field, const Il2CppType** type)
  916. {
  917. return il2cpp::vm::GlobalMetadata::GetFieldDefaultValue(field, type);
  918. }
  919. const uint8_t* il2cpp::vm::MetadataCache::GetParameterDefaultValue(const MethodInfo* method, int32_t parameterPosition, const Il2CppType** type, bool* isExplicitySetNullDefaultValue)
  920. {
  921. return il2cpp::vm::GlobalMetadata::GetParameterDefaultValue(method, parameterPosition, type, isExplicitySetNullDefaultValue);
  922. }
  923. int il2cpp::vm::MetadataCache::GetFieldMarshaledSizeForField(const FieldInfo* field)
  924. {
  925. return il2cpp::vm::GlobalMetadata::GetFieldMarshaledSizeForField(field);
  926. }
  927. int32_t il2cpp::vm::MetadataCache::GetFieldOffsetFromIndexLocked(const Il2CppClass* klass, int32_t fieldIndexInType, FieldInfo* field, const il2cpp::os::FastAutoLock& lock)
  928. {
  929. int32_t offset = il2cpp::vm::GlobalMetadata::GetFieldOffset(klass, fieldIndexInType, field);
  930. if (offset < 0)
  931. {
  932. AddThreadLocalStaticOffsetForFieldLocked(field, offset & ~THREAD_LOCAL_STATIC_MASK, lock);
  933. return THREAD_STATIC_FIELD_OFFSET;
  934. }
  935. return offset;
  936. }
  937. void il2cpp::vm::MetadataCache::AddThreadLocalStaticOffsetForFieldLocked(FieldInfo* field, int32_t offset, const il2cpp::os::FastAutoLock& lock)
  938. {
  939. s_ThreadLocalStaticOffsetMap.add(field, offset);
  940. }
  941. int32_t il2cpp::vm::MetadataCache::GetThreadLocalStaticOffsetForField(FieldInfo* field)
  942. {
  943. IL2CPP_ASSERT(field->offset == THREAD_STATIC_FIELD_OFFSET);
  944. il2cpp::os::FastAutoLock lock(&g_MetadataLock);
  945. Il2CppThreadLocalStaticOffsetHashMapIter iter = s_ThreadLocalStaticOffsetMap.find(field);
  946. IL2CPP_ASSERT(iter != s_ThreadLocalStaticOffsetMap.end());
  947. return iter->second;
  948. }
  949. Il2CppMetadataCustomAttributeHandle il2cpp::vm::MetadataCache::GetCustomAttributeTypeToken(const Il2CppImage* image, uint32_t token)
  950. {
  951. return il2cpp::vm::GlobalMetadata::GetCustomAttributeTypeToken(image, token);
  952. }
  953. std::tuple<void*, void*> il2cpp::vm::MetadataCache::GetCustomAttributeDataRange(const Il2CppImage* image, uint32_t token)
  954. {
  955. return il2cpp::vm::GlobalMetadata::GetCustomAttributeDataRange(image, token);
  956. }
  957. const Il2CppAssembly* il2cpp::vm::MetadataCache::GetReferencedAssembly(const Il2CppAssembly* assembly, int32_t referencedAssemblyTableIndex)
  958. {
  959. return il2cpp::vm::GlobalMetadata::GetReferencedAssembly(assembly, referencedAssemblyTableIndex, s_AssembliesTable, s_AssembliesCount);
  960. }
  961. CustomAttributesCache* il2cpp::vm::MetadataCache::GenerateCustomAttributesCache(Il2CppMetadataCustomAttributeHandle handle)
  962. {
  963. return il2cpp::vm::GlobalMetadata::GenerateCustomAttributesCache(handle);
  964. }
  965. CustomAttributesCache* il2cpp::vm::MetadataCache::GenerateCustomAttributesCache(const Il2CppImage* image, uint32_t token)
  966. {
  967. return il2cpp::vm::GlobalMetadata::GenerateCustomAttributesCache(image, token);
  968. }
  969. bool il2cpp::vm::MetadataCache::HasAttribute(Il2CppMetadataCustomAttributeHandle token, Il2CppClass* attribute)
  970. {
  971. return il2cpp::vm::GlobalMetadata::HasAttribute(token, attribute);
  972. }
  973. bool il2cpp::vm::MetadataCache::HasAttribute(const Il2CppImage* image, uint32_t token, Il2CppClass* attribute)
  974. {
  975. return il2cpp::vm::GlobalMetadata::HasAttribute(image, token, attribute);
  976. }
  977. void il2cpp::vm::MetadataCache::InitializeAllMethodMetadata()
  978. {
  979. il2cpp::vm::GlobalMetadata::InitializeAllMethodMetadata();
  980. }
  981. void* il2cpp::vm::MetadataCache::InitializeRuntimeMetadata(uintptr_t* metadataPointer)
  982. {
  983. return il2cpp::vm::GlobalMetadata::InitializeRuntimeMetadata(metadataPointer, true);
  984. }
  985. void il2cpp::vm::MetadataCache::WalkPointerTypes(WalkTypesCallback callback, void* context)
  986. {
  987. os::FastAutoLock lock(&g_MetadataLock);
  988. for (PointerTypeMap::iterator it = s_MetadataCache.m_PointerTypes.UnlockedBegin(); it != s_MetadataCache.m_PointerTypes.UnlockedEnd(); it++)
  989. {
  990. callback(it->second, context);
  991. }
  992. }
  993. Il2CppMetadataTypeHandle il2cpp::vm::MetadataCache::GetTypeHandleFromIndex(const Il2CppImage* image, TypeDefinitionIndex typeIndex)
  994. {
  995. return il2cpp::vm::GlobalMetadata::GetTypeHandleFromIndex(typeIndex);
  996. }
  997. Il2CppMetadataTypeHandle il2cpp::vm::MetadataCache::GetTypeHandleFromType(const Il2CppType* type)
  998. {
  999. return il2cpp::vm::GlobalMetadata::GetTypeHandleFromType(type);
  1000. }
  1001. bool il2cpp::vm::MetadataCache::TypeIsNested(Il2CppMetadataTypeHandle handle)
  1002. {
  1003. return il2cpp::vm::GlobalMetadata::TypeIsNested(handle);
  1004. }
  1005. bool il2cpp::vm::MetadataCache::TypeIsValueType(Il2CppMetadataTypeHandle handle)
  1006. {
  1007. return il2cpp::vm::GlobalMetadata::TypeIsValueType(handle);
  1008. }
  1009. bool il2cpp::vm::MetadataCache::StructLayoutPackIsDefault(Il2CppMetadataTypeHandle handle)
  1010. {
  1011. return il2cpp::vm::GlobalMetadata::StructLayoutPackIsDefault(handle);
  1012. }
  1013. int32_t il2cpp::vm::MetadataCache::StructLayoutPack(Il2CppMetadataTypeHandle handle)
  1014. {
  1015. return il2cpp::vm::GlobalMetadata::StructLayoutPack(handle);
  1016. }
  1017. bool il2cpp::vm::MetadataCache::StructLayoutSizeIsDefault(Il2CppMetadataTypeHandle handle)
  1018. {
  1019. return il2cpp::vm::GlobalMetadata::StructLayoutSizeIsDefault(handle);
  1020. }
  1021. std::pair<const char*, const char*> il2cpp::vm::MetadataCache::GetTypeNamespaceAndName(Il2CppMetadataTypeHandle handle)
  1022. {
  1023. return il2cpp::vm::GlobalMetadata::GetTypeNamespaceAndName(handle);
  1024. }
  1025. Il2CppMetadataTypeHandle il2cpp::vm::MetadataCache::GetNestedTypes(Il2CppClass *klass, void* *iter)
  1026. {
  1027. return GetNestedTypes(
  1028. klass->typeMetadataHandle,
  1029. iter
  1030. );
  1031. }
  1032. Il2CppMetadataTypeHandle il2cpp::vm::MetadataCache::GetNestedTypes(Il2CppMetadataTypeHandle handle, void** iter)
  1033. {
  1034. return il2cpp::vm::GlobalMetadata::GetNestedTypes(handle, iter);
  1035. }
  1036. Il2CppMetadataFieldInfo il2cpp::vm::MetadataCache::GetFieldInfo(const Il2CppClass* klass, TypeFieldIndex fieldIndex)
  1037. {
  1038. return il2cpp::vm::GlobalMetadata::GetFieldInfo(klass, fieldIndex);
  1039. }
  1040. Il2CppMetadataMethodInfo il2cpp::vm::MetadataCache::GetMethodInfo(const Il2CppClass* klass, TypeMethodIndex index)
  1041. {
  1042. return il2cpp::vm::GlobalMetadata::GetMethodInfo(klass, index);
  1043. }
  1044. Il2CppMetadataParameterInfo il2cpp::vm::MetadataCache::GetParameterInfo(const Il2CppClass* klass, Il2CppMetadataMethodDefinitionHandle handle, MethodParameterIndex paramIndex)
  1045. {
  1046. return il2cpp::vm::GlobalMetadata::GetParameterInfo(klass, handle, paramIndex);
  1047. }
  1048. Il2CppMetadataPropertyInfo il2cpp::vm::MetadataCache::GetPropertyInfo(const Il2CppClass* klass, TypePropertyIndex index)
  1049. {
  1050. return il2cpp::vm::GlobalMetadata::GetPropertyInfo(klass, index);
  1051. }
  1052. Il2CppMetadataEventInfo il2cpp::vm::MetadataCache::GetEventInfo(const Il2CppClass* klass, TypeEventIndex index)
  1053. {
  1054. return il2cpp::vm::GlobalMetadata::GetEventInfo(klass, index);
  1055. }
  1056. uint32_t il2cpp::vm::MetadataCache::GetGenericContainerCount(Il2CppMetadataGenericContainerHandle handle)
  1057. {
  1058. return il2cpp::vm::GlobalMetadata::GetGenericContainerCount(handle);
  1059. }
  1060. void il2cpp::vm::MetadataCache::MakeGenericArgType(Il2CppMetadataGenericContainerHandle containerHandle, Il2CppMetadataGenericParameterHandle paramHandle, Il2CppType* arg)
  1061. {
  1062. return il2cpp::vm::GlobalMetadata::MakeGenericArgType(containerHandle, paramHandle, arg);
  1063. }
  1064. bool il2cpp::vm::MetadataCache::GetGenericContainerIsMethod(Il2CppMetadataGenericContainerHandle handle)
  1065. {
  1066. return il2cpp::vm::GlobalMetadata::GetGenericContainerIsMethod(handle);
  1067. }
  1068. int16_t il2cpp::vm::MetadataCache::GetGenericConstraintCount(Il2CppMetadataGenericParameterHandle handle)
  1069. {
  1070. return il2cpp::vm::GlobalMetadata::GetGenericConstraintCount(handle);
  1071. }
  1072. const char* il2cpp::vm::MetadataCache::GetGenericParameterName(Il2CppMetadataGenericParameterHandle handle)
  1073. {
  1074. return il2cpp::vm::GlobalMetadata::GetGenericParameterName(handle);
  1075. }
  1076. Il2CppGenericParameterInfo il2cpp::vm::MetadataCache::GetGenericParameterInfo(Il2CppMetadataGenericParameterHandle handle)
  1077. {
  1078. return il2cpp::vm::GlobalMetadata::GetGenericParameterInfo(handle);
  1079. }
  1080. uint16_t il2cpp::vm::MetadataCache::GetGenericParameterFlags(Il2CppMetadataGenericParameterHandle handle)
  1081. {
  1082. return il2cpp::vm::GlobalMetadata::GetGenericParameterFlags(handle);
  1083. }
  1084. const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromCatchPoint(const Il2CppImage* image, const Il2CppCatchPoint* cp)
  1085. {
  1086. return il2cpp::vm::GlobalMetadata::GetMethodInfoFromCatchPoint(cp);
  1087. }
  1088. const MethodInfo* il2cpp::vm::MetadataCache::GetMethodInfoFromSequencePoint(const Il2CppImage* image, const Il2CppSequencePoint* seqPoint)
  1089. {
  1090. return il2cpp::vm::GlobalMetadata::GetMethodInfoFromSequencePoint(seqPoint);
  1091. }
  1092. Il2CppClass* il2cpp::vm::MetadataCache::GetTypeInfoFromTypeSourcePair(const Il2CppImage* image, const Il2CppTypeSourceFilePair* pair)
  1093. {
  1094. return il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeSourcePair(pair);
  1095. }