Skip to content

Commit

Permalink
[unity]消除il2cpp反射调用返回值为值类型的函数的gc
Browse files Browse the repository at this point in the history
  • Loading branch information
chexiongsheng committed Dec 27, 2024
1 parent 53d5c61 commit cdde98f
Show file tree
Hide file tree
Showing 2 changed files with 1,196 additions and 1,054 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -641,85 +641,89 @@ pesapi_value TryTranslateBuiltin(struct pesapi_ffi* apis, pesapi_env env, Il2Cpp
return nullptr;
}

static pesapi_value TryTranslatePrimitiveWithClass(struct pesapi_ffi* apis, pesapi_env env, Il2CppObject* obj, Il2CppClass *klass = nullptr)
static pesapi_value TryTranslatePrimitivePtr(struct pesapi_ffi* apis, pesapi_env env, Il2CppTypeEnum type, void* ptr)
{
if (obj)
switch (type)
{
const Il2CppType *type = Class::GetType(klass ? klass : obj->klass);
int t = type->type;
if (t == IL2CPP_TYPE_STRING)
case IL2CPP_TYPE_I1:
{
const Il2CppChar* utf16 = il2cpp::utils::StringUtils::GetChars((Il2CppString*)obj);
std::string str = il2cpp::utils::StringUtils::Utf16ToUtf8(utf16);
return apis->create_string_utf8(env, str.c_str(), str.size());
return apis->create_int32(env, (int32_t)(*((int8_t*)ptr)));
}
void* ptr = Object::Unbox(obj);
switch (t)
case IL2CPP_TYPE_BOOLEAN:
{
case IL2CPP_TYPE_I1:
{
return apis->create_int32(env, (int32_t)(*((int8_t*)ptr)));
}
case IL2CPP_TYPE_BOOLEAN:
{
return apis->create_boolean(env, (bool)(*((uint8_t*)ptr)));
}
case IL2CPP_TYPE_U1:
{
return apis->create_uint32(env, (uint32_t)(*((uint8_t*)ptr)));
}
case IL2CPP_TYPE_I2:
{
return apis->create_int32(env, (int32_t)(*((int16_t*)ptr)));
}
case IL2CPP_TYPE_U2:
{
return apis->create_uint32(env, (uint32_t)(*((uint16_t*)ptr)));
}
case IL2CPP_TYPE_CHAR:
{
return apis->create_int32(env, (int32_t)(*((Il2CppChar*)ptr)));
}
return apis->create_boolean(env, (bool)(*((uint8_t*)ptr)));
}
case IL2CPP_TYPE_U1:
{
return apis->create_uint32(env, (uint32_t)(*((uint8_t*)ptr)));
}
case IL2CPP_TYPE_I2:
{
return apis->create_int32(env, (int32_t)(*((int16_t*)ptr)));
}
case IL2CPP_TYPE_U2:
{
return apis->create_uint32(env, (uint32_t)(*((uint16_t*)ptr)));
}
case IL2CPP_TYPE_CHAR:
{
return apis->create_int32(env, (int32_t)(*((Il2CppChar*)ptr)));
}
#if IL2CPP_SIZEOF_VOID_P == 4
case IL2CPP_TYPE_I:
case IL2CPP_TYPE_I:
#endif
case IL2CPP_TYPE_I4:
{
return apis->create_int32(env, (int32_t)(*((int32_t*)ptr)));
}
case IL2CPP_TYPE_I4:
{
return apis->create_int32(env, (int32_t)(*((int32_t*)ptr)));
}
#if IL2CPP_SIZEOF_VOID_P == 4
case IL2CPP_TYPE_U:
case IL2CPP_TYPE_U:
#endif
case IL2CPP_TYPE_U4:
{
return apis->create_uint32(env, (uint32_t)(*((uint32_t*)ptr)));
}
case IL2CPP_TYPE_U4:
{
return apis->create_uint32(env, (uint32_t)(*((uint32_t*)ptr)));
}
#if IL2CPP_SIZEOF_VOID_P == 8
case IL2CPP_TYPE_I:
case IL2CPP_TYPE_I:
#endif
case IL2CPP_TYPE_I8:
{
return apis->create_int64(env, *((int64_t*)ptr));
}
case IL2CPP_TYPE_I8:
{
return apis->create_int64(env, *((int64_t*)ptr));
}
#if IL2CPP_SIZEOF_VOID_P == 8
case IL2CPP_TYPE_U:
case IL2CPP_TYPE_U:
#endif
case IL2CPP_TYPE_U8:
{
return apis->create_uint64(env, *((uint64_t*)ptr));
}
case IL2CPP_TYPE_R4:
{
return apis->create_double(env, (double)(*((float*)ptr)));
}
case IL2CPP_TYPE_R8:
{
return apis->create_double(env, *((double*)ptr));
}

default:
return nullptr;
case IL2CPP_TYPE_U8:
{
return apis->create_uint64(env, *((uint64_t*)ptr));
}
case IL2CPP_TYPE_R4:
{
return apis->create_double(env, (double)(*((float*)ptr)));
}
case IL2CPP_TYPE_R8:
{
return apis->create_double(env, *((double*)ptr));
}

default:
return nullptr;
}
}

