【归一化】JSEnvironment提供统一线程环境能力及Stage模型适配

Signed-off-by: 杨亮 <yangliang36@huawei.com>
Change-Id: Ie85015c1dc1f7f60ccc35e95f82d3a5a3cba6ff0
This commit is contained in:
杨亮 2023-05-28 18:52:06 +08:00
parent 1fab291fc6
commit 1a43506160
12 changed files with 214 additions and 134 deletions

View File

@ -28,7 +28,6 @@
#include "constants.h"
#include "connect_server_manager.h"
#include "ecmascript/napi/include/jsnapi.h"
#include "event_handler.h"
#include "extract_resource_manager.h"
#include "file_path_utils.h"
#include "hdc_register.h"
@ -74,7 +73,6 @@ constexpr char ARK_DEBUGGER_LIB_PATH[] = "/system/lib/libark_debugger.z.so";
constexpr char ARK_DEBUGGER_LIB_PATH[] = "/system/lib64/libark_debugger.z.so";
#endif
constexpr char TIMER_TASK[] = "uv_timer_task";
constexpr char MERGE_ABC_PATH[] = "/ets/modules.abc";
constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
constexpr const char* PERMISSION_RUN_ANY_CODE = "ohos.permission.RUN_ANY_CODE";
@ -123,73 +121,6 @@ void InitSyscapModule(NativeEngine& engine, NativeObject& globalObject)
BindNativeFunction(engine, globalObject, "canIUse", moduleName, CanIUse);
}
class UvLoopHandler : public AppExecFwk::FileDescriptorListener, public std::enable_shared_from_this<UvLoopHandler> {
public:
explicit UvLoopHandler(uv_loop_t* uvLoop) : uvLoop_(uvLoop) {}
void OnReadable(int32_t) override
{
HILOG_DEBUG("UvLoopHandler::OnReadable is triggered");
OnTriggered();
}
void OnWritable(int32_t) override
{
HILOG_DEBUG("UvLoopHandler::OnWritable is triggered");
OnTriggered();
}
private:
void OnTriggered()
{
HILOG_DEBUG("UvLoopHandler::OnTriggered is triggered");
auto fd = uv_backend_fd(uvLoop_);
struct epoll_event ev;
do {
uv_run(uvLoop_, UV_RUN_NOWAIT);
} while (epoll_wait(fd, &ev, 1, 0) > 0);
auto eventHandler = GetOwner();
if (!eventHandler) {
return;
}
int32_t timeout = uv_backend_timeout(uvLoop_);
if (timeout < 0) {
if (haveTimerTask_) {
eventHandler->RemoveTask(TIMER_TASK);
}
return;
}
int64_t timeStamp = static_cast<int64_t>(uv_now(uvLoop_)) + timeout;
if (timeStamp == lastTimeStamp_) {
return;
}
if (haveTimerTask_) {
eventHandler->RemoveTask(TIMER_TASK);
}
auto callback = [wp = weak_from_this()] {
auto sp = wp.lock();
if (sp) {
// Timer task is triggered, so there is no timer task now.
sp->haveTimerTask_ = false;
sp->OnTriggered();
}
};
eventHandler->PostTask(callback, TIMER_TASK, timeout);
lastTimeStamp_ = timeStamp;
haveTimerTask_ = true;
}
uv_loop_t* uvLoop_ = nullptr;
int64_t lastTimeStamp_ = 0;
bool haveTimerTask_ = false;
};
int32_t PrintVmLog(int32_t, int32_t, const char*, const char*, const char* message)
{
HILOG_INFO("ArkLog: %{public}s", message);
@ -239,15 +170,15 @@ void JsRuntime::StartDebugMode(bool needBreakPoint)
HILOG_INFO("Already in debug mode");
return;
}
CHECK_POINTER(jsEnv_);
// Set instance id to tid after the first instance.
if (JsRuntime::hasInstance.exchange(true, std::memory_order_relaxed)) {
instanceId_ = static_cast<uint32_t>(gettid());
}
HILOG_INFO("Ark VM is starting debug mode [%{public}s]", needBreakPoint ? "break" : "normal");
auto debuggerPostTask = [eventHandler = eventHandler_](std::function<void()>&& task) {
eventHandler->PostTask(task);
auto debuggerPostTask = [jsEnv = jsEnv_](std::function<void()>&& task) {
jsEnv->PostTask(task);
};
StartDebuggerInWorkerModule();
HdcRegister::Get().StartHdcRegister(bundleName_);
@ -610,25 +541,8 @@ void JsRuntime::PreloadAce(const Options& options)
bool JsRuntime::InitLoop(const std::shared_ptr<AppExecFwk::EventRunner>& eventRunner)
{
auto nativeEngine = GetNativeEnginePointer();
CHECK_POINTER_AND_RETURN(nativeEngine, false);
// Create event handler for runtime
eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(eventRunner);
auto uvLoop = nativeEngine->GetUVLoop();
auto fd = uvLoop != nullptr ? uv_backend_fd(uvLoop) : -1;
if (fd < 0) {
HILOG_ERROR("Failed to get backend fd from uv loop");
return false;
}
// MUST run uv loop once before we listen its backend fd.
uv_run(uvLoop, UV_RUN_NOWAIT);
uint32_t events = AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT | AppExecFwk::FILE_DESCRIPTOR_OUTPUT_EVENT;
eventHandler_->AddFileDescriptorListener(fd, events, std::make_shared<UvLoopHandler>(uvLoop));
return true;
CHECK_POINTER_AND_RETURN(jsEnv_, false);
return jsEnv_->InitLoop(eventRunner);
}
void JsRuntime::SetAppLibPath(const AppLibPathMap& appLibPaths, const bool& isSystemApp)
@ -667,15 +581,9 @@ void JsRuntime::Deinitialize()
}
methodRequireNapiRef_.reset();
auto nativeEngine = GetNativeEnginePointer();
CHECK_POINTER(nativeEngine);
auto uvLoop = nativeEngine->GetUVLoop();
auto fd = uvLoop != nullptr ? uv_backend_fd(uvLoop) : -1;
if (fd >= 0 && eventHandler_ != nullptr) {
eventHandler_->RemoveFileDescriptorListener(fd);
}
RemoveTask(TIMER_TASK);
CHECK_POINTER(jsEnv_);
jsEnv_->DeInitLoop();
}
NativeValue* JsRuntime::LoadJsBundle(const std::string& path, const std::string& hapPath, bool useCommonChunk)
@ -900,16 +808,14 @@ bool JsRuntime::RunSandboxScript(const std::string& path, const std::string& hap
void JsRuntime::PostTask(const std::function<void()>& task, const std::string& name, int64_t delayTime)
{
if (eventHandler_ != nullptr) {
eventHandler_->PostTask(task, name, delayTime);
}
CHECK_POINTER(jsEnv_);
jsEnv_->PostTask(task, name, delayTime);
}
void JsRuntime::RemoveTask(const std::string& name)
{
if (eventHandler_ != nullptr) {
eventHandler_->RemoveTask(name);
}
CHECK_POINTER(jsEnv_);
jsEnv_->RemoveTask(name);
}
void JsRuntime::DumpHeapSnapshot(bool isPrivate)

View File

@ -14,6 +14,7 @@
*/
#include "ohos_js_environment_impl.h"
#include "ohos_loop_handler.h"
#include "commonlibrary/ets_utils/js_sys_module/console/console.h"
#include "commonlibrary/ets_utils/js_sys_module/timer/timer.h"
#include "hilog_wrapper.h"
@ -37,11 +38,17 @@ OHOSJsEnvironmentImpl::~OHOSJsEnvironmentImpl()
void OHOSJsEnvironmentImpl::PostTask(const std::function<void()>& task, const std::string& name, int64_t delayTime)
{
HILOG_DEBUG("called");
if (eventHandler_ != nullptr) {
eventHandler_->PostTask(task, name, delayTime);
}
}
void OHOSJsEnvironmentImpl::RemoveTask(const std::string& name)
{
HILOG_DEBUG("called");
if (eventHandler_ != nullptr) {
eventHandler_->RemoveTask(name);
}
}
void OHOSJsEnvironmentImpl::InitTimerModule(NativeEngine* engine)
@ -56,12 +63,39 @@ void OHOSJsEnvironmentImpl::InitTimerModule(NativeEngine* engine)
JsSysModule::Timer::RegisterTime(reinterpret_cast<napi_env>(engine));
}
void OHOSJsEnvironmentImpl::InitConsoleModule(NativeEngine *engine)
void OHOSJsEnvironmentImpl::InitConsoleModule(NativeEngine* engine)
{
HILOG_DEBUG("called");
JsSysModule::Console::InitConsoleModule(reinterpret_cast<napi_env>(engine));
}
bool OHOSJsEnvironmentImpl::InitLoop(NativeEngine* engine, const std::shared_ptr<AppExecFwk::EventRunner>& eventRunner)
{
HILOG_DEBUG("called");
eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(eventRunner);
auto uvLoop = engine->GetUVLoop();
auto fd = uvLoop != nullptr ? uv_backend_fd(uvLoop) : -1;
if (fd < 0) {
HILOG_ERROR("Failed to get backend fd from uv loop");
return false;
}
uv_run(uvLoop, UV_RUN_NOWAIT);
uint32_t events = AppExecFwk::FILE_DESCRIPTOR_INPUT_EVENT | AppExecFwk::FILE_DESCRIPTOR_OUTPUT_EVENT;
eventHandler_->AddFileDescriptorListener(fd, events, std::make_shared<OHOSLoopHandler>(uvLoop));
return true;
}
void OHOSJsEnvironmentImpl::DeInitLoop(NativeEngine* engine)
{
auto uvLoop = engine->GetUVLoop();
auto fd = uvLoop != nullptr ? uv_backend_fd(uvLoop) : -1;
if (fd >= 0 && eventHandler_ != nullptr) {
eventHandler_->RemoveFileDescriptorListener(fd);
}
RemoveTask(TIMER_TASK);
}
void OHOSJsEnvironmentImpl::InitWorkerModule(NativeEngine& engine, const std::string& codePath,
bool isDebugVersion, bool isBundle)
{

View File

@ -31,12 +31,19 @@ public:
void InitTimerModule(NativeEngine* engine) override;
void InitConsoleModule(NativeEngine *engine) override;
void InitConsoleModule(NativeEngine* engine) override;
bool InitLoop(NativeEngine* engine, const std::shared_ptr<AppExecFwk::EventRunner>& eventRunner) override;
void DeInitLoop(NativeEngine* engine) override;
void InitWorkerModule(NativeEngine& engine, const std::string& codePath, bool isDebugVersion,
bool isBundle) override;
void InitSyscapModule() override;
private:
std::shared_ptr<AppExecFwk::EventHandler> eventHandler_;
};
} // namespace AbilityRuntime
} // namespace OHOS

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ohos_loop_handler.h"
namespace OHOS {
namespace AbilityRuntime {
void OHOSLoopHandler::OnReadable(int32_t)
{
HILOG_DEBUG("OHOSLoopHandler::OnReadable is triggered");
OnTriggered();
}
void OHOSLoopHandler::OnWritable(int32_t)
{
HILOG_DEBUG("OHOSLoopHandler::OnWritable is triggered");
OnTriggered();
}
void OHOSLoopHandler::OnTriggered()
{
HILOG_DEBUG("OHOSLoopHandler::OnTriggered is triggered");
auto fd = uv_backend_fd(uvLoop_);
struct epoll_event ev;
do {
uv_run(uvLoop_, UV_RUN_NOWAIT);
} while (epoll_wait(fd, &ev, 1, 0) > 0);
auto eventHandler = GetOwner();
if (!eventHandler) {
return;
}
int32_t timeout = uv_backend_timeout(uvLoop_);
if (timeout < 0) {
if (haveTimerTask_) {
eventHandler->RemoveTask(TIMER_TASK);
}
return;
}
int64_t timeStamp = static_cast<int64_t>(uv_now(uvLoop_)) + timeout;
if (timeStamp == lastTimeStamp_) {
return;
}
if (haveTimerTask_) {
eventHandler->RemoveTask(TIMER_TASK);
}
auto callback = [wp = weak_from_this()] {
auto sp = wp.lock();
if (sp) {
// Timer task is triggered, so there is no timer task now.
sp->haveTimerTask_ = false;
sp->OnTriggered();
}
};
eventHandler->PostTask(callback, TIMER_TASK, timeout);
lastTimeStamp_ = timeStamp;
haveTimerTask_ = true;
}
} // namespace AbilityRuntime
} // namespace OHOS

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_ABILITY_RUNTIME_OHOS_LOOP_HANDLER_H
#define OHOS_ABILITY_RUNTIME_OHOS_LOOP_HANDLER_H
#include <sys/epoll.h>
#include "event_handler.h"
#include "hilog_wrapper.h"
#include "native_engine/native_engine.h"
namespace OHOS {
namespace AbilityRuntime {
constexpr char TIMER_TASK[] = "uv_timer_task";
class OHOSLoopHandler : public AppExecFwk::FileDescriptorListener,
public std::enable_shared_from_this<OHOSLoopHandler> {
public:
explicit OHOSLoopHandler(uv_loop_t* uvLoop) : uvLoop_(uvLoop) {}
void OnReadable(int32_t) override;
void OnWritable(int32_t) override;
private:
void OnTriggered();
private:
uv_loop_t* uvLoop_ = nullptr;
int64_t lastTimeStamp_ = 0;
bool haveTimerTask_ = false;
};
} // namespace AbilityRuntime
} // namespace OHOS
#endif // OHOS_ABILITY_RUNTIME_OHOS_LOOP_HANDLER_H

