16fac447555dc94a935b78198479cce645c837b89Ian Rogers/*
26fac447555dc94a935b78198479cce645c837b89Ian Rogers * Copyright (C) 2014 The Android Open Source Project
36fac447555dc94a935b78198479cce645c837b89Ian Rogers *
46fac447555dc94a935b78198479cce645c837b89Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License");
56fac447555dc94a935b78198479cce645c837b89Ian Rogers * you may not use this file except in compliance with the License.
66fac447555dc94a935b78198479cce645c837b89Ian Rogers * You may obtain a copy of the License at
76fac447555dc94a935b78198479cce645c837b89Ian Rogers *
86fac447555dc94a935b78198479cce645c837b89Ian Rogers *      http://www.apache.org/licenses/LICENSE-2.0
96fac447555dc94a935b78198479cce645c837b89Ian Rogers *
106fac447555dc94a935b78198479cce645c837b89Ian Rogers * Unless required by applicable law or agreed to in writing, software
116fac447555dc94a935b78198479cce645c837b89Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS,
126fac447555dc94a935b78198479cce645c837b89Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136fac447555dc94a935b78198479cce645c837b89Ian Rogers * See the License for the specific language governing permissions and
146fac447555dc94a935b78198479cce645c837b89Ian Rogers * limitations under the License.
156fac447555dc94a935b78198479cce645c837b89Ian Rogers */
166fac447555dc94a935b78198479cce645c837b89Ian Rogers
171e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov#ifndef ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_INL_H_
181e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov#define ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_INL_H_
196fac447555dc94a935b78198479cce645c837b89Ian Rogers
201e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov#include "memory_tool_malloc_space.h"
218cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe
228cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "base/memory_tool.h"
231e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov#include "memory_tool_settings.h"
248cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "mirror/object-inl.h"
25d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
266fac447555dc94a935b78198479cce645c837b89Ian Rogersnamespace art {
276fac447555dc94a935b78198479cce645c837b89Ian Rogersnamespace gc {
286fac447555dc94a935b78198479cce645c837b89Ian Rogersnamespace space {
296fac447555dc94a935b78198479cce645c837b89Ian Rogers
301e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovnamespace memory_tool_details {
316fac447555dc94a935b78198479cce645c837b89Ian Rogers
321e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovtemplate <size_t kMemoryToolRedZoneBytes, bool kUseObjSizeForUsable>
33d7576328811e5103e99d31f834a857522cc1463fAndreas Gampeinline mirror::Object* AdjustForValgrind(void* obj_with_rdz, size_t num_bytes,
34d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                                         size_t bytes_allocated, size_t usable_size,
354460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                         size_t bytes_tl_bulk_allocated,
364460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                         size_t* bytes_allocated_out, size_t* usable_size_out,
374460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                         size_t* bytes_tl_bulk_allocated_out) {
38d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  if (bytes_allocated_out != nullptr) {
39d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    *bytes_allocated_out = bytes_allocated;
406fac447555dc94a935b78198479cce645c837b89Ian Rogers  }
414460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi  if (bytes_tl_bulk_allocated_out != nullptr) {
424460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    *bytes_tl_bulk_allocated_out = bytes_tl_bulk_allocated;
434460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi  }
44d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
45d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // This cuts over-provision and is a trade-off between testing the over-provisioning code paths
46d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // vs checking overflows in the regular paths.
47d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  if (usable_size_out != nullptr) {
48d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    if (kUseObjSizeForUsable) {
49d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe      *usable_size_out = num_bytes;
50d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    } else {
511e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov      *usable_size_out = usable_size - 2 * kMemoryToolRedZoneBytes;
52d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    }
53d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  }
54d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
55d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // Left redzone.
561e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  MEMORY_TOOL_MAKE_NOACCESS(obj_with_rdz, kMemoryToolRedZoneBytes);
57d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
58d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // Make requested memory readable.
59d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // (If the allocator assumes memory is zeroed out, we might get UNDEFINED warnings, so make
60d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  //  everything DEFINED initially.)
616fac447555dc94a935b78198479cce645c837b89Ian Rogers  mirror::Object* result = reinterpret_cast<mirror::Object*>(
621e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov      reinterpret_cast<uint8_t*>(obj_with_rdz) + kMemoryToolRedZoneBytes);
631e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  MEMORY_TOOL_MAKE_DEFINED(result, num_bytes);
64d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
65d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // Right redzone. Assumes that if bytes_allocated > usable_size, then the difference is
66d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // management data at the upper end, and for simplicity we will not protect that.
67d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // At the moment, this fits RosAlloc (no management data in a slot, usable_size == alloc_size)
68d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // and DlMalloc (allocation_size = (usable_size == num_bytes) + 4, 4 is management)
691e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  MEMORY_TOOL_MAKE_NOACCESS(reinterpret_cast<uint8_t*>(result) + num_bytes,
701e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                    usable_size - (num_bytes + kMemoryToolRedZoneBytes));
71d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
726fac447555dc94a935b78198479cce645c837b89Ian Rogers  return result;
736fac447555dc94a935b78198479cce645c837b89Ian Rogers}
746fac447555dc94a935b78198479cce645c837b89Ian Rogers
75d7576328811e5103e99d31f834a857522cc1463fAndreas Gampeinline size_t GetObjSizeNoThreadSafety(mirror::Object* obj) NO_THREAD_SAFETY_ANALYSIS {
76d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  return obj->SizeOf<kVerifyNone>();
77d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe}
78d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
791e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov}  // namespace memory_tool_details
80d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
81d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename S,
821e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
83d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kAdjustForRedzoneInAllocSize,
84d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kUseObjSizeForUsable>
85d7576328811e5103e99d31f834a857522cc1463fAndreas Gampemirror::Object*
861e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii StepanovMemoryToolMallocSpace<S,
871e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                    kMemoryToolRedZoneBytes,
88d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                    kAdjustForRedzoneInAllocSize,
89d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                    kUseObjSizeForUsable>::AllocWithGrowth(
904460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out,
914460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    size_t* bytes_tl_bulk_allocated_out) {
92d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  size_t bytes_allocated;
93d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  size_t usable_size;
944460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi  size_t bytes_tl_bulk_allocated;
951e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  void* obj_with_rdz = S::AllocWithGrowth(self, num_bytes + 2 * kMemoryToolRedZoneBytes,
964460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                          &bytes_allocated, &usable_size,
974460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                          &bytes_tl_bulk_allocated);
986fac447555dc94a935b78198479cce645c837b89Ian Rogers  if (obj_with_rdz == nullptr) {
996fac447555dc94a935b78198479cce645c837b89Ian Rogers    return nullptr;
1006fac447555dc94a935b78198479cce645c837b89Ian Rogers  }
101d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
1021e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  return memory_tool_details::AdjustForValgrind<kMemoryToolRedZoneBytes, kUseObjSizeForUsable>(
1034460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      obj_with_rdz, num_bytes,
1044460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_allocated, usable_size,
1054460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_tl_bulk_allocated,
1064460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_allocated_out,
1074460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      usable_size_out,
1084460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_tl_bulk_allocated_out);
1096fac447555dc94a935b78198479cce645c837b89Ian Rogers}
1106fac447555dc94a935b78198479cce645c837b89Ian Rogers
111d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename S,
1121e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
113d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kAdjustForRedzoneInAllocSize,
114d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kUseObjSizeForUsable>
1151e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovmirror::Object* MemoryToolMallocSpace<S,
1161e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                                    kMemoryToolRedZoneBytes,
117d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                                    kAdjustForRedzoneInAllocSize,
118d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                                    kUseObjSizeForUsable>::Alloc(
1194460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out,
1204460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    size_t* bytes_tl_bulk_allocated_out) {
121d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  size_t bytes_allocated;
122d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  size_t usable_size;
1234460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi  size_t bytes_tl_bulk_allocated;
1241e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  void* obj_with_rdz = S::Alloc(self, num_bytes + 2 * kMemoryToolRedZoneBytes,
1254460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                &bytes_allocated, &usable_size, &bytes_tl_bulk_allocated);
126d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  if (obj_with_rdz == nullptr) {
127d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    return nullptr;
128d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  }
129d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
1301e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  return memory_tool_details::AdjustForValgrind<kMemoryToolRedZoneBytes,
131d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                                             kUseObjSizeForUsable>(obj_with_rdz, num_bytes,
132d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                                                                   bytes_allocated, usable_size,
1334460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                                                   bytes_tl_bulk_allocated,
134d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                                                                   bytes_allocated_out,
1354460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                                                   usable_size_out,
1364460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                                                   bytes_tl_bulk_allocated_out);
137d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe}
138d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
139d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename S,
1401e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
141d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kAdjustForRedzoneInAllocSize,
142d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kUseObjSizeForUsable>
1431e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovmirror::Object* MemoryToolMallocSpace<S,
1441e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                                    kMemoryToolRedZoneBytes,
14524a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe                                    kAdjustForRedzoneInAllocSize,
14624a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe                                    kUseObjSizeForUsable>::AllocThreadUnsafe(
1474460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    Thread* self, size_t num_bytes, size_t* bytes_allocated_out, size_t* usable_size_out,
1484460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi    size_t* bytes_tl_bulk_allocated_out) {
14924a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe  size_t bytes_allocated;
15024a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe  size_t usable_size;
1514460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi  size_t bytes_tl_bulk_allocated;
1521e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  void* obj_with_rdz = S::AllocThreadUnsafe(self, num_bytes + 2 * kMemoryToolRedZoneBytes,
1534460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                            &bytes_allocated, &usable_size,
1544460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                                            &bytes_tl_bulk_allocated);
15524a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe  if (obj_with_rdz == nullptr) {
15624a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe    return nullptr;
15724a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe  }
15824a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe
1591e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  return memory_tool_details::AdjustForValgrind<kMemoryToolRedZoneBytes, kUseObjSizeForUsable>(
1604460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      obj_with_rdz, num_bytes,
1614460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_allocated, usable_size,
1624460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_tl_bulk_allocated,
1634460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_allocated_out,
1644460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      usable_size_out,
1654460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi      bytes_tl_bulk_allocated_out);
16624a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe}
16724a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe
16824a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampetemplate <typename S,
1691e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
17024a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe          bool kAdjustForRedzoneInAllocSize,
17124a5a3003aa7dbc29db698ac86bfa18ef64b2593Andreas Gampe          bool kUseObjSizeForUsable>
1721e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovsize_t MemoryToolMallocSpace<S,
1731e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                           kMemoryToolRedZoneBytes,
174d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                           kAdjustForRedzoneInAllocSize,
175d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                           kUseObjSizeForUsable>::AllocationSize(
176d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    mirror::Object* obj, size_t* usable_size) {
1776fac447555dc94a935b78198479cce645c837b89Ian Rogers  size_t result = S::AllocationSize(reinterpret_cast<mirror::Object*>(
1781e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov      reinterpret_cast<uint8_t*>(obj) - (kAdjustForRedzoneInAllocSize ? kMemoryToolRedZoneBytes : 0)),
179d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe      usable_size);
180d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  if (usable_size != nullptr) {
181d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    if (kUseObjSizeForUsable) {
1821e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov      *usable_size = memory_tool_details::GetObjSizeNoThreadSafety(obj);
183d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    } else {
1841e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov      *usable_size = *usable_size - 2 * kMemoryToolRedZoneBytes;
185d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    }
186d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  }
187661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  return result;
1886fac447555dc94a935b78198479cce645c837b89Ian Rogers}
1896fac447555dc94a935b78198479cce645c837b89Ian Rogers
190d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename S,
1911e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
192d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kAdjustForRedzoneInAllocSize,
193d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kUseObjSizeForUsable>
1941e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovsize_t MemoryToolMallocSpace<S,
1951e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                           kMemoryToolRedZoneBytes,
196d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                           kAdjustForRedzoneInAllocSize,
197d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                           kUseObjSizeForUsable>::Free(
198d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    Thread* self, mirror::Object* ptr) {
1996fac447555dc94a935b78198479cce645c837b89Ian Rogers  void* obj_after_rdz = reinterpret_cast<void*>(ptr);
2001e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  uint8_t* obj_with_rdz = reinterpret_cast<uint8_t*>(obj_after_rdz) - kMemoryToolRedZoneBytes;
2011e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov
2026fac447555dc94a935b78198479cce645c837b89Ian Rogers  // Make redzones undefined.
203d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  size_t usable_size;
204d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  size_t allocation_size = AllocationSize(ptr, &usable_size);
205d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
206d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // Unprotect the allocation.
207d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // Use the obj-size-for-usable flag to determine whether usable_size is the more important one,
208d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  // e.g., whether there's data in the allocation_size (and usable_size can't be trusted).
209d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  if (kUseObjSizeForUsable) {
2101e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov    MEMORY_TOOL_MAKE_UNDEFINED(obj_with_rdz, allocation_size);
211d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  } else {
2121e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov    MEMORY_TOOL_MAKE_UNDEFINED(obj_with_rdz, usable_size + 2 * kMemoryToolRedZoneBytes);
213d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe  }
214d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe
215661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier  return S::Free(self, reinterpret_cast<mirror::Object*>(obj_with_rdz));
2166fac447555dc94a935b78198479cce645c837b89Ian Rogers}
2176fac447555dc94a935b78198479cce645c837b89Ian Rogers
218d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename S,
2191e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
220d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kAdjustForRedzoneInAllocSize,
221d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kUseObjSizeForUsable>
2221e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovsize_t MemoryToolMallocSpace<S,
2231e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                           kMemoryToolRedZoneBytes,
224d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                           kAdjustForRedzoneInAllocSize,
225d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                           kUseObjSizeForUsable>::FreeList(
226d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    Thread* self, size_t num_ptrs, mirror::Object** ptrs) {
2276fac447555dc94a935b78198479cce645c837b89Ian Rogers  size_t freed = 0;
2286fac447555dc94a935b78198479cce645c837b89Ian Rogers  for (size_t i = 0; i < num_ptrs; i++) {
2296fac447555dc94a935b78198479cce645c837b89Ian Rogers    freed += Free(self, ptrs[i]);
230661974a5561e5ccdfbac8cb5d8df8b7e6f3483b8Mathieu Chartier    ptrs[i] = nullptr;
2316fac447555dc94a935b78198479cce645c837b89Ian Rogers  }
2326fac447555dc94a935b78198479cce645c837b89Ian Rogers  return freed;
2336fac447555dc94a935b78198479cce645c837b89Ian Rogers}
2346fac447555dc94a935b78198479cce645c837b89Ian Rogers
235d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename S,
2361e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
237d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kAdjustForRedzoneInAllocSize,
238d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe          bool kUseObjSizeForUsable>
239d7576328811e5103e99d31f834a857522cc1463fAndreas Gampetemplate <typename... Params>
2401e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii StepanovMemoryToolMallocSpace<S,
2411e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                    kMemoryToolRedZoneBytes,
242d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe                    kAdjustForRedzoneInAllocSize,
2431e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                    kUseObjSizeForUsable>::MemoryToolMallocSpace(
244d7576328811e5103e99d31f834a857522cc1463fAndreas Gampe    MemMap* mem_map, size_t initial_size, Params... params) : S(mem_map, initial_size, params...) {
245b5e31f3dd5f792ff60225a4daa048a57d261cdd0Hiroshi Yamauchi  // Don't want to change the valgrind states of the mem map here as the allocator is already
246b5e31f3dd5f792ff60225a4daa048a57d261cdd0Hiroshi Yamauchi  // initialized at this point and that may interfere with what the allocator does internally. Note
247b5e31f3dd5f792ff60225a4daa048a57d261cdd0Hiroshi Yamauchi  // that the tail beyond the initial size is mprotected.
2486fac447555dc94a935b78198479cce645c837b89Ian Rogers}
2496fac447555dc94a935b78198479cce645c837b89Ian Rogers
2504460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchitemplate <typename S,
2511e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov          size_t kMemoryToolRedZoneBytes,
2524460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi          bool kAdjustForRedzoneInAllocSize,
2534460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi          bool kUseObjSizeForUsable>
2541e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanovsize_t MemoryToolMallocSpace<S,
2551e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov                           kMemoryToolRedZoneBytes,
2564460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                           kAdjustForRedzoneInAllocSize,
2574460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi                           kUseObjSizeForUsable>::MaxBytesBulkAllocatedFor(size_t num_bytes) {
2581e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov  return S::MaxBytesBulkAllocatedFor(num_bytes + 2 * kMemoryToolRedZoneBytes);
2594460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi}
2604460a84be92b5a94ecfb5c650aef4945ab849c93Hiroshi Yamauchi
2616fac447555dc94a935b78198479cce645c837b89Ian Rogers}  // namespace space
2626fac447555dc94a935b78198479cce645c837b89Ian Rogers}  // namespace gc
2636fac447555dc94a935b78198479cce645c837b89Ian Rogers}  // namespace art
2646fac447555dc94a935b78198479cce645c837b89Ian Rogers
2651e13374baf7dfaf442ffbf9809c37c131d681eafEvgenii Stepanov#endif  // ART_RUNTIME_GC_SPACE_MEMORY_TOOL_MALLOC_SPACE_INL_H_
266