static pesapi_value TryTranslatePrimitiveWithClass(struct pesapi_ffi* apis, pesapi_env env, Il2CppObject* obj, Il2CppClass *klass = nullptr)
{
if (obj)
{
const Il2CppType *type = Class::GetType(klass ? klass : obj->klass);
if (type->type == IL2CPP_TYPE_STRING)
{
const Il2CppChar* utf16 = il2cpp::utils::StringUtils::GetChars((Il2CppString*)obj);
std::string str = il2cpp::utils::StringUtils::Utf16ToUtf8(utf16);
return apis->create_string_utf8(env, str.c_str(), str.size());
}
void* ptr = Object::Unbox(obj);
return TryTranslatePrimitivePtr(apis, env, type->type, ptr);
}

return nullptr;
Expand Down Expand Up @@ -1082,6 +1086,60 @@ pesapi_value CSRefToJsValue(struct pesapi_ffi* apis, pesapi_env env, Il2CppClass
return apis->native_object_to_value(env, objClass, obj, false);
}

static bool NullableHasValue(Il2CppClass* klass, void* data)
{
uint8_t* hasValueByte = static_cast<uint8_t*>(data);
return *hasValueByte != 0;
}

pesapi_value CSValueTypePtrToJsValue(struct pesapi_ffi* apis, pesapi_env env, Il2CppClass* targetClass, void* ptr)
{
if (targetClass == il2cpp_defaults.void_class) return apis->create_undefined(env);
if (!ptr) return apis->create_null(env);

if (!targetClass)
{
targetClass = il2cpp_defaults.object_class;
}

bool isNullable = Class::IsNullable(targetClass);

if (isNullable)
{
if (!NullableHasValue(targetClass, ptr))
{
return apis->create_null(env);
}
uint8_t* valueStart = static_cast<uint8_t*>(ptr);
int32_t nullableShift = targetClass->fields[1].offset - sizeof(Il2CppObject);
valueStart += nullableShift;
ptr = valueStart;
}

if (Class::IsEnum(targetClass))
{
targetClass = Class::GetElementClass(targetClass);
}
const Il2CppType* type = Class::GetType(targetClass);

pesapi_value jsVal = TryTranslatePrimitivePtr(apis, env, type->type, ptr);

if (jsVal)
{
return jsVal;
}

auto len = targetClass->native_size;
if (len < 0)
{
len = targetClass->instance_size - sizeof(Il2CppObject);
}

auto buff = new uint8_t[len];
memcpy(buff, ptr, len);
return apis->native_object_to_value(env, targetClass, buff, true);
}

static bool GetValueTypeFromJs(struct pesapi_ffi* apis, pesapi_env env, pesapi_value jsValue, Il2CppClass* klass, void* storage)
{
bool hasValue = false;
Expand Down Expand Up @@ -1576,7 +1634,39 @@ handle_underlying:
}
}

Il2CppObject* ret = Runtime::InvokeWithThrow(method, self, args); //返回ValueType有boxing
//Il2CppObject* ret = Runtime::InvokeWithThrow(method, self, args); //返回ValueType有boxing
void* returnValue = NULL;
bool returnIsValueType = false;
Il2CppClass* returnType = Class::FromIl2CppType(method->return_type);
if (method->return_type->type == IL2CPP_TYPE_VOID)
{
method->invoker_method(method->methodPointer, method, self, args, NULL);
}
else
{
if (method->return_type->valuetype)
{
Class::Init(returnType);
returnValue = alloca(returnType->instance_size - sizeof(Il2CppObject));
method->invoker_method(method->methodPointer, method, self, args, returnValue);
returnIsValueType = true;
}
else
{
method->invoker_method(method->methodPointer, method, self, args, &returnValue);
if (method->return_type->byref)
{
if (Class::IsValuetype(returnType))
{
returnIsValueType = true;
}
else
{
returnValue = *(Il2CppObject**)returnValue;
}
}
}
}

for (int i = csArgStart; i < method->parameters_count; ++i)
{
Expand Down Expand Up @@ -1617,10 +1707,16 @@ handle_underlying:
}
}

auto returnType = Class::FromIl2CppType(method->return_type);
if (returnType != il2cpp_defaults.void_class)
if (method->return_type->type != IL2CPP_TYPE_VOID)
{
apis->add_return(info, CSRefToJsValue(apis, env, returnType, ret));
if (returnIsValueType)
{
apis->add_return(info, CSValueTypePtrToJsValue(apis, env, returnType, returnValue));
}
else
{
apis->add_return(info, CSRefToJsValue(apis, env, returnType, (Il2CppObject*)returnValue));
}
}

return true;
Expand Down
Loading

0 comments on commit cdde98f

Please sign in to comment.