ClassInlines.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #include "ClassInlines.h"
  2. #include "vm/Class.h"
  3. #include "vm/Exception.h"
  4. #include "vm/Method.h"
  5. #include "vm/RCW.h"
  6. #include "gc/GCHandle.h"
  7. #include "metadata/GenericMethod.h"
  8. namespace il2cpp
  9. {
  10. namespace vm
  11. {
  12. Il2CppClass* ClassInlines::InitFromCodegenSlow(Il2CppClass *klass)
  13. {
  14. IL2CPP_ASSERT(klass != il2cpp_defaults.il2cpp_fully_shared_type);
  15. Class::Init(klass);
  16. if (klass->initializationExceptionGCHandle)
  17. il2cpp::vm::Exception::Raise((Il2CppException*)gc::GCHandle::GetTarget(klass->initializationExceptionGCHandle));
  18. return klass;
  19. }
  20. Il2CppClass* ClassInlines::InitFromCodegenSlow(Il2CppClass *klass, bool throwOnError)
  21. {
  22. IL2CPP_ASSERT(klass != il2cpp_defaults.il2cpp_fully_shared_type);
  23. if (throwOnError)
  24. return InitFromCodegenSlow(klass);
  25. Class::Init(klass);
  26. if (klass->initializationExceptionGCHandle)
  27. return NULL;
  28. return klass;
  29. }
  30. const MethodInfo* ClassInlines::InitRgctxFromCodegenSlow(const MethodInfo* method)
  31. {
  32. il2cpp::metadata::GenericMethod::InflateRGCTX(method);
  33. return method;
  34. }
  35. NORETURN static void RaiseExceptionForNotFoundInterface(const Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot)
  36. {
  37. std::string message;
  38. message = "Attempt to access method '" + Type::GetName(&itf->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL) + "." + Method::GetName(itf->methods[slot])
  39. + "' on type '" + Type::GetName(&klass->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL) + "' failed.";
  40. Exception::Raise(il2cpp::vm::Exception::GetMethodAccessException(message.c_str()));
  41. }
  42. const VirtualInvokeData* ClassInlines::GetInterfaceInvokeDataFromVTableSlowPath(const Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot)
  43. {
  44. if (itf->generic_class != NULL)
  45. {
  46. for (uint16_t i = 0; i < klass->interface_offsets_count; ++i)
  47. {
  48. const Il2CppRuntimeInterfaceOffsetPair* pair = klass->interfaceOffsets + i;
  49. if (Class::IsGenericClassAssignableFromVariance(itf, pair->interfaceType, klass))
  50. {
  51. IL2CPP_ASSERT(pair->offset + slot < klass->vtable_count);
  52. //return &klass->vtable[pair->offset + slot];
  53. return Class::GetOrSetupOneVTableSlot(const_cast<Il2CppClass*>(klass), NULL, pair->offset + slot);
  54. }
  55. }
  56. }
  57. return NULL;
  58. }
  59. const VirtualInvokeData& ClassInlines::GetInterfaceInvokeDataFromVTable(Il2CppObject* obj,const Il2CppClass* itf, Il2CppMethodSlot slot)
  60. {
  61. const VirtualInvokeData* result = GetInterfaceInvokeDataFromVTable(obj->klass,itf,slot);
  62. if (result)
  63. return *result;
  64. return GetInterfaceInvokeDataFromVTableSlowPath(obj,itf,slot);
  65. }
  66. const VirtualInvokeData& ClassInlines::GetInterfaceInvokeDataFromVTableSlowPath(Il2CppObject* obj, const Il2CppClass* itf, Il2CppMethodSlot slot)
  67. {
  68. const Il2CppClass* klass = obj->klass;
  69. const VirtualInvokeData* data;
  70. data = GetInterfaceInvokeDataFromVTableSlowPath(klass, itf, slot);
  71. if (data)
  72. return *data;
  73. #if !IL2CPP_TRIM_COM
  74. if (klass->is_import_or_windows_runtime)
  75. {
  76. Il2CppComObject* rcw = static_cast<Il2CppComObject*>(obj);
  77. // It might be null if it's called on a dead (already released) or fake object
  78. if (rcw->identity != NULL)
  79. {
  80. const VirtualInvokeData* invokeData = RCW::GetComInterfaceInvokeData(rcw, itf, slot);
  81. if (invokeData != NULL)
  82. {
  83. // Nothing will be referencing these types directly, so we need to initialize them here
  84. Class::Init(invokeData->method->klass);
  85. return *invokeData;
  86. }
  87. }
  88. }
  89. #endif
  90. RaiseExceptionForNotFoundInterface(klass, itf, slot);
  91. IL2CPP_UNREACHABLE;
  92. }
  93. const VirtualInvokeData& ClassInlines::GetVirtualInvokeData(Il2CppMethodSlot slot, const Il2CppObject* obj)
  94. {
  95. Assert(slot != kInvalidIl2CppMethodSlot && "MethodSlot is invalid!");
  96. //quick pass
  97. Il2CppClass* klass = obj->klass;
  98. if(slot < klass->vtable_count && klass->vtable[slot].method != NULL)
  99. return klass->vtable[slot];
  100. return *Class::GetOrSetupOneVTableSlot(obj->klass, NULL, slot);
  101. }
  102. bool ClassInlines::HasParent(const Il2CppClass* klass, const Il2CppClass* parent)
  103. {
  104. return Class::HasParent(const_cast<Il2CppClass*>(klass), const_cast<Il2CppClass*>(parent));
  105. }
  106. const VirtualInvokeData* ClassInlines::GetInterfaceInvokeDataFromVTable(Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot)
  107. {
  108. IL2CPP_ASSERT(slot < itf->method_count);
  109. //quick pass
  110. if (klass->interfaceOffsets != NULL) {
  111. for (uint16_t i = 0; i < klass->interface_offsets_count; i++)
  112. {
  113. if (klass->interfaceOffsets[i].interfaceType == itf)
  114. {
  115. int32_t offset = klass->interfaceOffsets[i].offset;
  116. IL2CPP_ASSERT(offset != -1);
  117. IL2CPP_ASSERT(offset + slot < klass->vtable_count);
  118. if (klass->vtable[offset + slot].method != NULL)
  119. return &(klass->vtable[offset + slot]);
  120. }
  121. }
  122. }
  123. const VirtualInvokeData* data = Class::GetOrSetupOneVTableSlot(klass, itf, slot);
  124. if (data)
  125. return data;
  126. return GetInterfaceInvokeDataFromVTableSlowPath(klass, itf, slot);
  127. }
  128. }
  129. }