From c2a8be7cb485de7b97141ddd6d055dc868a60fb3 Mon Sep 17 00:00:00 2001 From: Zhenlin Yang Date: Tue, 13 Jun 2023 22:56:22 +0800 Subject: [PATCH] Optimization for xlua_hotfix_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 背景:开发人员难以保证只对主线程执行的代码进行插桩,也难以保证在 xlua_set_hotfix_flag 的过程中时其他线程不执行到被插桩的代码。考虑到运行效率,加锁是不现实的。 做法:由于 xlua_set_hotfix_flag 的过程可以保证在单线程进行,在 xlua_set_hotfix_flag 时,保证其他线程可以安全执行 xlua_get_hotfix_flag 等方法是一种折中处理方式。 (1) xlua_hotfix_flags 和 DelegateBridge.DelegateBridgeList 的元素修改不是原子操作,需要避免xlua_get_hotfix_flag 返回 true 时 DelegateBridge.DelegateBridgeList[n] 取到NullReference。 (2) realloc(xlua_hotfix_flags, (idx + 1) * sizeof(int)) 执行后,原 xlua_hotfix_flags 内存空间已被释放,新申请的内存空间在之后才重新赋值给 xlua_hotfix_flags。此过程不是原子操作,在此过程中如果执行 xlua_get_hotfix_flag 会出现SIGSEGV。 (3) xlua_hotfix_flags 从 int 标记改为 bool 标记,节省内存使用。 --- Assets/Plugins/iOS/HotfixFlags.cpp | 68 +++++++++++++++++------------- Assets/XLua/Src/DelegateBridge.cs | 13 +++++- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/Assets/Plugins/iOS/HotfixFlags.cpp b/Assets/Plugins/iOS/HotfixFlags.cpp index 645149710..d84c8f9b1 100644 --- a/Assets/Plugins/iOS/HotfixFlags.cpp +++ b/Assets/Plugins/iOS/HotfixFlags.cpp @@ -1,37 +1,47 @@ #include #include +#include -int* xlua_hotfix_flags = NULL; +bool* xlua_hotfix_flags = NULL; int xlua_hotfix_flags_len = 0; -extern "C" { +extern "C" +{ + int xlua_get_hotfix_flag(int idx) + { + if (idx >= xlua_hotfix_flags_len) + { + return 0; + } + else + { + return xlua_hotfix_flags[idx]; + } + } -int xlua_get_hotfix_flag(int idx) { - if (idx >= xlua_hotfix_flags_len) { - return 0; - } else { - return xlua_hotfix_flags[idx]; - } -} + void xlua_set_hotfix_flag(int idx, int flag) + { + if (idx >= xlua_hotfix_flags_len) + { + bool* new_hotfix_flags = (bool*)malloc(idx + 1); -void xlua_set_hotfix_flag(int idx, int flag) { - int i = 0; - int* new_hotfix_flags = NULL; - if (idx >= xlua_hotfix_flags_len) { - if (xlua_hotfix_flags == NULL) { - xlua_hotfix_flags = (int*)malloc((idx + 1) * sizeof(int)); - } else { - new_hotfix_flags = (int*)realloc(xlua_hotfix_flags, (idx + 1) * sizeof(int)); - if (NULL == new_hotfix_flags) { // just skip operation - return; - } - xlua_hotfix_flags = new_hotfix_flags; - } - for(i = xlua_hotfix_flags_len; i < (idx + 1); i++) { - xlua_hotfix_flags[i] = 0; - } - xlua_hotfix_flags_len = idx + 1; - } - xlua_hotfix_flags[idx] = flag; -} + if (xlua_hotfix_flags == NULL) + { + memset(new_hotfix_flags, 0, (idx + 1)); + xlua_hotfix_flags = new_hotfix_flags; + } + else + { + memcpy(new_hotfix_flags, xlua_hotfix_flags, xlua_hotfix_flags_len); + memset(new_hotfix_flags + xlua_hotfix_flags_len, 0, (idx + 1 - xlua_hotfix_flags_len)); + bool* tmp = xlua_hotfix_flags; + xlua_hotfix_flags = new_hotfix_flags; + free(tmp); + } + + xlua_hotfix_flags_len = idx + 1; + } + + xlua_hotfix_flags[idx] = flag; + } } diff --git a/Assets/XLua/Src/DelegateBridge.cs b/Assets/XLua/Src/DelegateBridge.cs index c0e8eb0b1..900147291 100644 --- a/Assets/XLua/Src/DelegateBridge.cs +++ b/Assets/XLua/Src/DelegateBridge.cs @@ -116,10 +116,21 @@ public static void Set(int idx, DelegateBridge val) } DelegateBridge.DelegateBridgeList = newList; } + +#if (UNITY_IPHONE || UNITY_TVOS) && !UNITY_EDITOR + if (val == null) + { + xlua_set_hotfix_flag(idx, false); + } +#endif DelegateBridge.DelegateBridgeList[idx] = val; #if (UNITY_IPHONE || UNITY_TVOS) && !UNITY_EDITOR - xlua_set_hotfix_flag(idx, val != null); + if (val != null) + { + xlua_set_hotfix_flag(idx, true); + } #endif + } }