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 <chrono>
17 #include <cmath>
18 #include <limits>
19 #include <string>
20 #include <string_view>
21 #include <type_traits>
22
23 #include "libpandabase/macros.h"
24 #include "libpandabase/utils/logger.h"
25 #include "libpandabase/utils/span.h"
26 #include "libpandabase/utils/time.h"
27 #include "runtime/include/exceptions.h"
28 #include "runtime/include/compiler_interface.h"
29 #include "runtime/include/coretypes/array.h"
30 #include "runtime/include/coretypes/string.h"
31 #include "runtime/include/panda_vm.h"
32 #include "runtime/include/runtime.h"
33 #include "runtime/include/thread.h"
34 #include "runtime/include/thread_status.h"
35 #include "runtime/interpreter/frame.h"
36 #include "utils/math_helpers.h"
37 #include "intrinsics.h"
38
39 namespace panda::intrinsics {
40
IsInfF64(double v)41 uint8_t IsInfF64(double v)
42 {
43 return static_cast<uint8_t>(std::isinf(v));
44 }
45
IsInfF32(float v)46 uint8_t IsInfF32(float v)
47 {
48 return static_cast<uint8_t>(std::isinf(v));
49 }
50
AbsI32(int32_t v)51 int32_t AbsI32(int32_t v)
52 {
53 return std::abs(v);
54 }
55
AbsI64(int64_t v)56 int64_t AbsI64(int64_t v)
57 {
58 return std::abs(v);
59 }
60
AbsF32(float v)61 float AbsF32(float v)
62 {
63 return std::abs(v);
64 }
65
AbsF64(double v)66 double AbsF64(double v)
67 {
68 return std::abs(v);
69 }
70
SinF32(float v)71 float SinF32(float v)
72 {
73 return std::sin(v);
74 }
75
SinF64(double v)76 double SinF64(double v)
77 {
78 return std::sin(v);
79 }
80
CosF32(float v)81 float CosF32(float v)
82 {
83 return std::cos(v);
84 }
85
CosF64(double v)86 double CosF64(double v)
87 {
88 return std::cos(v);
89 }
90
PowF32(float base,float exp)91 float PowF32(float base, float exp)
92 {
93 return std::pow(base, exp);
94 }
95
PowF64(double base,double exp)96 double PowF64(double base, double exp)
97 {
98 return std::pow(base, exp);
99 }
100
SqrtF32(float v)101 float SqrtF32(float v)
102 {
103 return std::sqrt(v);
104 }
105
SqrtF64(double v)106 double SqrtF64(double v)
107 {
108 return std::sqrt(v);
109 }
110
MinI32(int32_t a,int32_t b)111 int32_t MinI32(int32_t a, int32_t b)
112 {
113 return std::min(a, b);
114 }
115
MinI64(int64_t a,int64_t b)116 int64_t MinI64(int64_t a, int64_t b)
117 {
118 return std::min(a, b);
119 }
120
MinF32(float a,float b)121 float MinF32(float a, float b)
122 {
123 return panda::helpers::math::min(a, b);
124 }
125
MinF64(double a,double b)126 double MinF64(double a, double b)
127 {
128 return panda::helpers::math::min(a, b);
129 }
130
MaxI32(int32_t a,int32_t b)131 int32_t MaxI32(int32_t a, int32_t b)
132 {
133 return std::max(a, b);
134 }
135
MaxI64(int64_t a,int64_t b)136 int64_t MaxI64(int64_t a, int64_t b)
137 {
138 return std::max(a, b);
139 }
140
MaxF32(float a,float b)141 float MaxF32(float a, float b)
142 {
143 return panda::helpers::math::max(a, b);
144 }
145
MaxF64(double a,double b)146 double MaxF64(double a, double b)
147 {
148 return panda::helpers::math::max(a, b);
149 }
150
151 template <bool is_err, class T>
Print(T v)152 void Print(T v)
153 {
154 if (is_err) {
155 std::cerr << v;
156 } else {
157 std::cout << v;
158 }
159 }
160
161 template <bool is_err, class T>
PrintW(T v)162 void PrintW(T v)
163 {
164 if (is_err) {
165 std::wcerr << v;
166 } else {
167 std::wcout << v;
168 }
169 }
170
171 template <bool is_err>
PrintStringInternal(coretypes::String * v)172 void PrintStringInternal(coretypes::String *v)
173 {
174 if (v->IsUtf16()) {
175 Span<const char16_t> sp(reinterpret_cast<const char16_t *>(v->GetDataUtf16()), v->GetLength());
176 for (wchar_t c : sp) {
177 PrintW<is_err>(c);
178 }
179 } else {
180 Span<const char> sp(reinterpret_cast<const char *>(v->GetDataMUtf8()), v->GetLength());
181 for (char c : sp) {
182 Print<is_err>(c);
183 }
184 }
185 }
186
PrintString(coretypes::String * v)187 void PrintString(coretypes::String *v)
188 {
189 PrintStringInternal<false>(v);
190 }
191
PrintF32(float v)192 void PrintF32(float v)
193 {
194 Print<false>(v);
195 }
196
PrintF64(double v)197 void PrintF64(double v)
198 {
199 Print<false>(v);
200 }
201
PrintI32(int32_t v)202 void PrintI32(int32_t v)
203 {
204 Print<false>(v);
205 }
206
PrintU32(uint32_t v)207 void PrintU32(uint32_t v)
208 {
209 Print<false>(v);
210 }
211
PrintI64(int64_t v)212 void PrintI64(int64_t v)
213 {
214 Print<false>(v);
215 }
216
PrintU64(uint64_t v)217 void PrintU64(uint64_t v)
218 {
219 Print<false>(v);
220 }
221
NanoTime()222 int64_t NanoTime()
223 {
224 return time::GetCurrentTimeInNanos();
225 }
226
Assert(uint8_t cond)227 void Assert(uint8_t cond)
228 {
229 if (cond == 0) {
230 Runtime::Abort();
231 }
232 }
233
UnknownIntrinsic()234 void UnknownIntrinsic()
235 {
236 std::cerr << "UnknownIntrinsic\n";
237 Runtime::Abort();
238 }
239
AssertPrint(uint8_t cond,coretypes::String * s)240 void AssertPrint(uint8_t cond, coretypes::String *s)
241 {
242 if (cond == 0) {
243 PrintStringInternal<true>(s);
244 Runtime::Abort();
245 }
246 }
247
248 #ifndef PANDA_PRODUCT_BUILD
CompileMethod(coretypes::String * full_method_name)249 uint8_t CompileMethod(coretypes::String *full_method_name)
250 {
251 auto name = ConvertToString(full_method_name);
252 auto *class_linker = Runtime::GetCurrent()->GetClassLinker();
253
254 size_t pos = name.find_last_of("::");
255 if (pos == std::string_view::npos) {
256 return 1;
257 }
258 auto class_name = PandaString(name.substr(0, pos - 1));
259 auto method_name = PandaString(name.substr(pos + 1));
260
261 PandaString descriptor;
262 auto class_name_bytes = ClassHelper::GetDescriptor(utf::CStringAsMutf8(class_name.c_str()), &descriptor);
263 auto method_name_bytes = utf::CStringAsMutf8(method_name.c_str());
264
265 ClassLinkerExtension *ext = class_linker->GetExtension(panda_file::SourceLang::PANDA_ASSEMBLY);
266 Class *cls = class_linker->GetClass(class_name_bytes, true, ext->GetBootContext());
267 if (cls == nullptr) {
268 static constexpr uint8_t CLASS_IS_NULL = 2;
269 return CLASS_IS_NULL;
270 }
271
272 auto method = cls->GetDirectMethod(method_name_bytes);
273 if (method == nullptr) {
274 static constexpr uint8_t METHOD_IS_NULL = 3;
275 return METHOD_IS_NULL;
276 }
277
278 if (method->IsAbstract()) {
279 static constexpr uint8_t ABSTRACT_ERROR = 4;
280 return ABSTRACT_ERROR;
281 }
282 if (method->HasCompiledCode()) {
283 return 0;
284 }
285 auto *compiler = Runtime::GetCurrent()->GetPandaVM()->GetCompiler();
286 auto status = method->GetCompilationStatus();
287 for (; (status != Method::COMPILED) && (status != Method::FAILED); status = method->GetCompilationStatus()) {
288 if (status == Method::NOT_COMPILED) {
289 ASSERT(!method->HasCompiledCode());
290 compiler->CompileMethod(method, 0, false);
291 }
292 static constexpr uint64_t SLEEP_MS = 10;
293 MTManagedThread::GetCurrent()->TimedWait(ThreadStatus::IS_COMPILER_WAITING, SLEEP_MS, 0);
294 }
295 static constexpr uint8_t COMPILATION_FAILED = 5;
296 return (status == Method::COMPILED ? 0 : COMPILATION_FAILED);
297 }
298 #endif // PANDA_PRODUCT_BUILD
299
300 // TODO(kbaladurin) : Convert methods should be implemented in managed library
301
ConvertStringToI32(coretypes::String * s)302 int32_t ConvertStringToI32(coretypes::String *s)
303 {
304 return static_cast<int32_t>(PandaStringToLL(ConvertToString(s)));
305 }
306
ConvertStringToU32(coretypes::String * s)307 uint32_t ConvertStringToU32(coretypes::String *s)
308 {
309 return static_cast<uint32_t>(PandaStringToULL(ConvertToString(s)));
310 }
311
ConvertStringToI64(coretypes::String * s)312 int64_t ConvertStringToI64(coretypes::String *s)
313 {
314 return static_cast<int64_t>(PandaStringToLL(ConvertToString(s)));
315 }
316
ConvertStringToU64(coretypes::String * s)317 uint64_t ConvertStringToU64(coretypes::String *s)
318 {
319 return static_cast<uint64_t>(PandaStringToULL(ConvertToString(s)));
320 }
321
ConvertStringToF32(coretypes::String * s)322 float ConvertStringToF32(coretypes::String *s)
323 {
324 return PandaStringToF(ConvertToString(s));
325 }
326
ConvertStringToF64(coretypes::String * s)327 double ConvertStringToF64(coretypes::String *s)
328 {
329 return PandaStringToD(ConvertToString(s));
330 }
331
SystemExit(int32_t status)332 void SystemExit(int32_t status)
333 {
334 Runtime::Halt(status);
335 }
336
ObjectCreateNonMovable(coretypes::Class * cls)337 ObjectHeader *ObjectCreateNonMovable(coretypes::Class *cls)
338 {
339 ASSERT(cls != nullptr);
340 return ObjectHeader::CreateNonMovable(cls->GetRuntimeClass());
341 }
342
ObjectMonitorEnter(ObjectHeader * header)343 void ObjectMonitorEnter(ObjectHeader *header)
344 {
345 if (header == nullptr) {
346 panda::ThrowNullPointerException();
347 return;
348 }
349 auto res = Monitor::MonitorEnter(header);
350 // Expected results: OK, ILLEGAL
351 ASSERT(res != Monitor::State::INTERRUPTED);
352 if (UNLIKELY(res != Monitor::State::OK)) {
353 // This should never happen
354 LOG(FATAL, RUNTIME) << "MonitorEnter for " << std::hex << header << " returned Illegal state!";
355 }
356 }
357
ObjectMonitorExit(ObjectHeader * header)358 void ObjectMonitorExit(ObjectHeader *header)
359 {
360 if (header == nullptr) {
361 panda::ThrowNullPointerException();
362 return;
363 }
364 auto res = Monitor::MonitorExit(header);
365 // Expected results: OK, ILLEGAL
366 ASSERT(res != Monitor::State::INTERRUPTED);
367 if (res == Monitor::State::ILLEGAL) {
368 PandaStringStream ss;
369 ss << "MonitorExit for object " << std::hex << header << " returned Illegal state";
370 panda::ThrowIllegalMonitorStateException(ss.str());
371 }
372 }
373
ObjectWait(ObjectHeader * header)374 void ObjectWait(ObjectHeader *header)
375 {
376 Monitor::State state = Monitor::Wait(header, ThreadStatus::IS_WAITING, 0, 0);
377 LOG_IF(state == Monitor::State::ILLEGAL, FATAL, RUNTIME) << "Monitor::Wait() failed";
378 }
379
ObjectTimedWait(ObjectHeader * header,uint64_t timeout)380 void ObjectTimedWait(ObjectHeader *header, uint64_t timeout)
381 {
382 Monitor::State state = Monitor::Wait(header, ThreadStatus::IS_TIMED_WAITING, timeout, 0);
383 LOG_IF(state == Monitor::State::ILLEGAL, FATAL, RUNTIME) << "Monitor::Wait() failed";
384 }
385
ObjectTimedWaitNanos(ObjectHeader * header,uint64_t timeout,uint64_t nanos)386 void ObjectTimedWaitNanos(ObjectHeader *header, uint64_t timeout, uint64_t nanos)
387 {
388 Monitor::State state = Monitor::Wait(header, ThreadStatus::IS_TIMED_WAITING, timeout, nanos);
389 LOG_IF(state == Monitor::State::ILLEGAL, FATAL, RUNTIME) << "Monitor::Wait() failed";
390 }
391
ObjectNotify(ObjectHeader * header)392 void ObjectNotify(ObjectHeader *header)
393 {
394 Monitor::State state = Monitor::Notify(header);
395 LOG_IF(state != Monitor::State::OK, FATAL, RUNTIME) << "Monitor::Notify() failed";
396 }
397
ObjectNotifyAll(ObjectHeader * header)398 void ObjectNotifyAll(ObjectHeader *header)
399 {
400 Monitor::State state = Monitor::NotifyAll(header);
401 LOG_IF(state != Monitor::State::OK, FATAL, RUNTIME) << "Monitor::NotifyAll() failed";
402 }
403
404 } // namespace panda::intrinsics
405
406 #include <intrinsics_gen.h>
407