/* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_RUNTIME_ENTRYPOINTS_QUICK_RUNTIME_ENTRYPOINTS_LIST_H_ #define ART_RUNTIME_ENTRYPOINTS_QUICK_RUNTIME_ENTRYPOINTS_LIST_H_ #include "entrypoints/entrypoint_utils.h" #include "arch/instruction_set.h" #include namespace art { namespace mirror { class Array; class Class; template class CompressedReference; class Object; class String; class Throwable; template class PrimitiveArray; using ByteArray = PrimitiveArray; using CharArray = PrimitiveArray; } // namespace mirror class ArtMethod; template class GcRoot; template class StackReference; class Thread; class Context; enum class DeoptimizationKind; // All C++ quick entrypoints, i.e.: C++ entrypoint functions called from quick assembly code. // Format is name, attribute, return type, argument types. #define RUNTIME_ENTRYPOINT_LIST(V) \ V(artDeliverPendingExceptionFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self) \ V(artInvokeObsoleteMethod, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ ArtMethod* method, \ Thread* self) \ V(artDeliverExceptionFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ mirror::Throwable* exception, \ Thread* self) \ V(artThrowNullPointerExceptionFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self) \ V(artThrowNullPointerExceptionFromSignal, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ uintptr_t addr, \ Thread* self) \ V(artThrowDivZeroFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self) \ V(artThrowArrayBoundsFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ int index, \ int length, \ Thread* self) \ V(artThrowStringBoundsFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ int index, \ int length, \ Thread* self) \ V(artThrowStackOverflowFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self) \ V(artThrowClassCastExceptionForObject, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ mirror::Object* obj, \ mirror::Class* dest_type, \ Thread* self) \ V(artThrowArrayStoreException, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ mirror::Object* array, \ mirror::Object* value, \ Thread* self) \ \ V(artDeoptimizeIfNeeded, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self, \ uintptr_t result, \ bool is_ref) \ V(artTestSuspendFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self) \ V(artImplicitSuspendFromCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self) \ V(artCompileOptimized, REQUIRES_SHARED(Locks::mutator_lock_), void, \ ArtMethod* method, \ Thread* self) \ \ V(artQuickToInterpreterBridge, REQUIRES_SHARED(Locks::mutator_lock_), uint64_t, \ ArtMethod* method, \ Thread* self, \ ArtMethod** sp) \ V(artQuickProxyInvokeHandler, REQUIRES_SHARED(Locks::mutator_lock_), uint64_t, \ ArtMethod* proxy_method, \ mirror::Object* receiver, \ Thread* self, \ ArtMethod** sp) \ V(artQuickResolutionTrampoline, REQUIRES_SHARED(Locks::mutator_lock_), const void*, \ ArtMethod* called, \ mirror::Object* receiver, \ Thread* self, \ ArtMethod** sp) \ V(artQuickGenericJniTrampoline, REQUIRES_SHARED(Locks::mutator_lock_) \ NO_THREAD_SAFETY_ANALYSIS, const void*, \ Thread* self, \ ArtMethod** managed_sp, \ uintptr_t* reserved_area) \ V(artQuickGenericJniEndTrampoline, , uint64_t, \ Thread* self, \ jvalue result, \ uint64_t result_fp) \ V(artInvokeInterfaceTrampolineWithAccessCheck, REQUIRES_SHARED(Locks::mutator_lock_), \ TwoWordReturn, \ uint32_t method_idx, \ mirror::Object* this_object, \ Thread* self, \ ArtMethod** sp) \ V(artInvokeDirectTrampolineWithAccessCheck, REQUIRES_SHARED(Locks::mutator_lock_), \ TwoWordReturn, \ uint32_t method_idx, \ mirror::Object* this_object, \ Thread* self, \ ArtMethod** sp) \ V(artInvokeStaticTrampolineWithAccessCheck, REQUIRES_SHARED(Locks::mutator_lock_), \ TwoWordReturn, \ uint32_t method_idx, \ [[maybe_unused]] mirror::Object* this_object, \ Thread* self, \ ArtMethod** sp) \ V(artInvokeSuperTrampolineWithAccessCheck, REQUIRES_SHARED(Locks::mutator_lock_), \ TwoWordReturn, \ uint32_t method_idx, \ mirror::Object* this_object, \ Thread* self, \ ArtMethod** sp) \ V(artInvokeVirtualTrampolineWithAccessCheck, REQUIRES_SHARED(Locks::mutator_lock_), \ TwoWordReturn, \ uint32_t method_idx, \ mirror::Object* this_object, \ Thread* self, \ ArtMethod** sp) \ V(artInvokeInterfaceTrampoline, REQUIRES_SHARED(Locks::mutator_lock_), TwoWordReturn, \ ArtMethod* interface_method, \ mirror::Object* raw_this_object, \ Thread* self, \ ArtMethod** sp) \ V(artInvokePolymorphic, REQUIRES_SHARED(Locks::mutator_lock_), uint64_t, \ mirror::Object* raw_receiver, \ Thread* self, \ ArtMethod** sp) \ V(artInvokePolymorphicWithHiddenReceiver, REQUIRES_SHARED(Locks::mutator_lock_), uint64_t, \ mirror::Object* raw_receiver, \ Thread* self, \ ArtMethod** sp) \ V(artInvokeCustom, REQUIRES_SHARED(Locks::mutator_lock_), uint64_t, \ uint32_t call_site_idx, \ Thread* self, \ ArtMethod** sp) \ V(artJniMethodEntryHook, REQUIRES_SHARED(Locks::mutator_lock_), void, \ Thread* self) \ V(artMethodEntryHook, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ ArtMethod* method, \ Thread* self, \ ArtMethod** sp) \ V(artMethodExitHook, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self, \ ArtMethod** sp, \ uint64_t* gpr_result, \ uint64_t* fpr_result, \ uint32_t frame_size) \ \ V(artIsAssignableFromCode, REQUIRES_SHARED(Locks::mutator_lock_), size_t, \ mirror::Class* klass, \ mirror::Class* ref_class) \ V(artInstanceOfFromCode, REQUIRES_SHARED(Locks::mutator_lock_), size_t, \ mirror::Object* obj, \ mirror::Class* ref_class) \ \ V(artInitializeStaticStorageFromCode, REQUIRES_SHARED(Locks::mutator_lock_), mirror::Class*, \ mirror::Class* klass, \ Thread* self) \ V(artResolveTypeFromCode, REQUIRES_SHARED(Locks::mutator_lock_), mirror::Class*, \ uint32_t type_idx, \ Thread* self) \ V(artResolveTypeAndVerifyAccessFromCode, REQUIRES_SHARED(Locks::mutator_lock_), mirror::Class*, \ uint32_t type_idx, \ Thread* self) \ V(artResolveMethodHandleFromCode, REQUIRES_SHARED(Locks::mutator_lock_), mirror::MethodHandle*, \ uint32_t method_handle_idx, \ Thread* self) \ V(artResolveMethodTypeFromCode, REQUIRES_SHARED(Locks::mutator_lock_), mirror::MethodType*, \ uint32_t proto_idx, \ Thread* self) \ V(artResolveStringFromCode, REQUIRES_SHARED(Locks::mutator_lock_), mirror::String*, \ int32_t string_idx, Thread* self) \ \ V(artDeoptimize, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ Thread* self, \ bool skip_method_exit_callbacks) \ V(artDeoptimizeFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), Context*, \ DeoptimizationKind kind, \ Thread* self) \ \ V(artHandleFillArrayDataFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ const Instruction::ArrayDataPayload* payload, \ mirror::Array* array, \ Thread* self) \ \ V(artJniReadBarrier, REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR, void, \ ArtMethod* method) \ V(artJniMethodStart, UNLOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR, void, \ Thread* self) \ V(artJniUnlockObject, NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) \ REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR, void, \ mirror::Object* locked, \ Thread* self) \ V(artJniMethodEnd, SHARED_LOCK_FUNCTION(Locks::mutator_lock_) HOT_ATTR, void, \ Thread* self) \ V(artJniMonitoredMethodStart, UNLOCK_FUNCTION(Locks::mutator_lock_), void, \ Thread* self) \ V(artJniMonitoredMethodEnd, SHARED_LOCK_FUNCTION(Locks::mutator_lock_), void, \ Thread* self) \ \ V(artStringBuilderAppend, REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR, mirror::String*, \ uint32_t format, \ const uint32_t* args, \ Thread* self) \ \ V(artContextCopyForLongJump, , void, \ Context* context, \ uintptr_t* gprs, \ uintptr_t* fprs) \ \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, DlMalloc) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, RosAlloc) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, BumpPointer) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, TLAB) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, Region) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, RegionTLAB) \ \ ART_GET_FIELD_FROM_CODE_DECL(V, Byte, ssize_t, uint32_t) \ ART_GET_FIELD_FROM_CODE_DECL(V, Boolean, size_t, uint32_t) \ ART_GET_FIELD_FROM_CODE_DECL(V, Short, ssize_t, uint16_t) \ ART_GET_FIELD_FROM_CODE_DECL(V, Char, size_t, uint16_t) \ ART_GET_FIELD_FROM_CODE_DECL(V, 32, FIELD_RETURN_TYPE_32, uint32_t) \ ART_GET_FIELD_FROM_CODE_DECL(V, 64, uint64_t, uint64_t) \ ART_GET_FIELD_FROM_CODE_DECL(V, Obj, mirror::Object*, mirror::Object*) \ V(artSet8StaticFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ uint32_t new_value, \ Thread* self) \ V(artSet16StaticFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ uint16_t new_value, \ Thread* self) \ V(artSet8InstanceFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ mirror::Object* obj, \ uint8_t new_value, \ Thread* self) \ V(artSet16InstanceFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ mirror::Object* obj, \ uint16_t new_value, \ Thread* self) \ V(artSet8StaticFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ uint32_t new_value, \ ArtMethod* referrer, \ Thread* self) \ V(artSet16StaticFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ uint16_t new_value, \ ArtMethod* referrer, \ Thread* self) \ V(artSet8InstanceFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ mirror::Object* obj, \ uint8_t new_value, \ ArtMethod* referrer, \ Thread* self) \ V(artSet16InstanceFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ mirror::Object* obj, \ uint16_t new_value, \ ArtMethod* referrer, \ Thread* self) \ V(artReadBarrierMark, REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR, mirror::Object*, \ mirror::Object* obj) \ V(artReadBarrierSlow, REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR, mirror::Object*, \ mirror::Object* ref, \ mirror::Object* obj, \ uint32_t offset) \ V(artReadBarrierForRootSlow, REQUIRES_SHARED(Locks::mutator_lock_) HOT_ATTR, mirror::Object*, \ GcRoot* root) \ \ V(artLockObjectFromCode, NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) \ REQUIRES_SHARED(Locks::mutator_lock_), int, \ mirror::Object* obj, \ Thread* self) \ V(artUnlockObjectFromCode, NO_THREAD_SAFETY_ANALYSIS REQUIRES(!Roles::uninterruptible_) \ REQUIRES_SHARED(Locks::mutator_lock_), int, \ mirror::Object* obj, \ Thread* self) \ \ V(artFindNativeMethodRunnable, REQUIRES_SHARED(Locks::mutator_lock_), const void*, \ Thread* self) \ V(artFindNativeMethod, , const void*, \ Thread* self) \ V(artCriticalNativeFrameSize, REQUIRES_SHARED(Locks::mutator_lock_), size_t, \ ArtMethod* method, \ uintptr_t caller_pc) \ \ V(artLmul, , int64_t, \ int64_t a, \ int64_t b) \ V(artLdiv, , int64_t, \ int64_t a, \ int64_t b) \ V(artLmod, , int64_t, \ int64_t a, \ int64_t b) \ \ V(art_l2d, , double, \ int64_t l) \ V(art_l2f, , float, \ int64_t l) \ V(art_d2l, , int64_t, \ double d) \ V(art_f2l, , int64_t, \ float f) \ V(art_d2i, , int32_t, \ double d) \ V(art_f2i, , int32_t, \ float f) \ V(fmodf, , float, \ float, \ float) \ V(fmod, , double, \ double, \ double) // Declarations from quick_alloc_entrypoints.cc #define GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR_INST(V, suffix, suffix2) \ V(artAllocObjectFromCodeWithChecks##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::Object*, \ mirror::Class* klass, \ Thread* self) \ V(artAllocObjectFromCodeResolved##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::Object*, \ mirror::Class* klass, \ Thread* self) \ V(artAllocObjectFromCodeInitialized##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::Object*, \ mirror::Class* klass, \ Thread* self) \ V(artAllocStringObject##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::String*, \ mirror::Class* klass, \ Thread* self) \ V(artAllocArrayFromCodeResolved##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::Array*, \ mirror::Class* klass, \ int32_t component_count, \ Thread* self) \ V(artAllocStringFromBytesFromCode##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::String*, \ mirror::ByteArray* byte_array, \ int32_t high, \ int32_t offset, \ int32_t byte_count, \ Thread* self) \ V(artAllocStringFromCharsFromCode##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::String*, \ int32_t offset, \ int32_t char_count, \ mirror::CharArray* char_array, \ Thread* self) \ V(artAllocStringFromStringFromCode##suffix##suffix2, REQUIRES_SHARED(Locks::mutator_lock_), \ mirror::String*, \ mirror::String* string, \ Thread* self) #define GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR(V, suffix) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR_INST(V, suffix, Instrumented) \ GENERATE_ENTRYPOINTS_DECL_FOR_ALLOCATOR_INST(V, suffix, ) // Declarations from quick_field_entrypoints.cc #define ART_GET_FIELD_FROM_CODE_DECL(V, Kind, RetType, SetType) \ V(artGet ## Kind ## StaticFromCode, REQUIRES_SHARED(Locks::mutator_lock_), RetType, \ uint32_t field_idx, \ ArtMethod* referrer, \ Thread* self) \ V(artGet ## Kind ## InstanceFromCode, REQUIRES_SHARED(Locks::mutator_lock_), RetType, \ uint32_t field_idx, \ mirror::Object* obj, \ ArtMethod* referrer, \ Thread* self) \ V(artSet ## Kind ## StaticFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ SetType new_value, \ ArtMethod* referrer, \ Thread* self) \ V(artSet ## Kind ## InstanceFromCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ mirror::Object* obj, \ SetType new_value, \ ArtMethod* referrer, \ Thread* self) \ V(artGet ## Kind ## StaticFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), RetType, \ uint32_t field_idx, \ Thread* self) \ V(artGet ## Kind ## InstanceFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), RetType, \ uint32_t field_idx, \ mirror::Object* obj, \ Thread* self) \ V(artSet ## Kind ## StaticFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ SetType new_value, \ Thread* self) \ V(artSet ## Kind ## InstanceFromCompiledCode, REQUIRES_SHARED(Locks::mutator_lock_), int, \ uint32_t field_idx, \ mirror::Object* obj, \ SetType new_value, \ Thread* self) #if defined(__riscv) #define FIELD_RETURN_TYPE_32 uint32_t #else #define FIELD_RETURN_TYPE_32 size_t #endif // Define a macro that will extract information from RUNTIME_ENTRYPOINT_LIST to create a function // declaration. #define ENTRYPOINT_ENUM(name, attr, rettype, ...) \ extern "C" rettype name(__VA_ARGS__) attr; // Declare all C++ quick entrypoints. RUNTIME_ENTRYPOINT_LIST(ENTRYPOINT_ENUM) #undef ENTRYPOINT_ENUM } // namespace art #endif // ART_RUNTIME_ENTRYPOINTS_QUICK_RUNTIME_ENTRYPOINTS_LIST_H_