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 38 struct TryMallocReturnValue { 39 TryMallocReturnValue(void* data) 40 : m_data(data) 41 { 42 } 43 TryMallocReturnValue(const TryMallocReturnValue& source) 44 : m_data(source.m_data) 45 { 46 source.m_data = 0; 47 } 48 ~TryMallocReturnValue() { ASSERT(!m_data); } 49 template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN; 50 template <typename T> operator PossiblyNull<T>() 51 { 52 T value; 53 getValue(value); 54 return PossiblyNull<T>(value); 55 } 56 private: 57 mutable void* m_data; 58 }; 59 60 template <typename T> bool TryMallocReturnValue::getValue(T& data) 61 { 62 union u { void* data; T target; } res; 63 res.data = m_data; 64 data = res.target; 65 bool returnValue = !!m_data; 66 m_data = 0; 67 return returnValue; 68 } 69 70 TryMallocReturnValue tryFastMalloc(size_t n); 71 TryMallocReturnValue tryFastZeroedMalloc(size_t n); 72 TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size); 73 TryMallocReturnValue tryFastRealloc(void* p, size_t n); 74 75 void fastFree(void*); 76 77 #ifndef NDEBUG 78 void fastMallocForbid(); 79 void fastMallocAllow(); 80 #endif 81 82 void releaseFastMallocFreeMemory(); 83 84 struct FastMallocStatistics { 85 size_t heapSize; 86 size_t freeSizeInHeap; 87 size_t freeSizeInCaches; 88 size_t returnedSize; 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::fastMalloc; 184 using WTF::fastZeroedMalloc; 185 using WTF::fastCalloc; 186 using WTF::fastRealloc; 187 using WTF::tryFastMalloc; 188 using WTF::tryFastZeroedMalloc; 189 using WTF::tryFastCalloc; 190 using WTF::tryFastRealloc; 191 using WTF::fastFree; 192 using WTF::fastStrDup; 193 194 #ifndef NDEBUG 195 using WTF::fastMallocForbid; 196 using WTF::fastMallocAllow; 197 #endif 198 199 #if COMPILER(GCC) && OS(DARWIN) 200 #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) 201 #elif COMPILER(GCC) 202 #define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) 203 #elif COMPILER(MSVC) || COMPILER(RVCT) 204 #define WTF_PRIVATE_INLINE __forceinline 205 #else 206 #define WTF_PRIVATE_INLINE inline 207 #endif 208 209 #if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) 210 211 // The nothrow functions here are actually not all that helpful, because fastMalloc will 212 // call CRASH() rather than returning 0, and returning 0 is what nothrow is all about. 213 // But since WebKit code never uses exceptions or nothrow at all, this is probably OK. 214 // Long term we will adopt FastAllocBase.h everywhere, and and replace this with 215 // debug-only code to make sure we don't use the system malloc via the default operator 216 // new by accident. 217 218 // We musn't customize the global operator new and delete for the Qt port. 219 #if !PLATFORM(QT) 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