diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentImpl.cpp index 82cae0e44abec02dec2971bcf76194f4ed923cae..e080c2332a5e07e08b2680e89037c257dfbd9da3 100644 --- a/src/xercesc/dom/impl/DOMDocumentImpl.cpp +++ b/src/xercesc/dom/impl/DOMDocumentImpl.cpp @@ -805,25 +805,23 @@ static const int kMaxSubAllocationSize = 4096; // Any request for more bytes // allocating directly with system. void * DOMDocumentImpl::allocate(size_t amount) -{ - - size_t sizeOfPointer = sizeof(void *); -// some MIPS or IA64 machines may misallign if the class has a long data type member -// see Bug 10648 for details -// size_t sizeOfPointer = sizeof(long); -// REVISIT: sizeof(long) crashes on IA64 machine, we will look into it later. - - if (amount%sizeOfPointer!=0) - amount = amount + (sizeOfPointer - (amount % sizeOfPointer)); +{ + // Align the request size so that suballocated blocks + // beyond this one will be maintained at the same alignment. + amount = XMLPlatformUtils::alignPointerForNewBlockAllocation(amount); // If the request is for a largish block, hand it off to the system // allocator. The block still must be linked into the list of // allocated blocks so that it will be deleted when the time comes. if (amount > kMaxSubAllocationSize) { + // The size of the header we add to our raw blocks + size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *)); + + // Try to allocate the block void* newBlock = 0; try { - newBlock = fMemoryManager->allocate(amount + sizeOfPointer); //new char[amount + sizeOfPointer]; + newBlock = fMemoryManager->allocate(sizeOfHeader + amount); //new char[amount + sizeOfHeader]; } catch (...) { ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory); @@ -831,6 +829,9 @@ void * DOMDocumentImpl::allocate(size_t amount) if (!newBlock) ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory); + // Link it into the list beyond current block, as current block + // is still being subdivided. If there is no current block + // then track that we have no bytes to further divide. if (fCurrentBlock) { *(void **)newBlock = *(void **)fCurrentBlock; @@ -842,16 +843,21 @@ void * DOMDocumentImpl::allocate(size_t amount) fFreePtr = 0; fFreeBytesRemaining = 0; } - void *retPtr = (char *)newBlock + sizeOfPointer; + + void *retPtr = (char *)newBlock + sizeOfHeader; return retPtr; } - - // It's a normal (sub-allocatable) request. - if (amount > fFreeBytesRemaining) + // It's a normal (sub-allocatable) request. + // Are we out of room in our current block? + if (amount > fFreeBytesRemaining) { // Request doesn't fit in the current block. - // Get a new one from the system allocator. + + // The size of the header we add to our raw blocks + size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *)); + + // Get a new block from the system allocator. void* newBlock = 0; try { newBlock = fMemoryManager->allocate(kHeapAllocSize); //new char[kHeapAllocSize]; @@ -864,29 +870,30 @@ void * DOMDocumentImpl::allocate(size_t amount) *(void **)newBlock = fCurrentBlock; fCurrentBlock = newBlock; - fFreePtr = (char *)newBlock + sizeOfPointer; - fFreeBytesRemaining = kHeapAllocSize - sizeOfPointer; + fFreePtr = (char *)newBlock + sizeOfHeader; + fFreeBytesRemaining = kHeapAllocSize - sizeOfHeader; } + // Subdivide the request off current block void *retPtr = fFreePtr; fFreePtr += amount; fFreeBytesRemaining -= amount; + return retPtr; } void DOMDocumentImpl::deleteHeap() { - void *block = fCurrentBlock; while (fCurrentBlock != 0) { void *nextBlock = *(void **)fCurrentBlock; fMemoryManager->deallocate(fCurrentBlock); //delete [] (char*) fCurrentBlock; fCurrentBlock = nextBlock; } - } + DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName) { if(!fNodeListPool) { diff --git a/src/xercesc/util/PlatformUtils.hpp b/src/xercesc/util/PlatformUtils.hpp index 62c8a5e9d4c0190ab686a52437fedc5df263bddf..72558338803697d4aed37f4adcc302c102a9dadf 100644 --- a/src/xercesc/util/PlatformUtils.hpp +++ b/src/xercesc/util/PlatformUtils.hpp @@ -699,7 +699,15 @@ public : */ static bool isStrictIANAEncoding(); //@} - + + /** + * Aligns the specified pointer per platform block allocation + * requirements. + * + * The results of this function may be altered by defining + * XML_PLATFORM_NEW_BLOCK_ALIGNMENT. + */ + static inline void* alignPointerForNewBlockAllocation(void* ptr); private : /** @name Private static methods */ @@ -780,6 +788,35 @@ private : MakeXMLException(XMLPlatformUtilsException, XMLUTIL_EXPORT) +// --------------------------------------------------------------------------- +// XMLPlatformUtils: alignPointerForNewBlockAllocation +// --------------------------------------------------------------------------- +// Calculate alignment required by platform for a new +// block allocation. We use this in our custom allocators +// to ensure that returned blocks are properly aligned. +inline void* +XMLPlatformUtils::alignPointerForNewBlockAllocation(void* ptr) +{ + // Macro XML_PLATFORM_NEW_BLOCK_ALIGNMENT may be defined + // as needed to dictate alignment requirements on a + // per-architecture basis. In the absense of that we + // take an educated guess. + #ifdef XML_PLATFORM_NEW_BLOCK_ALIGNMENT + size_t alignment = XML_PLATFORM_NEW_BLOCK_ALIGNMENT; + #else + size_t alignment = (sizeof(void*) >= sizeof(double)) ? sizeof(void*) : sizeof(double); + #endif + + // Calculate current alignment of pointer + size_t current = (long)ptr % alignment; + + // Adjust pointer alignment as needed + return (current == 0) + ? ptr + : ((char*)ptr + alignment - current); +} + + // --------------------------------------------------------------------------- // XMLDeleter: Public Destructor diff --git a/src/xercesc/util/XMemory.cpp b/src/xercesc/util/XMemory.cpp index 4cfe8578cd93dbfc3d69896eface68de4e1551a3..735e0722831f16b86fd7309ea4b99992db385863 100644 --- a/src/xercesc/util/XMemory.cpp +++ b/src/xercesc/util/XMemory.cpp @@ -69,31 +69,11 @@ XERCES_CPP_NAMESPACE_BEGIN - -// Calculate alignment required by platform. -// Total size of our header must match platform -// architecture-specific alignment, in order -// that the returned block ptr (which follows our -// header), maintains block/structure alignment. -inline size_t -CalculateBlockHeaderSize() -{ - // Macro XML_NEW_BLOCK_ALIGNMENT may be defined - // as needed to calculate alignment on a per-architecture - // basis. - #ifdef XML_NEW_BLOCK_ALIGNMENT - size_t alignment = XML_NEW_BLOCK_ALIGNMENT; - #else - size_t alignment = sizeof(void*) > sizeof(double) ? sizeof(void*) : sizeof(double); - #endif - - size_t headerUsage = sizeof(MemoryManager*); - return (headerUsage + (alignment - headerUsage % alignment)); -} - void* XMemory::operator new(size_t size) { - size_t headerSize = CalculateBlockHeaderSize(); + size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation( + sizeof(MemoryManager*)); + void* const block = XMLPlatformUtils::fgMemoryManager->allocate ( headerSize + size @@ -107,7 +87,8 @@ void* XMemory::operator new(size_t size, MemoryManager* manager) { assert(manager != 0); - size_t headerSize = CalculateBlockHeaderSize(); + size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation( + sizeof(MemoryManager*)); void* const block = manager->allocate(headerSize + size); *(MemoryManager**)block = manager; @@ -118,7 +99,8 @@ void XMemory::operator delete(void* p) { if (p != 0) { - size_t headerSize = CalculateBlockHeaderSize(); + size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation( + sizeof(MemoryManager*)); void* const block = (char*)p - headerSize; MemoryManager* const manager = *(MemoryManager**)block; @@ -136,7 +118,8 @@ void XMemory::operator delete(void* p, MemoryManager* manager) if (p != 0) { - size_t headerSize = CalculateBlockHeaderSize(); + size_t headerSize = XMLPlatformUtils::alignPointerForNewBlockAllocation( + sizeof(MemoryManager*)); void* const block = (char*)p - headerSize; assert(*(MemoryManager**)block == manager);