1 /**
2 * Copyright (c) 2021-2022 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 panda::Logger::PandaLog2MobileLog::DEBUG:
33 OHOS::HiviewDFX::HiLog::Debug(LABEL, "%{public}s", msg);
34 break;
35 case panda::Logger::PandaLog2MobileLog::INFO:
36 OHOS::HiviewDFX::HiLog::Info(LABEL, "%{public}s", msg);
37 break;
38 case panda::Logger::PandaLog2MobileLog::ERROR:
39 OHOS::HiviewDFX::HiLog::Error(LABEL, "%{public}s", msg);
40 break;
41 case panda::Logger::PandaLog2MobileLog::FATAL:
42 OHOS::HiviewDFX::HiLog::Fatal(LABEL, "%{public}s", msg);
43 break;
44 case panda::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 panda::Logger::PandaLog2MobileLog::DEBUG:
53 OH_LOG_Print(LOG_APP, LOG_DEBUG, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
54 break;
55 case panda::Logger::PandaLog2MobileLog::INFO:
56 OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
57 break;
58 case panda::Logger::PandaLog2MobileLog::ERROR:
59 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
60 break;
61 case panda::Logger::PandaLog2MobileLog::FATAL:
62 OH_LOG_Print(LOG_APP, LOG_FATAL, 0xFF00, "ArkEtsVm", "%s: %s", component, msg);
63 break;
64 case panda::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 panda::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 = panda::RuntimeOptions("app");
85 runtimeOptions.SetLoadRuntimes({"ets"});
86 #ifdef PANDA_TARGET_OHOS
87 runtimeOptions.SetMobileLog(reinterpret_cast<void *>(LogPrint));
88 #endif
89
90 panda::base_options::Options baseOptions("app");
91
92 if (!addOptions(&baseOptions, &runtimeOptions)) {
93 return false;
94 }
95
96 panda::Logger::Initialize(baseOptions);
97
98 LOG(DEBUG, RUNTIME) << "CreateRuntime";
99
100 if (!panda::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 = [&](base_options::Options *baseOptions, panda::RuntimeOptions *runtimeOptions) {
110 baseOptions->SetLogLevel("info");
111 runtimeOptions->SetBootPandaFiles({stdlibAbc, pathAbc});
112 runtimeOptions->SetPandaFiles({pathAbc});
113 runtimeOptions->SetGcTriggerType("heap-trigger");
114 runtimeOptions->SetCompilerEnableJit(useJit);
115 runtimeOptions->SetEnableAn(useAot);
116 runtimeOptions->SetCoroutineJsMode(true);
117 runtimeOptions->SetCoroutineImpl("stackful");
118 return true;
119 };
120 return CreateRuntime(addOpts);
121 }
122
DestroyRuntime()123 bool DestroyRuntime()
124 {
125 LOG(DEBUG, RUNTIME) << "DestroyEtsRuntime: enter";
126 auto res = panda::Runtime::Destroy();
127 LOG(DEBUG, RUNTIME) << "DestroyEtsRuntime: result = " << res;
128 return res;
129 }
130
ExecuteMain()131 std::pair<bool, int> ExecuteMain()
132 {
133 auto runtime = panda::Runtime::GetCurrent();
134 auto pfPath = runtime->GetPandaFiles()[0];
135 LOG(INFO, RUNTIME) << "ExecuteEtsMain: '" << pfPath << "'";
136 auto res = panda::Runtime::GetCurrent()->ExecutePandaFile(pfPath, "ETSGLOBAL::main", {});
137 LOG(INFO, RUNTIME) << "ExecuteEtsMain: result = " << (res ? std::to_string(res.Value()) : "failed");
138 return res ? std::make_pair(true, res.Value()) : std::make_pair(false, 1);
139 }
140
BindNative(const char * classDescriptor,const char * methodName,void * impl)141 bool BindNative(const char *classDescriptor, const char *methodName, void *impl)
142 {
143 auto *runtime = panda::Runtime::GetCurrent();
144 auto *classLinker = runtime->GetClassLinker();
145 auto *ext = classLinker->GetExtension(panda::SourceLanguage::ETS);
146 auto *klass = ext->GetClass(panda::utf::CStringAsMutf8(classDescriptor));
147
148 if (klass == nullptr) {
149 panda::ManagedThread::GetCurrent()->ClearException();
150 LOG(DEBUG, RUNTIME) << "BindNative: Cannot find class '" << classDescriptor << "'";
151 return false;
152 }
153
154 auto *method = klass->GetDirectMethod(panda::utf::CStringAsMutf8(methodName));
155
156 if (method == nullptr) {
157 panda::ManagedThread::GetCurrent()->ClearException();
158 LOG(DEBUG, RUNTIME) << "BindNative: Cannot find method '" << classDescriptor << "." << methodName << "'`";
159 return false;
160 }
161
162 method->SetCompiledEntryPoint(impl);
163 return true;
164 }
165
LogError(const std::string & msg)166 void LogError(const std::string &msg)
167 {
168 LogPrint(0, panda::Logger::PandaLog2MobileLog::ERROR, nullptr, nullptr, msg.c_str());
169 }
170
171 } // namespace panda::ets
172