Ignore:
Timestamp:
Mar 4, 2009, 10:04:18 PM (16 years ago)
Author:
[email protected]
Message:

<rdar://problem/6354858> FastMallocZone's enumeration code reports fragmented administration space

Reviewed by Oliver Hunt.

The handling of MALLOC_ADMIN_REGION_RANGE_TYPE in FastMalloc's zone was incorrect. It was attempting
to record the memory containing and individual span as an administrative region, when all memory
allocated via MetaDataAlloc should in fact be recorded. This was causing memory regions allocated
via MetaDataAlloc to appear as "VM_ALLOCATE ?" in vmmap output. They are now correctly reported as
"MALLOC_OTHER" regions associated with the JavaScriptCore FastMalloc zone.

Memory is allocated via MetaDataAlloc from two locations: PageHeapAllocator, and TCMalloc_PageMap{2,3}.
These two cases are handled differently.

PageHeapAllocator is extended to keep a linked list of memory regions that it has allocated. The
first object in an allocated region contains the link to the previously allocated region. To record
the administrative regions of a PageHeapAllocator we can simply walk the linked list and record
each allocated region we encounter.

TCMalloc_PageMaps allocate memory via MetaDataAlloc to store each level of the radix tree. To record
the administrative regions of a TCMalloc_PageMap we walk the tree and record the storage used for nodes
at each position rather than the nodes themselves.

A small performance improvement is achieved by coalescing adjacent memory regions inside the PageMapMemoryUsageRecorder
so that fewer calls in to the range recorder are necessary. We further reduce the number of calls to the
range recorder by aggregating the in-use ranges of a given memory region into a local buffer before recording
them with a single call. A similar approach is also used by AdminRegionRecorder.

  • wtf/FastMalloc.cpp:

(WTF::PageHeapAllocator::Init):
(WTF::PageHeapAllocator::New):
(WTF::PageHeapAllocator::recordAdministrativeRegions):
(WTF::TCMallocStats::FreeObjectFinder::isFreeObject):
(WTF::TCMallocStats::PageMapMemoryUsageRecorder::~PageMapMemoryUsageRecorder):
(WTF::TCMallocStats::PageMapMemoryUsageRecorder::recordPendingRegions):
(WTF::TCMallocStats::PageMapMemoryUsageRecorder::visit):
(WTF::TCMallocStats::AdminRegionRecorder::AdminRegionRecorder):
(WTF::TCMallocStats::AdminRegionRecorder::recordRegion):
(WTF::TCMallocStats::AdminRegionRecorder::visit):
(WTF::TCMallocStats::AdminRegionRecorder::recordPendingRegions):
(WTF::TCMallocStats::AdminRegionRecorder::~AdminRegionRecorder):
(WTF::TCMallocStats::FastMallocZone::enumerate):
(WTF::TCMallocStats::FastMallocZone::FastMallocZone):
(WTF::TCMallocStats::FastMallocZone::init):

  • wtf/TCPageMap.h:

(TCMalloc_PageMap2::visitValues):
(TCMalloc_PageMap2::visitAllocations):
(TCMalloc_PageMap3::visitValues):
(TCMalloc_PageMap3::visitAllocations):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/wtf/TCPageMap.h

    r28434 r41443  
    5555
    5656#include <string.h>
    57 
    5857#include "Assertions.h"
    5958
     
    165164#ifdef WTF_CHANGES
    166165  template<class Visitor, class MemoryReader>
    167   void visit(const Visitor& visitor, const MemoryReader& reader)
     166  void visitValues(Visitor& visitor, const MemoryReader& reader)
    168167  {
    169168    for (int i = 0; i < ROOT_LENGTH; i++) {
     
    174173      for (int j = 0; j < LEAF_LENGTH; j += visitor.visit(l->values[j]))
    175174        ;
     175    }
     176  }
     177
     178  template<class Visitor, class MemoryReader>
     179  void visitAllocations(Visitor& visitor, const MemoryReader&) {
     180    for (int i = 0; i < ROOT_LENGTH; i++) {
     181      if (root_[i])
     182        visitor.visit(root_[i], sizeof(Leaf));
    176183    }
    177184  }
     
    267274#ifdef WTF_CHANGES
    268275  template<class Visitor, class MemoryReader>
    269   void visit(const Visitor& visitor, const MemoryReader& reader) {
     276  void visitValues(Visitor& visitor, const MemoryReader& reader) {
    270277    Node* root = reader(root_);
    271278    for (int i = 0; i < INTERIOR_LENGTH; i++) {
     
    284291    }
    285292  }
     293
     294  template<class Visitor, class MemoryReader>
     295  void visitAllocations(Visitor& visitor, const MemoryReader& reader) {
     296    visitor.visit(root_, sizeof(Node));
     297
     298    Node* root = reader(root_);
     299    for (int i = 0; i < INTERIOR_LENGTH; i++) {
     300      if (!root->ptrs[i])
     301        continue;
     302
     303      visitor.visit(root->ptrs[i], sizeof(Node));
     304      Node* n = reader(root->ptrs[i]);
     305      for (int j = 0; j < INTERIOR_LENGTH; j++) {
     306        if (!n->ptrs[j])
     307          continue;
     308
     309        visitor.visit(n->ptrs[j], sizeof(Leaf));
     310      }
     311    }
     312  }
    286313#endif
    287314};
Note: See TracChangeset for help on using the changeset viewer.