• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 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 #ifndef PANDA_INTERPRETER_RUNTIME_INTERFACE_H_
16 #define PANDA_INTERPRETER_RUNTIME_INTERFACE_H_
17 
18 #include <memory>
19 
20 #include "libpandabase/utils/logger.h"
21 #include "libpandafile/file_items.h"
22 #include "runtime/entrypoints/entrypoints.h"
23 #include "runtime/include/class_linker-inl.h"
24 #include "runtime/include/coretypes/array.h"
25 #include "runtime/include/coretypes/string.h"
26 #include "runtime/include/exceptions.h"
27 #include "runtime/include/field.h"
28 #include "runtime/include/method.h"
29 #include "runtime/include/runtime.h"
30 #include "runtime/include/managed_thread.h"
31 #include "runtime/mem/gc/gc.h"
32 
33 namespace ark::interpreter {
34 
35 class RuntimeInterface {
36 public:
37     static constexpr bool NEED_READ_BARRIER = true;
38     static constexpr bool NEED_WRITE_BARRIER = true;
39 
ResolveMethod(ManagedThread * thread,const Method & caller,BytecodeId id)40     static Method *ResolveMethod(ManagedThread *thread, const Method &caller, BytecodeId id)
41     {
42         auto resolvedId = caller.GetClass()->ResolveMethodIndex(id.AsIndex());
43         auto *classLinker = Runtime::GetCurrent()->GetClassLinker();
44         auto *method = classLinker->GetMethod(caller, resolvedId);
45         if (method == nullptr) {
46             return nullptr;
47         }
48 
49         auto *klass = method->GetClass();
50         if (!klass->IsInitialized() && !classLinker->InitializeClass(thread, klass)) {
51             return nullptr;
52         }
53 
54         return method;
55     }
56 
GetMethodName(const Method * caller,BytecodeId methodId)57     static const uint8_t *GetMethodName(const Method *caller, BytecodeId methodId)
58     {
59         auto resolvedId = caller->GetClass()->ResolveMethodIndex(methodId.AsIndex());
60         const auto *pf = caller->GetPandaFile();
61         const panda_file::MethodDataAccessor mda(*pf, resolvedId);
62         return pf->GetStringData(mda.GetNameId()).data;
63     }
64 
GetMethodClass(const Method * caller,BytecodeId methodId)65     static Class *GetMethodClass(const Method *caller, BytecodeId methodId)
66     {
67         auto resolvedId = caller->GetClass()->ResolveMethodIndex(methodId.AsIndex());
68         const auto *pf = caller->GetPandaFile();
69         const panda_file::MethodDataAccessor mda(*pf, resolvedId);
70         auto classId = mda.GetClassId();
71 
72         auto *classLinker = Runtime::GetCurrent()->GetClassLinker();
73         return classLinker->GetClass(*caller, classId);
74     }
75 
GetMethodArgumentsCount(Method * caller,BytecodeId methodId)76     static uint32_t GetMethodArgumentsCount(Method *caller, BytecodeId methodId)
77     {
78         auto resolvedId = caller->GetClass()->ResolveMethodIndex(methodId.AsIndex());
79         auto *pf = caller->GetPandaFile();
80         panda_file::MethodDataAccessor mda(*pf, resolvedId);
81         panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
82         return pda.GetNumArgs();
83     }
84 
ResolveField(ManagedThread * thread,const Method & caller,BytecodeId id,bool isStatic)85     static Field *ResolveField(ManagedThread *thread, const Method &caller, BytecodeId id, bool isStatic)
86     {
87         auto resolvedId = caller.GetClass()->ResolveFieldIndex(id.AsIndex());
88         auto *classLinker = Runtime::GetCurrent()->GetClassLinker();
89         auto *field = classLinker->GetField(caller, resolvedId, isStatic);
90         if (field == nullptr) {
91             return nullptr;
92         }
93 
94         auto *klass = field->GetClass();
95         if (!klass->IsInitialized() && !classLinker->InitializeClass(thread, field->GetClass())) {
96             return nullptr;
97         }
98 
99         return field;
100     }
101 
102     template <bool NEED_INIT>
ResolveClass(ManagedThread * thread,const Method & caller,BytecodeId id)103     static Class *ResolveClass(ManagedThread *thread, const Method &caller, BytecodeId id)
104     {
105         auto resolvedId = caller.GetClass()->ResolveClassIndex(id.AsIndex());
106         ClassLinker *classLinker = Runtime::GetCurrent()->GetClassLinker();
107         Class *klass = classLinker->GetClass(caller, resolvedId);
108 
109         if (klass == nullptr) {
110             return nullptr;
111         }
112 
113         if (NEED_INIT) {
114             auto *klassLinker = Runtime::GetCurrent()->GetClassLinker();
115             if (!klass->IsInitialized() && !klassLinker->InitializeClass(thread, klass)) {
116                 return nullptr;
117             }
118         }
119 
120         return klass;
121     }
122 
ResolveLiteralArray(PandaVM * vm,const Method & caller,BytecodeId id)123     static coretypes::Array *ResolveLiteralArray(PandaVM *vm, const Method &caller, BytecodeId id)
124     {
125         return Runtime::GetCurrent()->ResolveLiteralArray(vm, caller, id.AsIndex());
126     }
127 
GetCompilerHotnessThreshold()128     static uint32_t GetCompilerHotnessThreshold()
129     {
130         return Runtime::GetOptions().GetCompilerHotnessThreshold();
131     }
132 
IsCompilerEnableJit()133     static bool IsCompilerEnableJit()
134     {
135         return Runtime::GetOptions().IsCompilerEnableJit();
136     }
137 
SetCurrentFrame(ManagedThread * thread,Frame * frame)138     static void SetCurrentFrame(ManagedThread *thread, Frame *frame)
139     {
140         thread->SetCurrentFrame(frame);
141     }
142 
GetNotificationManager()143     static RuntimeNotificationManager *GetNotificationManager()
144     {
145         return Runtime::GetCurrent()->GetNotificationManager();
146     }
147 
CreateArray(Class * klass,coretypes::ArraySizeT length)148     static coretypes::Array *CreateArray(Class *klass, coretypes::ArraySizeT length)
149     {
150         return coretypes::Array::Create(klass, length);
151     }
152 
153     static ObjectHeader *CreateObject(Class *klass);
154     static ObjectHeader *CreateObject(ManagedThread *thread, Class *klass);
155 
InvokeMethod(ManagedThread * thread,Method * method,Value * args)156     static Value InvokeMethod(ManagedThread *thread, Method *method, Value *args)
157     {
158         return method->Invoke(thread, args);
159     }
160 
FindCatchBlock(const Method & method,ObjectHeader * exception,uint32_t pc)161     static uint32_t FindCatchBlock(const Method &method, ObjectHeader *exception, uint32_t pc)
162     {
163         return method.FindCatchBlock(exception->ClassAddr<Class>(), pc);
164     }
165 
ThrowNullPointerException()166     static void ThrowNullPointerException()
167     {
168         return ark::ThrowNullPointerException();
169     }
170 
ThrowArrayIndexOutOfBoundsException(coretypes::ArraySsizeT idx,coretypes::ArraySizeT length)171     static void ThrowArrayIndexOutOfBoundsException(coretypes::ArraySsizeT idx, coretypes::ArraySizeT length)
172     {
173         ark::ThrowArrayIndexOutOfBoundsException(idx, length);
174     }
175 
ThrowNegativeArraySizeException(coretypes::ArraySsizeT size)176     static void ThrowNegativeArraySizeException(coretypes::ArraySsizeT size)
177     {
178         ark::ThrowNegativeArraySizeException(size);
179     }
180 
ThrowArithmeticException()181     static void ThrowArithmeticException()
182     {
183         ark::ThrowArithmeticException();
184     }
185 
ThrowClassCastException(Class * dstType,Class * srcType)186     static void ThrowClassCastException(Class *dstType, Class *srcType)
187     {
188         ark::ThrowClassCastException(dstType, srcType);
189     }
190 
ThrowAbstractMethodError(Method * method)191     static void ThrowAbstractMethodError(Method *method)
192     {
193         ark::ThrowAbstractMethodError(method);
194     }
195 
ThrowIncompatibleClassChangeErrorForMethodConflict(Method * method)196     static void ThrowIncompatibleClassChangeErrorForMethodConflict(Method *method)
197     {
198         ark::ThrowIncompatibleClassChangeErrorForMethodConflict(method);
199     }
200 
ThrowOutOfMemoryError(const PandaString & msg)201     static void ThrowOutOfMemoryError(const PandaString &msg)
202     {
203         ark::ThrowOutOfMemoryError(msg);
204     }
205 
ThrowArrayStoreException(Class * arrayClass,Class * elemClass)206     static void ThrowArrayStoreException(Class *arrayClass, Class *elemClass)
207     {
208         ark::ThrowArrayStoreException(arrayClass, elemClass);
209     }
210 
ThrowIllegalAccessException(const PandaString & msg)211     static void ThrowIllegalAccessException(const PandaString &msg)
212     {
213         ark::ThrowIllegalAccessException(msg);
214     }
215 
ThrowVerificationException(const PandaString & msg)216     static void ThrowVerificationException(const PandaString &msg)
217     {
218         return ark::ThrowVerificationException(msg);
219     }
220 
ThrowTypedErrorDyn(const std::string & msg)221     static void ThrowTypedErrorDyn(const std::string &msg)
222     {
223         ark::ThrowTypedErrorDyn(msg);
224     }
225 
ThrowReferenceErrorDyn(const std::string & msg)226     static void ThrowReferenceErrorDyn(const std::string &msg)
227     {
228         ark::ThrowReferenceErrorDyn(msg);
229     }
230 
231     template <bool IS_DYNAMIC = false>
CreateFrame(uint32_t nregs,Method * method,Frame * prev)232     static Frame *CreateFrame(uint32_t nregs, Method *method, Frame *prev)
233     {
234         return ark::CreateFrameWithSize(Frame::GetActualSize<IS_DYNAMIC>(nregs), nregs, method, prev);
235     }
236 
237     template <bool IS_DYNAMIC = false>
CreateFrameWithActualArgs(uint32_t nregs,uint32_t numActualArgs,Method * method,Frame * prev)238     static Frame *CreateFrameWithActualArgs(uint32_t nregs, uint32_t numActualArgs, Method *method, Frame *prev)
239     {
240         return ark::CreateFrameWithActualArgsAndSize(Frame::GetActualSize<IS_DYNAMIC>(nregs), nregs, numActualArgs,
241                                                      method, prev);
242     }
243 
CreateFrameWithActualArgsAndSize(uint32_t size,uint32_t nregs,uint32_t numActualArgs,Method * method,Frame * prev)244     ALWAYS_INLINE static Frame *CreateFrameWithActualArgsAndSize(uint32_t size, uint32_t nregs, uint32_t numActualArgs,
245                                                                  Method *method, Frame *prev)
246     {
247         return ark::CreateFrameWithActualArgsAndSize(size, nregs, numActualArgs, method, prev);
248     }
249 
250     template <bool IS_DYNAMIC = false>
CreateNativeFrameWithActualArgs(uint32_t nregs,uint32_t numActualArgs,Method * method,Frame * prev)251     static Frame *CreateNativeFrameWithActualArgs(uint32_t nregs, uint32_t numActualArgs, Method *method, Frame *prev)
252     {
253         return ark::CreateNativeFrameWithActualArgsAndSize(Frame::GetActualSize<IS_DYNAMIC>(nregs), nregs,
254                                                            numActualArgs, method, prev);
255     }
256 
FreeFrame(ManagedThread * thread,Frame * frame)257     ALWAYS_INLINE static void FreeFrame(ManagedThread *thread, Frame *frame)
258     {
259         thread->GetStackFrameAllocator()->Free(frame->GetExt());
260     }
261 
ThreadSuspension(ManagedThread * thread)262     static void ThreadSuspension(ManagedThread *thread)
263     {
264         thread->WaitSuspension();
265     }
266 
ThreadRuntimeTermination(ManagedThread * thread)267     static void ThreadRuntimeTermination(ManagedThread *thread)
268     {
269         thread->OnRuntimeTerminated();
270     }
271 
GetLanguageContext(Method * methodPtr)272     static panda_file::SourceLang GetLanguageContext(Method *methodPtr)
273     {
274         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*methodPtr);
275         return ctx.GetLanguage();
276     }
277 
278     /**
279      * @brief Executes external implementation of safepoint
280      *
281      * It is not-inlined version of safepoint.
282      * Shouldn't be used in production in the JIT.
283      */
Safepoint(ManagedThread * thread)284     static void Safepoint(ManagedThread *thread)
285     {
286 #ifndef NDEBUG
287         // NOTE(sarychevkonstantin, #I9624): achieve consistency between mutator lock ownership and IsManaged method
288         if (Runtime::GetOptions().IsRunGcEverySafepoint() && Thread::GetCurrent()->GetMutatorLock()->HasLock()) {
289             auto *vm = ManagedThread::GetCurrent()->GetVM();
290             vm->GetGCTrigger()->TriggerGcIfNeeded(vm->GetGC());
291         }
292 #endif
293         ASSERT(thread != nullptr);
294         ASSERT(thread->IsRuntimeCallEnabled());
295         if (UNLIKELY(thread->IsRuntimeTerminated())) {
296             ThreadRuntimeTermination(thread);
297         }
298         if (thread->IsSuspended()) {
299             ThreadSuspension(thread);
300         }
301     }
302 
Safepoint()303     static void Safepoint()
304     {
305         Safepoint(ManagedThread::GetCurrent());
306     }
307 
GetLanguageContext(const Method & method)308     static LanguageContext GetLanguageContext(const Method &method)
309     {
310         return Runtime::GetCurrent()->GetLanguageContext(method);
311     }
312 };
313 
314 }  // namespace ark::interpreter
315 
316 #endif  // PANDA_INTERPRETER_RUNTIME_INTERFACE_H_
317