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 "Platform.h" 25 #include "PossiblyNull.h" 26 #include <stdlib.h> 27 #include <new> 28 29 namespace WTF { 30 31 // These functions call CRASH() if an allocation fails. 32 void* fastMalloc(size_t); 33 void* fastZeroedMalloc(size_t); 34 void* fastCalloc(size_t numElements, size_t elementSize); 35 void* fastRealloc(void*, size_t); 36 char* fastStrDup(const char*); 37 size_t fastMallocSize(const void*); 38 39 struct TryMallocReturnValue { 40 TryMallocReturnValue(void* data) 41 : m_data(data) 42 { 43 } 44 TryMallocReturnValue(const TryMallocReturnValue& source) 45 : m_data(source.m_data) 46 { 47 source.m_data = 0; 48 } 49 ~TryMallocReturnValue() { ASSERT(!m_data); } 50 template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN; 51 template <typename T> operator PossiblyNull<T>() 52 { 53 T value; 54 getValue(value); 55 return PossiblyNull<T>(value); 56 } 57 private: 58 mutable void* m_data; 59 }; 60 61 template <typename T> bool TryMallocReturnValue::getValue(T& data) 62 { 63 union u { void* data; T target; } res; 64 res.data = m_data; 65 data = res.target; 66 bool returnValue = !!m_data; 67 m_data = 0; 68 return returnValue; 69 } 70 71 TryMallocReturnValue tryFastMalloc(size_t n); 72 TryMallocReturnValue tryFastZeroedMalloc(size_t n); 73 TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size); 74 TryMallocReturnValue tryFastRealloc(void* p, size_t n); 75 76 void fastFree(void*); 77 78 #ifndef NDEBUG 79 void fastMallocForbid(); 80 void fastMallocAllow(); 81 #endif 82 83 void releaseFastMallocFreeMemory(); 84 85 struct FastMallocStatistics { 86 size_t reservedVMBytes; 87 size_t committedVMBytes; 88 size_t freeListBytes; 89 }; 90 FastMallocStatistics fastMallocStatistics(); 91 92 // This defines a type which holds an unsigned integer and is the same 93 // size as the minimally aligned memory allocation. 94 typedef unsigned long long AllocAlignmentInteger; 95 96 namespace Internal { 97 enum AllocType { // Start with an unusual number instead of zero, because zero is common. 98 AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. 99 AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. 100 AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. 101 AllocTypeFastNew, // Encompasses fastNew. 102 AllocTypeFastNewArray, // Encompasses fastNewArray. 103 AllocTypeNew, // Encompasses global operator new. 104 AllocTypeNewArray // Encompasses global operator new[]. 105 }; 106 } 107 108 #if ENABLE(FAST_MALLOC_MATCH_VALIDATION) 109 110 // Malloc validation is a scheme whereby a tag is attached to an 111 // allocation which identifies how it was originally allocated. 112 // This allows us to verify that the freeing operation matches the 113 // allocation operation. If memory is allocated with operator new[] 114 // but freed with free or delete, this system would detect that. 115 // In the implementation here, the tag is an integer prepended to 116 // the allocation memory which is assigned one of the AllocType 117 // enumeration values. An alternative implementation of this 118 // scheme could store the tag somewhere else or ignore it. 119 // Users of FastMalloc don't need to know or care how this tagging 120 // is implemented. 121 122 namespace Internal { 123 124 // Return the AllocType tag associated with the allocated block p. 125 inline AllocType fastMallocMatchValidationType(const void* p) 126 { 127 const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1; 128 return static_cast<AllocType>(*type); 129 } 130 131 // Return the address of the AllocType tag associated with the allocated block p. 132 inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p) 133 { 134 return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger)); 135 } 136 137 // Set the AllocType tag to be associaged with the allocated block p. 138 inline void setFastMallocMatchValidationType(void* p, AllocType allocType) 139 { 140 AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1; 141 *type = static_cast<AllocAlignmentInteger>(allocType); 142 } 143 144 // Handle a detected alloc/free mismatch. By default this calls CRASH(). 145 void fastMallocMatchFailed(void* p); 146 147 } // namespace Internal 148 149 // This is a higher level function which is used by FastMalloc-using code. 150 inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) 151 { 152 if (!p) 153 return; 154 155 Internal::setFastMallocMatchValidationType(p, allocType); 156 } 157 158 // This is a higher level function which is used by FastMalloc-using code. 159 inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType) 160 { 161 if (!p) 162 return; 163 164 if (Internal::fastMallocMatchValidationType(p) != allocType) 165 Internal::fastMallocMatchFailed(p); 166 Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. 167 } 168 169 #else 170 171 inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) 172 { 173 } 174 175 inline void fastMallocMatchValidateFree(void*, Internal::AllocType) 176 { 177 } 178 179 #endif 180 181 } // namespace WTF 182 183 using WTF::fastCalloc; 184 using WTF::fastFree; 185 using WTF::fastMalloc; 186 using WTF::fastMallocSize; 187 using WTF::fastRealloc; 188 using WTF::fastStrDup; 189 using WTF::fastZeroedMalloc; 190 using WTF::tryFastCalloc; 191 using WTF::tryFastMalloc; 192 using WTF::tryFastRealloc; 193 using WTF::tryFastZeroedMalloc; 194 195 #ifndef NDEBUG 196 using WTF::fastMallocForbid; 197 using WTF::fastMallocAllow; 198 #endif 199 200 #if COMPILER(GCC) && OS(DARWIN) 201 #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) 202 #elif COMPILER(GCC) 203 #define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) 204 #elif COMPILER(MSVC) || COMPILER(RVCT) 205 #define WTF_PRIVATE_INLINE __forceinline 206 #else 207 #define WTF_PRIVATE_INLINE inline 208 #endif 209 210 #if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC && !PLATFORM(BREWMP)) 211 212 // The nothrow functions here are actually not all that helpful, because fastMalloc will 213 // call CRASH() rather than returning 0, and returning 0 is what nothrow is all about. 214 // But since WebKit code never uses exceptions or nothrow at all, this is probably OK. 215 // Long term we will adopt FastAllocBase.h everywhere, and and replace this with 216 // debug-only code to make sure we don't use the system malloc via the default operator 217 // new by accident. 218 219 #if ENABLE(GLOBAL_FASTMALLOC_NEW) 220 221 #if COMPILER(MSVC) 222 #pragma warning(push) 223 #pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning. 224 #endif 225 WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); } 226 WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } 227 WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); } 228 WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } 229 WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); } 230 WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } 231 WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); } 232 WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } 233 #if COMPILER(MSVC) 234 #pragma warning(pop) 235 #endif 236 237 #endif 238 239 #endif 240 241 #endif /* WTF_FastMalloc_h */ 242