• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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