Method.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. #include "il2cpp-config.h"
  2. #include "vm/Method.h"
  3. #include "il2cpp-tabledefs.h"
  4. #include "il2cpp-class-internals.h"
  5. #include "vm/Class.h"
  6. #include "vm/MetadataCache.h"
  7. #include "vm/Object.h"
  8. #include "vm/Reflection.h"
  9. #include "vm/Runtime.h"
  10. #include "vm/Type.h"
  11. namespace il2cpp
  12. {
  13. namespace vm
  14. {
  15. const Il2CppType* Method::GetReturnType(const MethodInfo* method)
  16. {
  17. return method->return_type;
  18. }
  19. Il2CppClass *Method::GetDeclaringType(const MethodInfo* method)
  20. {
  21. return method->klass;
  22. }
  23. const char* Method::GetName(const MethodInfo *method)
  24. {
  25. return method->name;
  26. }
  27. std::string Method::GetNameWithGenericTypes(const MethodInfo* method)
  28. {
  29. std::string str;
  30. str += method->name;
  31. if (method->is_inflated && method->genericMethod->context.method_inst)
  32. {
  33. const Il2CppGenericInst *inst = method->genericMethod->context.method_inst;
  34. str += '<';
  35. for (unsigned int i = 0; i < inst->type_argc; ++i)
  36. {
  37. str += Type::GetName(inst->type_argv[i], IL2CPP_TYPE_NAME_FORMAT_FULL_NAME);
  38. if (i < inst->type_argc - 1)
  39. str += ",";
  40. }
  41. str += '>';
  42. }
  43. return str;
  44. }
  45. bool Method::IsGeneric(const MethodInfo *method)
  46. {
  47. return method->is_generic;
  48. }
  49. bool Method::IsInflated(const MethodInfo *method)
  50. {
  51. return method->is_inflated;
  52. }
  53. bool Method::IsGenericInstance(const MethodInfo *method)
  54. {
  55. return method->is_inflated && !method->is_generic;
  56. }
  57. bool Method::IsGenericInstanceMethod(const MethodInfo *method)
  58. {
  59. return method->is_inflated && !method->is_generic && method->genericMethod->context.method_inst;
  60. }
  61. bool Method::IsDefaultInterfaceMethodOnGenericInstance(const MethodInfo* method)
  62. {
  63. return method->methodPointer && Class::IsInterface(method->klass) && Class::IsInflated(method->klass) && !method->klass->is_import_or_windows_runtime;
  64. }
  65. bool Method::IsInstance(const MethodInfo *method)
  66. {
  67. return !(method->flags & METHOD_ATTRIBUTE_STATIC);
  68. }
  69. uint32_t Method::GetParamCount(const MethodInfo *method)
  70. {
  71. return method->parameters_count;
  72. }
  73. uint32_t Method::GetGenericParamCount(const MethodInfo *method)
  74. {
  75. if (IsGeneric(method) && method->genericContainerHandle != NULL)
  76. return MetadataCache::GetGenericContainerCount(method->genericContainerHandle);
  77. return 0;
  78. }
  79. const Il2CppType* Method::GetParam(const MethodInfo *method, uint32_t index)
  80. {
  81. if (index < method->parameters_count)
  82. return method->parameters[index];
  83. else
  84. return NULL;
  85. }
  86. const char* Method::GetParamName(const MethodInfo *method, uint32_t index)
  87. {
  88. IL2CPP_ASSERT(method != NULL && "Method::GetParamName cannot be invoked with a NULL MethodInfo.");
  89. if (index >= method->parameters_count)
  90. return NULL;
  91. if (method->is_inflated)
  92. {
  93. method = il2cpp::vm::MetadataCache::GetGenericMethodDefinition(method);
  94. }
  95. // we construct some 'pseudo' methods for things like arrays
  96. if (!method->methodMetadataHandle)
  97. return NULL;
  98. Il2CppMetadataParameterInfo paramInfo = MetadataCache::GetParameterInfo(method->klass, method->methodMetadataHandle, index);
  99. return paramInfo.name;
  100. }
  101. Il2CppClass* Method::GetClass(const MethodInfo *method)
  102. {
  103. return method->klass;
  104. }
  105. bool Method::HasAttribute(const MethodInfo *method, Il2CppClass *attr_class)
  106. {
  107. return Reflection::HasAttribute(method, attr_class);
  108. }
  109. uint32_t Method::GetImplementationFlags(const MethodInfo *method)
  110. {
  111. return method->iflags;
  112. }
  113. uint32_t Method::GetFlags(const MethodInfo *method)
  114. {
  115. return method->flags;
  116. }
  117. uint32_t Method::GetToken(const MethodInfo *method)
  118. {
  119. return method->token;
  120. }
  121. // From ECMA-335, I.10.2 Overloading
  122. // Methods and properties can be overloaded by:
  123. // * Number of parameters
  124. // * Type of any parameter
  125. // * Calling convention <------ not stored in our metadata yet
  126. // * Custom modifiers <------ not supported by il2cpp
  127. // * Whether a parameter is passed by value or by reference
  128. static bool AreParametersSame(const Il2CppType** params1, const Il2CppType** params2, int count)
  129. {
  130. for (int i = 0; i < count; i++)
  131. {
  132. const Il2CppType* param1 = params1[i];
  133. const Il2CppType* param2 = params2[i];
  134. if (param1->byref != param2->byref)
  135. {
  136. return false;
  137. }
  138. if (Class::FromIl2CppType(param1) != Class::FromIl2CppType(param2))
  139. {
  140. return false;
  141. }
  142. }
  143. return true;
  144. }
  145. static int CompareParameters(const Il2CppType** params1, const Il2CppType** params2, int count)
  146. {
  147. for (int i = 0; i < count; i++)
  148. {
  149. const Il2CppType* param1 = params1[i];
  150. const Il2CppType* param2 = params2[i];
  151. if (param1->byref == param2->byref)
  152. {
  153. return Class::FromIl2CppType(param1) < Class::FromIl2CppType(param2);
  154. }
  155. return param1->byref < param2->byref;
  156. }
  157. return true;
  158. }
  159. bool Method::IsSameOverloadSignature(const MethodInfo* method1, const MethodInfo* method2)
  160. {
  161. if (method1->parameters_count != method2->parameters_count)
  162. {
  163. return false;
  164. }
  165. return AreParametersSame(method1->parameters, method2->parameters, method1->parameters_count);
  166. }
  167. bool Method::IsSameOverloadSignature(const PropertyInfo* property1, const PropertyInfo* property2)
  168. {
  169. uint8_t parameterCount1, parameterCount2;
  170. const Il2CppType** parameters1;
  171. const Il2CppType** parameters2;
  172. if (property1->get != NULL)
  173. {
  174. parameterCount1 = property1->get->parameters_count;
  175. parameters1 = property1->get->parameters;
  176. }
  177. else
  178. {
  179. // In set method, value is the last parameter, so we just don't care about it
  180. parameterCount1 = property1->set->parameters_count - 1;
  181. parameters1 = property1->set->parameters;
  182. }
  183. if (property2->get != NULL)
  184. {
  185. parameterCount2 = property2->get->parameters_count;
  186. parameters2 = property2->get->parameters;
  187. }
  188. else
  189. {
  190. parameterCount2 = property2->set->parameters_count - 1;
  191. parameters2 = property2->set->parameters;
  192. }
  193. if (parameterCount1 != parameterCount2)
  194. {
  195. return false;
  196. }
  197. return AreParametersSame(parameters1, parameters2, parameterCount1);
  198. }
  199. int Method::CompareOverloadSignature(const PropertyInfo* property1, const PropertyInfo* property2)
  200. {
  201. uint8_t parameterCount1, parameterCount2;
  202. const Il2CppType** parameters1;
  203. const Il2CppType** parameters2;
  204. if (property1->get != NULL)
  205. {
  206. parameterCount1 = property1->get->parameters_count;
  207. parameters1 = property1->get->parameters;
  208. }
  209. else
  210. {
  211. // In set method, value is the last parameter, so we just don't care about it
  212. parameterCount1 = property1->set->parameters_count - 1;
  213. parameters1 = property1->set->parameters;
  214. }
  215. if (property2->get != NULL)
  216. {
  217. parameterCount2 = property2->get->parameters_count;
  218. parameters2 = property2->get->parameters;
  219. }
  220. else
  221. {
  222. parameterCount2 = property2->set->parameters_count - 1;
  223. parameters2 = property2->set->parameters;
  224. }
  225. if (parameterCount1 == parameterCount2)
  226. {
  227. return CompareParameters(parameters1, parameters2, parameterCount1);
  228. }
  229. return parameterCount1 < parameterCount2;
  230. }
  231. const char* Method::GetParameterDefaultValue(const MethodInfo* method, int32_t parameterPosition, const Il2CppType** type, bool* isExplicitySetNullDefaultValue)
  232. {
  233. return reinterpret_cast<const char*>(MetadataCache::GetParameterDefaultValue(method, parameterPosition, type, isExplicitySetNullDefaultValue));
  234. }
  235. uint32_t Method::GetParameterToken(const MethodInfo* method, int32_t index)
  236. {
  237. if (index >= method->parameters_count)
  238. return 0;
  239. if (method->is_inflated)
  240. {
  241. method = il2cpp::vm::MetadataCache::GetGenericMethodDefinition(method);
  242. }
  243. // we construct some 'pseudo' methods for things like arrays
  244. if (!method->methodMetadataHandle)
  245. return 0;
  246. Il2CppMetadataParameterInfo paramInfo = MetadataCache::GetParameterInfo(method->klass, method->methodMetadataHandle, index);
  247. return paramInfo.token;
  248. }
  249. std::string Method::GetFullName(const MethodInfo* method)
  250. {
  251. std::string str;
  252. str += Type::GetName(&method->klass->byval_arg, IL2CPP_TYPE_NAME_FORMAT_FULL_NAME);
  253. str += "::";
  254. str += Method::GetNameWithGenericTypes(method);
  255. return str;
  256. }
  257. static void AmbiguousImplementationMethod()
  258. {
  259. il2cpp::vm::Runtime::RaiseAmbiguousImplementationException(NULL);
  260. }
  261. static void AmbiguousImplementationMethodInvoker(Il2CppMethodPointer ptr, const MethodInfo* method, void* obj, void** args, void* ret)
  262. {
  263. il2cpp::vm::Runtime::RaiseAmbiguousImplementationException(method);
  264. }
  265. static void EntryPointNotFoundImplementationMethod()
  266. {
  267. il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetEntryPointNotFoundException(""));
  268. }
  269. static void EntryPointNotFoundMethodInvoker(Il2CppMethodPointer ptr, const MethodInfo* method, void* obj, void** args, void* ret)
  270. {
  271. std::string name = "";
  272. if (method != NULL && method->name != NULL)
  273. name = Method::GetFullName(method);
  274. il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetEntryPointNotFoundException(name.c_str()));
  275. }
  276. const static MethodInfo ambiguousMethodInfo =
  277. {
  278. AmbiguousImplementationMethod, // method_ptr
  279. AmbiguousImplementationMethod, // virtual_method_ptr
  280. AmbiguousImplementationMethodInvoker, // invoker_method
  281. };
  282. const static MethodInfo entryPointNoFoundMethodInfo =
  283. {
  284. EntryPointNotFoundImplementationMethod, // method_ptr
  285. EntryPointNotFoundImplementationMethod, // virtual_method_ptr
  286. EntryPointNotFoundMethodInvoker, // invoker_method
  287. };
  288. const MethodInfo* Method::GetAmbiguousMethodInfo()
  289. {
  290. IL2CPP_ASSERT(ambiguousMethodInfo.methodPointer == AmbiguousImplementationMethod);
  291. IL2CPP_ASSERT(ambiguousMethodInfo.virtualMethodPointer == AmbiguousImplementationMethod);
  292. IL2CPP_ASSERT(ambiguousMethodInfo.invoker_method == AmbiguousImplementationMethodInvoker);
  293. // GenericMethod::GetMethod relies on ambiguousMethodInfo being a singleton
  294. return &ambiguousMethodInfo;
  295. }
  296. const MethodInfo* Method::GetEntryPointNotFoundMethodInfo()
  297. {
  298. IL2CPP_ASSERT(entryPointNoFoundMethodInfo.methodPointer == EntryPointNotFoundImplementationMethod);
  299. IL2CPP_ASSERT(entryPointNoFoundMethodInfo.virtualMethodPointer == EntryPointNotFoundImplementationMethod);
  300. IL2CPP_ASSERT(entryPointNoFoundMethodInfo.invoker_method == EntryPointNotFoundMethodInvoker);
  301. return &entryPointNoFoundMethodInfo;
  302. }
  303. bool Method::IsAmbiguousMethodInfo(const MethodInfo* method)
  304. {
  305. return method == &ambiguousMethodInfo || metadata::GenericMethod::IsGenericAmbiguousMethodInfo(method);
  306. }
  307. bool Method::IsEntryPointNotFoundMethodInfo(const MethodInfo* method)
  308. {
  309. return method == &entryPointNoFoundMethodInfo;
  310. }
  311. bool Method::HasFullGenericSharingSignature(const MethodInfo* method)
  312. {
  313. return method->has_full_generic_sharing_signature;
  314. }
  315. } /* namespace vm */
  316. } /* namespace il2cpp */