123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include "ClassInlines.h"
- #include "vm/Class.h"
- #include "vm/Exception.h"
- #include "vm/Method.h"
- #include "vm/RCW.h"
- #include "gc/GCHandle.h"
- #include "metadata/GenericMethod.h"
- namespace il2cpp
- {
- namespace vm
- {
- Il2CppClass* ClassInlines::InitFromCodegenSlow(Il2CppClass *klass)
- {
- IL2CPP_ASSERT(klass != il2cpp_defaults.il2cpp_fully_shared_type);
- Class::Init(klass);
- if (klass->initializationExceptionGCHandle)
- il2cpp::vm::Exception::Raise((Il2CppException*)gc::GCHandle::GetTarget(klass->initializationExceptionGCHandle));
- return klass;
- }
- Il2CppClass* ClassInlines::InitFromCodegenSlow(Il2CppClass *klass, bool throwOnError)
- {
- IL2CPP_ASSERT(klass != il2cpp_defaults.il2cpp_fully_shared_type);
- if (throwOnError)
- return InitFromCodegenSlow(klass);
- Class::Init(klass);
- if (klass->initializationExceptionGCHandle)
- return NULL;
- return klass;
- }
- const MethodInfo* ClassInlines::InitRgctxFromCodegenSlow(const MethodInfo* method)
- {
- il2cpp::metadata::GenericMethod::InflateRGCTX(method);
- return method;
- }
- NORETURN static void RaiseExceptionForNotFoundInterface(const Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot)
- {
- std::string message;
- message = "Attempt to access method '" + Type::GetName(&itf->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL) + "." + Method::GetName(itf->methods[slot])
- + "' on type '" + Type::GetName(&klass->byval_arg, IL2CPP_TYPE_NAME_FORMAT_IL) + "' failed.";
- Exception::Raise(il2cpp::vm::Exception::GetMethodAccessException(message.c_str()));
- }
- const VirtualInvokeData* ClassInlines::GetInterfaceInvokeDataFromVTableSlowPath(const Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot)
- {
- if (itf->generic_class != NULL)
- {
- for (uint16_t i = 0; i < klass->interface_offsets_count; ++i)
- {
- const Il2CppRuntimeInterfaceOffsetPair* pair = klass->interfaceOffsets + i;
- if (Class::IsGenericClassAssignableFromVariance(itf, pair->interfaceType, klass))
- {
- IL2CPP_ASSERT(pair->offset + slot < klass->vtable_count);
- //return &klass->vtable[pair->offset + slot];
- return Class::GetOrSetupOneVTableSlot(const_cast<Il2CppClass*>(klass), NULL, pair->offset + slot);
- }
- }
- }
- return NULL;
- }
- const VirtualInvokeData& ClassInlines::GetInterfaceInvokeDataFromVTable(Il2CppObject* obj,const Il2CppClass* itf, Il2CppMethodSlot slot)
- {
- const VirtualInvokeData* result = GetInterfaceInvokeDataFromVTable(obj->klass,itf,slot);
- if (result)
- return *result;
- return GetInterfaceInvokeDataFromVTableSlowPath(obj,itf,slot);
- }
- const VirtualInvokeData& ClassInlines::GetInterfaceInvokeDataFromVTableSlowPath(Il2CppObject* obj, const Il2CppClass* itf, Il2CppMethodSlot slot)
- {
- const Il2CppClass* klass = obj->klass;
- const VirtualInvokeData* data;
- data = GetInterfaceInvokeDataFromVTableSlowPath(klass, itf, slot);
- if (data)
- return *data;
- #if !IL2CPP_TRIM_COM
- if (klass->is_import_or_windows_runtime)
- {
- Il2CppComObject* rcw = static_cast<Il2CppComObject*>(obj);
- // It might be null if it's called on a dead (already released) or fake object
- if (rcw->identity != NULL)
- {
- const VirtualInvokeData* invokeData = RCW::GetComInterfaceInvokeData(rcw, itf, slot);
- if (invokeData != NULL)
- {
- // Nothing will be referencing these types directly, so we need to initialize them here
- Class::Init(invokeData->method->klass);
- return *invokeData;
- }
- }
- }
- #endif
- RaiseExceptionForNotFoundInterface(klass, itf, slot);
- IL2CPP_UNREACHABLE;
- }
- const VirtualInvokeData& ClassInlines::GetVirtualInvokeData(Il2CppMethodSlot slot, const Il2CppObject* obj)
- {
- Assert(slot != kInvalidIl2CppMethodSlot && "MethodSlot is invalid!");
- //quick pass
- Il2CppClass* klass = obj->klass;
- if(slot < klass->vtable_count && klass->vtable[slot].method != NULL)
- return klass->vtable[slot];
- return *Class::GetOrSetupOneVTableSlot(obj->klass, NULL, slot);
- }
- bool ClassInlines::HasParent(const Il2CppClass* klass, const Il2CppClass* parent)
- {
- return Class::HasParent(const_cast<Il2CppClass*>(klass), const_cast<Il2CppClass*>(parent));
- }
- const VirtualInvokeData* ClassInlines::GetInterfaceInvokeDataFromVTable(Il2CppClass* klass, const Il2CppClass* itf, Il2CppMethodSlot slot)
- {
- IL2CPP_ASSERT(slot < itf->method_count);
- //quick pass
- if (klass->interfaceOffsets != NULL) {
- for (uint16_t i = 0; i < klass->interface_offsets_count; i++)
- {
- if (klass->interfaceOffsets[i].interfaceType == itf)
- {
- int32_t offset = klass->interfaceOffsets[i].offset;
- IL2CPP_ASSERT(offset != -1);
- IL2CPP_ASSERT(offset + slot < klass->vtable_count);
- if (klass->vtable[offset + slot].method != NULL)
- return &(klass->vtable[offset + slot]);
- }
- }
- }
- const VirtualInvokeData* data = Class::GetOrSetupOneVTableSlot(klass, itf, slot);
- if (data)
- return data;
- return GetInterfaceInvokeDataFromVTableSlowPath(klass, itf, slot);
- }
- }
- }
|