diff options
Diffstat (limited to 'Source/WebCore/platform/mac/PurgeableBufferMac.cpp')
| -rw-r--r-- | Source/WebCore/platform/mac/PurgeableBufferMac.cpp | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/Source/WebCore/platform/mac/PurgeableBufferMac.cpp b/Source/WebCore/platform/mac/PurgeableBufferMac.cpp new file mode 100644 index 0000000..fdbac1f --- /dev/null +++ b/Source/WebCore/platform/mac/PurgeableBufferMac.cpp @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(PURGEABLE_MEMORY) + +#include "PurgeableBuffer.h" + +#include <mach/mach.h> +#include <wtf/Assertions.h> +#include <wtf/VMTags.h> + +namespace WebCore { + +// Purgeable buffers are allocated in multiples of the page size (4KB in common CPUs) so +// it does not make sense for very small buffers. Set our minimum size to 16KB. +static const size_t minPurgeableBufferSize = 4 * 4096; + +PurgeableBuffer::PurgeableBuffer(char* data, size_t size) + : m_data(data) + , m_size(size) + , m_purgePriority(PurgeDefault) + , m_state(NonVolatile) +{ +} + +PurgeableBuffer::~PurgeableBuffer() +{ + vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), m_size); +} + +PassOwnPtr<PurgeableBuffer> PurgeableBuffer::create(const char* data, size_t size) +{ + if (size < minPurgeableBufferSize) + return PassOwnPtr<PurgeableBuffer>(); + + vm_address_t buffer = 0; + kern_return_t ret = vm_allocate(mach_task_self(), &buffer, size, VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE | VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY); + + ASSERT(ret == KERN_SUCCESS); + if (ret != KERN_SUCCESS) + return PassOwnPtr<PurgeableBuffer>(); + + ret = vm_copy(mach_task_self(), reinterpret_cast<vm_address_t>(data), size, buffer); + + ASSERT(ret == KERN_SUCCESS); + if (ret != KERN_SUCCESS) { + vm_deallocate(mach_task_self(), buffer, size); + return PassOwnPtr<PurgeableBuffer>(); + } + + return adoptPtr(new PurgeableBuffer(reinterpret_cast<char*>(buffer), size)); +} + +bool PurgeableBuffer::makePurgeable(bool purgeable) +{ + if (purgeable) { + if (m_state != NonVolatile) + return true; + + int volatileGroup; + if (m_purgePriority == PurgeFirst) + volatileGroup = VM_VOLATILE_GROUP_0; + else if (m_purgePriority == PurgeMiddle) + volatileGroup = VM_VOLATILE_GROUP_4; + else + volatileGroup = VM_VOLATILE_GROUP_7; + + int state = VM_PURGABLE_VOLATILE | volatileGroup; + // So apparently "purgeable" is the correct spelling and the API here is misspelled. + kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_SET_STATE, &state); + + if (ret != KERN_SUCCESS) { + // If that failed we have no clue what state we are in so assume purged. + m_state = Purged; + return true; + } + + m_state = Volatile; + return true; + } + + if (m_state == NonVolatile) + return true; + if (m_state == Purged) + return false; + + int state = VM_PURGABLE_NONVOLATILE; + kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_SET_STATE, &state); + + if (ret != KERN_SUCCESS) { + // If that failed we have no clue what state we are in so assume purged. + m_state = Purged; + return false; + } + + m_state = state & VM_PURGABLE_EMPTY ? Purged : NonVolatile; + return m_state == NonVolatile; +} + +bool PurgeableBuffer::wasPurged() const +{ + if (m_state == NonVolatile) + return false; + if (m_state == Purged) + return true; + + int state; + kern_return_t ret = vm_purgable_control(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), VM_PURGABLE_GET_STATE, &state); + + if (ret != KERN_SUCCESS) { + // If that failed we have no clue what state we are in so assume purged. + m_state = Purged; + return true; + } + + if (state & VM_PURGABLE_EMPTY) { + m_state = Purged; + return true; + } + + return false; +} + +const char* PurgeableBuffer::data() const +{ + ASSERT(m_state == NonVolatile); + return m_data; +} + +} + +#endif // BUILDING_ON_TIGER |
