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