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