diff --git a/ets_environment/frameworks/ets_environment/BUILD.gn b/ets_environment/frameworks/ets_environment/BUILD.gn index fd6ab9040b0680de04e2e283b63fd3f19371a1ff..32cc779fb52836d7c206faa339cb8411df87faf7 100644 --- a/ets_environment/frameworks/ets_environment/BUILD.gn +++ b/ets_environment/frameworks/ets_environment/BUILD.gn @@ -54,6 +54,7 @@ ohos_shared_library("ets_environment") { "json:nlohmann_json_static", "napi:ace_napi", "runtime_core:ani", + "runtime_core:libarkruntime", ] if (ability_runtime_graphics) { diff --git a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp index 1a0e9bb2116fef5d6a10214a6c26e85551c5d489..8d2ae2b503da7a35d8c6055aed641deab6dcb46d 100644 --- a/ets_environment/frameworks/ets_environment/src/ets_environment.cpp +++ b/ets_environment/frameworks/ets_environment/src/ets_environment.cpp @@ -24,6 +24,13 @@ #include #include +#include "ets_ani_expo.h" +#ifdef LIKELY +#undef LIKELY +#endif +#ifdef UNLIKELY +#undef UNLIKELY +#endif #include "dynamic_loader.h" #include "elf_factory.h" #include "event_handler.h" @@ -206,7 +213,7 @@ void ETSEnvironment::InitETSSysNS(const std::string &path) dlns_inherit(&ns, &ndk, "allow_all_shared_libs"); } -bool ETSEnvironment::Initialize(void *napiEnv, const std::string &aotPath) +bool ETSEnvironment::Initialize() { TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called"); if (!LoadRuntimeApis()) { @@ -220,13 +227,6 @@ bool ETSEnvironment::Initialize(void *napiEnv, const std::string &aotPath) } std::vector options; - std::string aotPathString = ""; - if (!aotPath.empty()) { - aotPathString = "--ext:--aot-file=" + aotPath; - options.push_back(ani_option { aotPathString.data(), nullptr }); - options.push_back(ani_option { "--ext:--enable-an", nullptr }); - TAG_LOGD(AAFwkTag::ETSRUNTIME, "aotPathString: %{public}s", aotPathString.c_str()); - } // Create boot-panda-files options std::string bootString = "--ext:--boot-panda-files=" + bootfiles; options.push_back(ani_option { bootString.data(), nullptr }); @@ -235,7 +235,6 @@ bool ETSEnvironment::Initialize(void *napiEnv, const std::string &aotPath) options.push_back(ani_option { "--ext:--log-level=info", nullptr }); options.push_back(ani_option { "--ext:--verification-enabled=true", nullptr }); options.push_back(ani_option { "--ext:--verification-mode=on-the-fly", nullptr }); - options.push_back(ani_option { "--ext:interop", napiEnv }); ani_options optionsPtr = { options.size(), options.data() }; ani_status status = ANI_ERROR; if ((status = lazyApis_.ANI_CreateVM(&optionsPtr, ANI_VERSION_1, &vmEntry_.aniVm_)) != ANI_OK) { @@ -489,6 +488,36 @@ bool ETSEnvironment::LoadModule(const std::string &modulePath, const std::string return true; } +void ETSEnvironment::FinishPreload() { + ani_env *env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed: ANI env nullptr"); + return; + } + ark::ets::ETSAni::Prefork(env); +} + +void ETSEnvironment::PostFork(void *napiEnv, const std::string &aotPath) +{ + std::vector options; + std::string aotPathString = ""; + if (!aotPath.empty()) { + aotPathString = "--ext:--aot-file=" + aotPath; + options.push_back(ani_option { aotPathString.data(), nullptr }); + options.push_back(ani_option { "--ext:--enable-an", nullptr }); + TAG_LOGD(AAFwkTag::ETSRUNTIME, "aotPathString: %{public}s", aotPathString.c_str()); + } + + options.push_back(ani_option { "--ext:interop", napiEnv }); + + ani_env *env = GetAniEnv(); + if (env == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed: ANI env nullptr"); + return; + } + ark::ets::ETSAni::Postfork(env, options); +} + ETSEnvFuncs *ETSEnvironment::RegisterFuncs() { static ETSEnvFuncs funcs { @@ -498,8 +527,8 @@ ETSEnvFuncs *ETSEnvironment::RegisterFuncs() .InitETSSysNS = [](const std::string &path) { ETSEnvironment::InitETSSysNS(path); }, - .Initialize = [](void *napiEnv, const std::string &aotPath) { - return ETSEnvironment::GetInstance()->Initialize(napiEnv, aotPath); + .Initialize = []() { + return ETSEnvironment::GetInstance()->Initialize(); }, .RegisterUncaughtExceptionHandler = [](const ETSUncaughtExceptionInfo &exceptionInfo) { ETSEnvironment::GetInstance()->RegisterUncaughtExceptionHandler(exceptionInfo); @@ -513,6 +542,12 @@ ETSEnvFuncs *ETSEnvironment::RegisterFuncs() .LoadModule = [](const std::string &modulePath, const std::string &srcEntrance, void *&cls, void *&obj, void *&ref) { return ETSEnvironment::GetInstance()->LoadModule(modulePath, srcEntrance, cls, obj, ref); + }, + .FinishPreload = []() { + ETSEnvironment::GetInstance()->FinishPreload(); + }, + .PostFork = [](void *napiEnv, const std::string &aotPath) { + ETSEnvironment::GetInstance()->PostFork(napiEnv, aotPath); } }; return &funcs; diff --git a/ets_environment/interfaces/inner_api/ets_environment.h b/ets_environment/interfaces/inner_api/ets_environment.h index 267b7128341d85f4ec476fc7337af9321e8bad51..1baab9a72343998927a3b50feef62b6ee29f663e 100644 --- a/ets_environment/interfaces/inner_api/ets_environment.h +++ b/ets_environment/interfaces/inner_api/ets_environment.h @@ -50,13 +50,15 @@ public: static void InitETSSysNS(const std::string &path); static ETSEnvFuncs *RegisterFuncs(); - bool Initialize(void *napiEnv, const std::string &aotPath); + bool Initialize(); void RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle); ani_env *GetAniEnv(); bool HandleUncaughtError(); bool PreloadModule(const std::string &modulePath); bool LoadModule(const std::string &modulePath, const std::string &srcEntrance, void *&cls, void *&obj, void *&ref); + void FinishPreload(); + void PostFork(void *napiEnv, const std::string &aotPath); struct VMEntry { ani_vm *aniVm_; diff --git a/ets_environment/interfaces/inner_api/ets_interface.h b/ets_environment/interfaces/inner_api/ets_interface.h index e65ab84ec608909c6ecadd6283ee9dc8a4511dec..c9fa1d258aef70b468c62bd5053954b27f72f995 100644 --- a/ets_environment/interfaces/inner_api/ets_interface.h +++ b/ets_environment/interfaces/inner_api/ets_interface.h @@ -26,7 +26,7 @@ struct ETSEnvFuncs { void (*InitETSSDKNS)(const std::string &path) = nullptr; void (*InitETSSysNS)(const std::string &path) = nullptr; - bool (*Initialize)(void *napiEnv, const std::string &aotPath) = nullptr; + bool (*Initialize)() = nullptr; void (*RegisterUncaughtExceptionHandler)( const OHOS::EtsEnv::ETSUncaughtExceptionInfo &uncaughtExceptionInfo) = nullptr; ani_env *(*GetAniEnv)() = nullptr; @@ -34,6 +34,8 @@ struct ETSEnvFuncs { bool (*PreloadModule)(const std::string &modulePath) = nullptr; bool (*LoadModule)(const std::string &modulePath, const std::string &srcEntrance, void *&cls, void *&obj, void *&ref) = nullptr; + void (*FinishPreload)() = nullptr; + void (*PostFork)(void *napiEnv, const std::string &aotPath) = nullptr; }; } #endif // OHOS_ABILITY_RUNTIME_ETS_INTERFACE_H diff --git a/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp b/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp index d9f811de11ede58722f83e2ace8c0af771af6567..1d794e695334e2141e5c1555775d4cdb0a920046 100644 --- a/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp +++ b/ets_environment/test/unittest/ets_environment_test/ets_environment_test.cpp @@ -251,9 +251,7 @@ HWTEST_F(EtsEnvironmentTest, Initialize_0100, TestSize.Level0) { auto etsEnv = std::make_shared(); ASSERT_NE(etsEnv, nullptr); - void *napiEnv = reinterpret_cast(0x1); - std::string aotStr = ""; - bool result = etsEnv->Initialize(napiEnv, aotStr); + bool result = etsEnv->Initialize(); EXPECT_FALSE(result); } diff --git a/frameworks/native/runtime/ets_runtime.cpp b/frameworks/native/runtime/ets_runtime.cpp index cbc2a3854c834c149fe65159c214c25bb47192d8..d05858f18bc51b58a451e6f18460a63ba9c38a5f 100644 --- a/frameworks/native/runtime/ets_runtime.cpp +++ b/frameworks/native/runtime/ets_runtime.cpp @@ -200,35 +200,80 @@ bool RegisterETSEnvFuncs() } } // namespace +std::unique_ptr ETSRuntime::PreFork(const Options &options, std::unique_ptr &jsRuntime) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "PreFork begin"); + std::unique_ptr instance = std::make_unique(); + + if (!instance->Initialize(options, jsRuntime)) { + return std::unique_ptr(); + } + EntryPathManager::GetInstance().Init(); + return instance; +} + +void ETSRuntime::PostFork(const Options &options, std::unique_ptr &jsRuntime) +{ + TAG_LOGD(AAFwkTag::ETSRUNTIME, "PostFork begin"); + codePath_ = options.codePath; + + if (g_etsEnvFuncs == nullptr || + g_etsEnvFuncs->PostFork == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or PostFork"); + return; + } + + if (jsRuntime != nullptr) { + jsRuntime_ = std::move(jsRuntime); + } + if (jsRuntime_ != nullptr) { + auto vm = static_cast(jsRuntime_.get())->GetEcmaVm(); + panda::JSNApi::SetHostResolveBufferTrackerForHybridApp( + vm, HybridJsModuleReader(options.bundleName, options.hapPath, options.isUnique)); + } + + std::string aotFilePath = ""; + if (!options.arkNativeFilePath.empty()) { + aotFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath + options.moduleName + ".an"; + } + napi_env napiEnv = static_cast(jsRuntime_.get())->GetNapiEnv(); + g_etsEnvFuncs->PostFork(reinterpret_cast(napiEnv), aotFilePath); +} + std::unique_ptr ETSRuntime::Create(const Options &options, std::unique_ptr &jsRuntime) { TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create called"); + if (!RegisterETSEnvFuncs()) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "RegisterETSEnvFuncs failed"); + return std::unique_ptr(); + } + + if (g_etsEnvFuncs == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs"); + return std::unique_ptr(); + } + if (jsRuntime == nullptr) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "null jsRuntime"); return std::unique_ptr(); } std::unique_ptr instance; - if (!options.preload) { - auto preloadedInstance = Runtime::GetPreloaded(); + auto preloadedInstance = Runtime::GetPreloaded(Language::ETS); #ifdef SUPPORT_SCREEN - // reload ace if compatible mode changes - if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { - preloadedInstance.reset(); - } + // reload ace if compatible mode changes + if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { + preloadedInstance.reset(); + } #endif - if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::ETS) { - instance.reset(static_cast(preloadedInstance.release())); - } else { - instance = std::make_unique(); - } + if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::ETS) { + instance.reset(static_cast(preloadedInstance.release())); } else { - instance = std::make_unique(); + instance = PreFork(options, jsRuntime); } - if (!instance->Initialize(options, jsRuntime)) { - return std::unique_ptr(); + if (instance != nullptr && !options.preload) { + instance->PostFork(options, jsRuntime); } - EntryPathManager::GetInstance().Init(); return instance; } @@ -266,8 +311,10 @@ bool ETSRuntime::Initialize(const Options &options, std::unique_ptr & return false; } - jsRuntime_ = std::move(jsRuntime); - if (!CreateEtsEnv(options, jsRuntime_.get())) { + if (jsRuntime != nullptr) { + jsRuntime_ = std::move(jsRuntime); + } + if (!CreateEtsEnv(options)) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "CreateEtsEnv failed"); return false; } @@ -283,6 +330,20 @@ bool ETSRuntime::Initialize(const Options &options, std::unique_ptr & return true; } +void ETSRuntime::FinishPreload() +{ + if (jsRuntime_ != nullptr) { + jsRuntime_->FinishPreload(); + } + + if (g_etsEnvFuncs == nullptr || + g_etsEnvFuncs->FinishPreload == nullptr) { + TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or FinishPreload"); + return; + } + g_etsEnvFuncs->FinishPreload(); +} + void ETSRuntime::RegisterUncaughtExceptionHandler(const EtsEnv::ETSUncaughtExceptionInfo &uncaughtExceptionInfo) { if (g_etsEnvFuncs == nullptr || @@ -304,7 +365,7 @@ void ETSRuntime::Deinitialize() TAG_LOGD(AAFwkTag::ETSRUNTIME, "Deinitialize called"); } -bool ETSRuntime::CreateEtsEnv(const Options &options, Runtime *jsRuntime) +bool ETSRuntime::CreateEtsEnv(const Options &options) { TAG_LOGD(AAFwkTag::ETSRUNTIME, "CreateEtsEnv called"); if (g_etsEnvFuncs == nullptr || @@ -313,12 +374,7 @@ bool ETSRuntime::CreateEtsEnv(const Options &options, Runtime *jsRuntime) return false; } - std::string aotFilePath = ""; - if (!options.arkNativeFilePath.empty()) { - aotFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath + options.moduleName + ".an"; - } - napi_env napiEnv = static_cast(jsRuntime)->GetNapiEnv(); - if (!g_etsEnvFuncs->Initialize(reinterpret_cast(napiEnv), aotFilePath)) { + if (!g_etsEnvFuncs->Initialize()) { TAG_LOGE(AAFwkTag::ETSRUNTIME, "Initialize failed"); return false; } @@ -425,5 +481,17 @@ const std::unique_ptr &ETSRuntime::GetJsRuntime() const { return jsRuntime_; } + +std::unique_ptr ETSRuntime::MoveJsRuntime() +{ + return std::move(jsRuntime_); +} + +void ETSRuntime::PreloadSystemModule(const std::string &moduleName) +{ + if (jsRuntime_ != nullptr) { + jsRuntime_->PreloadSystemModule(moduleName); + } +} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp index 4e5eb21356d4598d8c2bffd2449c1452333c8611..e0df21d06e8bb2d179edca48b95cb783b6fdbecd 100644 --- a/frameworks/native/runtime/js_runtime.cpp +++ b/frameworks/native/runtime/js_runtime.cpp @@ -138,7 +138,7 @@ std::unique_ptr JsRuntime::Create(const Options& options) std::unique_ptr instance; JsRuntimeLite::InitJsRuntimeLite(options); if (!options.preload && options.isStageModel) { - auto preloadedInstance = Runtime::GetPreloaded(); + auto preloadedInstance = Runtime::GetPreloaded(Language::JS); #ifdef SUPPORT_SCREEN // reload ace if compatible mode changes if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) { diff --git a/frameworks/native/runtime/runtime.cpp b/frameworks/native/runtime/runtime.cpp index 4e2dba3f6d4c60931dc328f66a5951b4aee234aa..57d72e7412dc4a794ef6069cd4be67a4fbe7a2d7 100644 --- a/frameworks/native/runtime/runtime.cpp +++ b/frameworks/native/runtime/runtime.cpp @@ -50,7 +50,7 @@ std::unique_ptr Runtime::Create(Runtime::Options &options) } } -void Runtime::SavePreloaded(std::unique_ptr&& instance) +void Runtime::SavePreloaded(std::unique_ptr &&instance) { if (instance) { instance->FinishPreload(); @@ -58,8 +58,13 @@ void Runtime::SavePreloaded(std::unique_ptr&& instance) g_preloadedInstance = std::move(instance); } -std::unique_ptr Runtime::GetPreloaded() +std::unique_ptr Runtime::GetPreloaded(Language key) { + if (g_preloadedInstance && + g_preloadedInstance->GetLanguage() == Language::ETS && + key == Language::JS) { + return static_cast(g_preloadedInstance.get())->MoveJsRuntime(); + } return std::move(g_preloadedInstance); } } // namespace AbilityRuntime diff --git a/interfaces/inner_api/runtime/include/ets_runtime.h b/interfaces/inner_api/runtime/include/ets_runtime.h index 2b332eee8a3e45ffd233dcde20d3b1f52c0c6b25..e4626cd06072760e3d993a86a280f2c69fe59c85 100644 --- a/interfaces/inner_api/runtime/include/ets_runtime.h +++ b/interfaces/inner_api/runtime/include/ets_runtime.h @@ -58,14 +58,14 @@ public: void NotifyApplicationState(bool isBackground) override {} bool SuspendVM(uint32_t tid) override { return false; } void ResumeVM(uint32_t tid) override {} - void PreloadSystemModule(const std::string &moduleName) override {} + void PreloadSystemModule(const std::string &moduleName) override; void PreloadMainAbility(const std::string &moduleName, const std::string &srcPath, const std::string &hapPath, bool isEsMode, const std::string &srcEntrance) override {} void PreloadModule(const std::string &moduleName, const std::string &srcPath, const std::string &hapPath, bool isEsMode, bool useCommonTrunk) override {} void PreloadModule( const std::string &moduleName, const std::string &hapPath, bool isEsMode, bool useCommonTrunk) override; - void FinishPreload() override {} + void FinishPreload() override; bool LoadRepairPatch(const std::string &patchFile, const std::string &baseFile) override { return false; } bool NotifyHotReloadPage() override { return false; } bool UnLoadRepairPatch(const std::string &patchFile) override { return false; } @@ -87,13 +87,16 @@ public: bool useCommonChunk, const std::string &srcEntrance); bool HandleUncaughtError(); const std::unique_ptr &GetJsRuntime() const; + std::unique_ptr MoveJsRuntime(); + static std::unique_ptr PreFork(const Options &options, std::unique_ptr &jsRuntime); private: bool Initialize(const Options &options, std::unique_ptr &jsRuntime); void Deinitialize(); - bool CreateEtsEnv(const Options &options, Runtime *jsRuntime); + bool CreateEtsEnv(const Options &options); std::unique_ptr LoadEtsModule(const std::string &moduleName, const std::string &fileName, const std::string &hapPath, const std::string &srcEntrance); + void PostFork(const Options &options, std::unique_ptr &jsRuntime); int32_t apiTargetVersion_ = 0; std::string codePath_; std::string moduleName_; diff --git a/interfaces/inner_api/runtime/include/runtime.h b/interfaces/inner_api/runtime/include/runtime.h index 457106ae905d73728812cd8a2a3186d34adc9c92..c13823388bfc78ca93eb950ef32ddbd53fb9d02f 100644 --- a/interfaces/inner_api/runtime/include/runtime.h +++ b/interfaces/inner_api/runtime/include/runtime.h @@ -91,8 +91,8 @@ public: }; static std::unique_ptr Create(Options &options); - static void SavePreloaded(std::unique_ptr&& instance); - static std::unique_ptr GetPreloaded(); + static void SavePreloaded(std::unique_ptr &&instance); + static std::unique_ptr GetPreloaded(Language key); Runtime() = default; virtual ~Runtime() = default; diff --git a/test/unittest/frameworks_kits_ability_native_test/ability_runtime_test.cpp b/test/unittest/frameworks_kits_ability_native_test/ability_runtime_test.cpp index 38fb3b1bafbf0988ba913d5e4c49da9a0732dd21..7a18245839593272b4d31284f71a0d1d428a8084 100644 --- a/test/unittest/frameworks_kits_ability_native_test/ability_runtime_test.cpp +++ b/test/unittest/frameworks_kits_ability_native_test/ability_runtime_test.cpp @@ -108,7 +108,7 @@ HWTEST_F(RuntimeTest, GetPreloaded_0100, TestSize.Level2) std::unique_ptr runtime = std::make_unique(); auto instance = std::make_unique(); runtime->SavePreloaded(std::move(instance)); - EXPECT_TRUE(runtime->GetPreloaded() != nullptr); + EXPECT_TRUE(runtime->GetPreloaded(Runtime::Language::JS) != nullptr); GTEST_LOG_(INFO) << "RuntimeTest GetPreloaded_0100 end"; } diff --git a/test/unittest/runtime_test/BUILD.gn b/test/unittest/runtime_test/BUILD.gn index 99d92adbb8cb62ea7e84ae004b16ffe9f8af2fbf..e4f1504fa7338cfba09c11d13948606e57cbec80 100644 --- a/test/unittest/runtime_test/BUILD.gn +++ b/test/unittest/runtime_test/BUILD.gn @@ -300,6 +300,7 @@ ohos_unittest("ets_runtime_test") { "json:nlohmann_json_static", "napi:ace_napi", "runtime_core:ani", + "runtime_core:libarkruntime", ] if (ability_runtime_graphics) { diff --git a/test/unittest/runtime_test/js_runtime_test.cpp b/test/unittest/runtime_test/js_runtime_test.cpp index 18864eeb4f4145ea3ba6636f406604bf9cc5da53..e3bf5fcb6964909caf542259c5bf543f70830274 100755 --- a/test/unittest/runtime_test/js_runtime_test.cpp +++ b/test/unittest/runtime_test/js_runtime_test.cpp @@ -420,7 +420,7 @@ HWTEST_F(JsRuntimeTest, RuntimeSavePreloadedTest_0100, TestSize.Level1) TAG_LOGI(AAFwkTag::TEST, "SavePreloaded start"); Runtime::SavePreloaded(nullptr); - auto result = Runtime::GetPreloaded(); + auto result = Runtime::GetPreloaded(Runtime::Language::JS); EXPECT_EQ(result, nullptr); std::this_thread::sleep_for(std::chrono::milliseconds(200));