1 /**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <iostream>
17 #include "ets_vm_api.h"
18 #include "ets_vm.h"
19 #include "generated/base_options.h"
20
21 #ifdef PANDA_TARGET_OHOS
22 #include <hilog/log.h>
23
LogPrint(int id,int level,const char * component,const char * fmt,const char * msg)24 static void LogPrint([[maybe_unused]] int id, int level, const char *component, [[maybe_unused]] const char *fmt,
25 const char *msg)
26 {
27 #ifdef PANDA_USE_OHOS_LOG
28 constexpr static unsigned int ARK_DOMAIN = 0xD003F00;
29 constexpr static auto TAG = "ArkEtsVm";
30 constexpr static OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, ARK_DOMAIN, TAG};
31 switch (level) {
32 case ark::Logger::PandaLog2MobileLog::DEBUG:
33 OHOS::HiviewDFX::HiLog::Debug(LABEL, "%{public}s", msg);
34 break;
35 case ark::Logger::PandaLog2MobileLog::INFO:
36 OHOS::HiviewDFX::HiLog::Info(LABEL, "%{public}s", msg);
37 break;
38 case ark::Logger::PandaLog2MobileLog::ERROR:
39 OHOS::HiviewDFX::HiLog::Error(LABEL, "%{public}s", msg);
40 break;
41 case ark::Logger::PandaLog2MobileLog::FATAL:
42 OHOS::HiviewDFX::HiLog::Fatal(LABEL, "%{public}s", msg);
43 break;
44 case ark::Logger::PandaLog2MobileLog::WARN:
45 OHOS::HiviewDFX::HiLog::Warn(LABEL, "%{public}s", msg);
46 break;
47 default:
48 UNREACHABLE();
49 }
50 #else
51 switch (level) {
52 case ark::Logger::PandaLog2MobileLog::DEBUG:
53 OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
54 break;
55 case ark::Logger::PandaLog2MobileLog::INFO:
56 OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
57 break;
58 case ark::Logger::PandaLog2MobileLog::ERROR:
59 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
60 break;
61 case ark::Logger::PandaLog2MobileLog::FATAL:
62 OH_LOG_Print(LOG_APP, LOG_FATAL, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
63 break;
64 case ark::Logger::PandaLog2MobileLog::WARN:
65 OH_LOG_Print(LOG_APP, LOG_WARN, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
66 break;
67 default:
68 UNREACHABLE();
69 }
70 #endif // PANDA_USE_OHOS_LOG
71 }
72 #else
LogPrint(int id,int level,const char * component,const char * fmt,const char * msg)73 static void LogPrint([[maybe_unused]] int id, [[maybe_unused]] int level, [[maybe_unused]] const char *component,
74 [[maybe_unused]] const char *fmt, const char *msg)
75 {
76 std::cerr << msg << "\n";
77 }
78 #endif // PANDA_TARGET_OHOS
79
80 namespace ark::ets {
81
CreateRuntime(std::function<bool (base_options::Options *,RuntimeOptions *)> const & addOptions)82 bool CreateRuntime(std::function<bool(base_options::Options *, RuntimeOptions *)> const &addOptions)
83 {
84 auto runtimeOptions = ark::RuntimeOptions("app");
85 runtimeOptions.SetLoadRuntimes({"ets"});
86 #ifdef PANDA_TARGET_OHOS
87 runtimeOptions.SetMobileLog(reinterpret_cast<void *>(LogPrint));
88 #endif
89
90 ark::base_options::Options baseOptions("app");
91
92 if (!addOptions(&baseOptions, &runtimeOptions)) {
93 return false;
94 }
95
96 ark::Logger::Initialize(baseOptions);
97
98 LOG(DEBUG, RUNTIME) << "CreateRuntime";
99
100 if (!ark::Runtime::Create(runtimeOptions)) {
101 LOG(ERROR, RUNTIME) << "CreateRuntime: cannot create ets runtime";
102 return false;
103 }
104 return true;
105 }
106
CreateRuntime(const std::string & stdlibAbc,const std::string & pathAbc,const bool useJit,const bool useAot)107 bool CreateRuntime(const std::string &stdlibAbc, const std::string &pathAbc, const bool useJit, const bool useAot)
108 {
109 auto addOpts = [&stdlibAbc, &pathAbc, useJit, useAot](base_options::Options *baseOptions,
110 ark::RuntimeOptions *runtimeOptions) {
111 baseOptions->SetLogLevel("info");
112 runtimeOptions->SetBootPandaFiles({stdlibAbc, pathAbc});
113 runtimeOptions->SetPandaFiles({pathAbc});
114 runtimeOptions->SetGcTriggerType("heap-trigger");
115 runtimeOptions->SetCompilerEnableJit(useJit);
116 runtimeOptions->SetEnableAn(useAot);
117 runtimeOptions->SetCoroutineJsMode(true);
118 runtimeOptions->SetCoroutineImpl("stackful");
119 return true;
120 };
121 return CreateRuntime(addOpts);
122 }
123
DestroyRuntime()124 bool DestroyRuntime()
125 {
126 LOG(DEBUG, RUNTIME) << "DestroyEtsRuntime: enter";
127 auto res = ark::Runtime::Destroy();
128 LOG(DEBUG, RUNTIME) << "DestroyEtsRuntime: result = " << res;
129 return res;
130 }
131
ExecuteMain()132 std::pair<bool, int> ExecuteMain()
133 {
134 auto runtime = ark::Runtime::GetCurrent();
135 auto pfPath = runtime->GetPandaFiles()[0];
136 LOG(INFO, RUNTIME) << "ExecuteEtsMain: '" << pfPath << "'";
137 auto res = ark::Runtime::GetCurrent()->ExecutePandaFile(pfPath, "ETSGLOBAL::main", {});
138 LOG(INFO, RUNTIME) << "ExecuteEtsMain: result = " << (res ? std::to_string(res.Value()) : "failed");
139 return res ? std::make_pair(true, res.Value()) : std::make_pair(false, 1);
140 }
141
BindNative(const char * classDescriptor,const char * methodName,void * impl)142 bool BindNative(const char *classDescriptor, const char *methodName, void *impl)
143 {
144 auto *runtime = ark::Runtime::GetCurrent();
145 auto *classLinker = runtime->GetClassLinker();
146 auto *ext = classLinker->GetExtension(ark::SourceLanguage::ETS);
147 auto *klass = ext->GetClass(ark::utf::CStringAsMutf8(classDescriptor));
148
149 if (klass == nullptr) {
150 ark::ManagedThread::GetCurrent()->ClearException();
151 LOG(DEBUG, RUNTIME) << "BindNative: Cannot find class '" << classDescriptor << "'";
152 return false;
153 }
154
155 auto *method = klass->GetDirectMethod(ark::utf::CStringAsMutf8(methodName));
156
157 if (method == nullptr) {
158 ark::ManagedThread::GetCurrent()->ClearException();
159 LOG(DEBUG, RUNTIME) << "BindNative: Cannot find method '" << classDescriptor << "." << methodName << "'`";
160 return false;
161 }
162
163 method->SetCompiledEntryPoint(impl);
164 return true;
165 }
166
LogError(const std::string & msg)167 void LogError(const std::string &msg)
168 {
169 LogPrint(0, ark::Logger::PandaLog2MobileLog::ERROR, nullptr, nullptr, msg.c_str());
170 }
171
172 } // namespace ark::ets
173