• 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 #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 panda::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 resolved_id = caller.GetClass()->ResolveMethodIndex(id.AsIndex());
43         auto *class_linker = Runtime::GetCurrent()->GetClassLinker();
44         auto *method = class_linker->GetMethod(caller, resolved_id);
45         if (method == nullptr) {
46             return nullptr;
47         }
48 
49         auto *klass = method->GetClass();
50         if (!klass->IsInitialized() && !class_linker->InitializeClass(thread, klass)) {
51             return nullptr;
52         }
53 
54         return method;
55     }
56 
GetMethodName(const Method * caller,BytecodeId method_id)57     static const uint8_t *GetMethodName(const Method *caller, BytecodeId method_id)
58     {
59         auto resolved_id = caller->GetClass()->ResolveMethodIndex(method_id.AsIndex());
60         const auto *pf = caller->GetPandaFile();
61         const panda_file::MethodDataAccessor MDA(*pf, resolved_id);
62         return pf->GetStringData(MDA.GetNameId()).data;
63     }
64 
GetMethodClass(const Method * caller,BytecodeId method_id)65     static Class *GetMethodClass(const Method *caller, BytecodeId method_id)
66     {
67         auto resolved_id = caller->GetClass()->ResolveMethodIndex(method_id.AsIndex());
68         const auto *pf = caller->GetPandaFile();
69         const panda_file::MethodDataAccessor MDA(*pf, resolved_id);
70         auto class_id = MDA.GetClassId();
71 
72         auto *class_linker = Runtime::GetCurrent()->GetClassLinker();
73         return class_linker->GetClass(*caller, class_id);
74     }
75 
GetMethodArgumentsCount(Method * caller,BytecodeId method_id)76     static uint32_t GetMethodArgumentsCount(Method *caller, BytecodeId method_id)
77     {
78         auto resolved_id = caller->GetClass()->ResolveMethodIndex(method_id.AsIndex());
79         auto *pf = caller->GetPandaFile();
80         panda_file::MethodDataAccessor mda(*pf, resolved_id);
81         panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId());
82         return pda.GetNumArgs();
83     }
84 
ResolveField(ManagedThread * thread,const Method & caller,BytecodeId id)85     static Field *ResolveField(ManagedThread *thread, const Method &caller, BytecodeId id)
86     {
87         auto resolved_id = caller.GetClass()->ResolveFieldIndex(id.AsIndex());
88         auto *class_linker = Runtime::GetCurrent()->GetClassLinker();
89         auto *field = class_linker->GetField(caller, resolved_id);
90         if (field == nullptr) {
91             return nullptr;
92         }
93 
94         auto *klass = field->GetClass();
95         if (!klass->IsInitialized() && !class_linker->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 resolved_id = caller.GetClass()->ResolveClassIndex(id.AsIndex());
106         ClassLinker *class_linker = Runtime::GetCurrent()->GetClassLinker();
107         Class *klass = class_linker->GetClass(caller, resolved_id);
108 
109         if (klass == nullptr) {
110             return nullptr;
111         }
112 
113         if (need_init) {
114             auto *klass_linker = Runtime::GetCurrent()->GetClassLinker();
115             if (!klass->IsInitialized() && !klass_linker->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.AsFileId().GetOffset());
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::array_size_t length)148     static coretypes::Array *CreateArray(Class *klass, coretypes::array_size_t length)
149     {
150         return coretypes::Array::Create(klass, length);
151     }
152 
153     static ObjectHeader *CreateObject(Class *klass);
154 
InvokeMethod(ManagedThread * thread,Method * method,Value * args)155     static Value InvokeMethod(ManagedThread *thread, Method *method, Value *args)
156     {
157         return method->Invoke(thread, args);
158     }
159 
FindCatchBlock(const Method & method,ObjectHeader * exception,uint32_t pc)160     static uint32_t FindCatchBlock(const Method &method, ObjectHeader *exception, uint32_t pc)
161     {
162         return method.FindCatchBlock(exception->ClassAddr<Class>(), pc);
163     }
164 
ThrowNullPointerException()165     static void ThrowNullPointerException()
166     {
167         return panda::ThrowNullPointerException();
168     }
169 
ThrowArrayIndexOutOfBoundsException(coretypes::array_ssize_t idx,coretypes::array_size_t length)170     static void ThrowArrayIndexOutOfBoundsException(coretypes::array_ssize_t idx, coretypes::array_size_t length)
171     {
172         panda::ThrowArrayIndexOutOfBoundsException(idx, length);
173     }
174 
ThrowNegativeArraySizeException(coretypes::array_ssize_t size)175     static void ThrowNegativeArraySizeException(coretypes::array_ssize_t size)
176     {
177         panda::ThrowNegativeArraySizeException(size);
178     }
179 
ThrowArithmeticException()180     static void ThrowArithmeticException()
181     {
182         panda::ThrowArithmeticException();
183     }
184 
ThrowClassCastException(Class * dst_type,Class * src_type)185     static void ThrowClassCastException(Class *dst_type, Class *src_type)
186     {
187         panda::ThrowClassCastException(dst_type, src_type);
188     }
189 
ThrowAbstractMethodError(Method * method)190     static void ThrowAbstractMethodError(Method *method)
191     {
192         panda::ThrowAbstractMethodError(method);
193     }
194 
ThrowIncompatibleClassChangeErrorForMethodConflict(Method * method)195     static void ThrowIncompatibleClassChangeErrorForMethodConflict(Method *method)
196     {
197         panda::ThrowIncompatibleClassChangeErrorForMethodConflict(method);
198     }
199 
ThrowOutOfMemoryError(const PandaString & msg)200     static void ThrowOutOfMemoryError(const PandaString &msg)
201     {
202         panda::ThrowOutOfMemoryError(msg);
203     }
204 
ThrowArrayStoreException(Class * array_class,Class * elem_class)205     static void ThrowArrayStoreException(Class *array_class, Class *elem_class)
206     {
207         panda::ThrowArrayStoreException(array_class, elem_class);
208     }
209 
ThrowIllegalAccessException(const PandaString & msg)210     static void ThrowIllegalAccessException(const PandaString &msg)
211     {
212         panda::ThrowIllegalAccessException(msg);
213     }
214 
ThrowVerificationException(const PandaString & msg)215     static void ThrowVerificationException(const PandaString &msg)
216     {
217         return panda::ThrowVerificationException(msg);
218     }
219 
ThrowTypedErrorDyn(const std::string & msg)220     static void ThrowTypedErrorDyn(const std::string &msg)
221     {
222         panda::ThrowTypedErrorDyn(msg);
223     }
224 
ThrowReferenceErrorDyn(const std::string & msg)225     static void ThrowReferenceErrorDyn(const std::string &msg)
226     {
227         panda::ThrowReferenceErrorDyn(msg);
228     }
229 
230     template <bool is_dynamic = false>
CreateFrame(uint32_t nregs,Method * method,Frame * prev)231     static Frame *CreateFrame(uint32_t nregs, Method *method, Frame *prev)
232     {
233         return panda::CreateFrameWithSize(Frame::GetActualSize<is_dynamic>(nregs), nregs, method, prev);
234     }
235 
236     template <bool is_dynamic = false>
CreateFrameWithActualArgs(uint32_t nregs,uint32_t num_actual_args,Method * method,Frame * prev)237     static Frame *CreateFrameWithActualArgs(uint32_t nregs, uint32_t num_actual_args, Method *method, Frame *prev)
238     {
239         return panda::CreateFrameWithActualArgsAndSize(Frame::GetActualSize<is_dynamic>(nregs), nregs, num_actual_args,
240                                                        method, prev);
241     }
242 
CreateFrameWithActualArgsAndSize(uint32_t size,uint32_t nregs,uint32_t num_actual_args,Method * method,Frame * prev)243     ALWAYS_INLINE static Frame *CreateFrameWithActualArgsAndSize(uint32_t size, uint32_t nregs,
244                                                                  uint32_t num_actual_args, Method *method, Frame *prev)
245     {
246         return panda::CreateFrameWithActualArgsAndSize(size, nregs, num_actual_args, method, prev);
247     }
248 
249     template <bool is_dynamic = false>
CreateNativeFrameWithActualArgs(uint32_t nregs,uint32_t num_actual_args,Method * method,Frame * prev)250     static Frame *CreateNativeFrameWithActualArgs(uint32_t nregs, uint32_t num_actual_args, Method *method, Frame *prev)
251     {
252         return panda::CreateNativeFrameWithActualArgsAndSize(Frame::GetActualSize<is_dynamic>(nregs), nregs,
253                                                              num_actual_args, method, prev);
254     }
255 
FreeFrame(ManagedThread * thread,Frame * frame)256     ALWAYS_INLINE static void FreeFrame(ManagedThread *thread, Frame *frame)
257     {
258         thread->GetStackFrameAllocator()->Free(frame->GetExt());
259     }
260 
ThreadSuspension(ManagedThread * thread)261     static void ThreadSuspension(ManagedThread *thread)
262     {
263         thread->WaitSuspension();
264     }
265 
ThreadRuntimeTermination(ManagedThread * thread)266     static void ThreadRuntimeTermination(ManagedThread *thread)
267     {
268         thread->OnRuntimeTerminated();
269     }
270 
GetLanguageContext(Method * method_ptr)271     static panda_file::SourceLang GetLanguageContext(Method *method_ptr)
272     {
273         LanguageContext ctx = Runtime::GetCurrent()->GetLanguageContext(*method_ptr);
274         return ctx.GetLanguage();
275     }
276 
277     /**
278      * \brief Executes external implementation of safepoint
279      *
280      * It is not-inlined version of safepoint.
281      * Shouldn't be used in production in the JIT.
282      */
Safepoint()283     static void Safepoint()
284     {
285         ManagedThread *thread = ManagedThread::GetCurrent();
286         ASSERT(thread->IsRuntimeCallEnabled());
287         if (UNLIKELY(thread->IsRuntimeTerminated())) {
288             ThreadRuntimeTermination(thread);
289         }
290         if (thread->IsSuspended()) {
291             ThreadSuspension(thread);
292         }
293     }
294 
GetLanguageContext(const Method & method)295     static LanguageContext GetLanguageContext(const Method &method)
296     {
297         return Runtime::GetCurrent()->GetLanguageContext(method);
298     }
299 };
300 
301 }  // namespace panda::interpreter
302 
303 #endif  // PANDA_INTERPRETER_RUNTIME_INTERFACE_H_
304