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