1/* 2 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21#ifndef WTF_FastMalloc_h 22#define WTF_FastMalloc_h 23 24#include <new> 25#include <stdlib.h> 26#include <wtf/PossiblyNull.h> 27#include <wtf/StdLibExtras.h> 28 29namespace WTF { 30 31 // These functions call CRASH() if an allocation fails. 32 WTF_EXPORT_PRIVATE void* fastMalloc(size_t); 33 WTF_EXPORT_PRIVATE void* fastZeroedMalloc(size_t); 34 WTF_EXPORT_PRIVATE void* fastCalloc(size_t numElements, size_t elementSize); 35 WTF_EXPORT_PRIVATE void* fastRealloc(void*, size_t); 36 WTF_EXPORT_PRIVATE char* fastStrDup(const char*); 37 WTF_EXPORT_PRIVATE size_t fastMallocSize(const void*); 38 WTF_EXPORT_PRIVATE size_t fastMallocGoodSize(size_t); 39 40 struct TryMallocReturnValue { 41 TryMallocReturnValue(void* data) 42 : m_data(data) 43 { 44 } 45 TryMallocReturnValue(const TryMallocReturnValue& source) 46 : m_data(source.m_data) 47 { 48 source.m_data = 0; 49 } 50 ~TryMallocReturnValue() { ASSERT(!m_data); } 51 template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN; 52 template <typename T> operator PossiblyNull<T>() 53 { 54 T value; 55 getValue(value); 56 return PossiblyNull<T>(value); 57 } 58 private: 59 mutable void* m_data; 60 }; 61 62 template <typename T> bool TryMallocReturnValue::getValue(T& data) 63 { 64 union u { void* data; T target; } res; 65 res.data = m_data; 66 data = res.target; 67 bool returnValue = !!m_data; 68 m_data = 0; 69 return returnValue; 70 } 71 72 WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastMalloc(size_t n); 73 TryMallocReturnValue tryFastZeroedMalloc(size_t n); 74 WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size); 75 WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastRealloc(void* p, size_t n); 76 77 WTF_EXPORT_PRIVATE void fastFree(void*); 78 79#ifndef NDEBUG 80 WTF_EXPORT_PRIVATE void fastMallocForbid(); 81 WTF_EXPORT_PRIVATE void fastMallocAllow(); 82#endif 83 84 WTF_EXPORT_PRIVATE void releaseFastMallocFreeMemory(); 85 86 struct FastMallocStatistics { 87 size_t reservedVMBytes; 88 size_t committedVMBytes; 89 size_t freeListBytes; 90 }; 91 WTF_EXPORT_PRIVATE FastMallocStatistics fastMallocStatistics(); 92 93 // This defines a type which holds an unsigned integer and is the same 94 // size as the minimally aligned memory allocation. 95 typedef unsigned long long AllocAlignmentInteger; 96 97 namespace Internal { 98 enum AllocType { // Start with an unusual number instead of zero, because zero is common. 99 AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. 100 AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. 101 AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. 102 AllocTypeNew, // Encompasses global operator new. 103 AllocTypeNewArray // Encompasses global operator new[]. 104 }; 105 106 enum { 107 ValidationPrefix = 0xf00df00d, 108 ValidationSuffix = 0x0badf00d 109 }; 110 111 typedef unsigned ValidationTag; 112 113 struct ValidationHeader { 114 AllocType m_type; 115 unsigned m_size; 116 ValidationTag m_prefix; 117 unsigned m_alignment; 118 }; 119 120 static const int ValidationBufferSize = sizeof(ValidationHeader) + sizeof(ValidationTag); 121 } 122 123#if ENABLE(WTF_MALLOC_VALIDATION) 124 125 // Malloc validation is a scheme whereby a tag is attached to an 126 // allocation which identifies how it was originally allocated. 127 // This allows us to verify that the freeing operation matches the 128 // allocation operation. If memory is allocated with operator new[] 129 // but freed with free or delete, this system would detect that. 130 // In the implementation here, the tag is an integer prepended to 131 // the allocation memory which is assigned one of the AllocType 132 // enumeration values. An alternative implementation of this 133 // scheme could store the tag somewhere else or ignore it. 134 // Users of FastMalloc don't need to know or care how this tagging 135 // is implemented. 136 137 namespace Internal { 138 139 // Handle a detected alloc/free mismatch. By default this calls CRASH(). 140 void fastMallocMatchFailed(void* p); 141 142 inline ValidationHeader* fastMallocValidationHeader(void* p) 143 { 144 return reinterpret_cast<ValidationHeader*>(static_cast<char*>(p) - sizeof(ValidationHeader)); 145 } 146 147 inline ValidationTag* fastMallocValidationSuffix(void* p) 148 { 149 ValidationHeader* header = fastMallocValidationHeader(p); 150 if (header->m_prefix != static_cast<unsigned>(ValidationPrefix)) 151 fastMallocMatchFailed(p); 152 153 return reinterpret_cast<ValidationTag*>(static_cast<char*>(p) + header->m_size); 154 } 155 156 // Return the AllocType tag associated with the allocated block p. 157 inline AllocType fastMallocMatchValidationType(void* p) 158 { 159 return fastMallocValidationHeader(p)->m_type; 160 } 161 162 // Set the AllocType tag to be associaged with the allocated block p. 163 inline void setFastMallocMatchValidationType(void* p, AllocType allocType) 164 { 165 fastMallocValidationHeader(p)->m_type = allocType; 166 } 167 168 } // namespace Internal 169 170 // This is a higher level function which is used by FastMalloc-using code. 171 inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) 172 { 173 if (!p) 174 return; 175 176 Internal::setFastMallocMatchValidationType(p, allocType); 177 } 178 179 // This is a higher level function which is used by FastMalloc-using code. 180 inline void fastMallocMatchValidateFree(void* p, Internal::AllocType) 181 { 182 if (!p) 183 return; 184 185 Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); 186 if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix)) 187 Internal::fastMallocMatchFailed(p); 188 189 if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) 190 Internal::fastMallocMatchFailed(p); 191 192 Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. 193 } 194 195 inline void fastMallocValidate(void* p) 196 { 197 if (!p) 198 return; 199 200 Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); 201 if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix)) 202 Internal::fastMallocMatchFailed(p); 203 204 if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) 205 Internal::fastMallocMatchFailed(p); 206 } 207 208#else 209 210 inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) 211 { 212 } 213 214 inline void fastMallocMatchValidateFree(void*, Internal::AllocType) 215 { 216 } 217 218#endif 219 220} // namespace WTF 221 222using WTF::fastCalloc; 223using WTF::fastFree; 224using WTF::fastMalloc; 225using WTF::fastMallocGoodSize; 226using WTF::fastMallocSize; 227using WTF::fastRealloc; 228using WTF::fastStrDup; 229using WTF::fastZeroedMalloc; 230using WTF::tryFastCalloc; 231using WTF::tryFastMalloc; 232using WTF::tryFastRealloc; 233using WTF::tryFastZeroedMalloc; 234 235#ifndef NDEBUG 236using WTF::fastMallocForbid; 237using WTF::fastMallocAllow; 238#endif 239 240#if COMPILER(GCC) && OS(DARWIN) 241#define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) 242#elif COMPILER(GCC) 243#define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) 244#elif COMPILER(MSVC) 245#define WTF_PRIVATE_INLINE __forceinline 246#else 247#define WTF_PRIVATE_INLINE inline 248#endif 249 250#define WTF_MAKE_FAST_ALLOCATED \ 251public: \ 252 void* operator new(size_t, void* p) { return p; } \ 253 void* operator new[](size_t, void* p) { return p; } \ 254 \ 255 void* operator new(size_t size) \ 256 { \ 257 void* p = ::WTF::fastMalloc(size); \ 258 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \ 259 return p; \ 260 } \ 261 \ 262 void operator delete(void* p) \ 263 { \ 264 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \ 265 ::WTF::fastFree(p); \ 266 } \ 267 \ 268 void* operator new[](size_t size) \ 269 { \ 270 void* p = ::WTF::fastMalloc(size); \ 271 ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \ 272 return p; \ 273 } \ 274 \ 275 void operator delete[](void* p) \ 276 { \ 277 ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \ 278 ::WTF::fastFree(p); \ 279 } \ 280 void* operator new(size_t, NotNullTag, void* location) \ 281 { \ 282 ASSERT(location); \ 283 return location; \ 284 } \ 285private: \ 286typedef int __thisIsHereToForceASemicolonAfterThisMacro 287 288#endif /* WTF_FastMalloc_h */ 289