From 0c64722f961bb5ec241aa2808d9872db66ccf91f Mon Sep 17 00:00:00 2001 From: johnche Date: Fri, 11 Mar 2022 17:03:58 +0800 Subject: [PATCH] =?UTF-8?q?[unreal]=E4=BC=98=E5=8C=96=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BD=93/=E5=AE=B9=E5=99=A8=E6=8C=87=E9=92=88=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=9A=84=E6=80=A7=E8=83=BD=EF=BC=8Cfix=20https://gith?= =?UTF-8?q?ub.com/Tencent/puerts/issues/693?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Puerts/Source/JsEnv/Private/JsEnvImpl.cpp | 56 +++++++------------ .../Puerts/Source/JsEnv/Private/JsEnvImpl.h | 8 ++- .../Source/JsEnv/Private/ObjectMapper.h | 7 ++- .../JsEnv/Private/PropertyTranslator.cpp | 11 +++- .../Source/JsEnv/Private/PropertyTranslator.h | 2 + 5 files changed, 42 insertions(+), 42 deletions(-) diff --git a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp index 70aefa4819..78302a368a 100644 --- a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp +++ b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp @@ -792,28 +792,18 @@ FJsEnvImpl::~FJsEnvImpl() auto Isolate = MainIsolate; v8::Isolate::Scope IsolateScope(Isolate); v8::HandleScope HandleScope(Isolate); - for (auto Iter = ClassToTemplateMap.begin(); Iter != ClassToTemplateMap.end(); Iter++) - { - Iter->second.Reset(); - } + + ClassToTemplateMap.clear(); CppObjectMapper.UnInitialize(Isolate); - for (auto Iter = ObjectMap.begin(); Iter != ObjectMap.end(); Iter++) - { - Iter->second.Reset(); - } + ObjectMap.clear(); - for (auto Iter = GeneratedObjectMap.begin(); Iter != GeneratedObjectMap.end(); Iter++) - { - Iter->second.Reset(); - } GeneratedObjectMap.clear(); - for (auto Iter = StructMap.begin(); Iter != StructMap.end(); Iter++) - { - Iter->second.Reset(); - } + StructCache.clear(); + + ContainerCache.clear(); for (auto Iter = ScriptStructFinalizeInfoMap.begin(); Iter != ScriptStructFinalizeInfoMap.end(); Iter++) { @@ -1549,18 +1539,15 @@ v8::Local FJsEnvImpl::FindOrAdd(v8::Isolate* Isolate, v8::Local FJsEnvImpl::FindOrAddStruct( - v8::Isolate* Isolate, v8::Local& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) +v8::Local FJsEnvImpl::FindOrAddStruct(v8::Isolate* Isolate, v8::Local& Context, UScriptStruct* ScriptStruct, + void* Ptr, bool PassByPointer, bool ForceNoCache) { check(Ptr); // must not null - //查询历史记录,当初这么改是因为一个结构体如果其第一个成员也是结构体,这个结构体的指针将和这个第一个成员的指针值一样,导致访问该成员也会返回外层结构体 - //但问题是目前看,这部分是多余代码了,如果不是传指针才查,但不是传指针每次都是new堆内存,实际上是不可能查找到的,还是走到后面的逻辑 - //另外,这有没更好的解决办法呢?记录下ScriptStruct,如果类型不一致才new? - if (!PassByPointer) + if (LIKELY(!ForceNoCache)) // default: false { - auto Iter = StructMap.find(Ptr); - if (Iter != StructMap.end()) + auto Iter = StructCache.find(Ptr); + if (Iter != StructCache.end()) { return v8::Local::New(Isolate, Iter->second); } @@ -2405,13 +2392,10 @@ v8::Local FJsEnvImpl::FindOrAddContainer(v8::Isolate* Isolate, v8::Lo { check(Ptr); // must not null - if (!PassByPointer) + auto Iter = ContainerCache.find(Ptr); + if (Iter != ContainerCache.end()) { - auto Iter = StructMap.find(Ptr); - if (Iter != StructMap.end()) - { - return v8::Local::New(Isolate, Iter->second); - } + return v8::Local::New(Isolate, Iter->second); } auto BindTo = v8::External::New(Context->GetIsolate(), Ptr); @@ -2451,11 +2435,11 @@ void FJsEnvImpl::BindStruct( DataTransfer::SetPointer( MainIsolate, JSObject, static_cast(ScriptStructWrapper->Struct.Get()), 1); // add type info + StructCache[Ptr] = v8::UniquePersistent(MainIsolate, JSObject); if (!PassByPointer) { - StructMap[Ptr] = v8::UniquePersistent(MainIsolate, JSObject); ScriptStructFinalizeInfoMap[Ptr] = {ScriptStructWrapper->Struct, ScriptStructWrapper->ExternalFinalize}; - StructMap[Ptr].SetWeak( + StructCache[Ptr].SetWeak( ScriptStructWrapper, FScriptStructWrapper::OnGarbageCollectedWithFree, v8::WeakCallbackType::kInternalFields); } } @@ -2469,7 +2453,7 @@ void FJsEnvImpl::BindCppObject( void FJsEnvImpl::UnBindStruct(void* Ptr) { ScriptStructFinalizeInfoMap.erase(Ptr); - StructMap.erase(Ptr); + StructCache.erase(Ptr); } void FJsEnvImpl::UnBindCppObject(JSClassDefinition* ClassDefinition, void* Ptr) @@ -2480,13 +2464,13 @@ void FJsEnvImpl::UnBindCppObject(JSClassDefinition* ClassDefinition, void* Ptr) void FJsEnvImpl::BindContainer(void* Ptr, v8::Local JSObject, void (*Callback)(const v8::WeakCallbackInfo& data)) { DataTransfer::SetPointer(MainIsolate, JSObject, Ptr, 0); - StructMap[Ptr] = v8::UniquePersistent(MainIsolate, JSObject); - StructMap[Ptr].SetWeak(nullptr, Callback, v8::WeakCallbackType::kInternalFields); + ContainerCache[Ptr] = v8::UniquePersistent(MainIsolate, JSObject); + ContainerCache[Ptr].SetWeak(nullptr, Callback, v8::WeakCallbackType::kInternalFields); } void FJsEnvImpl::UnBindContainer(void* Ptr) { - StructMap.erase(Ptr); + ContainerCache.erase(Ptr); } std::shared_ptr FJsEnvImpl::GetStructWrapper(UStruct* InStruct) diff --git a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h index 6959a845cb..827d63edd7 100644 --- a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h +++ b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h @@ -120,8 +120,8 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD virtual void UnBindCppObject(JSClassDefinition* ClassDefinition, void* Ptr) override; - virtual v8::Local FindOrAddStruct( - v8::Isolate* Isolate, v8::Local& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) override; + virtual v8::Local FindOrAddStruct(v8::Isolate* Isolate, v8::Local& Context, UScriptStruct* ScriptStruct, + void* Ptr, bool PassByPointer, bool ForceNoCache) override; virtual void BindCppObject(v8::Isolate* InIsolate, JSClassDefinition* ClassDefinition, void* Ptr, v8::Local JSObject, bool PassByPointer) override; @@ -468,7 +468,9 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD std::map> ObjectMap; std::map> GeneratedObjectMap; - std::map> StructMap; + std::map> StructCache; + + std::map> ContainerCache; FCppObjectMapper CppObjectMapper; diff --git a/unreal/Puerts/Source/JsEnv/Private/ObjectMapper.h b/unreal/Puerts/Source/JsEnv/Private/ObjectMapper.h index ca3698ef93..268db63b01 100644 --- a/unreal/Puerts/Source/JsEnv/Private/ObjectMapper.h +++ b/unreal/Puerts/Source/JsEnv/Private/ObjectMapper.h @@ -55,8 +55,11 @@ class IObjectMapper : public ICppObjectMapper virtual void UnBindStruct(void* Ptr) = 0; - virtual v8::Local FindOrAddStruct( - v8::Isolate* Isolate, v8::Local& Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer) = 0; + // PassByPointer为false代表需要在js对象释放时,free相应的内存 + // ForceNoCache强制别cache,在结构体嵌套时,第一个成员为结构体时,可强制别cache + // 相关信息见该issue:https://github.com/Tencent/puerts/issues/693 + virtual v8::Local FindOrAddStruct(v8::Isolate* Isolate, v8::Local& Context, UScriptStruct* ScriptStruct, + void* Ptr, bool PassByPointer, bool ForceNoCache = false) = 0; virtual void Merge( v8::Isolate* Isolate, v8::Local Context, v8::Local Src, UStruct* DesType, void* Des) = 0; diff --git a/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.cpp b/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.cpp index 9b09aeb124..fc6a35ee12 100644 --- a/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.cpp +++ b/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.cpp @@ -553,6 +553,15 @@ class FScriptStructPropertyTranslator : public FPropertyWithDestructorReflection { ParamShallowCopySize = StructProperty->Struct->GetStructureSize(); } +#if ENGINE_MINOR_VERSION >= 25 || ENGINE_MAJOR_VERSION > 4 + auto Owner = Property->GetOwnerUObject(); +#else + auto Owner = Property->GetOuter(); +#endif + if (Owner && Owner->IsA() && Property->GetOffset_ForInternal() == 0) + { + ForceNoCache = true; + } } v8::Local UEToJs( @@ -569,7 +578,7 @@ class FScriptStructPropertyTranslator : public FPropertyWithDestructorReflection StructProperty->CopySingleValue(Ptr, ValuePtr); } return FV8Utils::IsolateData(Isolate)->FindOrAddStruct( - Isolate, Context, StructProperty->Struct, Ptr, PassByPointer); + Isolate, Context, StructProperty->Struct, Ptr, PassByPointer, ForceNoCache); } bool JsToUE(v8::Isolate* Isolate, v8::Local& Context, const v8::Local& Value, void* ValuePtr, diff --git a/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.h b/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.h index b604b84d10..b928554a46 100644 --- a/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.h +++ b/unreal/Puerts/Source/JsEnv/Private/PropertyTranslator.h @@ -133,6 +133,8 @@ class FPropertyTranslator std::unique_ptr Inner; + bool ForceNoCache = false; + static void Getter(const v8::FunctionCallbackInfo& Info); void Getter(v8::Isolate* Isolate, v8::Local& Context, const v8::FunctionCallbackInfo& Info);