Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: src/platform-win32.cc

Issue 23641009: Refactor and cleanup VirtualMemory. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed nits. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/platform-solaris.cc ('k') | src/platform/virtual-memory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 // Extra functions for MinGW. Most of these are the _s functions which are in 62 // Extra functions for MinGW. Most of these are the _s functions which are in
63 // the Microsoft Visual Studio C++ CRT. 63 // the Microsoft Visual Studio C++ CRT.
64 #ifdef __MINGW32__ 64 #ifdef __MINGW32__
65 65
66 66
67 #ifndef __MINGW64_VERSION_MAJOR 67 #ifndef __MINGW64_VERSION_MAJOR
68 68
69 #define _TRUNCATE 0 69 #define _TRUNCATE 0
70 #define STRUNCATE 80 70 #define STRUNCATE 80
71 71
72 inline void MemoryBarrier() {
73 int barrier = 0;
74 __asm__ __volatile__("xchgl %%eax,%0 ":"=r" (barrier));
75 }
76
77 #endif // __MINGW64_VERSION_MAJOR 72 #endif // __MINGW64_VERSION_MAJOR
78 73
79 74
80 int localtime_s(tm* out_tm, const time_t* time) { 75 int localtime_s(tm* out_tm, const time_t* time) {
81 tm* posix_local_time_struct = localtime(time); 76 tm* posix_local_time_struct = localtime(time);
82 if (posix_local_time_struct == NULL) return 1; 77 if (posix_local_time_struct == NULL) return 1;
83 *out_tm = *posix_local_time_struct; 78 *out_tm = *posix_local_time_struct;
84 return 0; 79 return 0;
85 } 80 }
86 81
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 CHECK_GT(dest_size, 0); 116 CHECK_GT(dest_size, 0);
122 *dest = 0; 117 *dest = 0;
123 return 0; 118 return 0;
124 } 119 }
125 120
126 #endif // __MINGW32__ 121 #endif // __MINGW32__
127 122
128 namespace v8 { 123 namespace v8 {
129 namespace internal { 124 namespace internal {
130 125
131 intptr_t OS::MaxVirtualMemory() {
132 return 0;
133 }
134
135
136 double ceiling(double x) { 126 double ceiling(double x) {
137 return ceil(x); 127 return ceil(x);
138 } 128 }
139 129
140 130
141 #if V8_TARGET_ARCH_IA32 131 #if V8_TARGET_ARCH_IA32
142 static void MemMoveWrapper(void* dest, const void* src, size_t size) { 132 static void MemMoveWrapper(void* dest, const void* src, size_t size) {
143 memmove(dest, src, size); 133 memmove(dest, src, size);
144 } 134 }
145 135
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 int result = strncpy_s(dest.start(), dest.length(), src, n); 726 int result = strncpy_s(dest.start(), dest.length(), src, n);
737 USE(result); 727 USE(result);
738 ASSERT(result == 0 || (n == _TRUNCATE && result == STRUNCATE)); 728 ASSERT(result == 0 || (n == _TRUNCATE && result == STRUNCATE));
739 } 729 }
740 730
741 731
742 #undef _TRUNCATE 732 #undef _TRUNCATE
743 #undef STRUNCATE 733 #undef STRUNCATE
744 734
745 735
746 // Get the system's page size used by VirtualAlloc() or the next power
747 // of two. The reason for always returning a power of two is that the
748 // rounding up in OS::Allocate expects that.
749 static size_t GetPageSize() {
750 static size_t page_size = 0;
751 if (page_size == 0) {
752 SYSTEM_INFO info;
753 GetSystemInfo(&info);
754 page_size = RoundUpToPowerOf2(info.dwPageSize);
755 }
756 return page_size;
757 }
758
759
760 // The allocation alignment is the guaranteed alignment for
761 // VirtualAlloc'ed blocks of memory.
762 size_t OS::AllocateAlignment() {
763 static size_t allocate_alignment = 0;
764 if (allocate_alignment == 0) {
765 SYSTEM_INFO info;
766 GetSystemInfo(&info);
767 allocate_alignment = info.dwAllocationGranularity;
768 }
769 return allocate_alignment;
770 }
771
772
773 void* OS::GetRandomMmapAddr() {
774 Isolate* isolate = Isolate::UncheckedCurrent();
775 // Note that the current isolate isn't set up in a call path via
776 // CpuFeatures::Probe. We don't care about randomization in this case because
777 // the code page is immediately freed.
778 if (isolate != NULL) {
779 // The address range used to randomize RWX allocations in OS::Allocate
780 // Try not to map pages into the default range that windows loads DLLs
781 // Use a multiple of 64k to prevent committing unused memory.
782 // Note: This does not guarantee RWX regions will be within the
783 // range kAllocationRandomAddressMin to kAllocationRandomAddressMax
784 #ifdef V8_HOST_ARCH_64_BIT
785 static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
786 static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
787 #else
788 static const intptr_t kAllocationRandomAddressMin = 0x04000000;
789 static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
790 #endif
791 uintptr_t address =
792 (isolate->random_number_generator()->NextInt() << kPageSizeBits) |
793 kAllocationRandomAddressMin;
794 address &= kAllocationRandomAddressMax;
795 return reinterpret_cast<void *>(address);
796 }
797 return NULL;
798 }
799
800
801 static void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
802 LPVOID base = NULL;
803
804 if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
805 // For exectutable pages try and randomize the allocation address
806 for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
807 base = VirtualAlloc(OS::GetRandomMmapAddr(), size, action, protection);
808 }
809 }
810
811 // After three attempts give up and let the OS find an address to use.
812 if (base == NULL) base = VirtualAlloc(NULL, size, action, protection);
813
814 return base;
815 }
816
817
818 void* OS::Allocate(const size_t requested,
819 size_t* allocated,
820 bool is_executable) {
821 // VirtualAlloc rounds allocated size to page size automatically.
822 size_t msize = RoundUp(requested, static_cast<int>(GetPageSize()));
823
824 // Windows XP SP2 allows Data Excution Prevention (DEP).
825 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
826
827 LPVOID mbase = RandomizedVirtualAlloc(msize,
828 MEM_COMMIT | MEM_RESERVE,
829 prot);
830
831 if (mbase == NULL) {
832 LOG(Isolate::Current(), StringEvent("OS::Allocate", "VirtualAlloc failed"));
833 return NULL;
834 }
835
836 ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment()));
837
838 *allocated = msize;
839 return mbase;
840 }
841
842
843 void OS::Free(void* address, const size_t size) {
844 // TODO(1240712): VirtualFree has a return value which is ignored here.
845 VirtualFree(address, 0, MEM_RELEASE);
846 USE(size);
847 }
848
849
850 intptr_t OS::CommitPageSize() {
851 return 4096;
852 }
853
854
855 void OS::ProtectCode(void* address, const size_t size) {
856 DWORD old_protect;
857 VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
858 }
859
860
861 void OS::Guard(void* address, const size_t size) {
862 DWORD oldprotect;
863 VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect);
864 }
865
866
867 void OS::Sleep(int milliseconds) { 736 void OS::Sleep(int milliseconds) {
868 ::Sleep(milliseconds); 737 ::Sleep(milliseconds);
869 } 738 }
870 739
871 740
872 void OS::Abort() { 741 void OS::Abort() {
873 if (IsDebuggerPresent() || FLAG_break_on_abort) { 742 if (IsDebuggerPresent() || FLAG_break_on_abort) {
874 DebugBreak(); 743 DebugBreak();
875 } else { 744 } else {
876 // Make the MSVCRT do a silent abort. 745 // Make the MSVCRT do a silent abort.
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
1361 #elif defined(__MINGW32__) 1230 #elif defined(__MINGW32__)
1362 // With gcc 4.4 the tree vectorization optimizer can generate code 1231 // With gcc 4.4 the tree vectorization optimizer can generate code
1363 // that requires 16 byte alignment such as movdqa on x86. 1232 // that requires 16 byte alignment such as movdqa on x86.
1364 return 16; 1233 return 16;
1365 #else 1234 #else
1366 return 8; // Floating-point math runs faster with 8-byte alignment. 1235 return 8; // Floating-point math runs faster with 8-byte alignment.
1367 #endif 1236 #endif
1368 } 1237 }
1369 1238
1370 1239
1371 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
1372
1373
1374 VirtualMemory::VirtualMemory(size_t size)
1375 : address_(ReserveRegion(size)), size_(size) { }
1376
1377
1378 VirtualMemory::VirtualMemory(size_t size, size_t alignment)
1379 : address_(NULL), size_(0) {
1380 ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
1381 size_t request_size = RoundUp(size + alignment,
1382 static_cast<intptr_t>(OS::AllocateAlignment()));
1383 void* address = ReserveRegion(request_size);
1384 if (address == NULL) return;
1385 Address base = RoundUp(static_cast<Address>(address), alignment);
1386 // Try reducing the size by freeing and then reallocating a specific area.
1387 bool result = ReleaseRegion(address, request_size);
1388 USE(result);
1389 ASSERT(result);
1390 address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS);
1391 if (address != NULL) {
1392 request_size = size;
1393 ASSERT(base == static_cast<Address>(address));
1394 } else {
1395 // Resizing failed, just go with a bigger area.
1396 address = ReserveRegion(request_size);
1397 if (address == NULL) return;
1398 }
1399 address_ = address;
1400 size_ = request_size;
1401 }
1402
1403
1404 VirtualMemory::~VirtualMemory() {
1405 if (IsReserved()) {
1406 bool result = ReleaseRegion(address(), size());
1407 ASSERT(result);
1408 USE(result);
1409 }
1410 }
1411
1412
1413 bool VirtualMemory::IsReserved() {
1414 return address_ != NULL;
1415 }
1416
1417
1418 void VirtualMemory::Reset() {
1419 address_ = NULL;
1420 size_ = 0;
1421 }
1422
1423
1424 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
1425 return CommitRegion(address, size, is_executable);
1426 }
1427
1428
1429 bool VirtualMemory::Uncommit(void* address, size_t size) {
1430 ASSERT(IsReserved());
1431 return UncommitRegion(address, size);
1432 }
1433
1434
1435 bool VirtualMemory::Guard(void* address) {
1436 if (NULL == VirtualAlloc(address,
1437 OS::CommitPageSize(),
1438 MEM_COMMIT,
1439 PAGE_NOACCESS)) {
1440 return false;
1441 }
1442 return true;
1443 }
1444
1445
1446 void* VirtualMemory::ReserveRegion(size_t size) {
1447 return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS);
1448 }
1449
1450
1451 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
1452 int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
1453 if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) {
1454 return false;
1455 }
1456 return true;
1457 }
1458
1459
1460 bool VirtualMemory::UncommitRegion(void* base, size_t size) {
1461 return VirtualFree(base, size, MEM_DECOMMIT) != 0;
1462 }
1463
1464
1465 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
1466 return VirtualFree(base, 0, MEM_RELEASE) != 0;
1467 }
1468
1469
1470 bool VirtualMemory::HasLazyCommits() {
1471 // TODO(alph): implement for the platform.
1472 return false;
1473 }
1474
1475
1476 // ---------------------------------------------------------------------------- 1240 // ----------------------------------------------------------------------------
1477 // Win32 thread support. 1241 // Win32 thread support.
1478 1242
1479 // Definition of invalid thread handle and id. 1243 // Definition of invalid thread handle and id.
1480 static const HANDLE kNoThread = INVALID_HANDLE_VALUE; 1244 static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
1481 1245
1482 // Entry point for threads. The supplied argument is a pointer to the thread 1246 // Entry point for threads. The supplied argument is a pointer to the thread
1483 // object. The entry function dispatches to the run method in the thread 1247 // object. The entry function dispatches to the run method in the thread
1484 // object. It is important that this function has __stdcall calling 1248 // object. It is important that this function has __stdcall calling
1485 // convention. 1249 // convention.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 ASSERT(result); 1333 ASSERT(result);
1570 } 1334 }
1571 1335
1572 1336
1573 1337
1574 void Thread::YieldCPU() { 1338 void Thread::YieldCPU() {
1575 Sleep(0); 1339 Sleep(0);
1576 } 1340 }
1577 1341
1578 } } // namespace v8::internal 1342 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-solaris.cc ('k') | src/platform/virtual-memory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698