123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- #include "InterpreterModule.h"
- #include "Interpreter.h"
- #include <unordered_map>
- #include "vm/GlobalMetadata.h"
- #include "vm/MetadataCache.h"
- #include "vm/MetadataLock.h"
- #include "vm/Class.h"
- #include "vm/Object.h"
- #include "vm/Method.h"
- #include "../metadata/MetadataModule.h"
- #include "../metadata/MetadataUtil.h"
- #include "../metadata/InterpreterImage.h"
- #include "../transform/Transform.h"
- #include "MethodBridge.h"
- #include "InterpreterUtil.h"
- namespace hybridclr
- {
- namespace interpreter
- {
- il2cpp::os::ThreadLocalValue InterpreterModule::s_machineState;
- static Il2CppHashMap<const char*, Managed2NativeCallMethod, CStringHash, CStringEqualTo> g_managed2natives;
- static Il2CppHashMap<const char*, Il2CppMethodPointer, CStringHash, CStringEqualTo> g_native2manageds;
- static Il2CppHashMap<const char*, Il2CppMethodPointer, CStringHash, CStringEqualTo> g_adjustThunks;
- static Il2CppHashMap<const char*, const char*, CStringHash, CStringEqualTo> g_fullName2signature;
- MachineState& InterpreterModule::GetCurrentThreadMachineState()
- {
- MachineState* state = nullptr;
- s_machineState.GetValue((void**)&state);
- if (!state)
- {
- state = new MachineState();
- s_machineState.SetValue(state);
- }
- return *state;
- }
- void InterpreterModule::FreeThreadLocalMachineState()
- {
- MachineState* state = nullptr;
- s_machineState.GetValue((void**)&state);
- if (state)
- {
- delete state;
- s_machineState.SetValue(nullptr);
- }
- }
- void InterpreterModule::Initialize()
- {
- for (size_t i = 0; ; i++)
- {
- Managed2NativeMethodInfo& method = g_managed2nativeStub[i];
- if (!method.signature)
- {
- break;
- }
- g_managed2natives.insert({ method.signature, method.method });
- }
- for (size_t i = 0; ; i++)
- {
- Native2ManagedMethodInfo& method = g_native2managedStub[i];
- if (!method.signature)
- {
- break;
- }
- g_native2manageds.insert({ method.signature, method.method });
- }
- for (size_t i = 0; ; i++)
- {
- NativeAdjustThunkMethodInfo& method = g_adjustThunkStub[i];
- if (!method.signature)
- {
- break;
- }
- g_adjustThunks.insert({ method.signature, method.method });
- }
- for (size_t i = 0 ; ; i++)
- {
- FullName2Signature& nameSig = g_fullName2SignatureStub[i];
- if (!nameSig.fullName)
- {
- break;
- }
- g_fullName2signature.insert({ nameSig.fullName, nameSig.signature });
- }
- }
- void InterpreterModule::NotSupportNative2Managed()
- {
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException("NotSupportNative2Managed"));
- }
- void InterpreterModule::NotSupportAdjustorThunk()
- {
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException("NotSupportAdjustorThunk"));
- }
- const char* InterpreterModule::GetValueTypeSignature(const char* fullName)
- {
- auto it = g_fullName2signature.find(fullName);
- return it != g_fullName2signature.end() ? it->second : "$";
- }
- static void* NotSupportInvoke(Il2CppMethodPointer, const MethodInfo* method, void*, void**)
- {
- char sigName[1000];
- ComputeSignature(method, true, sigName, sizeof(sigName) - 1);
- TEMP_FORMAT(errMsg, "Invoke method missing. sinature:%s %s.%s::%s", sigName, method->klass->namespaze, method->klass->name, method->name);
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
- return nullptr;
- }
- template<typename T>
- const Managed2NativeCallMethod GetManaged2NativeMethod(const T* method, bool forceStatic)
- {
- char sigName[1000];
- ComputeSignature(method, !forceStatic, sigName, sizeof(sigName) - 1);
- auto it = g_managed2natives.find(sigName);
- return it != g_managed2natives.end() ? it->second : nullptr;
- }
- template<typename T>
- const Il2CppMethodPointer GetNative2ManagedMethod(const T* method, bool forceStatic)
- {
- char sigName[1000];
- ComputeSignature(method, !forceStatic, sigName, sizeof(sigName) - 1);
- auto it = g_native2manageds.find(sigName);
- return it != g_native2manageds.end() ? it->second : InterpreterModule::NotSupportNative2Managed;
- }
- template<typename T>
- const Il2CppMethodPointer GetNativeAdjustMethodMethod(const T* method, bool forceStatic)
- {
- char sigName[1000];
- ComputeSignature(method, !forceStatic, sigName, sizeof(sigName) - 1);
- auto it = g_adjustThunks.find(sigName);
- return it != g_adjustThunks.end() ? it->second : InterpreterModule::NotSupportAdjustorThunk;
- }
- static void RaiseMethodNotSupportException(const MethodInfo* method, const char* desc)
- {
- TEMP_FORMAT(errMsg, "%s. %s.%s::%s", desc, method->klass->namespaze, method->klass->name, method->name);
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
- }
- static void RaiseMethodNotSupportException(const Il2CppMethodDefinition* method, const char* desc)
- {
- Il2CppClass* klass = il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeDefinitionIndex(method->declaringType);
- TEMP_FORMAT(errMsg, "%s. %s.%s::%s", desc, klass->namespaze, klass->name, il2cpp::vm::GlobalMetadata::GetStringFromIndex(method->nameIndex));
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
- }
- Il2CppMethodPointer InterpreterModule::GetMethodPointer(const Il2CppMethodDefinition* method)
- {
- Il2CppMethodPointer ncm = GetNative2ManagedMethod(method, false);
- return ncm ? ncm : (Il2CppMethodPointer)NotSupportNative2Managed;
- }
- Il2CppMethodPointer InterpreterModule::GetMethodPointer(const MethodInfo* method)
- {
- Il2CppMethodPointer ncm = GetNative2ManagedMethod(method, false);
- return ncm ? ncm : (Il2CppMethodPointer)NotSupportNative2Managed;
- }
- Il2CppMethodPointer InterpreterModule::GetAdjustThunkMethodPointer(const Il2CppMethodDefinition* method)
- {
- return GetNativeAdjustMethodMethod(method, false);
- }
- Il2CppMethodPointer InterpreterModule::GetAdjustThunkMethodPointer(const MethodInfo* method)
- {
- return GetNativeAdjustMethodMethod(method, false);
- }
- void InterpreterModule::Managed2NativeCallByReflectionInvoke(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
- {
- if (hybridclr::metadata::IsInterpreterImplement(method))
- {
- Interpreter::Execute(method, localVarBase + argVarIndexs[0], ret);
- return;
- }
- if (method->invoker_method == nullptr)
- {
- char sigName[1000];
- ComputeSignature(method, true, sigName, sizeof(sigName) - 1);
- TEMP_FORMAT(errMsg, "GetManaged2NativeMethodPointer. sinature:%s not support.", sigName);
- RaiseMethodNotSupportException(method, errMsg);
- }
- if (!InitAndGetInterpreterDirectlyCallMethodPointer(method))
- {
- RaiseAOTGenericMethodNotInstantiatedException(method);
- }
- void* thisPtr;
- uint16_t* argVarIndexBase;
- if (hybridclr::metadata::IsInstanceMethod(method))
- {
- thisPtr = localVarBase[argVarIndexs[0]].obj;
- argVarIndexBase = argVarIndexs + 1;
- }
- else
- {
- thisPtr = nullptr;
- argVarIndexBase = argVarIndexs;
- }
- void* invokeParams[256];
- for (uint8_t i = 0; i < method->parameters_count; i++)
- {
- const Il2CppType* argType = GET_METHOD_PARAMETER_TYPE(method->parameters[i]);
- StackObject* argValue = localVarBase + argVarIndexBase[i];
- if (!argType->byref && hybridclr::metadata::IsValueType(argType))
- {
- invokeParams[i] = argValue;
- }
- else
- {
- invokeParams[i] = argValue->ptr;
- }
- }
- #if HYBRIDCLR_UNITY_2021_OR_NEW
- method->invoker_method(method->methodPointerCallByInterp, method, thisPtr, invokeParams, ret);
- #else
- void* retObj = method->invoker_method(method->methodPointerCallByInterp, method, thisPtr, invokeParams);
- if (ret)
- {
- const Il2CppType* returnType = method->return_type;
- if (hybridclr::metadata::IsValueType(returnType))
- {
- Il2CppClass* returnKlass = il2cpp::vm::Class::FromIl2CppType(returnType);
- if (il2cpp::vm::Class::IsNullable(returnKlass))
- {
- il2cpp::vm::Object::UnboxNullable((Il2CppObject*)retObj, returnKlass->element_class, ret);
- }
- else
- {
- std::memcpy(ret, il2cpp::vm::Object::Unbox((Il2CppObject*)retObj), il2cpp::vm::Class::GetValueSize(returnKlass, nullptr));
- }
- }
- else
- {
- *(void**)ret = retObj;
- }
- }
- #endif
- }
- Managed2NativeCallMethod InterpreterModule::GetManaged2NativeMethodPointer(const MethodInfo* method, bool forceStatic)
- {
- if (method->methodPointerCallByInterp == NotSupportNative2Managed
- #if HYBRIDCLR_UNITY_2021_OR_NEW
- || method->has_full_generic_sharing_signature
- #endif
- )
- {
- return Managed2NativeCallByReflectionInvoke;
- }
- char sigName[1000];
- ComputeSignature(method, !forceStatic, sigName, sizeof(sigName) - 1);
- auto it = g_managed2natives.find(sigName);
- return it != g_managed2natives.end() ? it->second : Managed2NativeCallByReflectionInvoke;
- }
- Managed2NativeCallMethod InterpreterModule::GetManaged2NativeMethodPointer(const metadata::ResolveStandAloneMethodSig& method)
- {
- char sigName[1000];
- ComputeSignature(&method.returnType, method.params, method.paramCount, metadata::IsPrologHasThis(method.flags), sigName, sizeof(sigName) - 1);
- auto it = g_managed2natives.find(sigName);
- return it != g_managed2natives.end() ? it->second : Managed2NativeCallByReflectionInvoke;
- }
- static void RaiseExecutionEngineExceptionMethodIsNotFound(const MethodInfo* method)
- {
- if (il2cpp::vm::Method::GetClass(method))
- RaiseExecutionEngineException(il2cpp::vm::Method::GetFullName(method).c_str());
- else
- RaiseExecutionEngineException(il2cpp::vm::Method::GetNameWithGenericTypes(method).c_str());
- }
- #ifdef HYBRIDCLR_UNITY_2021_OR_NEW
-
- static void InterpreterInvoke(Il2CppMethodPointer methodPointer, const MethodInfo* method, void* __this, void** __args, void* __ret)
- {
- InterpMethodInfo* imi = method->interpData ? (InterpMethodInfo*)method->interpData : InterpreterModule::GetInterpMethodInfo(method);
- bool isInstanceMethod = metadata::IsInstanceMethod(method);
- StackObject* args = (StackObject*)alloca(sizeof(StackObject) * imi->argStackObjectSize);
- if (isInstanceMethod)
- {
- if (IS_CLASS_VALUE_TYPE(method->klass))
- {
- __this = (Il2CppObject*)__this + (methodPointer != method->methodPointerCallByInterp);
- }
- args[0].ptr = __this;
- }
-
- MethodArgDesc* argDescs = imi->args + isInstanceMethod;
- ConvertInvokeArgs(args + isInstanceMethod, method, argDescs, __args);
- Interpreter::Execute(method, args, __ret);
- }
- static void InterpreterDelegateInvoke(Il2CppMethodPointer, const MethodInfo* method, void* __this, void** __args, void* __ret)
- {
- Il2CppMulticastDelegate* del = (Il2CppMulticastDelegate*)__this;
- Il2CppDelegate** firstSubDel;
- int32_t subDelCount;
- if (del->delegates)
- {
- firstSubDel = (Il2CppDelegate**)il2cpp::vm::Array::GetFirstElementAddress(del->delegates);
- subDelCount = il2cpp::vm::Array::GetLength(del->delegates);
- }
- else
- {
- firstSubDel = (Il2CppDelegate**)&del;
- subDelCount = 1;
- }
- for (int32_t i = 0; i < subDelCount; i++)
- {
- Il2CppDelegate* cur = firstSubDel[i];
- const MethodInfo* curMethod = cur->method;
- Il2CppObject* curTarget = cur->target;
- if (curMethod->invoker_method == nullptr)
- {
- RaiseExecutionEngineExceptionMethodIsNotFound(curMethod);
- }
- switch ((int)(method->parameters_count - curMethod->parameters_count))
- {
- case 0:
- {
- if (metadata::IsInstanceMethod(curMethod) && !curTarget)
- {
- il2cpp::vm::Exception::RaiseNullReferenceException();
- }
- curTarget += (IS_CLASS_VALUE_TYPE(curMethod->klass));
- curMethod->invoker_method(curMethod->methodPointerCallByInterp, curMethod, curTarget, __args, __ret);
- break;
- }
- case -1:
- {
- IL2CPP_ASSERT(!hybridclr::metadata::IsInstanceMethod(curMethod));
- void** newArgs = (void**)alloca(sizeof(void*) * (size_t)curMethod->parameters_count);
- newArgs[0] = curTarget;
- for (int k = 0, endK = curMethod->parameters_count; k < endK; k++)
- {
- newArgs[k + 1] = __args[k];
- }
- curMethod->invoker_method(curMethod->methodPointerCallByInterp, curMethod, nullptr, newArgs, __ret);
- break;
- }
- case 1:
- {
- IL2CPP_ASSERT(hybridclr::metadata::IsInstanceMethod(curMethod) && curMethod->parameters_count);
- curTarget = (Il2CppObject*)__args[0];
- if (!curTarget)
- {
- il2cpp::vm::Exception::RaiseNullReferenceException();
- }
- curMethod->invoker_method(curMethod->methodPointerCallByInterp, curMethod, curTarget, __args + 1, __ret);
- break;
- }
- default:
- {
- RaiseExecutionEngineException("bad delegate method");
- break;
- }
- }
- }
- }
- #else
- static void* InterpreterInvoke(Il2CppMethodPointer methodPointer, const MethodInfo* method, void* __this, void** __args)
- {
- StackObject args[256];
- bool isInstanceMethod = metadata::IsInstanceMethod(method);
- if (isInstanceMethod)
- {
- if (IS_CLASS_VALUE_TYPE(method->klass))
- {
- __this = (Il2CppObject*)__this + (methodPointer != method->methodPointerCallByInterp);
- }
- args[0].ptr = __this;
- }
- InterpMethodInfo* imi = method->interpData ? (InterpMethodInfo*)method->interpData : InterpreterModule::GetInterpMethodInfo(method);
- MethodArgDesc* argDescs = imi->args + isInstanceMethod;
- ConvertInvokeArgs(args + isInstanceMethod, method, argDescs, __args);
- if (method->return_type->type == IL2CPP_TYPE_VOID)
- {
- Interpreter::Execute(method, args, nullptr);
- return nullptr;
- }
- else
- {
- IL2CPP_ASSERT(GetTypeArgDesc(method->return_type).stackObjectSize <= hybridclr::metadata::kMaxRetValueTypeStackObjectSize);
- StackObject ret[hybridclr::metadata::kMaxRetValueTypeStackObjectSize];
- Interpreter::Execute(method, args, ret);
- return TranslateNativeValueToBoxValue(method->return_type, ret);
- }
- }
- static void* InterpreterDelegateInvoke(Il2CppMethodPointer, const MethodInfo* method, void* __this, void** __args)
- {
- Il2CppMulticastDelegate* del = (Il2CppMulticastDelegate*)__this;
- Il2CppDelegate** firstSubDel;
- int32_t subDelCount;
- if (del->delegates)
- {
- firstSubDel = (Il2CppDelegate**)il2cpp::vm::Array::GetFirstElementAddress(del->delegates);
- subDelCount = il2cpp::vm::Array::GetLength(del->delegates);
- }
- else
- {
- firstSubDel = (Il2CppDelegate**)&del;
- subDelCount = 1;
- }
- void* ret = nullptr;
- for (int32_t i = 0; i < subDelCount; i++)
- {
- Il2CppDelegate* cur = firstSubDel[i];
- const MethodInfo* curMethod = cur->method;
- Il2CppObject* curTarget = cur->target;
- if (curMethod->invoker_method == nullptr)
- {
- RaiseExecutionEngineExceptionMethodIsNotFound(curMethod);
- }
- switch ((int)(method->parameters_count - curMethod->parameters_count))
- {
- case 0:
- {
- if (metadata::IsInstanceMethod(curMethod) && !curTarget)
- {
- il2cpp::vm::Exception::RaiseNullReferenceException();
- }
- curTarget += (IS_CLASS_VALUE_TYPE(curMethod->klass));
- ret = curMethod->invoker_method(curMethod->methodPointerCallByInterp, curMethod, curTarget, __args);
- break;
- }
- case -1:
- {
- IL2CPP_ASSERT(!hybridclr::metadata::IsInstanceMethod(curMethod));
- void** newArgs = (void**)alloca(sizeof(void*) * (size_t)curMethod->parameters_count);
- newArgs[0] = curTarget;
- for (int k = 0, endK = curMethod->parameters_count; k < endK; k++)
- {
- newArgs[k + 1] = __args[k];
- }
- ret = curMethod->invoker_method(curMethod->methodPointerCallByInterp, curMethod, nullptr, newArgs);
- break;
- }
- case 1:
- {
- IL2CPP_ASSERT(hybridclr::metadata::IsInstanceMethod(curMethod) && curMethod->parameters_count);
- curTarget = (Il2CppObject*)__args[0];
- if (!curTarget)
- {
- il2cpp::vm::Exception::RaiseNullReferenceException();
- }
- ret = curMethod->invoker_method(curMethod->methodPointerCallByInterp, curMethod, curTarget, __args + 1);
- break;
- }
- default:
- {
- RaiseExecutionEngineException("bad delegate method");
- break;
- }
- }
- }
- return ret;
- }
- #endif
- InvokerMethod InterpreterModule::GetMethodInvoker(const Il2CppMethodDefinition* method)
- {
- Il2CppClass* klass = il2cpp::vm::GlobalMetadata::GetTypeInfoFromTypeDefinitionIndex(method->declaringType);
- const char* methodName = il2cpp::vm::GlobalMetadata::GetStringFromIndex(method->nameIndex);
-
- return !klass || !metadata::IsChildTypeOfMulticastDelegate(klass) || strcmp(methodName, "Invoke") ? InterpreterInvoke : InterpreterDelegateInvoke;
- }
- InvokerMethod InterpreterModule::GetMethodInvoker(const MethodInfo* method)
- {
- Il2CppClass* klass = method->klass;
- return !klass || !metadata::IsChildTypeOfMulticastDelegate(klass) || strcmp(method->name, "Invoke") ? InterpreterInvoke : InterpreterDelegateInvoke;
- }
- bool InterpreterModule::IsImplementsByInterpreter(const MethodInfo* method)
- {
- return method->invoker_method == InterpreterDelegateInvoke || method->invoker_method == InterpreterInvoke;
- }
- InterpMethodInfo* InterpreterModule::GetInterpMethodInfo(const MethodInfo* methodInfo)
- {
- RuntimeInitClassCCtor(methodInfo);
- il2cpp::os::FastAutoLock lock(&il2cpp::vm::g_MetadataLock);
- if (methodInfo->interpData)
- {
- return (InterpMethodInfo*)methodInfo->interpData;
- }
- IL2CPP_ASSERT(methodInfo->isInterpterImpl);
- metadata::Image* image = metadata::IsInterpreterMethod(methodInfo) ? hybridclr::metadata::MetadataModule::GetImage(methodInfo->klass)
- : (metadata::Image*)hybridclr::metadata::AOTHomologousImage::FindImageByAssembly(
- methodInfo->klass->rank ? il2cpp_defaults.corlib->assembly : methodInfo->klass->image->assembly);
- IL2CPP_ASSERT(image);
- metadata::MethodBody* methodBody = image->GetMethodBody(methodInfo->token);
- if (methodBody == nullptr || methodBody->ilcodes == nullptr)
- {
- TEMP_FORMAT(errMsg, "Method body is null. %s.%s::%s", methodInfo->klass->namespaze, methodInfo->klass->name, methodInfo->name);
- il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
- }
- InterpMethodInfo* imi = new (HYBRIDCLR_MALLOC_ZERO(sizeof(InterpMethodInfo))) InterpMethodInfo;
- transform::HiTransform::Transform(image, methodInfo, *methodBody, *imi);
- il2cpp::os::Atomic::FullMemoryBarrier();
- const_cast<MethodInfo*>(methodInfo)->interpData = imi;
- return imi;
- }
- }
- }
|