PartitionAlloc: Distinguish OOMs where a lot of super pages are not committed.

This CL distinguishes
specific OOMs (where a lot of super pages are allocated but not committed) from
actual OOMs (where a lot of physical memory is allocated) in crash reports.
- By crashing in partitionOutOfMemoryWithLotsOfUncommitedPages.
- By crashing at a special address (0x9b) in Windows, because reported stack
  traces are not accurate.
This check is enabled on 32-bit environments only.

BUG=421387

Review URL: https://codereview.chromium.org/683043002

git-svn-id: svn://svn.chromium.org/blink/trunk@185286 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent e2deb142
......@@ -114,6 +114,7 @@ static void parititonAllocBaseInit(PartitionRootBase* root)
root->initialized = true;
root->totalSizeOfCommittedPages = 0;
root->totalSizeOfSuperPages = 0;
root->totalSizeOfDirectMappedPages = 0;
root->nextSuperPage = 0;
root->nextPartitionPage = 0;
root->nextPartitionPageEnd = 0;
......@@ -296,15 +297,41 @@ bool partitionAllocGenericShutdown(PartitionRootGeneric* root)
return noLeaks;
}
static NEVER_INLINE void partitionOutOfMemory()
#if !CPU(64BIT)
static NEVER_INLINE void partitionOutOfMemoryWithLotsOfUncommitedPages()
{
#if OS(WIN)
// Crash at a special address (0x9b)
// to be easily distinguished on crash reports.
// This is because crash stack traces are inaccurate on Windows and
// partitionOutOfMemoryWithLotsOfUncommitedPages might be not included
// in the stack traces.
reinterpret_cast<void(*)()>(0x9b)();
#endif
// On non-Windows environment, IMMEDIATE_CRASH is sufficient
// because partitionOutOfMemoryWithLotsOfUncommitedPages will appear
// in crash stack traces.
IMMEDIATE_CRASH();
}
#endif
static NEVER_INLINE void partitionOutOfMemory(const PartitionRootBase* root)
{
#if !CPU(64BIT)
// Check whether this OOM is due to a lot of super pages that are allocated
// but not committed, probably due to http://crbug.com/421387.
if (root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages - root->totalSizeOfCommittedPages > kReasonableSizeOfUnusedPages) {
partitionOutOfMemoryWithLotsOfUncommitedPages();
}
#endif
IMMEDIATE_CRASH();
}
static ALWAYS_INLINE void partitionDecommitSystemPages(PartitionRootBase* root, void* addr, size_t len)
{
decommitSystemPages(addr, len);
ASSERT(root->totalSizeOfCommittedPages > len);
ASSERT(root->totalSizeOfCommittedPages >= len);
root->totalSizeOfCommittedPages -= len;
}
......@@ -312,6 +339,7 @@ static ALWAYS_INLINE void partitionRecommitSystemPages(PartitionRootBase* root,
{
recommitSystemPages(addr, len);
root->totalSizeOfCommittedPages += len;
ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages);
}
static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root, int flags, uint16_t numPartitionPages)
......@@ -327,6 +355,7 @@ static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root,
char* ret = root->nextPartitionPage;
root->nextPartitionPage += totalSize;
root->totalSizeOfCommittedPages += totalSize;
ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages);
return ret;
}
......@@ -338,6 +367,7 @@ static ALWAYS_INLINE void* partitionAllocPartitionPages(PartitionRootBase* root,
root->totalSizeOfSuperPages += kSuperPageSize;
root->totalSizeOfCommittedPages += totalSize;
ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages);
root->nextSuperPage = superPage + kSuperPageSize;
char* ret = superPage + kPartitionPageSize;
......@@ -568,7 +598,10 @@ static ALWAYS_INLINE void* partitionDirectMap(PartitionRootBase* root, int flags
mapSize += kPageAllocationGranularityOffsetMask;
mapSize &= kPageAllocationGranularityBaseMask;
root->totalSizeOfCommittedPages += size + kSystemPageSize;
size_t committedPageSize = size + kSystemPageSize;
root->totalSizeOfCommittedPages += committedPageSize;
root->totalSizeOfDirectMappedPages += committedPageSize;
ASSERT(root->totalSizeOfCommittedPages <= root->totalSizeOfSuperPages + root->totalSizeOfDirectMappedPages);
// TODO: we may want to let the operating system place these allocations
// where it pleases. On 32-bit, this might limit address space
......@@ -624,7 +657,11 @@ static ALWAYS_INLINE void partitionDirectUnmap(PartitionPage* page)
unmapSize += kPartitionPageSize + kSystemPageSize;
PartitionRootBase* root = partitionPageToRoot(page);
root->totalSizeOfCommittedPages -= page->bucket->slotSize + kSystemPageSize;
size_t uncommittedPageSize = page->bucket->slotSize + kSystemPageSize;
ASSERT(root->totalSizeOfCommittedPages >= uncommittedPageSize);
root->totalSizeOfCommittedPages -= uncommittedPageSize;
ASSERT(root->totalSizeOfDirectMappedPages >= uncommittedPageSize);
root->totalSizeOfDirectMappedPages -= uncommittedPageSize;
ASSERT(!(unmapSize & kPageAllocationGranularityOffsetMask));
......@@ -709,7 +746,7 @@ partitionAllocSlowPathFailed:
bucket->activePagesHead = &PartitionRootGeneric::gSeedPage;
return nullptr;
}
partitionOutOfMemory();
partitionOutOfMemory(root);
return nullptr;
}
......
......@@ -184,6 +184,13 @@ static const size_t kBitsPerSizet = sizeof(void*) * CHAR_BIT;
// Constants for the memory reclaim logic.
static const size_t kMaxFreeableSpans = 16;
// If the total size in bytes of allocated but not committed pages exceeds this
// value (probably it is a "out of virtual address space" crash),
// a special crash stack trace is generated at |partitionOutOfMemory|.
// This is to distinguish "out of virtual address space" from
// "out of physical memory" in crash reports.
static const size_t kReasonableSizeOfUnusedPages = 1024 * 1024 * 1024; // 1GiB
#if ENABLE(ASSERT)
// These two byte values match tcmalloc.
static const unsigned char kUninitializedByte = 0xAB;
......@@ -250,6 +257,8 @@ struct PartitionSuperPageExtentEntry {
struct WTF_EXPORT PartitionRootBase {
size_t totalSizeOfCommittedPages;
size_t totalSizeOfSuperPages;
size_t totalSizeOfDirectMappedPages;
// Invariant: totalSizeOfCommittedPages <= totalSizeOfSuperPages + totalSizeOfDirectMappedPages.
unsigned numBuckets;
unsigned maxAllocation;
bool initialized;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment