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 #include "entrypoints/quick/quick_alloc_entrypoints.h" 18 19 #include "callee_save_frame.h" 20 #include "entrypoints/entrypoint_utils-inl.h" 21 #include "mirror/art_method-inl.h" 22 #include "mirror/class-inl.h" 23 #include "mirror/object_array-inl.h" 24 #include "mirror/object-inl.h" 25 26 namespace art { 27 28 #define GENERATE_ENTRYPOINTS_FOR_ALLOCATOR_INST(suffix, suffix2, instrumented_bool, allocator_type) \ 29 extern "C" mirror::Object* artAllocObjectFromCode ##suffix##suffix2( \ 30 uint32_t type_idx, mirror::ArtMethod* method, Thread* self, \ 31 StackReference<mirror::ArtMethod>* sp) \ 32 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 33 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 34 return AllocObjectFromCode<false, instrumented_bool>(type_idx, method, self, allocator_type); \ 35 } \ 36 extern "C" mirror::Object* artAllocObjectFromCodeResolved##suffix##suffix2( \ 37 mirror::Class* klass, mirror::ArtMethod* method, Thread* self, \ 38 StackReference<mirror::ArtMethod>* sp) \ 39 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 40 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 41 return AllocObjectFromCodeResolved<instrumented_bool>(klass, method, self, allocator_type); \ 42 } \ 43 extern "C" mirror::Object* artAllocObjectFromCodeInitialized##suffix##suffix2( \ 44 mirror::Class* klass, mirror::ArtMethod* method, Thread* self, \ 45 StackReference<mirror::ArtMethod>* sp) \ 46 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 47 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 48 return AllocObjectFromCodeInitialized<instrumented_bool>(klass, method, self, allocator_type); \ 49 } \ 50 extern "C" mirror::Object* artAllocObjectFromCodeWithAccessCheck##suffix##suffix2( \ 51 uint32_t type_idx, mirror::ArtMethod* method, Thread* self, \ 52 StackReference<mirror::ArtMethod>* sp) \ 53 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 54 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 55 return AllocObjectFromCode<true, instrumented_bool>(type_idx, method, self, allocator_type); \ 56 } \ 57 extern "C" mirror::Array* artAllocArrayFromCode##suffix##suffix2( \ 58 uint32_t type_idx, mirror::ArtMethod* method, int32_t component_count, Thread* self, \ 59 StackReference<mirror::ArtMethod>* sp) \ 60 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 61 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 62 return AllocArrayFromCode<false, instrumented_bool>(type_idx, method, component_count, self, \ 63 allocator_type); \ 64 } \ 65 extern "C" mirror::Array* artAllocArrayFromCodeResolved##suffix##suffix2( \ 66 mirror::Class* klass, mirror::ArtMethod* method, int32_t component_count, Thread* self, \ 67 StackReference<mirror::ArtMethod>* sp) \ 68 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 69 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 70 return AllocArrayFromCodeResolved<false, instrumented_bool>(klass, method, component_count, self, \ 71 allocator_type); \ 72 } \ 73 extern "C" mirror::Array* artAllocArrayFromCodeWithAccessCheck##suffix##suffix2( \ 74 uint32_t type_idx, mirror::ArtMethod* method, int32_t component_count, Thread* self, \ 75 StackReference<mirror::ArtMethod>* sp) \ 76 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 77 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 78 return AllocArrayFromCode<true, instrumented_bool>(type_idx, method, component_count, self, \ 79 allocator_type); \ 80 } \ 81 extern "C" mirror::Array* artCheckAndAllocArrayFromCode##suffix##suffix2( \ 82 uint32_t type_idx, mirror::ArtMethod* method, int32_t component_count, Thread* self, \ 83 StackReference<mirror::ArtMethod>* sp) \ 84 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 85 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 86 if (!instrumented_bool) { \ 87 return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, false, allocator_type); \ 88 } else { \ 89 return CheckAndAllocArrayFromCodeInstrumented(type_idx, method, component_count, self, false, allocator_type); \ 90 } \ 91 } \ 92 extern "C" mirror::Array* artCheckAndAllocArrayFromCodeWithAccessCheck##suffix##suffix2( \ 93 uint32_t type_idx, mirror::ArtMethod* method, int32_t component_count, Thread* self, \ 94 StackReference<mirror::ArtMethod>* sp) \ 95 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { \ 96 FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); \ 97 if (!instrumented_bool) { \ 98 return CheckAndAllocArrayFromCode(type_idx, method, component_count, self, true, allocator_type); \ 99 } else { \ 100 return CheckAndAllocArrayFromCodeInstrumented(type_idx, method, component_count, self, true, allocator_type); \ 101 } \ 102 } 103 104 #define GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(suffix, allocator_type) \ 105 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR_INST(suffix, Instrumented, true, allocator_type) \ 106 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR_INST(suffix, , false, allocator_type) 107 108 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(DlMalloc, gc::kAllocatorTypeDlMalloc) 109 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(RosAlloc, gc::kAllocatorTypeRosAlloc) 110 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(BumpPointer, gc::kAllocatorTypeBumpPointer) 111 GENERATE_ENTRYPOINTS_FOR_ALLOCATOR(TLAB, gc::kAllocatorTypeTLAB) 112 113 #define GENERATE_ENTRYPOINTS(suffix) \ 114 extern "C" void* art_quick_alloc_array##suffix(uint32_t, void*, int32_t); \ 115 extern "C" void* art_quick_alloc_array_resolved##suffix(void* klass, void*, int32_t); \ 116 extern "C" void* art_quick_alloc_array_with_access_check##suffix(uint32_t, void*, int32_t); \ 117 extern "C" void* art_quick_alloc_object##suffix(uint32_t type_idx, void* method); \ 118 extern "C" void* art_quick_alloc_object_resolved##suffix(void* klass, void* method); \ 119 extern "C" void* art_quick_alloc_object_initialized##suffix(void* klass, void* method); \ 120 extern "C" void* art_quick_alloc_object_with_access_check##suffix(uint32_t type_idx, void* method); \ 121 extern "C" void* art_quick_check_and_alloc_array##suffix(uint32_t, void*, int32_t); \ 122 extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix(uint32_t, void*, int32_t); \ 123 extern "C" void* art_quick_alloc_array##suffix##_instrumented(uint32_t, void*, int32_t); \ 124 extern "C" void* art_quick_alloc_array_resolved##suffix##_instrumented(void* klass, void*, int32_t); \ 125 extern "C" void* art_quick_alloc_array_with_access_check##suffix##_instrumented(uint32_t, void*, int32_t); \ 126 extern "C" void* art_quick_alloc_object##suffix##_instrumented(uint32_t type_idx, void* method); \ 127 extern "C" void* art_quick_alloc_object_resolved##suffix##_instrumented(void* klass, void* method); \ 128 extern "C" void* art_quick_alloc_object_initialized##suffix##_instrumented(void* klass, void* method); \ 129 extern "C" void* art_quick_alloc_object_with_access_check##suffix##_instrumented(uint32_t type_idx, void* method); \ 130 extern "C" void* art_quick_check_and_alloc_array##suffix##_instrumented(uint32_t, void*, int32_t); \ 131 extern "C" void* art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented(uint32_t, void*, int32_t); \ 132 void SetQuickAllocEntryPoints##suffix(QuickEntryPoints* qpoints, bool instrumented) { \ 133 if (instrumented) { \ 134 qpoints->pAllocArray = art_quick_alloc_array##suffix##_instrumented; \ 135 qpoints->pAllocArrayResolved = art_quick_alloc_array_resolved##suffix##_instrumented; \ 136 qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check##suffix##_instrumented; \ 137 qpoints->pAllocObject = art_quick_alloc_object##suffix##_instrumented; \ 138 qpoints->pAllocObjectResolved = art_quick_alloc_object_resolved##suffix##_instrumented; \ 139 qpoints->pAllocObjectInitialized = art_quick_alloc_object_initialized##suffix##_instrumented; \ 140 qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check##suffix##_instrumented; \ 141 qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array##suffix##_instrumented; \ 142 qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check##suffix##_instrumented; \ 143 } else { \ 144 qpoints->pAllocArray = art_quick_alloc_array##suffix; \ 145 qpoints->pAllocArrayResolved = art_quick_alloc_array_resolved##suffix; \ 146 qpoints->pAllocArrayWithAccessCheck = art_quick_alloc_array_with_access_check##suffix; \ 147 qpoints->pAllocObject = art_quick_alloc_object##suffix; \ 148 qpoints->pAllocObjectResolved = art_quick_alloc_object_resolved##suffix; \ 149 qpoints->pAllocObjectInitialized = art_quick_alloc_object_initialized##suffix; \ 150 qpoints->pAllocObjectWithAccessCheck = art_quick_alloc_object_with_access_check##suffix; \ 151 qpoints->pCheckAndAllocArray = art_quick_check_and_alloc_array##suffix; \ 152 qpoints->pCheckAndAllocArrayWithAccessCheck = art_quick_check_and_alloc_array_with_access_check##suffix; \ 153 } \ 154 } 155 156 // Generate the entrypoint functions. 157 #if !defined(__APPLE__) || !defined(__LP64__) 158 GENERATE_ENTRYPOINTS(_dlmalloc); 159 GENERATE_ENTRYPOINTS(_rosalloc); 160 GENERATE_ENTRYPOINTS(_bump_pointer); 161 GENERATE_ENTRYPOINTS(_tlab); 162 #endif 163 164 static bool entry_points_instrumented = false; 165 static gc::AllocatorType entry_points_allocator = gc::kAllocatorTypeDlMalloc; 166 167 void SetQuickAllocEntryPointsAllocator(gc::AllocatorType allocator) { 168 entry_points_allocator = allocator; 169 } 170 171 void SetQuickAllocEntryPointsInstrumented(bool instrumented) { 172 entry_points_instrumented = instrumented; 173 } 174 175 void ResetQuickAllocEntryPoints(QuickEntryPoints* qpoints) { 176 switch (entry_points_allocator) { 177 #if !defined(__APPLE__) || !defined(__LP64__) 178 case gc::kAllocatorTypeDlMalloc: { 179 SetQuickAllocEntryPoints_dlmalloc(qpoints, entry_points_instrumented); 180 break; 181 } 182 case gc::kAllocatorTypeRosAlloc: { 183 SetQuickAllocEntryPoints_rosalloc(qpoints, entry_points_instrumented); 184 break; 185 } 186 case gc::kAllocatorTypeBumpPointer: { 187 CHECK(kMovingCollector); 188 SetQuickAllocEntryPoints_bump_pointer(qpoints, entry_points_instrumented); 189 break; 190 } 191 case gc::kAllocatorTypeTLAB: { 192 CHECK(kMovingCollector); 193 SetQuickAllocEntryPoints_tlab(qpoints, entry_points_instrumented); 194 break; 195 } 196 #endif 197 default: { 198 LOG(FATAL) << "Unimplemented"; 199 } 200 } 201 } 202 203 } // namespace art 204