GenericClass.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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 "il2cpp-class-internals.h"
  16. #include "il2cpp-runtime-metadata.h"
  17. #include "il2cpp-runtime-stats.h"
  18. namespace il2cpp
  19. {
  20. namespace vm
  21. {
  22. void GenericClass::SetupMethods(Il2CppClass* genericInstanceType)
  23. {
  24. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  25. uint16_t methodCount = genericTypeDefinition->method_count;
  26. IL2CPP_ASSERT(genericTypeDefinition->method_count == genericInstanceType->method_count);
  27. if (methodCount == 0)
  28. {
  29. genericInstanceType->methods = NULL;
  30. return;
  31. }
  32. const MethodInfo** methods = (const MethodInfo**)MetadataCalloc(methodCount, sizeof(MethodInfo*));
  33. for (uint16_t methodIndex = 0; methodIndex < methodCount; ++methodIndex)
  34. {
  35. const MethodInfo* methodDefinition = genericTypeDefinition->methods[methodIndex];
  36. methods[methodIndex] = metadata::GenericMetadata::Inflate(methodDefinition, GenericClass::GetContext(genericInstanceType->generic_class));
  37. }
  38. genericInstanceType->methods = methods;
  39. il2cpp_runtime_stats.method_count += methodCount;
  40. }
  41. static void InflatePropertyDefinition(const PropertyInfo* propertyDefinition, PropertyInfo* newProperty, Il2CppClass* declaringClass, Il2CppGenericContext* context)
  42. {
  43. newProperty->attrs = propertyDefinition->attrs;
  44. newProperty->parent = declaringClass;
  45. newProperty->name = propertyDefinition->name;
  46. newProperty->token = propertyDefinition->token;
  47. if (propertyDefinition->get)
  48. newProperty->get = metadata::GenericMetadata::Inflate(propertyDefinition->get, context);
  49. if (propertyDefinition->set)
  50. newProperty->set = metadata::GenericMetadata::Inflate(propertyDefinition->set, context);
  51. }
  52. void GenericClass::SetupProperties(Il2CppClass* genericInstanceType)
  53. {
  54. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  55. uint16_t propertyCount = genericTypeDefinition->property_count;
  56. IL2CPP_ASSERT(genericTypeDefinition->property_count == genericInstanceType->property_count);
  57. if (propertyCount == 0)
  58. {
  59. genericInstanceType->properties = NULL;
  60. return;
  61. }
  62. PropertyInfo* properties = (PropertyInfo*)MetadataCalloc(propertyCount, sizeof(PropertyInfo));
  63. PropertyInfo* property = properties;
  64. for (uint16_t propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
  65. {
  66. InflatePropertyDefinition(genericTypeDefinition->properties + propertyIndex, property, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  67. property++;
  68. }
  69. genericInstanceType->properties = properties;
  70. }
  71. static void InflateEventDefinition(const EventInfo* eventDefinition, EventInfo* newEvent, Il2CppClass* declaringClass, Il2CppGenericContext* context)
  72. {
  73. newEvent->eventType = metadata::GenericMetadata::InflateIfNeeded(eventDefinition->eventType, context, false);
  74. newEvent->name = eventDefinition->name;
  75. newEvent->parent = declaringClass;
  76. newEvent->token = eventDefinition->token;
  77. if (eventDefinition->add)
  78. newEvent->add = metadata::GenericMetadata::Inflate(eventDefinition->add, context);
  79. if (eventDefinition->raise)
  80. newEvent->raise = metadata::GenericMetadata::Inflate(eventDefinition->raise, context);
  81. if (eventDefinition->remove)
  82. newEvent->remove = metadata::GenericMetadata::Inflate(eventDefinition->remove, context);
  83. }
  84. void GenericClass::SetupEvents(Il2CppClass* genericInstanceType)
  85. {
  86. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  87. uint16_t eventCount = genericTypeDefinition->event_count;
  88. IL2CPP_ASSERT(genericTypeDefinition->event_count == genericInstanceType->event_count);
  89. if (eventCount == 0)
  90. {
  91. genericInstanceType->events = NULL;
  92. return;
  93. }
  94. EventInfo* events = (EventInfo*)MetadataCalloc(eventCount, sizeof(EventInfo));
  95. EventInfo* event = events;
  96. for (uint16_t eventIndex = 0; eventIndex < eventCount; ++eventIndex)
  97. {
  98. InflateEventDefinition(genericTypeDefinition->events + eventIndex, event, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  99. event++;
  100. }
  101. genericInstanceType->events = events;
  102. }
  103. static FieldInfo* InflateFieldDefinition(const FieldInfo* fieldDefinition, FieldInfo* newField, Il2CppClass* declaringClass, Il2CppGenericContext* context)
  104. {
  105. newField->type = metadata::GenericMetadata::InflateIfNeeded(fieldDefinition->type, context, false);
  106. newField->name = fieldDefinition->name;
  107. newField->parent = declaringClass;
  108. newField->offset = fieldDefinition->offset;
  109. newField->token = fieldDefinition->token;
  110. return newField;
  111. }
  112. void GenericClass::SetupFields(Il2CppClass* genericInstanceType)
  113. {
  114. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(genericInstanceType->generic_class);
  115. uint16_t fieldCount = genericTypeDefinition->field_count;
  116. IL2CPP_ASSERT(genericTypeDefinition->field_count == genericInstanceType->field_count);
  117. if (fieldCount == 0)
  118. {
  119. genericInstanceType->fields = NULL;
  120. return;
  121. }
  122. FieldInfo* fields = (FieldInfo*)MetadataCalloc(fieldCount, sizeof(FieldInfo));
  123. FieldInfo* field = fields;
  124. for (uint16_t fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
  125. {
  126. InflateFieldDefinition(genericTypeDefinition->fields + fieldIndex, field, genericInstanceType, GenericClass::GetContext(genericInstanceType->generic_class));
  127. field++;
  128. }
  129. genericInstanceType->fields = fields;
  130. }
  131. Il2CppClass* GenericClass::GetClass(Il2CppGenericClass* gclass, bool throwOnError)
  132. {
  133. Il2CppClass* cachedClass = os::Atomic::LoadPointerRelaxed(&gclass->cached_class);
  134. if (cachedClass)
  135. return cachedClass;
  136. return CreateClass(gclass, throwOnError);
  137. }
  138. typedef Il2CppHashSet < Il2CppGenericClass*, il2cpp::metadata::Il2CppGenericClassHash, il2cpp::metadata::Il2CppGenericClassCompare > Il2CppGenericClassSet;
  139. static Il2CppGenericClassSet s_GenericClassSet;
  140. Il2CppClass* GenericClass::CreateClass(Il2CppGenericClass *gclass, bool throwOnError)
  141. {
  142. Il2CppClass* definition = GetTypeDefinition(gclass);
  143. if (definition == NULL)
  144. {
  145. if (throwOnError)
  146. vm::Exception::Raise(vm::Exception::GetMaximumNestedGenericsException());
  147. return NULL;
  148. }
  149. os::FastAutoLock lock(&g_MetadataLock);
  150. Il2CppGenericClassSet::const_iterator iter = s_GenericClassSet.find(gclass);
  151. if (iter != s_GenericClassSet.end())
  152. {
  153. Il2CppGenericClass* cacheGclass = *iter;
  154. IL2CPP_ASSERT(cacheGclass->cached_class);
  155. il2cpp::os::Atomic::ExchangePointer(&gclass->cached_class, cacheGclass->cached_class);
  156. return gclass->cached_class;
  157. }
  158. if (!gclass->cached_class)
  159. {
  160. Il2CppClass* klass = (Il2CppClass*)MetadataCalloc(1, sizeof(Il2CppClass) + (sizeof(VirtualInvokeData) * definition->vtable_count));
  161. klass->klass = klass;
  162. klass->name = definition->name;
  163. klass->namespaze = definition->namespaze;
  164. klass->image = definition->image;
  165. klass->flags = definition->flags;
  166. //klass->type_token = definition->type_token;
  167. klass->generic_class = gclass;
  168. Il2CppClass* genericTypeDefinition = GenericClass::GetTypeDefinition(klass->generic_class);
  169. Il2CppGenericContext* context = &klass->generic_class->context;
  170. if (genericTypeDefinition->parent)
  171. klass->parent = Class::FromIl2CppType(metadata::GenericMetadata::InflateIfNeeded(&genericTypeDefinition->parent->byval_arg, context, false));
  172. if (genericTypeDefinition->declaringType)
  173. klass->declaringType = Class::FromIl2CppType(metadata::GenericMetadata::InflateIfNeeded(&genericTypeDefinition->declaringType->byval_arg, context, false));
  174. klass->this_arg.type = klass->byval_arg.type = IL2CPP_TYPE_GENERICINST;
  175. klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
  176. klass->this_arg.byref = true;
  177. klass->byval_arg.valuetype = genericTypeDefinition->byval_arg.valuetype;
  178. klass->event_count = definition->event_count;
  179. klass->field_count = definition->field_count;
  180. klass->interfaces_count = definition->interfaces_count;
  181. klass->method_count = definition->method_count;
  182. klass->property_count = definition->property_count;
  183. klass->enumtype = definition->enumtype;
  184. klass->element_class = klass->castClass = klass;
  185. klass->has_cctor = definition->has_cctor;
  186. klass->cctor_finished_or_no_cctor = !definition->has_cctor;
  187. klass->has_finalize = definition->has_finalize;
  188. klass->native_size = klass->thread_static_fields_offset = -1;
  189. klass->token = definition->token;
  190. klass->interopData = MetadataCache::GetInteropDataForType(&klass->byval_arg);
  191. if (GenericClass::GetTypeDefinition(klass->generic_class) == il2cpp_defaults.generic_nullable_class)
  192. {
  193. klass->element_class = klass->castClass = Class::FromIl2CppType(klass->generic_class->context.class_inst->type_argv[0]);
  194. klass->nullabletype = true;
  195. }
  196. if (klass->enumtype)
  197. klass->element_class = klass->castClass = definition->element_class;
  198. klass->is_import_or_windows_runtime = definition->is_import_or_windows_runtime;
  199. // Do not update gclass->cached_class until `klass` is fully initialized
  200. // And do so with an atomic barrier so no threads observer the writes out of order
  201. il2cpp::os::Atomic::ExchangePointer(&gclass->cached_class, klass);
  202. s_GenericClassSet.insert(gclass);
  203. }
  204. return gclass->cached_class;
  205. }
  206. Il2CppGenericContext* GenericClass::GetContext(Il2CppGenericClass *gclass)
  207. {
  208. return &gclass->context;
  209. }
  210. Il2CppClass* GenericClass::GetTypeDefinition(Il2CppGenericClass *gclass)
  211. {
  212. return MetadataCache::GetTypeInfoFromType(gclass->type);
  213. }
  214. bool GenericClass::IsEnum(Il2CppGenericClass *gclass)
  215. {
  216. return IsValueType(gclass) && GetTypeDefinition(gclass)->enumtype;
  217. }
  218. bool GenericClass::IsValueType(Il2CppGenericClass *gclass)
  219. {
  220. return GetTypeDefinition(gclass)->byval_arg.valuetype;
  221. }
  222. } /* namespace vm */
  223. } /* namespace il2cpp */