blob: ae8e892e29a9840edacea44d132bfde9a9c86ac5 [file] [log] [blame]
Ian Rogers6fac4472014-02-25 17:01:10 -08001/*
2 * Copyright (C) 2014 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_GC_SPACE_VALGRIND_MALLOC_SPACE_INL_H_
18#define ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_INL_H_
19
20#include "valgrind_malloc_space.h"
21
22#include <memcheck/memcheck.h>
23
Andreas Gamped7576322014-10-24 22:13:45 -070024#include "valgrind_settings.h"
25
Ian Rogers6fac4472014-02-25 17:01:10 -080026namespace art {
27namespace gc {
28namespace space {
29
Andreas Gamped7576322014-10-24 22:13:45 -070030namespace valgrind_details {
Ian Rogers6fac4472014-02-25 17:01:10 -080031
Andreas Gamped7576322014-10-24 22:13:45 -070032template <size_t kValgrindRedZoneBytes, bool kUseObjSizeForUsable>
33inline mirror::Object* AdjustForValgrind(void* obj_with_rdz, size_t num_bytes,
34 size_t bytes_allocated, size_t usable_size,
35 size_t* bytes_allocated_out, size_t* usable_size_out) {
36 if (bytes_allocated_out != nullptr) {
37 *bytes_allocated_out = bytes_allocated;
38 }
39
40 // This cuts over-provision and is a trade-off between testing the over-provisioning code paths
41 // vs checking overflows in the regular paths.
42 if (usable_size_out != nullptr) {
43 if (kUseObjSizeForUsable) {
44 *usable_size_out = num_bytes;
45 } else {
46 *usable_size_out = usable_size - 2 * kValgrindRedZoneBytes;
47 }
48 }
49
50 // Left redzone.
51 VALGRIND_MAKE_MEM_NOACCESS(obj_with_rdz, kValgrindRedZoneBytes);
52
53 // Make requested memory readable.
54 // (If the allocator assumes memory is zeroed out, we might get UNDEFINED warnings, so make
55 // everything DEFINED initially.)
56 mirror::Object* result = reinterpret_cast<mirror::Object*>(
57 reinterpret_cast<uint8_t*>(obj_with_rdz) + kValgrindRedZoneBytes);
58 VALGRIND_MAKE_MEM_DEFINED(result, num_bytes);
59
60 // Right redzone. Assumes that if bytes_allocated > usable_size, then the difference is
61 // management data at the upper end, and for simplicity we will not protect that.
62 // At the moment, this fits RosAlloc (no management data in a slot, usable_size == alloc_size)
63 // and DlMalloc (allocation_size = (usable_size == num_bytes) + 4, 4 is management)
64 VALGRIND_MAKE_MEM_NOACCESS(reinterpret_cast<uint8_t*>(result) + num_bytes,
65 usable_size - (num_bytes + kValgrindRedZoneBytes));
66
67 return result;
68}
69
70inline size_t GetObjSizeNoThreadSafety(mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS {
71 return obj->SizeOf<kVerifyNone>();
72}
73
74} // namespace valgrind_details
75
76template <typename S,
77 size_t kValgrindRedZoneBytes,
78 bool kAdjustForRedzoneInAllocSize,
79 bool kUseObjSizeForUsable>
80mirror::Object*
81ValgrindMallocSpace<S,
82 kValgrindRedZoneBytes,
83 kAdjustForRedzoneInAllocSize,
84 kUseObjSizeForUsable>::AllocWithGrowth(
85 Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out) {
86 size_t bytes_allocated;
87 size_t usable_size;
Ian Rogers6fac4472014-02-25 17:01:10 -080088 void* obj_with_rdz = S::AllocWithGrowth(self, num_bytes + 2 * kValgrindRedZoneBytes,
Andreas Gamped7576322014-10-24 22:13:45 -070089 &bytes_allocated, &usable_size);
Ian Rogers6fac4472014-02-25 17:01:10 -080090 if (obj_with_rdz == nullptr) {
91 return nullptr;
92 }
Andreas Gamped7576322014-10-24 22:13:45 -070093
94 return valgrind_details::AdjustForValgrind<kValgrindRedZoneBytes,
95 kUseObjSizeForUsable>(obj_with_rdz, num_bytes,
96 bytes_allocated, usable_size,
97 bytes_allocated_out,
98 usable_size_out);
Ian Rogers6fac4472014-02-25 17:01:10 -080099}
100
Andreas Gamped7576322014-10-24 22:13:45 -0700101template <typename S,
102 size_t kValgrindRedZoneBytes,
103 bool kAdjustForRedzoneInAllocSize,
104 bool kUseObjSizeForUsable>
105mirror::Object* ValgrindMallocSpace<S,
106 kValgrindRedZoneBytes,
107 kAdjustForRedzoneInAllocSize,
108 kUseObjSizeForUsable>::Alloc(
109 Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out) {
110 size_t bytes_allocated;
111 size_t usable_size;
112 void* obj_with_rdz = S::Alloc(self, num_bytes + 2 * kValgrindRedZoneBytes,
113 &bytes_allocated, &usable_size);
Ian Rogers6fac4472014-02-25 17:01:10 -0800114 if (obj_with_rdz == nullptr) {
115 return nullptr;
116 }
Andreas Gamped7576322014-10-24 22:13:45 -0700117
118 return valgrind_details::AdjustForValgrind<kValgrindRedZoneBytes,
119 kUseObjSizeForUsable>(obj_with_rdz, num_bytes,
120 bytes_allocated, usable_size,
121 bytes_allocated_out,
122 usable_size_out);
Ian Rogers6fac4472014-02-25 17:01:10 -0800123}
124
Andreas Gamped7576322014-10-24 22:13:45 -0700125template <typename S,
126 size_t kValgrindRedZoneBytes,
127 bool kAdjustForRedzoneInAllocSize,
128 bool kUseObjSizeForUsable>
Andreas Gampe24a5a302014-11-21 19:45:53 -0800129mirror::Object* ValgrindMallocSpace<S,
130 kValgrindRedZoneBytes,
131 kAdjustForRedzoneInAllocSize,
132 kUseObjSizeForUsable>::AllocThreadUnsafe(
133 Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out) {
134 size_t bytes_allocated;
135 size_t usable_size;
136 void* obj_with_rdz = S::AllocThreadUnsafe(self, num_bytes + 2 * kValgrindRedZoneBytes,
137 &bytes_allocated, &usable_size);
138 if (obj_with_rdz == nullptr) {
139 return nullptr;
140 }
141
142 return valgrind_details::AdjustForValgrind<kValgrindRedZoneBytes,
143 kUseObjSizeForUsable>(obj_with_rdz, num_bytes,
144 bytes_allocated, usable_size,
145 bytes_allocated_out,
146 usable_size_out);
147}
148
149template <typename S,
150 size_t kValgrindRedZoneBytes,
151 bool kAdjustForRedzoneInAllocSize,
152 bool kUseObjSizeForUsable>
Andreas Gamped7576322014-10-24 22:13:45 -0700153size_t ValgrindMallocSpace<S,
154 kValgrindRedZoneBytes,
155 kAdjustForRedzoneInAllocSize,
156 kUseObjSizeForUsable>::AllocationSize(
157 mirror::Object* obj, size_t* usable_size) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800158 size_t result = S::AllocationSize(reinterpret_cast<mirror::Object*>(
Andreas Gamped7576322014-10-24 22:13:45 -0700159 reinterpret_cast<uint8_t*>(obj) - (kAdjustForRedzoneInAllocSize ? kValgrindRedZoneBytes : 0)),
160 usable_size);
161 if (usable_size != nullptr) {
162 if (kUseObjSizeForUsable) {
163 *usable_size = valgrind_details::GetObjSizeNoThreadSafety(obj);
164 } else {
165 *usable_size = *usable_size - 2 * kValgrindRedZoneBytes;
166 }
167 }
Mathieu Chartier661974a2014-01-09 11:23:53 -0800168 return result;
Ian Rogers6fac4472014-02-25 17:01:10 -0800169}
170
Andreas Gamped7576322014-10-24 22:13:45 -0700171template <typename S,
172 size_t kValgrindRedZoneBytes,
173 bool kAdjustForRedzoneInAllocSize,
174 bool kUseObjSizeForUsable>
175size_t ValgrindMallocSpace<S,
176 kValgrindRedZoneBytes,
177 kAdjustForRedzoneInAllocSize,
178 kUseObjSizeForUsable>::Free(
179 Thread* self, mirror::Object* ptr) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800180 void* obj_after_rdz = reinterpret_cast<void*>(ptr);
Andreas Gamped7576322014-10-24 22:13:45 -0700181 uint8_t* obj_with_rdz = reinterpret_cast<uint8_t*>(obj_after_rdz) - kValgrindRedZoneBytes;
Ian Rogers6fac4472014-02-25 17:01:10 -0800182 // Make redzones undefined.
Andreas Gamped7576322014-10-24 22:13:45 -0700183 size_t usable_size;
184 size_t allocation_size = AllocationSize(ptr, &usable_size);
185
186 // Unprotect the allocation.
187 // Use the obj-size-for-usable flag to determine whether usable_size is the more important one,
188 // e.g., whether there's data in the allocation_size (and usable_size can't be trusted).
189 if (kUseObjSizeForUsable) {
190 VALGRIND_MAKE_MEM_UNDEFINED(obj_with_rdz, allocation_size);
191 } else {
192 VALGRIND_MAKE_MEM_UNDEFINED(obj_with_rdz, usable_size + 2 * kValgrindRedZoneBytes);
193 }
194
Mathieu Chartier661974a2014-01-09 11:23:53 -0800195 return S::Free(self, reinterpret_cast<mirror::Object*>(obj_with_rdz));
Ian Rogers6fac4472014-02-25 17:01:10 -0800196}
197
Andreas Gamped7576322014-10-24 22:13:45 -0700198template <typename S,
199 size_t kValgrindRedZoneBytes,
200 bool kAdjustForRedzoneInAllocSize,
201 bool kUseObjSizeForUsable>
202size_t ValgrindMallocSpace<S,
203 kValgrindRedZoneBytes,
204 kAdjustForRedzoneInAllocSize,
205 kUseObjSizeForUsable>::FreeList(
206 Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
Ian Rogers6fac4472014-02-25 17:01:10 -0800207 size_t freed = 0;
208 for (size_t i = 0; i < num_ptrs; i++) {
209 freed += Free(self, ptrs[i]);
Mathieu Chartier661974a2014-01-09 11:23:53 -0800210 ptrs[i] = nullptr;
Ian Rogers6fac4472014-02-25 17:01:10 -0800211 }
212 return freed;
213}
214
Andreas Gamped7576322014-10-24 22:13:45 -0700215template <typename S,
216 size_t kValgrindRedZoneBytes,
217 bool kAdjustForRedzoneInAllocSize,
218 bool kUseObjSizeForUsable>
219template <typename... Params>
220ValgrindMallocSpace<S,
221 kValgrindRedZoneBytes,
222 kAdjustForRedzoneInAllocSize,
223 kUseObjSizeForUsable>::ValgrindMallocSpace(
224 MemMap* mem_map, size_t initial_size, Params... params) : S(mem_map, initial_size, params...) {
225 VALGRIND_MAKE_MEM_UNDEFINED(mem_map->Begin() + initial_size,
226 mem_map->Size() - initial_size);
Ian Rogers6fac4472014-02-25 17:01:10 -0800227}
228
229} // namespace space
230} // namespace gc
231} // namespace art
232
233#endif // ART_RUNTIME_GC_SPACE_VALGRIND_MALLOC_SPACE_INL_H_