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 29namespace 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 183using WTF::fastCalloc; 184using WTF::fastFree; 185using WTF::fastMalloc; 186using WTF::fastMallocSize; 187using WTF::fastRealloc; 188using WTF::fastStrDup; 189using WTF::fastZeroedMalloc; 190using WTF::tryFastCalloc; 191using WTF::tryFastMalloc; 192using WTF::tryFastRealloc; 193using WTF::tryFastZeroedMalloc; 194 195#ifndef NDEBUG 196using WTF::fastMallocForbid; 197using 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 225WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); } 226WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } 227WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); } 228WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } 229WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); } 230WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } 231WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); } 232WTF_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