Index: src/platform-cygwin.cc |
=================================================================== |
--- src/platform-cygwin.cc (revision 14269) |
+++ src/platform-cygwin.cc (working copy) |
@@ -194,6 +194,11 @@ |
} |
+void OS::DumpBacktrace() { |
+ // Currently unsupported. |
+} |
+ |
+ |
class PosixMemoryMappedFile : public OS::MemoryMappedFile { |
public: |
PosixMemoryMappedFile(FILE* file, void* memory, int size) |
@@ -319,6 +324,50 @@ |
// This causes VirtualMemory::Commit to not always commit the memory region |
// specified. |
+static void* GetRandomAddr() { |
+ Isolate* isolate = Isolate::UncheckedCurrent(); |
+ // Note that the current isolate isn't set up in a call path via |
+ // CpuFeatures::Probe. We don't care about randomization in this case because |
+ // the code page is immediately freed. |
+ if (isolate != NULL) { |
+ // The address range used to randomize RWX allocations in OS::Allocate |
+ // Try not to map pages into the default range that windows loads DLLs |
+ // Use a multiple of 64k to prevent committing unused memory. |
+ // Note: This does not guarantee RWX regions will be within the |
+ // range kAllocationRandomAddressMin to kAllocationRandomAddressMax |
+#ifdef V8_HOST_ARCH_64_BIT |
+ static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000; |
+ static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000; |
+#else |
+ static const intptr_t kAllocationRandomAddressMin = 0x04000000; |
+ static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; |
+#endif |
+ uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits) |
+ | kAllocationRandomAddressMin; |
+ address &= kAllocationRandomAddressMax; |
+ return reinterpret_cast<void *>(address); |
+ } |
+ return NULL; |
+} |
+ |
+ |
+static void* RandomizedVirtualAlloc(size_t size, int action, int protection) { |
+ LPVOID base = NULL; |
+ |
+ if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) { |
+ // For exectutable pages try and randomize the allocation address |
+ for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) { |
+ base = VirtualAlloc(GetRandomAddr(), size, action, protection); |
+ } |
+ } |
+ |
+ // After three attempts give up and let the OS find an address to use. |
+ if (base == NULL) base = VirtualAlloc(NULL, size, action, protection); |
+ |
+ return base; |
+} |
+ |
+ |
VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } |
@@ -326,9 +375,37 @@ |
: address_(ReserveRegion(size)), size_(size) { } |
+VirtualMemory::VirtualMemory(size_t size, size_t alignment) |
+ : address_(NULL), size_(0) { |
+ ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); |
+ size_t request_size = RoundUp(size + alignment, |
+ static_cast<intptr_t>(OS::AllocateAlignment())); |
+ void* address = ReserveRegion(request_size); |
+ if (address == NULL) return; |
+ Address base = RoundUp(static_cast<Address>(address), alignment); |
+ // Try reducing the size by freeing and then reallocating a specific area. |
+ bool result = ReleaseRegion(address, request_size); |
+ USE(result); |
+ ASSERT(result); |
+ address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS); |
+ if (address != NULL) { |
+ request_size = size; |
+ ASSERT(base == static_cast<Address>(address)); |
+ } else { |
+ // Resizing failed, just go with a bigger area. |
+ address = ReserveRegion(request_size); |
+ if (address == NULL) return; |
+ } |
+ address_ = address; |
+ size_ = request_size; |
+} |
+ |
+ |
VirtualMemory::~VirtualMemory() { |
if (IsReserved()) { |
- if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL; |
+ bool result = ReleaseRegion(address_, size_); |
+ ASSERT(result); |
+ USE(result); |
} |
} |
@@ -345,22 +422,32 @@ |
bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { |
+ return CommitRegion(address, size, is_executable); |
+} |
+ |
+ |
+bool VirtualMemory::Uncommit(void* address, size_t size) { |
+ ASSERT(IsReserved()); |
+ return UncommitRegion(address, size); |
+} |
+ |
+ |
+void* VirtualMemory::ReserveRegion(size_t size) { |
+ return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS); |
+} |
+ |
+ |
+bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { |
int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; |
- if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) { |
+ if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) { |
return false; |
} |
- UpdateAllocatedSpaceLimits(address, static_cast<int>(size)); |
+ UpdateAllocatedSpaceLimits(base, static_cast<int>(size)); |
return true; |
} |
-bool VirtualMemory::Uncommit(void* address, size_t size) { |
- ASSERT(IsReserved()); |
- return VirtualFree(address, size, MEM_DECOMMIT) != false; |
-} |
- |
- |
bool VirtualMemory::Guard(void* address) { |
if (NULL == VirtualAlloc(address, |
OS::CommitPageSize(), |
@@ -372,26 +459,13 @@ |
} |
-void* VirtualMemory::ReserveRegion(size_t size) { |
- return VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); |
-} |
- |
- |
-bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { |
- UNIMPLEMENTED(); |
- return false; |
-} |
- |
- |
bool VirtualMemory::UncommitRegion(void* base, size_t size) { |
- UNIMPLEMENTED(); |
- return false; |
+ return VirtualFree(base, size, MEM_DECOMMIT) != 0; |
} |
bool VirtualMemory::ReleaseRegion(void* base, size_t size) { |
- UNIMPLEMENTED(); |
- return false; |
+ return VirtualFree(base, 0, MEM_RELEASE) != 0; |
} |
@@ -408,8 +482,6 @@ |
}; |
- |
- |
Thread::Thread(const Options& options) |
: data_(new PlatformData()), |
stack_size_(options.stack_size()), |