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

Unified Diff: src/heap/spaces.cc

Issue 1772733002: [heap] Move to two-level free-list (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase on disabled black allocation Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap/spaces.h ('k') | src/heap/spaces-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/spaces.cc
diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc
index f7cce1430e55eee5e436f9b49639efcfaebb858b..1e0ed9c8fd10dbefc3e1646de6fd1c979ada6b38 100644
--- a/src/heap/spaces.cc
+++ b/src/heap/spaces.cc
@@ -1030,79 +1030,46 @@ void PagedSpace::TearDown() {
accounting_stats_.Clear();
}
-
-void PagedSpace::AddMemory(Address start, intptr_t size) {
- accounting_stats_.ExpandSpace(static_cast<int>(size));
- Free(start, static_cast<int>(size));
-}
-
-
void PagedSpace::RefillFreeList() {
- MarkCompactCollector* collector = heap()->mark_compact_collector();
- FreeList* free_list = nullptr;
- if (this == heap()->old_space()) {
- free_list = collector->free_list_old_space().get();
- } else if (this == heap()->code_space()) {
- free_list = collector->free_list_code_space().get();
- } else if (this == heap()->map_space()) {
- free_list = collector->free_list_map_space().get();
- } else {
- // Any PagedSpace might invoke RefillFreeList. We filter all but our old
- // generation spaces out.
+ // Any PagedSpace might invoke RefillFreeList. We filter all but our old
+ // generation spaces out.
+ if (identity() != OLD_SPACE && identity() != CODE_SPACE &&
+ identity() != MAP_SPACE) {
return;
}
- DCHECK(free_list != nullptr);
- intptr_t added = free_list_.Concatenate(free_list);
- accounting_stats_.IncreaseCapacity(added);
-}
-
-
-void CompactionSpace::RefillFreeList() {
MarkCompactCollector* collector = heap()->mark_compact_collector();
- FreeList* free_list = nullptr;
- if (identity() == OLD_SPACE) {
- free_list = collector->free_list_old_space().get();
- } else if (identity() == CODE_SPACE) {
- free_list = collector->free_list_code_space().get();
- } else {
- // Compaction spaces only represent old or code space.
- UNREACHABLE();
- }
- DCHECK(free_list != nullptr);
- intptr_t refilled = 0;
- while (refilled < kCompactionMemoryWanted) {
- FreeSpace* node =
- free_list->TryRemoveMemory(kCompactionMemoryWanted - refilled);
- if (node == nullptr) return;
- refilled += node->size();
- AddMemory(node->address(), node->size());
+ List<Page*>* swept_pages = collector->swept_pages(identity());
+ intptr_t added = 0;
+ {
+ base::LockGuard<base::Mutex> guard(collector->swept_pages_mutex());
+ for (int i = swept_pages->length() - 1; i >= 0; --i) {
+ Page* p = (*swept_pages)[i];
+ // Only during compaction pages can actually change ownership. This is
+ // safe because there exists no other competing action on the page links
+ // during compaction.
+ if (is_local() && (p->owner() != this)) {
+ if (added > kCompactionMemoryWanted) break;
+ base::LockGuard<base::Mutex> guard(
+ reinterpret_cast<PagedSpace*>(p->owner())->mutex());
+ p->Unlink();
+ p->set_owner(this);
+ p->InsertAfter(anchor_.prev_page());
+ }
+ added += RelinkFreeListCategories(p);
+ added += p->wasted_memory();
+ swept_pages->Remove(i);
+ }
}
-}
-
-void PagedSpace::MoveOverFreeMemory(PagedSpace* other) {
- DCHECK(identity() == other->identity());
- // Destroy the linear allocation space of {other}. This is needed to
- // (a) not waste the memory and
- // (b) keep the rest of the chunk in an iterable state (filler is needed).
- other->EmptyAllocationInfo();
-
- // Move over the free list. Concatenate makes sure that the source free list
- // gets properly reset after moving over all nodes.
- intptr_t added = free_list_.Concatenate(other->free_list());
-
- // Moved memory is not recorded as allocated memory, but rather increases and
- // decreases capacity of the corresponding spaces.
- other->accounting_stats_.DecreaseCapacity(added);
accounting_stats_.IncreaseCapacity(added);
}
-
void PagedSpace::MergeCompactionSpace(CompactionSpace* other) {
+ DCHECK(identity() == other->identity());
// Unmerged fields:
// area_size_
// anchor_
- MoveOverFreeMemory(other);
+ other->EmptyAllocationInfo();
// Update and clear accounting statistics.
accounting_stats_.Merge(other->accounting_stats_);
@@ -1119,9 +1086,14 @@ void PagedSpace::MergeCompactionSpace(CompactionSpace* other) {
Page* p = nullptr;
while (it.has_next()) {
p = it.next();
+
+ // Relinking requires the category to be unlinked.
+ other->UnlinkFreeListCategories(p);
+
p->Unlink();
p->set_owner(this);
p->InsertAfter(anchor_.prev_page());
+ RelinkFreeListCategories(p);
}
}
@@ -1238,17 +1210,12 @@ void PagedSpace::IncreaseCapacity(int size) {
accounting_stats_.ExpandSpace(size);
}
+void PagedSpace::ReleasePage(Page* page) {
+ DCHECK_EQ(page->LiveBytes(), 0);
+ DCHECK_EQ(AreaSize(), page->area_size());
+ DCHECK_EQ(page->owner(), this);
-void PagedSpace::ReleasePage(Page* page, bool evict_free_list_items) {
- DCHECK(page->LiveBytes() == 0);
- DCHECK(AreaSize() == page->area_size());
-
- if (evict_free_list_items) {
- intptr_t size = free_list_.EvictFreeListItems(page);
- accounting_stats_.AllocateBytes(size);
- DCHECK_EQ(AreaSize(), static_cast<int>(size));
- }
-
+ free_list_.EvictFreeListItems(page);
DCHECK(!free_list_.ContainsPageFreeListItems(page));
if (Page::FromAllocationTop(allocation_info_.top()) == page) {
@@ -1268,7 +1235,6 @@ void PagedSpace::ReleasePage(Page* page, bool evict_free_list_items) {
accounting_stats_.ShrinkSpace(AreaSize());
}
-
#ifdef DEBUG
void PagedSpace::Print() {}
#endif
@@ -2175,137 +2141,54 @@ size_t NewSpace::CommittedPhysicalMemory() {
// -----------------------------------------------------------------------------
// Free lists for old object spaces implementation
-intptr_t FreeListCategory::Concatenate(FreeListCategory* category) {
- intptr_t free_bytes = 0;
- if (category->top() != NULL) {
- DCHECK(category->end_ != NULL);
- free_bytes = category->available();
- if (end_ == NULL) {
- end_ = category->end();
- } else {
- category->end()->set_next(top());
- }
- set_top(category->top());
- available_ += category->available();
- category->Reset();
- }
- return free_bytes;
-}
-
void FreeListCategory::Reset() {
set_top(nullptr);
- set_end(nullptr);
+ set_prev(nullptr);
+ set_next(nullptr);
available_ = 0;
}
-
-intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) {
- intptr_t sum = 0;
- FreeSpace* prev_node = nullptr;
- for (FreeSpace* cur_node = top(); cur_node != nullptr;
- cur_node = cur_node->next()) {
- Page* page_for_node = Page::FromAddress(cur_node->address());
- if (page_for_node == p) {
- // FreeSpace node on eviction page found, unlink it.
- int size = cur_node->size();
- sum += size;
- DCHECK((prev_node != nullptr) || (top() == cur_node));
- if (cur_node == top()) {
- set_top(cur_node->next());
- }
- if (cur_node == end()) {
- set_end(prev_node);
- }
- if (prev_node != nullptr) {
- prev_node->set_next(cur_node->next());
- }
- continue;
- }
- prev_node = cur_node;
- }
- p->add_available_in_free_list(-sum);
- available_ -= sum;
- return sum;
-}
-
-
-bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) {
- FreeSpace* node = top();
- while (node != NULL) {
- if (Page::FromAddress(node->address()) == p) return true;
- node = node->next();
- }
- return false;
-}
-
-
FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) {
+ DCHECK(page()->CanAllocate());
+
FreeSpace* node = top();
if (node == nullptr) return nullptr;
-
- Page* page = Page::FromAddress(node->address());
- while ((node != nullptr) && !page->CanAllocate()) {
- available_ -= node->size();
- page->add_available_in_free_list(-(node->Size()));
- node = node->next();
- }
-
- if (node != nullptr) {
- set_top(node->next());
- *node_size = node->Size();
- available_ -= *node_size;
- } else {
- set_top(nullptr);
- }
-
- if (top() == nullptr) {
- set_end(nullptr);
- }
-
+ set_top(node->next());
+ *node_size = node->Size();
+ available_ -= *node_size;
return node;
}
+FreeSpace* FreeListCategory::TryPickNodeFromList(int minimum_size,
+ int* node_size) {
+ DCHECK(page()->CanAllocate());
-FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes,
- int* node_size) {
FreeSpace* node = PickNodeFromList(node_size);
- if ((node != nullptr) && (*node_size < size_in_bytes)) {
- Free(node, *node_size);
+ if ((node != nullptr) && (*node_size < minimum_size)) {
+ Free(node, *node_size, kLinkCategory);
*node_size = 0;
return nullptr;
}
return node;
}
-
-FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes,
+FreeSpace* FreeListCategory::SearchForNodeInList(int minimum_size,
int* node_size) {
+ DCHECK(page()->CanAllocate());
+
FreeSpace* prev_non_evac_node = nullptr;
for (FreeSpace* cur_node = top(); cur_node != nullptr;
cur_node = cur_node->next()) {
int size = cur_node->size();
- Page* page_for_node = Page::FromAddress(cur_node->address());
-
- if ((size >= size_in_bytes) || !page_for_node->CanAllocate()) {
- // The node is either large enough or contained in an evacuation
- // candidate. In both cases we need to unlink it from the list.
+ if (size >= minimum_size) {
available_ -= size;
if (cur_node == top()) {
set_top(cur_node->next());
}
- if (cur_node == end()) {
- set_end(prev_non_evac_node);
- }
if (prev_non_evac_node != nullptr) {
prev_non_evac_node->set_next(cur_node->next());
}
- // For evacuation candidates we continue.
- if (!page_for_node->CanAllocate()) {
- page_for_node->add_available_in_free_list(-size);
- continue;
- }
- // Otherwise we have a large enough node and can return.
*node_size = size;
return cur_node;
}
@@ -2315,14 +2198,17 @@ FreeSpace* FreeListCategory::SearchForNodeInList(int size_in_bytes,
return nullptr;
}
+bool FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes,
+ FreeMode mode) {
+ if (!page()->CanAllocate()) return false;
-void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) {
free_space->set_next(top());
set_top(free_space);
- if (end_ == NULL) {
- end_ = free_space;
- }
available_ += size_in_bytes;
+ if ((mode == kLinkCategory) && (prev() == nullptr) && (next() == nullptr)) {
+ owner()->AddCategory(this);
+ }
+ return true;
}
@@ -2339,49 +2225,35 @@ void FreeListCategory::RepairFreeList(Heap* heap) {
}
}
-FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) {
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- category_[i].Initialize(this, static_cast<FreeListCategoryType>(i));
- }
- Reset();
+void FreeListCategory::Relink() {
+ DCHECK(!is_linked());
+ owner()->AddCategory(this);
}
+void FreeListCategory::Invalidate() {
+ page()->add_available_in_free_list(-available());
+ Reset();
+ type_ = kInvalidCategory;
+}
-intptr_t FreeList::Concatenate(FreeList* other) {
- intptr_t usable_bytes = 0;
- intptr_t wasted_bytes = 0;
-
- // This is safe (not going to deadlock) since Concatenate operations
- // are never performed on the same free lists at the same time in
- // reverse order. Furthermore, we only lock if the PagedSpace containing
- // the free list is know to be globally available, i.e., not local.
- if (!owner()->is_local()) mutex_.Lock();
- if (!other->owner()->is_local()) other->mutex()->Lock();
-
- wasted_bytes = other->wasted_bytes_;
- wasted_bytes_ += wasted_bytes;
- other->wasted_bytes_ = 0;
-
+FreeList::FreeList(PagedSpace* owner) : owner_(owner), wasted_bytes_(0) {
for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- usable_bytes += category_[i].Concatenate(
- other->GetFreeListCategory(static_cast<FreeListCategoryType>(i)));
+ categories_[i] = nullptr;
}
-
- if (!other->owner()->is_local()) other->mutex()->Unlock();
- if (!owner()->is_local()) mutex_.Unlock();
- return usable_bytes + wasted_bytes;
+ Reset();
}
void FreeList::Reset() {
+ ForAllFreeListCategories(
+ [](FreeListCategory* category) { category->Reset(); });
for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- category_[i].Reset();
+ categories_[i] = nullptr;
}
ResetStats();
}
-
-int FreeList::Free(Address start, int size_in_bytes) {
+int FreeList::Free(Address start, int size_in_bytes, FreeMode mode) {
if (size_in_bytes == 0) return 0;
owner()->heap()->CreateFillerObjectAt(start, size_in_bytes,
@@ -2392,7 +2264,7 @@ int FreeList::Free(Address start, int size_in_bytes) {
// Blocks have to be a minimum size to hold free list items.
if (size_in_bytes < kMinBlockSize) {
page->add_wasted_memory(size_in_bytes);
- wasted_bytes_ += size_in_bytes;
+ wasted_bytes_.Increment(size_in_bytes);
return size_in_bytes;
}
@@ -2400,16 +2272,34 @@ int FreeList::Free(Address start, int size_in_bytes) {
// Insert other blocks at the head of a free list of the appropriate
// magnitude.
FreeListCategoryType type = SelectFreeListCategoryType(size_in_bytes);
- category_[type].Free(free_space, size_in_bytes);
- page->add_available_in_free_list(size_in_bytes);
-
- DCHECK(IsVeryLong() || Available() == SumFreeLists());
+ if (page->free_list_category(type)->Free(free_space, size_in_bytes, mode)) {
+ page->add_available_in_free_list(size_in_bytes);
+ }
return 0;
}
+FreeSpace* FreeList::FindNodeIn(FreeListCategoryType type, int* node_size) {
+ FreeListCategoryIterator it(this, type);
+ FreeSpace* node = nullptr;
+ while (it.HasNext()) {
+ FreeListCategory* current = it.Next();
+ node = current->PickNodeFromList(node_size);
+ if (node != nullptr) {
+ Page::FromAddress(node->address())
+ ->add_available_in_free_list(-(*node_size));
+ DCHECK(IsVeryLong() || Available() == SumFreeLists());
+ return node;
+ }
+ RemoveCategory(current);
+ }
+ return node;
+}
-FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) {
- FreeSpace* node = GetFreeListCategory(category)->PickNodeFromList(node_size);
+FreeSpace* FreeList::TryFindNodeIn(FreeListCategoryType type, int* node_size,
+ int minimum_size) {
+ if (categories_[type] == nullptr) return nullptr;
+ FreeSpace* node =
+ categories_[type]->TryPickNodeFromList(minimum_size, node_size);
if (node != nullptr) {
Page::FromAddress(node->address())
->add_available_in_free_list(-(*node_size));
@@ -2418,6 +2308,22 @@ FreeSpace* FreeList::FindNodeIn(FreeListCategoryType category, int* node_size) {
return node;
}
+FreeSpace* FreeList::SearchForNodeInList(FreeListCategoryType type,
+ int* node_size, int minimum_size) {
+ FreeListCategoryIterator it(this, type);
+ FreeSpace* node = nullptr;
+ while (it.HasNext()) {
+ FreeListCategory* current = it.Next();
+ node = current->SearchForNodeInList(minimum_size, node_size);
+ if (node != nullptr) {
+ Page::FromAddress(node->address())
+ ->add_available_in_free_list(-(*node_size));
+ DCHECK(IsVeryLong() || Available() == SumFreeLists());
+ return node;
+ }
+ }
+ return node;
+}
FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
FreeSpace* node = nullptr;
@@ -2434,10 +2340,8 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
// Next search the huge list for free list nodes. This takes linear time in
// the number of huge elements.
- node = category_[kHuge].SearchForNodeInList(size_in_bytes, node_size);
+ node = SearchForNodeInList(kHuge, node_size, size_in_bytes);
if (node != nullptr) {
- page = Page::FromAddress(node->address());
- page->add_available_in_free_list(-(*node_size));
DCHECK(IsVeryLong() || Available() == SumFreeLists());
return node;
}
@@ -2449,7 +2353,7 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
// Now search the best fitting free list for a node that has at least the
// requested size.
type = SelectFreeListCategoryType(size_in_bytes);
- node = category_[type].PickNodeFromList(size_in_bytes, node_size);
+ node = TryFindNodeIn(type, node_size, size_in_bytes);
if (node != nullptr) {
DCHECK(size_in_bytes <= *node_size);
page = Page::FromAddress(node->address());
@@ -2460,38 +2364,6 @@ FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
return node;
}
-
-FreeSpace* FreeList::TryRemoveMemory(intptr_t hint_size_in_bytes) {
- hint_size_in_bytes = RoundDown(hint_size_in_bytes, kPointerSize);
- base::LockGuard<base::Mutex> guard(&mutex_);
- FreeSpace* node = nullptr;
- int node_size = 0;
- // Try to find a node that fits exactly.
- node = FindNodeFor(static_cast<int>(hint_size_in_bytes), &node_size);
- // If no node could be found get as much memory as possible.
- if (node == nullptr) node = FindNodeIn(kHuge, &node_size);
- if (node == nullptr) node = FindNodeIn(kLarge, &node_size);
- if (node != nullptr) {
- // We round up the size to (kMinBlockSize + kPointerSize) to (a) have a
- // size larger then the minimum size required for FreeSpace, and (b) to get
- // a block that can actually be freed into some FreeList later on.
- if (hint_size_in_bytes <= kMinBlockSize) {
- hint_size_in_bytes = kMinBlockSize + kPointerSize;
- }
- // Give back left overs that were not required by {size_in_bytes}.
- intptr_t left_over = node_size - hint_size_in_bytes;
-
- // Do not bother to return anything below {kMinBlockSize} as it would be
- // immediately discarded anyways.
- if (left_over > kMinBlockSize) {
- Free(node->address() + hint_size_in_bytes, static_cast<int>(left_over));
- node->set_size(static_cast<int>(hint_size_in_bytes));
- }
- }
- return node;
-}
-
-
// Allocation on the old space free list. If it succeeds then a new linear
// allocation space has been set up with the top and limit of the space. If
// the allocation fails then NULL is returned, and the caller can perform a GC
@@ -2565,32 +2437,76 @@ HeapObject* FreeList::Allocate(int size_in_bytes) {
return new_node;
}
-
-intptr_t FreeList::EvictFreeListItems(Page* p) {
- intptr_t sum = category_[kHuge].EvictFreeListItemsInList(p);
- if (sum < p->area_size()) {
- for (int i = kFirstCategory; i <= kLarge; i++) {
- sum += category_[i].EvictFreeListItemsInList(p);
- }
- }
+intptr_t FreeList::EvictFreeListItems(Page* page) {
+ intptr_t sum = 0;
+ page->ForAllFreeListCategories(
+ [this, &sum, page](FreeListCategory* category) {
+ DCHECK_EQ(this, category->owner());
+ sum += category->available();
+ RemoveCategory(category);
+ category->Invalidate();
+ });
return sum;
}
+bool FreeList::ContainsPageFreeListItems(Page* page) {
+ bool contained = false;
+ page->ForAllFreeListCategories(
+ [this, &contained](FreeListCategory* category) {
+ if (category->owner() == this && category->is_linked()) {
+ contained = true;
+ }
+ });
+ return contained;
+}
-bool FreeList::ContainsPageFreeListItems(Page* p) {
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- if (category_[i].EvictFreeListItemsInList(p)) {
- return true;
- }
+void FreeList::RepairLists(Heap* heap) {
+ ForAllFreeListCategories(
+ [heap](FreeListCategory* category) { category->RepairFreeList(heap); });
+}
+
+bool FreeList::AddCategory(FreeListCategory* category) {
+ FreeListCategoryType type = category->type_;
+ FreeListCategory* top = categories_[type];
+
+ if (category->is_empty()) return false;
+ if (top == category) return false;
+
+ // Common double-linked list insertion.
+ if (top != nullptr) {
+ top->set_prev(category);
}
- return false;
+ category->set_next(top);
+ categories_[type] = category;
+ return true;
}
+void FreeList::RemoveCategory(FreeListCategory* category) {
+ FreeListCategoryType type = category->type_;
+ FreeListCategory* top = categories_[type];
-void FreeList::RepairLists(Heap* heap) {
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- category_[i].RepairFreeList(heap);
+ // Common double-linked list removal.
+ if (top == category) {
+ categories_[type] = category->next();
+ }
+ if (category->prev() != nullptr) {
+ category->prev()->set_next(category->next());
+ }
+ if (category->next() != nullptr) {
+ category->next()->set_prev(category->prev());
+ }
+ category->set_next(nullptr);
+ category->set_prev(nullptr);
+}
+
+void FreeList::PrintCategories(FreeListCategoryType type) {
+ FreeListCategoryIterator it(this, type);
+ PrintF("FreeList[%p, top=%p, %d] ", this, categories_[type], type);
+ while (it.HasNext()) {
+ FreeListCategory* current = it.Next();
+ PrintF("%p -> ", current);
}
+ PrintF("null\n");
}
@@ -2606,7 +2522,6 @@ intptr_t FreeListCategory::SumFreeList() {
return sum;
}
-
int FreeListCategory::FreeListLength() {
int length = 0;
FreeSpace* cur = top();
@@ -2618,16 +2533,13 @@ int FreeListCategory::FreeListLength() {
return length;
}
-
-bool FreeListCategory::IsVeryLong() {
- return FreeListLength() == kVeryLongFreeList;
-}
-
-
bool FreeList::IsVeryLong() {
+ int len = 0;
for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- if (category_[i].IsVeryLong()) {
- return true;
+ FreeListCategoryIterator it(this, static_cast<FreeListCategoryType>(i));
+ while (it.HasNext()) {
+ len += it.Next()->FreeListLength();
+ if (len >= FreeListCategory::kVeryLongFreeList) return true;
}
}
return false;
@@ -2639,9 +2551,8 @@ bool FreeList::IsVeryLong() {
// kVeryLongFreeList.
intptr_t FreeList::SumFreeLists() {
intptr_t sum = 0;
- for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
- sum += category_[i].SumFreeList();
- }
+ ForAllFreeListCategories(
+ [&sum](FreeListCategory* category) { sum += category->SumFreeList(); });
return sum;
}
#endif
« no previous file with comments | « src/heap/spaces.h ('k') | src/heap/spaces-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698