summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/wtf/PageAllocation.h
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-08-11 14:44:44 +0100
committerBen Murdoch <benm@google.com>2010-08-12 19:15:41 +0100
commitdd8bb3de4f353a81954234999f1fea748aee2ea9 (patch)
tree729b52bf09294f0d6c67cd5ea80aee1b727b7bd8 /JavaScriptCore/wtf/PageAllocation.h
parentf3d41ba51d86bf719c7a65ab5297aea3c17e2d98 (diff)
downloadexternal_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.zip
external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.tar.gz
external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.tar.bz2
Merge WebKit at r65072 : Initial merge by git.
Change-Id: Ibcf418498376b2660aacb7f8d46ea7085ef91585
Diffstat (limited to 'JavaScriptCore/wtf/PageAllocation.h')
-rw-r--r--JavaScriptCore/wtf/PageAllocation.h298
1 files changed, 267 insertions, 31 deletions
diff --git a/JavaScriptCore/wtf/PageAllocation.h b/JavaScriptCore/wtf/PageAllocation.h
index b846482..26d53a5 100644
--- a/JavaScriptCore/wtf/PageAllocation.h
+++ b/JavaScriptCore/wtf/PageAllocation.h
@@ -26,21 +26,63 @@
#ifndef PageAllocation_h
#define PageAllocation_h
+#include <wtf/Assertions.h>
#include <wtf/UnusedParam.h>
#include <wtf/VMTags.h>
+#if OS(DARWIN)
+#include <mach/mach_init.h>
+#include <mach/vm_map.h>
+#endif
+
+#if OS(HAIKU)
+#include <OS.h>
+#endif
+
+#if OS(WINDOWS)
+#include <malloc.h>
+#include <windows.h>
+#endif
+
#if OS(SYMBIAN)
+#include <e32hal.h>
#include <e32std.h>
#endif
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
+
#if HAVE(MMAP)
-#define PAGE_ALLOCATION_ALLOCATE_AT 1
-#else
-#define PAGE_ALLOCATION_ALLOCATE_AT 0
+#include <sys/mman.h>
+#include <unistd.h>
#endif
namespace WTF {
+/*
+ PageAllocation
+
+ The PageAllocation class provides a cross-platform memory allocation interface
+ with similar capabilities to posix mmap/munmap. Memory is allocated by calling
+ PageAllocation::allocate, and deallocated by calling deallocate on the
+ PageAllocation object. The PageAllocation holds the allocation's base pointer
+ and size.
+
+ The allocate method is passed the size required (which must be a multiple of
+ the system page size, which can be accessed using PageAllocation::pageSize).
+ Callers may also optinally provide a flag indicating the usage (for use by
+ system memory usage tracking tools, where implemented), and boolean values
+ specifying the required protection (defaulting to writable, non-executable).
+
+ Where HAVE(PAGE_ALLOCATE_AT) and HAVE(PAGE_ALLOCATE_ALIGNED) are available
+ memory may also be allocated at a specified address, or with a specified
+ alignment respectively. PageAllocation::allocateAt take an address to try
+ to allocate at, and a boolean indicating whether this behaviour is strictly
+ required (if this address is unavailable, should memory at another address
+ be allocated instead). PageAllocation::allocateAligned requires that the
+ size is a power of two that is >= system page size.
+*/
class PageAllocation {
public:
enum Usage {
@@ -60,42 +102,56 @@ public:
{
}
- // Create a PageAllocation object representing a sub-region of an existing allocation;
- // deallocate should never be called on an object represnting a subregion, only on the
- // initial allocation.
- PageAllocation(void* base, size_t size, const PageAllocation& parent)
- : m_base(base)
- , m_size(size)
-#if OS(SYMBIAN)
- , m_chunk(parent.m_chunk)
-#endif
+ bool operator!() const { return !m_base; }
+ void* base() const { return m_base; }
+ size_t size() const { return m_size; }
+
+ static PageAllocation allocate(size_t size, Usage usage = UnknownUsage, bool writable = true, bool executable = false)
{
-#if defined(NDEBUG) && !OS(SYMBIAN)
- UNUSED_PARAM(parent);
-#endif
- ASSERT(base >= parent.m_base);
- ASSERT(size <= parent.m_size);
- ASSERT(static_cast<char*>(base) + size <= static_cast<char*>(parent.m_base) + parent.m_size);
+ ASSERT(isPageAligned(size));
+ return systemAllocate(size, usage, writable, executable);
}
- void* base() const { return m_base; }
- size_t size() const { return m_size; }
+#if HAVE(PAGE_ALLOCATE_AT)
+ static PageAllocation allocateAt(void* address, bool fixed, size_t size, Usage usage = UnknownUsage, bool writable = true, bool executable = false)
+ {
+ ASSERT(isPageAligned(address));
+ ASSERT(isPageAligned(size));
+ return systemAllocateAt(address, fixed, size, usage, writable, executable);
+ }
+#endif
- bool operator!() const { return !m_base; }
+#if HAVE(PAGE_ALLOCATE_ALIGNED)
+ static PageAllocation allocateAligned(size_t size, Usage usage = UnknownUsage)
+ {
+ ASSERT(isPageAligned(size));
+ ASSERT(isPowerOfTwo(size));
+ return systemAllocateAligned(size, usage);
+ }
+#endif
+
+ void deallocate()
+ {
+ ASSERT(m_base);
+ systemDeallocate(true);
+ }
- bool commit(void*, size_t, bool writable = true, bool executable = false) const;
- void decommit(void*, size_t) const;
- void deallocate();
+ static size_t pageSize()
+ {
+ if (!s_pageSize)
+ s_pageSize = systemPageSize();
+ ASSERT(isPowerOfTwo(s_pageSize));
+ return s_pageSize;
+ }
- static PageAllocation allocate(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
- static PageAllocation reserve(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
-#if PAGE_ALLOCATION_ALLOCATE_AT
- static PageAllocation allocateAt(void* address, bool fixed, size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
- static PageAllocation reserveAt(void* address, bool fixed, size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
+#ifndef NDEBUG
+ static bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); }
+ static bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); }
+ static bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); }
+ static int lastError();
#endif
- static size_t pagesize();
-private:
+protected:
#if OS(SYMBIAN)
PageAllocation(void* base, size_t size, RChunk* chunk)
: m_base(base)
@@ -111,13 +167,193 @@ private:
}
#endif
+ static PageAllocation systemAllocate(size_t, Usage, bool, bool);
+#if HAVE(PAGE_ALLOCATE_AT)
+ static PageAllocation systemAllocateAt(void*, bool, size_t, Usage, bool, bool);
+#endif
+#if HAVE(PAGE_ALLOCATE_ALIGNED)
+ static PageAllocation systemAllocateAligned(size_t, Usage);
+#endif
+ // systemDeallocate takes a parameter indicating whether memory is currently committed
+ // (this should always be true for PageAllocation, false for PageReservation).
+ void systemDeallocate(bool committed);
+ static size_t systemPageSize();
+
void* m_base;
size_t m_size;
#if OS(SYMBIAN)
RChunk* m_chunk;
#endif
+
+ static JS_EXPORTDATA size_t s_pageSize;
};
+
+#if HAVE(MMAP)
+
+
+inline PageAllocation PageAllocation::systemAllocate(size_t size, Usage usage, bool writable, bool executable)
+{
+ return systemAllocateAt(0, false, size, usage, writable, executable);
+}
+
+inline PageAllocation PageAllocation::systemAllocateAt(void* address, bool fixed, size_t size, Usage usage, bool writable, bool executable)
+{
+ int protection = PROT_READ;
+ if (writable)
+ protection |= PROT_WRITE;
+ if (executable)
+ protection |= PROT_EXEC;
+
+ int flags = MAP_PRIVATE | MAP_ANON;
+ if (fixed)
+ flags |= MAP_FIXED;
+
+#if OS(DARWIN) && !defined(BUILDING_ON_TIGER)
+ int fd = usage;
+#else
+ int fd = -1;
+#endif
+
+ void* base = mmap(address, size, protection, flags, fd, 0);
+ if (base == MAP_FAILED)
+ base = 0;
+ return PageAllocation(base, size);
+}
+
+inline PageAllocation PageAllocation::systemAllocateAligned(size_t size, Usage usage)
+{
+#if OS(DARWIN)
+ vm_address_t address = 0;
+ int flags = VM_FLAGS_ANYWHERE;
+ if (usage != -1)
+ flags |= usage;
+ vm_map(current_task(), &address, size, (size - 1), flags, MEMORY_OBJECT_NULL, 0, FALSE, PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE | PROT_EXEC, VM_INHERIT_DEFAULT);
+ return PageAllocation(reinterpret_cast<void*>(address), size);
+#elif HAVE(POSIX_MEMALIGN)
+ void* address;
+ posix_memalign(&address, size, size);
+ return PageAllocation(address, size);
+#else
+ size_t extra = size - pageSize();
+
+ // Check for overflow.
+ if ((size + extra) < size)
+ return PageAllocation(0, size);
+
+#if OS(DARWIN) && !defined(BUILDING_ON_TIGER)
+ int fd = usage;
+#else
+ int fd = -1;
+#endif
+ void* mmapResult = mmap(0, size + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, fd, 0);
+ if (mmapResult == MAP_FAILED)
+ return PageAllocation(0, size);
+ uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
+
+ size_t adjust = 0;
+ if ((address & (size - 1)))
+ adjust = size - (address & (size - 1));
+ if (adjust > 0)
+ munmap(reinterpret_cast<char*>(address), adjust);
+ if (adjust < extra)
+ munmap(reinterpret_cast<char*>(address + adjust + size), extra - adjust);
+ address += adjust;
+
+ return PageAllocation(reinterpret_cast<void*>(address), size);
+#endif
+}
+
+inline void PageAllocation::systemDeallocate(bool)
+{
+ int result = munmap(m_base, m_size);
+ ASSERT_UNUSED(result, !result);
+ m_base = 0;
+}
+
+inline size_t PageAllocation::systemPageSize()
+{
+ return getpagesize();
+}
+
+
+#elif HAVE(VIRTUALALLOC)
+
+
+inline PageAllocation PageAllocation::systemAllocate(size_t size, Usage, bool writable, bool executable)
+{
+ DWORD protection = executable ?
+ (writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ) :
+ (writable ? PAGE_READWRITE : PAGE_READONLY);
+ return PageAllocation(VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, protection), size);
+}
+
+#if HAVE(ALIGNED_MALLOC)
+inline PageAllocation PageAllocation::systemAllocateAligned(size_t size, Usage usage)
+{
+#if COMPILER(MINGW) && !COMPILER(MINGW64)
+ void* address = __mingw_aligned_malloc(size, size);
+#else
+ void* address = _aligned_malloc(size, size);
+#endif
+ memset(address, 0, size);
+ return PageAllocation(address, size);
+}
+#endif
+
+inline void PageAllocation::systemDeallocate(bool committed)
+{
+#if OS(WINCE)
+ if (committed)
+ VirtualFree(m_base, m_size, MEM_DECOMMIT);
+#else
+ UNUSED_PARAM(committed);
+#endif
+ VirtualFree(m_base, 0, MEM_RELEASE);
+ m_base = 0;
+}
+
+inline size_t PageAllocation::systemPageSize()
+{
+ static size_t size = 0;
+ SYSTEM_INFO system_info;
+ GetSystemInfo(&system_info);
+ size = system_info.dwPageSize;
+ return size;
+}
+
+
+#elif OS(SYMBIAN)
+
+
+inline PageAllocation PageAllocation::systemAllocate(size_t size, Usage usage, bool writable, bool executable)
+{
+ RChunk* rchunk = new RChunk();
+ if (executable)
+ rchunk->CreateLocalCode(size, size);
+ else
+ rchunk->CreateLocal(size, size);
+ return PageAllocation(rchunk->Base(), size, rchunk);
+}
+
+inline void PageAllocation::systemDeallocate(bool)
+{
+ m_chunk->Close();
+ delete m_chunk;
+ m_base = 0;
+}
+
+inline size_t PageAllocation::systemPageSize()
+{
+ static TInt page_size = 0;
+ UserHal::PageSizeInBytes(page_size);
+ return page_size;
+}
+
+
+#endif
+
+
}
using WTF::PageAllocation;