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 <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/compiler.h"
28 #include "runtime/include/exceptions.h"
29 #include "runtime/include/compiler_interface.h"
30 #include "runtime/include/coretypes/array.h"
31 #include "runtime/include/coretypes/string.h"
32 #include "runtime/include/panda_vm.h"
33 #include "runtime/include/runtime.h"
34 #include "runtime/include/thread.h"
35 #include "runtime/include/thread_status.h"
36 #include "runtime/interpreter/frame.h"
37 #include "runtime/coroutines/coroutine_manager.h"
38 #include "utils/math_helpers.h"
39 #include "intrinsics.h"
40
41 namespace ark::intrinsics {
42
IsInfF64(double v)43 uint8_t IsInfF64(double v)
44 {
45 return static_cast<uint8_t>(std::isinf(v));
46 }
47
IsInfF32(float v)48 uint8_t IsInfF32(float v)
49 {
50 return static_cast<uint8_t>(std::isinf(v));
51 }
52
AbsI32(int32_t v)53 int32_t AbsI32(int32_t v)
54 {
55 return std::abs(v);
56 }
57
AbsI64(int64_t v)58 int64_t AbsI64(int64_t v)
59 {
60 return std::abs(v);
61 }
62
AbsF32(float v)63 float AbsF32(float v)
64 {
65 return std::abs(v);
66 }
67
AbsF64(double v)68 double AbsF64(double v)
69 {
70 return std::abs(v);
71 }
72
SinF32(float v)73 float SinF32(float v)
74 {
75 return std::sin(v);
76 }
77
SinF64(double v)78 double SinF64(double v)
79 {
80 return std::sin(v);
81 }
82
CosF32(float v)83 float CosF32(float v)
84 {
85 return std::cos(v);
86 }
87
CosF64(double v)88 double CosF64(double v)
89 {
90 return std::cos(v);
91 }
92
PowF32(float base,float exp)93 float PowF32(float base, float exp)
94 {
95 return std::pow(base, exp);
96 }
97
PowF64(double base,double exp)98 double PowF64(double base, double exp)
99 {
100 return std::pow(base, exp);
101 }
102
SqrtF32(float v)103 float SqrtF32(float v)
104 {
105 return std::sqrt(v);
106 }
107
SqrtF64(double v)108 double SqrtF64(double v)
109 {
110 return std::sqrt(v);
111 }
112
MinI32(int32_t a,int32_t b)113 int32_t MinI32(int32_t a, int32_t b)
114 {
115 return std::min(a, b);
116 }
117
MinI64(int64_t a,int64_t b)118 int64_t MinI64(int64_t a, int64_t b)
119 {
120 return std::min(a, b);
121 }
122
MinF32(float a,float b)123 float MinF32(float a, float b)
124 {
125 return ark::helpers::math::Min(a, b);
126 }
127
MinF64(double a,double b)128 double MinF64(double a, double b)
129 {
130 return ark::helpers::math::Min(a, b);
131 }
132
MaxI32(int32_t a,int32_t b)133 int32_t MaxI32(int32_t a, int32_t b)
134 {
135 return std::max(a, b);
136 }
137
MaxI64(int64_t a,int64_t b)138 int64_t MaxI64(int64_t a, int64_t b)
139 {
140 return std::max(a, b);
141 }
142
MaxF32(float a,float b)143 float MaxF32(float a, float b)
144 {
145 return ark::helpers::math::Max(a, b);
146 }
147
MaxF64(double a,double b)148 double MaxF64(double a, double b)
149 {
150 return ark::helpers::math::Max(a, b);
151 }
152
153 template <bool IS_ERR, class T>
Print(T v)154 void Print(T v)
155 {
156 if (IS_ERR) {
157 std::cerr << v;
158 } else {
159 std::cout << v;
160 }
161 }
162
163 template <bool IS_ERR>
PrintStringInternal(coretypes::String * v)164 void PrintStringInternal(coretypes::String *v)
165 {
166 static auto &outstream = IS_ERR ? std::cerr : std::cout;
167 if (v->IsUtf16()) {
168 uint16_t *vdataPtr = v->GetDataUtf16();
169 uint32_t vlength = v->GetLength();
170 size_t mutf8Len = utf::Utf16ToMUtf8Size(vdataPtr, vlength);
171
172 PandaVector<uint8_t> out(mutf8Len);
173 utf::ConvertRegionUtf16ToMUtf8(vdataPtr, out.data(), vlength, mutf8Len, 0);
174
175 outstream << reinterpret_cast<const char *>(out.data());
176 } else {
177 outstream << std::string_view(reinterpret_cast<const char *>(v->GetDataMUtf8()), v->GetLength());
178 }
179 }
180
PrintString(coretypes::String * v)181 void PrintString(coretypes::String *v)
182 {
183 PrintStringInternal<false>(v);
184 }
185
PrintF32(float v)186 void PrintF32(float v)
187 {
188 Print<false>(v);
189 }
190
PrintF64(double v)191 void PrintF64(double v)
192 {
193 Print<false>(v);
194 }
195
PrintI32(int32_t v)196 void PrintI32(int32_t v)
197 {
198 Print<false>(v);
199 }
200
PrintU32(uint32_t v)201 void PrintU32(uint32_t v)
202 {
203 Print<false>(v);
204 }
205
PrintI64(int64_t v)206 void PrintI64(int64_t v)
207 {
208 Print<false>(v);
209 }
210
PrintU64(uint64_t v)211 void PrintU64(uint64_t v)
212 {
213 Print<false>(v);
214 }
215
NanoTime()216 int64_t NanoTime()
217 {
218 return time::GetCurrentTimeInNanos();
219 }
220
Assert(uint8_t cond)221 void Assert(uint8_t cond)
222 {
223 if (cond == 0) {
224 Runtime::Abort();
225 }
226 }
227
UnknownIntrinsic()228 void UnknownIntrinsic()
229 {
230 std::cerr << "UnknownIntrinsic\n";
231 Runtime::Abort();
232 }
233
AssertPrint(uint8_t cond,coretypes::String * s)234 void AssertPrint(uint8_t cond, coretypes::String *s)
235 {
236 if (cond == 0) {
237 PrintStringInternal<true>(s);
238 Runtime::Abort();
239 }
240 }
241
CheckTag(int64_t reg,int64_t expected)242 void CheckTag(int64_t reg, int64_t expected)
243 {
244 constexpr int ACC_NUM = std::numeric_limits<uint16_t>::max() + 1;
245 int64_t tag = 0;
246 StaticFrameHandler handler(ManagedThread::GetCurrent()->GetCurrentFrame());
247 if (reg == ACC_NUM) {
248 auto vreg = handler.GetAcc();
249 tag = vreg.GetTag();
250 } else {
251 auto vreg = handler.GetVReg(reg);
252 tag = vreg.GetTag();
253 }
254 if (tag != expected) {
255 std::cerr << "Error: "
256 << "Tag = " << tag << std::endl;
257 std::cerr << "Expected = " << expected << std::endl;
258 ark::PrintStack(std::cerr);
259 Runtime::Abort();
260 }
261 }
262
263 #ifndef PANDA_PRODUCT_BUILD
CompileMethod(coretypes::String * fullMethodName)264 uint8_t CompileMethod(coretypes::String *fullMethodName)
265 {
266 return ark::CompileMethodImpl(fullMethodName, panda_file::SourceLang::PANDA_ASSEMBLY);
267 }
268
CalculateDouble(uint32_t n,double s)269 double CalculateDouble(uint32_t n, double s)
270 {
271 double result = 0.0;
272 for (uint32_t i = 0U; i < n; ++i) {
273 result += i * s;
274 }
275 return result;
276 }
277
CalculateFloat(uint32_t n,float s)278 float CalculateFloat(uint32_t n, float s)
279 {
280 float result = 0.0F;
281 for (uint32_t i = 0U; i < n; ++i) {
282 result += i * s;
283 }
284 return result;
285 }
286 #endif // PANDA_PRODUCT_BUILD
287
288 // NOTE(kbaladurin) : Convert methods should be implemented in managed library
289
ConvertStringToI32(coretypes::String * s)290 int32_t ConvertStringToI32(coretypes::String *s)
291 {
292 return static_cast<int32_t>(PandaStringToLL(ConvertToString(s)));
293 }
294
ConvertStringToU32(coretypes::String * s)295 uint32_t ConvertStringToU32(coretypes::String *s)
296 {
297 return static_cast<uint32_t>(PandaStringToULL(ConvertToString(s)));
298 }
299
ConvertStringToI64(coretypes::String * s)300 int64_t ConvertStringToI64(coretypes::String *s)
301 {
302 return static_cast<int64_t>(PandaStringToLL(ConvertToString(s)));
303 }
304
ConvertStringToU64(coretypes::String * s)305 uint64_t ConvertStringToU64(coretypes::String *s)
306 {
307 return static_cast<uint64_t>(PandaStringToULL(ConvertToString(s)));
308 }
309
ConvertStringToF32(coretypes::String * s)310 float ConvertStringToF32(coretypes::String *s)
311 {
312 return PandaStringToF(ConvertToString(s));
313 }
314
ConvertStringToF64(coretypes::String * s)315 double ConvertStringToF64(coretypes::String *s)
316 {
317 return PandaStringToD(ConvertToString(s));
318 }
319
SystemExit(int32_t status)320 void SystemExit(int32_t status)
321 {
322 Runtime::Halt(status);
323 }
324
SystemScheduleCoroutine()325 void SystemScheduleCoroutine()
326 {
327 auto *cm = static_cast<CoroutineManager *>(Coroutine::GetCurrent()->GetVM()->GetThreadManager());
328 cm->Schedule();
329 }
330
SystemCoroutineGetWorkerId()331 int32_t SystemCoroutineGetWorkerId()
332 {
333 return os::thread::GetCurrentThreadId();
334 }
335
ObjectCreateNonMovable(coretypes::Class * cls)336 ObjectHeader *ObjectCreateNonMovable(coretypes::Class *cls)
337 {
338 ASSERT(cls != nullptr);
339 return ObjectHeader::CreateNonMovable(cls->GetRuntimeClass());
340 }
341
ObjectMonitorEnter(ObjectHeader * header)342 void ObjectMonitorEnter(ObjectHeader *header)
343 {
344 if (header == nullptr) {
345 ark::ThrowNullPointerException();
346 return;
347 }
348 auto res = Monitor::MonitorEnter(header);
349 // Expected results: OK, ILLEGAL
350 ASSERT(res != Monitor::State::INTERRUPTED);
351 if (UNLIKELY(res != Monitor::State::OK)) {
352 // This should never happen
353 // Object 'header' may be moved. It is no sence to wrap it into a handle just to print before exit
354 // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
355 LOG(FATAL, RUNTIME) << "MonitorEnter for " << header << " returned Illegal state!";
356 }
357 }
358
ObjectMonitorExit(ObjectHeader * header)359 void ObjectMonitorExit(ObjectHeader *header)
360 {
361 if (header == nullptr) {
362 ark::ThrowNullPointerException();
363 return;
364 }
365 auto res = Monitor::MonitorExit(header);
366 // Expected results: OK, ILLEGAL
367 ASSERT(res != Monitor::State::INTERRUPTED);
368 if (res == Monitor::State::ILLEGAL) {
369 PandaStringStream ss;
370 ss << "MonitorExit for object " << std::hex << header << " returned Illegal state";
371 ark::ThrowIllegalMonitorStateException(ss.str());
372 }
373 }
374
ObjectWait(ObjectHeader * header)375 void ObjectWait(ObjectHeader *header)
376 {
377 Monitor::State state = Monitor::Wait(header, ThreadStatus::IS_WAITING, 0, 0);
378 LOG_IF(state == Monitor::State::ILLEGAL, FATAL, RUNTIME) << "Monitor::Wait() failed";
379 }
380
ObjectTimedWait(ObjectHeader * header,uint64_t timeout)381 void ObjectTimedWait(ObjectHeader *header, uint64_t timeout)
382 {
383 Monitor::State state = Monitor::Wait(header, ThreadStatus::IS_TIMED_WAITING, timeout, 0);
384 LOG_IF(state == Monitor::State::ILLEGAL, FATAL, RUNTIME) << "Monitor::Wait() failed";
385 }
386
ObjectTimedWaitNanos(ObjectHeader * header,uint64_t timeout,uint64_t nanos)387 void ObjectTimedWaitNanos(ObjectHeader *header, uint64_t timeout, uint64_t nanos)
388 {
389 Monitor::State state = Monitor::Wait(header, ThreadStatus::IS_TIMED_WAITING, timeout, nanos);
390 LOG_IF(state == Monitor::State::ILLEGAL, FATAL, RUNTIME) << "Monitor::Wait() failed";
391 }
392
ObjectNotify(ObjectHeader * header)393 void ObjectNotify(ObjectHeader *header)
394 {
395 Monitor::State state = Monitor::Notify(header);
396 LOG_IF(state != Monitor::State::OK, FATAL, RUNTIME) << "Monitor::Notify() failed";
397 }
398
ObjectNotifyAll(ObjectHeader * header)399 void ObjectNotifyAll(ObjectHeader *header)
400 {
401 Monitor::State state = Monitor::NotifyAll(header);
402 LOG_IF(state != Monitor::State::OK, FATAL, RUNTIME) << "Monitor::NotifyAll() failed";
403 }
404
Memset8(ObjectHeader * array,uint8_t value,uint32_t initialIndex,uint32_t maxIndex)405 void Memset8(ObjectHeader *array, uint8_t value, uint32_t initialIndex, uint32_t maxIndex)
406 {
407 auto data = reinterpret_cast<uint8_t *>(ark::coretypes::Array::Cast(array)->GetData());
408 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
409 std::fill(data + initialIndex, data + maxIndex, value);
410 }
411
Memset16(ObjectHeader * array,uint16_t value,uint32_t initialIndex,uint32_t maxIndex)412 void Memset16(ObjectHeader *array, uint16_t value, uint32_t initialIndex, uint32_t maxIndex)
413 {
414 auto data = reinterpret_cast<uint16_t *>(ark::coretypes::Array::Cast(array)->GetData());
415 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
416 std::fill(data + initialIndex, data + maxIndex, value);
417 }
418
Memset32(ObjectHeader * array,uint32_t value,uint32_t initialIndex,uint32_t maxIndex)419 void Memset32(ObjectHeader *array, uint32_t value, uint32_t initialIndex, uint32_t maxIndex)
420 {
421 auto data = reinterpret_cast<uint32_t *>(ark::coretypes::Array::Cast(array)->GetData());
422 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
423 std::fill(data + initialIndex, data + maxIndex, value);
424 }
425
Memset64(ObjectHeader * array,uint64_t value,uint32_t initialIndex,uint32_t maxIndex)426 void Memset64(ObjectHeader *array, uint64_t value, uint32_t initialIndex, uint32_t maxIndex)
427 {
428 auto data = reinterpret_cast<uint64_t *>(ark::coretypes::Array::Cast(array)->GetData());
429 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
430 std::fill(data + initialIndex, data + maxIndex, value);
431 }
Memsetf32(ObjectHeader * array,float value,uint32_t initialIndex,uint32_t maxIndex)432 void Memsetf32(ObjectHeader *array, float value, uint32_t initialIndex, uint32_t maxIndex)
433 {
434 auto data = reinterpret_cast<float *>(ark::coretypes::Array::Cast(array)->GetData());
435 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
436 std::fill(data + initialIndex, data + maxIndex, value);
437 }
438
Memsetf64(ObjectHeader * array,double value,uint32_t initialIndex,uint32_t maxIndex)439 void Memsetf64(ObjectHeader *array, double value, uint32_t initialIndex, uint32_t maxIndex)
440 {
441 auto data = reinterpret_cast<double *>(ark::coretypes::Array::Cast(array)->GetData());
442 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
443 std::fill(data + initialIndex, data + maxIndex, value);
444 }
445 } // namespace ark::intrinsics
446
447 #include <intrinsics_gen.h>
448