1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ 18 #define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ 19 20 #include <jni.h> 21 #include <stdint.h> 22 23 #include "base/callee_save_type.h" 24 #include "base/locks.h" 25 #include "base/macros.h" 26 #include "dex/dex_file_types.h" 27 #include "dex/dex_instruction.h" 28 #include "gc/allocator_type.h" 29 #include "handle.h" 30 #include "jvalue.h" 31 32 namespace art { 33 34 namespace mirror { 35 class Array; 36 class Class; 37 class MethodHandle; 38 class MethodType; 39 class Object; 40 class String; 41 } // namespace mirror 42 43 class ArtField; 44 class ArtMethod; 45 class HandleScope; 46 enum InvokeType : uint32_t; 47 class MethodReference; 48 class OatQuickMethodHeader; 49 class ScopedObjectAccessAlreadyRunnable; 50 class Thread; 51 52 // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it 53 // cannot be resolved, throw an error. If it can, use it to create an instance. 54 template <bool kInstrumented = true> 55 ALWAYS_INLINE inline ObjPtr<mirror::Object> AllocObjectFromCode(ObjPtr<mirror::Class> klass, 56 Thread* self, 57 gc::AllocatorType allocator_type) 58 REQUIRES_SHARED(Locks::mutator_lock_) 59 REQUIRES(!Roles::uninterruptible_); 60 61 // Given the context of a calling Method and a resolved class, create an instance. 62 template <bool kInstrumented> 63 ALWAYS_INLINE 64 inline ObjPtr<mirror::Object> AllocObjectFromCodeResolved(ObjPtr<mirror::Class> klass, 65 Thread* self, 66 gc::AllocatorType allocator_type) 67 REQUIRES_SHARED(Locks::mutator_lock_) 68 REQUIRES(!Roles::uninterruptible_); 69 70 // Given the context of a calling Method and an initialized class, create an instance. 71 template <bool kInstrumented> 72 ALWAYS_INLINE 73 inline ObjPtr<mirror::Object> AllocObjectFromCodeInitialized(ObjPtr<mirror::Class> klass, 74 Thread* self, 75 gc::AllocatorType allocator_type) 76 REQUIRES_SHARED(Locks::mutator_lock_) 77 REQUIRES(!Roles::uninterruptible_); 78 79 80 template <bool kAccessCheck> 81 ALWAYS_INLINE inline ObjPtr<mirror::Class> CheckArrayAlloc(dex::TypeIndex type_idx, 82 int32_t component_count, 83 ArtMethod* method, 84 bool* slow_path) 85 REQUIRES_SHARED(Locks::mutator_lock_) 86 REQUIRES(!Roles::uninterruptible_); 87 88 // Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If 89 // it cannot be resolved, throw an error. If it can, use it to create an array. 90 // When verification/compiler hasn't been able to verify access, optionally perform an access 91 // check. 92 template <bool kAccessCheck, bool kInstrumented = true> 93 ALWAYS_INLINE inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx, 94 int32_t component_count, 95 ArtMethod* method, 96 Thread* self, 97 gc::AllocatorType allocator_type) 98 REQUIRES_SHARED(Locks::mutator_lock_) 99 REQUIRES(!Roles::uninterruptible_); 100 101 template <bool kInstrumented> 102 ALWAYS_INLINE 103 inline ObjPtr<mirror::Array> AllocArrayFromCodeResolved(ObjPtr<mirror::Class> klass, 104 int32_t component_count, 105 Thread* self, 106 gc::AllocatorType allocator_type) 107 REQUIRES_SHARED(Locks::mutator_lock_) 108 REQUIRES(!Roles::uninterruptible_); 109 110 enum FindFieldFlags { 111 InstanceBit = 1 << 0, 112 StaticBit = 1 << 1, 113 ObjectBit = 1 << 2, 114 PrimitiveBit = 1 << 3, 115 ReadBit = 1 << 4, 116 WriteBit = 1 << 5, 117 }; 118 119 // Type of find field operation for fast and slow case. 120 enum FindFieldType { 121 InstanceObjectRead = InstanceBit | ObjectBit | ReadBit, 122 InstanceObjectWrite = InstanceBit | ObjectBit | WriteBit, 123 InstancePrimitiveRead = InstanceBit | PrimitiveBit | ReadBit, 124 InstancePrimitiveWrite = InstanceBit | PrimitiveBit | WriteBit, 125 StaticObjectRead = StaticBit | ObjectBit | ReadBit, 126 StaticObjectWrite = StaticBit | ObjectBit | WriteBit, 127 StaticPrimitiveRead = StaticBit | PrimitiveBit | ReadBit, 128 StaticPrimitiveWrite = StaticBit | PrimitiveBit | WriteBit, 129 }; 130 131 template<FindFieldType type, bool access_check> 132 inline ArtField* FindFieldFromCode(uint32_t field_idx, 133 ArtMethod* referrer, 134 Thread* self, 135 size_t expected_size) 136 REQUIRES_SHARED(Locks::mutator_lock_) 137 REQUIRES(!Roles::uninterruptible_); 138 139 template<InvokeType type, bool access_check> 140 inline ArtMethod* FindMethodFromCode(uint32_t method_idx, 141 ObjPtr<mirror::Object>* this_object, 142 ArtMethod* referrer, 143 Thread* self) 144 REQUIRES_SHARED(Locks::mutator_lock_) 145 REQUIRES(!Roles::uninterruptible_); 146 147 // Fast path field resolution that can't initialize classes or throw exceptions. 148 inline ArtField* FindFieldFast(uint32_t field_idx, 149 ArtMethod* referrer, 150 FindFieldType type, 151 size_t expected_size) 152 REQUIRES_SHARED(Locks::mutator_lock_); 153 154 // Fast path method resolution that can't throw exceptions. 155 template <InvokeType type, bool access_check> 156 inline ArtMethod* FindMethodFast(uint32_t method_idx, 157 ObjPtr<mirror::Object> this_object, 158 ArtMethod* referrer) 159 REQUIRES_SHARED(Locks::mutator_lock_); 160 161 inline ObjPtr<mirror::Class> ResolveVerifyAndClinit(dex::TypeIndex type_idx, 162 ArtMethod* referrer, 163 Thread* self, 164 bool can_run_clinit, 165 bool verify_access) 166 REQUIRES_SHARED(Locks::mutator_lock_) 167 REQUIRES(!Roles::uninterruptible_); 168 169 ObjPtr<mirror::MethodHandle> ResolveMethodHandleFromCode(ArtMethod* referrer, 170 uint32_t method_handle_idx) 171 REQUIRES_SHARED(Locks::mutator_lock_) 172 REQUIRES(!Roles::uninterruptible_); 173 174 ObjPtr<mirror::MethodType> ResolveMethodTypeFromCode(ArtMethod* referrer, dex::ProtoIndex proto_idx) 175 REQUIRES_SHARED(Locks::mutator_lock_) 176 REQUIRES(!Roles::uninterruptible_); 177 178 void CheckReferenceResult(Handle<mirror::Object> o, Thread* self) 179 REQUIRES_SHARED(Locks::mutator_lock_) 180 REQUIRES(!Roles::uninterruptible_); 181 182 JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, 183 const char* shorty, 184 jobject rcvr_jobj, 185 jobject interface_art_method_jobj, 186 std::vector<jvalue>& args) 187 REQUIRES_SHARED(Locks::mutator_lock_) 188 REQUIRES(!Roles::uninterruptible_); 189 190 bool FillArrayData(ObjPtr<mirror::Object> obj, const Instruction::ArrayDataPayload* payload) 191 REQUIRES_SHARED(Locks::mutator_lock_) 192 REQUIRES(!Roles::uninterruptible_); 193 194 template <typename INT_TYPE, typename FLOAT_TYPE> 195 inline INT_TYPE art_float_to_integral(FLOAT_TYPE f); 196 197 ArtMethod* GetCalleeSaveMethodCaller(ArtMethod** sp, 198 CalleeSaveType type, 199 bool do_caller_check = false) 200 REQUIRES_SHARED(Locks::mutator_lock_); 201 202 struct CallerAndOuterMethod { 203 ArtMethod* caller; 204 ArtMethod* outer_method; 205 }; 206 207 CallerAndOuterMethod GetCalleeSaveMethodCallerAndOuterMethod(Thread* self, CalleeSaveType type) 208 REQUIRES_SHARED(Locks::mutator_lock_); 209 210 ArtMethod* GetCalleeSaveOuterMethod(Thread* self, CalleeSaveType type) 211 REQUIRES_SHARED(Locks::mutator_lock_); 212 213 // Returns whether we need to do class initialization check before invoking the method. 214 // The caller is responsible for performing that check. 215 bool NeedsClinitCheckBeforeCall(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_); 216 217 constexpr size_t kJniCookieSize = sizeof(uint32_t); 218 219 inline HandleScope* GetGenericJniHandleScope(ArtMethod** managed_sp, 220 size_t num_handle_scope_references); 221 222 // Update .bss method entrypoint if the `callee_reference` has an associated oat file 223 // and that oat file has a .bss entry for the `callee_reference`. 224 void MaybeUpdateBssMethodEntry(ArtMethod* callee, MethodReference callee_reference); 225 226 } // namespace art 227 228 #endif // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_ 229