GenericClass.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #include "il2cpp-config.h"
  2. #include "metadata/GenericMetadata.h"
  3. #include "metadata/Il2CppGenericClassHash.h"
  4. #include "metadata/Il2CppGenericClassCompare.h"
  5. #include "os/Atomic.h"
  6. #include "os/Mutex.h"
  7. #include "utils/Memory.h"
  8. #include "utils/Il2CppHashSet.h"
  9. #include "vm/Class.h"
  10. #include "vm/GenericClass.h"
  11. #include "vm/Exception.h"
  12. #include "vm/MetadataAlloc.h"
  13. #include "vm/MetadataCache.h"
  14. #include "vm/MetadataLock.h"
  15. #include "vm/Type.h"
  16. #include "il2cpp-class-internals.h"
  17. #include "il2cpp-runtime-metadata.h"
  18. #include "il2cpp-runtime-stats.h"
  19. namespace il2cpp
  20. {
  21. namespace vm
  22. {
  23. void GenericClass::SetupMethods(Il2CppClass* genericInstanceType)
  24. {
  25. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  26. uint16_t methodCount = genericTypeDefinition->method_count;
  27. IL2CPP_ASSERT(genericTypeDefinition->method_count == genericInstanceType->method_count);
  28. if (methodCount == 0)
  29. {
  30. genericInstanceType->methods = NULL;
  31. return;
  32. }
  33. if (genericInstanceType->methods == NULL) {
  34. genericInstanceType->methods = (const MethodInfo**)MetadataCalloc(methodCount, sizeof(MethodInfo*), IL2CPP_MSTAT_METHOD);
  35. }
  36. for (uint16_t methodIndex = 0; methodIndex < methodCount; ++methodIndex)
  37. {
  38. if (genericInstanceType->methods[methodIndex] != NULL)
  39. continue;
  40. //const MethodInfo* methodDefinition = genericTypeDefinition->methods[methodIndex];
  41. const MethodInfo* methodDefinition = Class::GetOrSetupOneMethod(genericTypeDefinition, methodIndex);
  42. genericInstanceType->methods[methodIndex] = metadata::GenericMetadata::Inflate(methodDefinition, GenericClass::GetContext(genericInstanceType->generic_class));
  43. ++il2cpp_runtime_stats.method_count;
  44. }
  45. }
  46. const MethodInfo* GenericClass::GetOrSetupOneMethod(Il2CppClass* genericInstanceType, MethodIndex index)
  47. {
  48. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  49. uint16_t methodCount = genericTypeDefinition->method_count;
  50. IL2CPP_ASSERT(genericTypeDefinition->method_count == genericInstanceType->method_count);
  51. if (methodCount == 0)
  52. {
  53. genericInstanceType->methods = NULL;
  54. return NULL;
  55. }
  56. if (genericInstanceType->methods == NULL) {
  57. genericInstanceType->methods = (const MethodInfo**)MetadataCalloc(methodCount, sizeof(MethodInfo*), IL2CPP_MSTAT_METHOD);
  58. }
  59. if (genericInstanceType->methods[index] == NULL)
  60. {
  61. //const MethodInfo* methodDefinition = genericTypeDefinition->methods[index];
  62. const MethodInfo* methodDefinition = Class::GetOrSetupOneMethod(genericTypeDefinition, index);
  63. genericInstanceType->methods[index] = metadata::GenericMetadata::Inflate(methodDefinition, GenericClass::GetContext(genericInstanceType->generic_class));
  64. ++il2cpp_runtime_stats.method_count;
  65. }
  66. return genericInstanceType->methods[index];
  67. }
  68. static void InflatePropertyDefinition(const PropertyInfo* propertyDefinition, PropertyInfo* newProperty, Il2CppClass* declaringClass, Il2CppGenericContext* context)
  69. {
  70. newProperty->attrs = propertyDefinition->attrs;
  71. newProperty->parent = declaringClass;
  72. newProperty->name = propertyDefinition->name;
  73. newProperty->token = propertyDefinition->token;
  74. if (propertyDefinition->get)
  75. newProperty->get = metadata::GenericMetadata::Inflate(propertyDefinition->get, context);
  76. if (propertyDefinition->set)
  77. newProperty->set = metadata::GenericMetadata::Inflate(propertyDefinition->set, context);
  78. }
  79. void GenericClass::SetupProperties(Il2CppClass* genericInstanceType)
  80. {
  81. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  82. uint16_t propertyCount = genericTypeDefinition->property_count;
  83. IL2CPP_ASSERT(genericTypeDefinition->property_count == genericInstanceType->property_count);
  84. if (propertyCount == 0)
  85. {
  86. genericInstanceType->properties = NULL;
  87. return;
  88. }
  89. Class::SetupProperties(genericTypeDefinition);
  90. //const PropertyInfo** properties = (const PropertyInfo**)MetadataCalloc(propertyCount, sizeof(PropertyInfo*), IL2CPP_MSTAT_PROPERTY);
  91. if(genericInstanceType->properties == nullptr)
  92. genericInstanceType->properties = (const PropertyInfo**)MetadataCalloc(propertyCount, sizeof(PropertyInfo*), IL2CPP_MSTAT_PROPERTY);
  93. const PropertyInfo** properties = genericInstanceType->properties;
  94. for (uint16_t propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
  95. {
  96. if (properties[propertyIndex] != nullptr)
  97. continue;
  98. PropertyInfo* property = (PropertyInfo*)MetadataCalloc(1, sizeof(PropertyInfo), IL2CPP_MSTAT_PROPERTY);
  99. InflatePropertyDefinition(genericTypeDefinition->properties[propertyIndex], property, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  100. properties[propertyIndex] = property;
  101. }
  102. //genericInstanceType->properties = properties;
  103. }
  104. const PropertyInfo* GenericClass::GetOrSetupOneProperty(Il2CppClass* genericInstanceType, PropertyIndex index)
  105. {
  106. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  107. uint16_t propertyCount = genericTypeDefinition->property_count;
  108. IL2CPP_ASSERT(genericTypeDefinition->property_count == genericInstanceType->property_count);
  109. if (propertyCount == 0)
  110. {
  111. genericInstanceType->properties = NULL;
  112. return nullptr;
  113. }
  114. Class::GetOrSetupOneProperty(genericTypeDefinition,index);
  115. if (genericInstanceType->properties == nullptr) {
  116. genericInstanceType->properties = (const PropertyInfo**)MetadataCalloc(propertyCount, sizeof(PropertyInfo*), IL2CPP_MSTAT_PROPERTY);
  117. }
  118. if (index >= propertyCount) {
  119. return nullptr;
  120. }
  121. if (genericInstanceType->properties[index] == nullptr) {
  122. PropertyInfo* property = (PropertyInfo*)MetadataCalloc(1, sizeof(PropertyInfo), IL2CPP_MSTAT_PROPERTY);
  123. InflatePropertyDefinition(genericTypeDefinition->properties[index], property, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  124. genericInstanceType->properties[index] = property;
  125. }
  126. return genericInstanceType->properties[index];
  127. }
  128. static void InflateEventDefinition(const EventInfo* eventDefinition, EventInfo* newEvent, Il2CppClass* declaringClass, Il2CppGenericContext* context)
  129. {
  130. newEvent->eventType = metadata::GenericMetadata::InflateIfNeeded(eventDefinition->eventType, context, false);
  131. newEvent->name = eventDefinition->name;
  132. newEvent->parent = declaringClass;
  133. newEvent->token = eventDefinition->token;
  134. if (eventDefinition->add)
  135. newEvent->add = metadata::GenericMetadata::Inflate(eventDefinition->add, context);
  136. if (eventDefinition->raise)
  137. newEvent->raise = metadata::GenericMetadata::Inflate(eventDefinition->raise, context);
  138. if (eventDefinition->remove)
  139. newEvent->remove = metadata::GenericMetadata::Inflate(eventDefinition->remove, context);
  140. }
  141. void GenericClass::SetupEvents(Il2CppClass* genericInstanceType)
  142. {
  143. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  144. uint16_t eventCount = genericTypeDefinition->event_count;
  145. IL2CPP_ASSERT(genericTypeDefinition->event_count == genericInstanceType->event_count);
  146. if (eventCount == 0)
  147. {
  148. genericInstanceType->events = NULL;
  149. return;
  150. }
  151. //[WL]
  152. Class::SetupEvents(genericTypeDefinition);
  153. EventInfo* events = (EventInfo*)MetadataCalloc(eventCount, sizeof(EventInfo), IL2CPP_MSTAT_FIELD);
  154. EventInfo* event = events;
  155. for (uint16_t eventIndex = 0; eventIndex < eventCount; ++eventIndex)
  156. {
  157. InflateEventDefinition(genericTypeDefinition->events + eventIndex, event, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  158. event++;
  159. }
  160. genericInstanceType->events = events;
  161. }
  162. static FieldInfo* InflateFieldDefinition(const FieldInfo* fieldDefinition, FieldInfo* newField, Il2CppClass* declaringClass, Il2CppGenericContext* context)
  163. {
  164. newField->type = metadata::GenericMetadata::InflateIfNeeded(fieldDefinition->type, context, false);
  165. newField->name = fieldDefinition->name;
  166. newField->parent = declaringClass;
  167. newField->offset = fieldDefinition->offset;
  168. newField->token = fieldDefinition->token;
  169. return newField;
  170. }
  171. void GenericClass::SetupFields(Il2CppClass* genericInstanceType)
  172. {
  173. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  174. uint16_t fieldCount = genericTypeDefinition->field_count;
  175. IL2CPP_ASSERT(genericTypeDefinition->field_count == genericInstanceType->field_count);
  176. if (fieldCount == 0)
  177. {
  178. genericInstanceType->fields = NULL;
  179. return;
  180. }
  181. FieldInfo* fields = (FieldInfo*)MetadataCalloc(fieldCount, sizeof(FieldInfo), IL2CPP_MSTAT_FIELD);
  182. FieldInfo* field = fields;
  183. for (uint16_t fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
  184. {
  185. InflateFieldDefinition(genericTypeDefinition->fields + fieldIndex, field, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  186. field++;
  187. }
  188. genericInstanceType->fields = fields;
  189. }
  190. Il2CppClass* GenericClass::GetClass(Il2CppGenericClass* gclass, bool throwOnError)
  191. {
  192. Il2CppClass* cachedClass = os::Atomic::LoadPointerRelaxed(&gclass->cached_class);
  193. if (cachedClass)
  194. return cachedClass;
  195. return CreateClass(gclass, throwOnError);
  196. }
  197. typedef Il2CppHashSet < Il2CppGenericClass*, il2cpp::metadata::Il2CppGenericClassHash, il2cpp::metadata::Il2CppGenericClassCompare > Il2CppGenericClassSet;
  198. static Il2CppGenericClassSet s_GenericClassSet;
  199. Il2CppClass* GenericClass::CreateClass(Il2CppGenericClass *gclass, bool throwOnError)
  200. {
  201. Il2CppClass* definition = GetTypeDefinition(gclass);
  202. if (definition == NULL)
  203. {
  204. if (throwOnError)
  205. vm::Exception::Raise(vm::Exception::GetMaximumNestedGenericsException());
  206. return NULL;
  207. }
  208. os::FastAutoLock lock(&g_MetadataLock);
  209. Il2CppGenericClassSet::const_iterator iter = s_GenericClassSet.find(gclass);
  210. if (iter != s_GenericClassSet.end())
  211. {
  212. Il2CppGenericClass* cacheGclass = *iter;
  213. IL2CPP_ASSERT(cacheGclass->cached_class);
  214. il2cpp::os::Atomic::ExchangePointer(&gclass->cached_class, cacheGclass->cached_class);
  215. return gclass->cached_class;
  216. }
  217. if (!gclass->cached_class)
  218. {
  219. Il2CppClass* klass = (Il2CppClass*)MetadataCalloc(1, sizeof(Il2CppClass) + (sizeof(VirtualInvokeData) * definition->vtable_count), IL2CPP_MSTAT_CLASS);
  220. #if !IL2CPP_SLIM_CLASS
  221. klass->klass = klass;
  222. #endif
  223. klass->name = definition->name;
  224. klass->namespaze = definition->namespaze;
  225. klass->image = definition->image;
  226. klass->flags = definition->flags;
  227. //klass->type_token = definition->type_token;
  228. klass->generic_class = gclass;
  229. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(klass->generic_class);
  230. Il2CppGenericContext* context = &klass->generic_class->context;
  231. if (genericTypeDefinition->parent)
  232. klass->parent = Class::FromIl2CppType(metadata::GenericMetadata::InflateIfNeeded(&genericTypeDefinition->parent->byval_arg, context, false));
  233. if (genericTypeDefinition->declaringType)
  234. klass->declaringType = Class::FromIl2CppType(metadata::GenericMetadata::InflateIfNeeded(&genericTypeDefinition->declaringType->byval_arg, context, false));
  235. klass->this_arg.type = klass->byval_arg.type = IL2CPP_TYPE_GENERICINST;
  236. klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
  237. klass->this_arg.byref = true;
  238. klass->byval_arg.valuetype = genericTypeDefinition->byval_arg.valuetype;
  239. klass->event_count = definition->event_count;
  240. klass->field_count = definition->field_count;
  241. klass->interfaces_count = definition->interfaces_count;
  242. klass->method_count = definition->method_count;
  243. klass->property_count = definition->property_count;
  244. klass->enumtype = definition->enumtype;
  245. klass->element_class = klass->castClass = klass;
  246. klass->has_cctor = definition->has_cctor;
  247. klass->cctor_finished_or_no_cctor = !definition->has_cctor;
  248. klass->has_finalize = definition->has_finalize;
  249. klass->native_size = klass->thread_static_fields_offset = -1;
  250. klass->token = definition->token;
  251. klass->interopData = MetadataCache::GetInteropDataForType(&klass->byval_arg);
  252. if (GenericClass::GetTypeDefinition(klass->generic_class) == il2cpp_defaults.generic_nullable_class)
  253. {
  254. klass->element_class = klass->castClass = Class::FromIl2CppType(klass->generic_class->context.class_inst->type_argv[0]);
  255. klass->nullabletype = true;
  256. }
  257. if (klass->enumtype)
  258. klass->element_class = klass->castClass = definition->element_class;
  259. klass->is_import_or_windows_runtime = definition->is_import_or_windows_runtime;
  260. // Do not update gclass->cached_class until `klass` is fully initialized
  261. // And do so with an atomic barrier so no threads observer the writes out of order
  262. il2cpp::os::Atomic::ExchangePointer(&gclass->cached_class, klass);
  263. Il2CppGenericClass* cloneGclass = (Il2CppGenericClass*)IL2CPP_MALLOC_ZERO(sizeof(Il2CppGenericClass), IL2CPP_MEM_META_POOL);
  264. *cloneGclass = *gclass;
  265. s_GenericClassSet.insert(cloneGclass);
  266. }
  267. return gclass->cached_class;
  268. }
  269. Il2CppGenericContext* GenericClass::GetContext(Il2CppGenericClass *gclass)
  270. {
  271. return &gclass->context;
  272. }
  273. Il2CppClass* GenericClass::GetTypeDefinition(Il2CppGenericClass *gclass)
  274. {
  275. return MetadataCache::GetTypeInfoFromType(gclass->type);
  276. }
  277. bool GenericClass::IsEnum(Il2CppGenericClass *gclass)
  278. {
  279. return Type::IsEnum(gclass->type);
  280. }
  281. bool GenericClass::IsValueType(Il2CppGenericClass *gclass)
  282. {
  283. return gclass->type->type == IL2CPP_TYPE_VALUETYPE;
  284. }
  285. } /* namespace vm */
  286. } /* namespace il2cpp */