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/macros.h"
24 #include "base/mutex.h"
25 #include "gc/allocator_type.h"
26 #include "invoke_type.h"
27 #include "jvalue.h"
28 
29 namespace art {
30 
31 namespace mirror {
32   class Class;
33   class Array;
34   class ArtField;
35   class ArtMethod;
36   class Object;
37   class String;
38 }  // namespace mirror
39 
40 class ScopedObjectAccessAlreadyRunnable;
41 class Thread;
42 
43 template <const bool kAccessCheck>
44 ALWAYS_INLINE static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
45                                                             mirror::ArtMethod* method,
46                                                             Thread* self, bool* slow_path)
47     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
48 
49 // TODO: Fix no thread safety analysis when annotalysis is smarter.
50 ALWAYS_INLINE static inline mirror::Class* CheckClassInitializedForObjectAlloc(mirror::Class* klass,
51                                                                                Thread* self, bool* slow_path)
52     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
53 
54 // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
55 // cannot be resolved, throw an error. If it can, use it to create an instance.
56 // When verification/compiler hasn't been able to verify access, optionally perform an access
57 // check.
58 template <bool kAccessCheck, bool kInstrumented>
59 ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCode(uint32_t type_idx,
60                                                                 mirror::ArtMethod* method,
61                                                                 Thread* self,
62                                                                 gc::AllocatorType allocator_type)
63     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
64 
65 // Given the context of a calling Method and a resolved class, create an instance.
66 template <bool kInstrumented>
67 ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCodeResolved(mirror::Class* klass,
68                                                                         mirror::ArtMethod* method,
69                                                                         Thread* self,
70                                                                         gc::AllocatorType allocator_type)
71     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
72 
73 // Given the context of a calling Method and an initialized class, create an instance.
74 template <bool kInstrumented>
75 ALWAYS_INLINE static inline mirror::Object* AllocObjectFromCodeInitialized(mirror::Class* klass,
76                                                                            mirror::ArtMethod* method,
77                                                                            Thread* self,
78                                                                            gc::AllocatorType allocator_type)
79     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
80 
81 
82 template <bool kAccessCheck>
83 ALWAYS_INLINE static inline mirror::Class* CheckArrayAlloc(uint32_t type_idx,
84                                                            mirror::ArtMethod* method,
85                                                            int32_t component_count,
86                                                            bool* slow_path)
87     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
88 
89 // Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
90 // it cannot be resolved, throw an error. If it can, use it to create an array.
91 // When verification/compiler hasn't been able to verify access, optionally perform an access
92 // check.
93 template <bool kAccessCheck, bool kInstrumented>
94 ALWAYS_INLINE static inline mirror::Array* AllocArrayFromCode(uint32_t type_idx,
95                                                               mirror::ArtMethod* method,
96                                                               int32_t component_count,
97                                                               Thread* self,
98                                                               gc::AllocatorType allocator_type)
99     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
100 
101 template <bool kAccessCheck, bool kInstrumented>
102 ALWAYS_INLINE static inline mirror::Array* AllocArrayFromCodeResolved(mirror::Class* klass,
103                                                                       mirror::ArtMethod* method,
104                                                                       int32_t component_count,
105                                                                       Thread* self,
106                                                                       gc::AllocatorType allocator_type)
107     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
108 
109 extern mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* method,
110                                                  int32_t component_count, Thread* self,
111                                                  bool access_check,
112                                                  gc::AllocatorType allocator_type)
113     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
114 
115 extern mirror::Array* CheckAndAllocArrayFromCodeInstrumented(uint32_t type_idx,
116                                                              mirror::ArtMethod* method,
117                                                              int32_t component_count, Thread* self,
118                                                              bool access_check,
119                                                              gc::AllocatorType allocator_type)
120     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
121 
122 // Type of find field operation for fast and slow case.
123 enum FindFieldType {
124   InstanceObjectRead,
125   InstanceObjectWrite,
126   InstancePrimitiveRead,
127   InstancePrimitiveWrite,
128   StaticObjectRead,
129   StaticObjectWrite,
130   StaticPrimitiveRead,
131   StaticPrimitiveWrite,
132 };
133 
134 template<FindFieldType type, bool access_check>
135 static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, mirror::ArtMethod* referrer,
136                                                   Thread* self, size_t expected_size)
137     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
138 
139 template<InvokeType type, bool access_check>
140 static inline mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx,
141                                                     mirror::Object** this_object,
142                                                     mirror::ArtMethod** referrer, Thread* self)
143     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
144 
145 // Fast path field resolution that can't initialize classes or throw exceptions.
146 static inline mirror::ArtField* FindFieldFast(uint32_t field_idx,
147                                               mirror::ArtMethod* referrer,
148                                               FindFieldType type, size_t expected_size)
149     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
150 
151 // Fast path method resolution that can't throw exceptions.
152 static inline mirror::ArtMethod* FindMethodFast(uint32_t method_idx,
153                                                 mirror::Object* this_object,
154                                                 mirror::ArtMethod* referrer,
155                                                 bool access_check, InvokeType type)
156     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
157 
158 static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
159                                                     mirror::ArtMethod* referrer,
160                                                     Thread* self, bool can_run_clinit,
161                                                     bool verify_access)
162     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
163 
164 extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
165 
166 static inline mirror::String* ResolveStringFromCode(mirror::ArtMethod* referrer,
167                                                     uint32_t string_idx)
168     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
169 
170 // TODO: annotalysis disabled as monitor semantics are maintained in Java code.
171 static inline void UnlockJniSynchronizedMethod(jobject locked, Thread* self)
172     NO_THREAD_SAFETY_ANALYSIS;
173 
174 void CheckReferenceResult(mirror::Object* o, Thread* self)
175     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
176 
177 static inline void CheckSuspend(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
178 
179 JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, const char* shorty,
180                                     jobject rcvr_jobj, jobject interface_art_method_jobj,
181                                     std::vector<jvalue>& args)
182     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
183 
184 // Entry point for deoptimization.
185 extern "C" void art_quick_deoptimize();
GetQuickDeoptimizationEntryPoint()186 static inline uintptr_t GetQuickDeoptimizationEntryPoint() {
187   return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
188 }
189 
190 // Return address of instrumentation stub.
191 extern "C" void art_quick_instrumentation_entry(void*);
GetQuickInstrumentationEntryPoint()192 static inline void* GetQuickInstrumentationEntryPoint() {
193   return reinterpret_cast<void*>(art_quick_instrumentation_entry);
194 }
195 
196 // The return_pc of instrumentation exit stub.
197 extern "C" void art_quick_instrumentation_exit();
GetQuickInstrumentationExitPc()198 static inline uintptr_t GetQuickInstrumentationExitPc() {
199   return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit);
200 }
201 
202 #if defined(ART_USE_PORTABLE_COMPILER)
203 extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*);
GetPortableToInterpreterBridge()204 static inline const void* GetPortableToInterpreterBridge() {
205   return reinterpret_cast<void*>(art_portable_to_interpreter_bridge);
206 }
207 
GetPortableToQuickBridge()208 static inline const void* GetPortableToQuickBridge() {
209   // TODO: portable to quick bridge. Bug: 8196384
210   return GetPortableToInterpreterBridge();
211 }
212 #endif
213 
214 extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
GetQuickToInterpreterBridge()215 static inline const void* GetQuickToInterpreterBridge() {
216   return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
217 }
218 
219 #if defined(ART_USE_PORTABLE_COMPILER)
GetQuickToPortableBridge()220 static inline const void* GetQuickToPortableBridge() {
221   // TODO: quick to portable bridge. Bug: 8196384
222   return GetQuickToInterpreterBridge();
223 }
224 
225 extern "C" void art_portable_proxy_invoke_handler();
GetPortableProxyInvokeHandler()226 static inline const void* GetPortableProxyInvokeHandler() {
227   return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
228 }
229 #endif
230 
231 extern "C" void art_quick_proxy_invoke_handler();
GetQuickProxyInvokeHandler()232 static inline const void* GetQuickProxyInvokeHandler() {
233   return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
234 }
235 
236 extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
GetJniDlsymLookupStub()237 static inline void* GetJniDlsymLookupStub() {
238   return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
239 }
240 
241 template <typename INT_TYPE, typename FLOAT_TYPE>
242 static inline INT_TYPE art_float_to_integral(FLOAT_TYPE f);
243 
244 }  // namespace art
245 
246 #endif  // ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
247