View File

@ -62,6 +62,7 @@ ohos_shared_library("runtime") {
"${ability_runtime_native_path}/runtime/js_worker.cpp",
"${ability_runtime_native_path}/runtime/ohos_js_env_logger.cpp",
"${ability_runtime_native_path}/runtime/ohos_js_environment_impl.cpp",
"${ability_runtime_native_path}/runtime/ohos_loop_handler.cpp",
"${ability_runtime_native_path}/runtime/runtime.cpp",
]

View File

@ -131,7 +131,6 @@ private:
std::string codePath_;
std::string moduleName_;
std::unique_ptr<NativeReference> methodRequireNapiRef_;
std::shared_ptr<AppExecFwk::EventHandler> eventHandler_;
std::unordered_map<std::string, NativeReference*> modules_;
std::shared_ptr<JsEnv::JsEnvironment> jsEnv_ = nullptr;
uint32_t instanceId_ = 0;

View File

@ -43,6 +43,7 @@ ohos_shared_library("js_environment") {
external_deps = [
"ets_runtime:libark_jsruntime",
"ets_utils:console",
"eventhandler:libeventhandler",
"napi:ace_napi",
"napi:ace_napi_ark",
]

View File

@ -165,6 +165,31 @@ void JsEnvironment::InitConsoleModule()
}
}
bool JsEnvironment::InitLoop(const std::shared_ptr<AppExecFwk::EventRunner>& eventRunner)
{
if (engine_ == nullptr) {
JSENV_LOG_E("Invalid Native Engine.");
return false;
}
if (impl_ != nullptr) {
impl_->InitLoop(engine_, eventRunner);
}
return true;
}
void JsEnvironment::DeInitLoop()
{
if (engine_ == nullptr) {
JSENV_LOG_E("Invalid Native Engine.");
return;
}
if (impl_ != nullptr) {
impl_->DeInitLoop(engine_);
}
}
bool JsEnvironment::LoadScript(const std::string& path, uint8_t *buffer, size_t len, bool isBundle)
{
return engine_->RunScriptBuffer(path.c_str(), buffer, len, isBundle);

View File

@ -46,15 +46,13 @@ public:
void InitTimerModule();
void InitConsoleLogModule();
void InitWorkerModule(const std::string& codePath, bool isDebugVersion, bool isBundle);
void InitSourceMap(const std::shared_ptr<JsEnv::SourceMapOperator> operatorObj);
void InitSyscapModule();
void PostTask(const std::function<void()>& task, const std::string& name, int64_t delayTime);
void PostTask(const std::function<void()>& task, const std::string& name = "", int64_t delayTime = 0);
void RemoveTask(const std::string& name);
@ -66,6 +64,10 @@ public:
void InitConsoleModule();
bool InitLoop(const std::shared_ptr<AppExecFwk::EventRunner>& eventRunner);
void DeInitLoop();
void StopDebugger();
bool LoadScript(const std::string& path, uint8_t *buffer, size_t len, bool isBundle);

View File

@ -17,6 +17,7 @@
#define OHOS_ABILITY_JS_ENVIRONMENT_JS_ENVIRONMENT_IMPL_H
#include <string>
#include "event_handler.h"
#include "native_engine/native_engine.h"
#include "native_engine/native_engine.h"
@ -36,6 +37,10 @@ public:
virtual void InitConsoleModule(NativeEngine *engine) = 0;
virtual bool InitLoop(NativeEngine *engine, const std::shared_ptr<AppExecFwk::EventRunner>& eventRunner) = 0;
virtual void DeInitLoop(NativeEngine *engine) = 0;
virtual void InitWorkerModule(NativeEngine& engine, const std::string& codePath, bool isDebugVersion,
bool isBundle) = 0;

View File

@ -322,28 +322,6 @@ HWTEST_F(JsRuntimeTest, JsRuntimeLoadSystemModuleTest_0100, TestSize.Level0)
HILOG_INFO("LoadSystemModule end");
}
/**
* @tc.name: JsRuntimePostTaskTest_0100
* @tc.desc: JsRuntime test for PostTask.
* @tc.type: FUNC
*/
HWTEST_F(JsRuntimeTest, JsRuntimePostTaskTest_0100, TestSize.Level0)
{
HILOG_INFO("PostTask start");
std::unique_ptr<JsRuntime> jsRuntime = std::make_unique<MockJsRuntime>();
EXPECT_TRUE(jsRuntime != nullptr);
jsRuntime->eventHandler_ = nullptr;
auto task = []() { GTEST_LOG_(INFO) << "JsRuntimePostTaskTest_0100 task called"; };
std::string name = "";
int64_t delayTime = 0;
jsRuntime->PostTask(task, name, delayTime);
HILOG_INFO("PostTask end");
}
/**
* @tc.name: RuntimeSavePreloadedTest_0100
* @tc.desc: Runtime test for SavePreloaded.