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

Side by Side Diff: src/spaces.cc

Issue 13895003: On-the-fly bookkeeping of PagedSpace memory kept in free-lists. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 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/spaces.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 chunk->area_end_ = area_end; 460 chunk->area_end_ = area_end;
461 chunk->flags_ = 0; 461 chunk->flags_ = 0;
462 chunk->set_owner(owner); 462 chunk->set_owner(owner);
463 chunk->InitializeReservedMemory(); 463 chunk->InitializeReservedMemory();
464 chunk->slots_buffer_ = NULL; 464 chunk->slots_buffer_ = NULL;
465 chunk->skip_list_ = NULL; 465 chunk->skip_list_ = NULL;
466 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity; 466 chunk->write_barrier_counter_ = kWriteBarrierCounterGranularity;
467 chunk->progress_bar_ = 0; 467 chunk->progress_bar_ = 0;
468 chunk->high_water_mark_ = static_cast<int>(area_start - base); 468 chunk->high_water_mark_ = static_cast<int>(area_start - base);
469 chunk->parallel_sweeping_ = 0; 469 chunk->parallel_sweeping_ = 0;
470 chunk->available_in_small_free_list_ = 0;
471 chunk->available_in_medium_free_list_ = 0;
472 chunk->available_in_large_free_list_ = 0;
473 chunk->available_in_huge_free_list_ = 0;
474 chunk->non_available_small_blocks_ = 0;
470 chunk->ResetLiveBytes(); 475 chunk->ResetLiveBytes();
471 Bitmap::Clear(chunk); 476 Bitmap::Clear(chunk);
472 chunk->initialize_scan_on_scavenge(false); 477 chunk->initialize_scan_on_scavenge(false);
473 chunk->SetFlag(WAS_SWEPT_PRECISELY); 478 chunk->SetFlag(WAS_SWEPT_PRECISELY);
474 479
475 ASSERT(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset); 480 ASSERT(OFFSET_OF(MemoryChunk, flags_) == kFlagsOffset);
476 ASSERT(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset); 481 ASSERT(OFFSET_OF(MemoryChunk, live_byte_count_) == kLiveBytesOffset);
477 482
478 if (executable == EXECUTABLE) { 483 if (executable == EXECUTABLE) {
479 chunk->SetFlag(IS_EXECUTABLE); 484 chunk->SetFlag(IS_EXECUTABLE);
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 chunk_size, 695 chunk_size,
691 area_start, 696 area_start,
692 area_end, 697 area_end,
693 executable, 698 executable,
694 owner); 699 owner);
695 result->set_reserved_memory(&reservation); 700 result->set_reserved_memory(&reservation);
696 return result; 701 return result;
697 } 702 }
698 703
699 704
705 void Page::ResetFreeListStatistics() {
706 non_available_small_blocks_ = 0;
707 available_in_small_free_list_ = 0;
708 available_in_medium_free_list_ = 0;
709 available_in_large_free_list_ = 0;
710 available_in_huge_free_list_ = 0;
711 }
712
713
700 Page* MemoryAllocator::AllocatePage(intptr_t size, 714 Page* MemoryAllocator::AllocatePage(intptr_t size,
701 PagedSpace* owner, 715 PagedSpace* owner,
702 Executability executable) { 716 Executability executable) {
703 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner); 717 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner);
704 718
705 if (chunk == NULL) return NULL; 719 if (chunk == NULL) return NULL;
706 720
707 return Page::Initialize(isolate_->heap(), chunk, executable, owner); 721 return Page::Initialize(isolate_->heap(), chunk, executable, owner);
708 } 722 }
709 723
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 PageIterator it(this); 1064 PageIterator it(this);
1051 int count = 0; 1065 int count = 0;
1052 while (it.has_next()) { 1066 while (it.has_next()) {
1053 it.next(); 1067 it.next();
1054 count++; 1068 count++;
1055 } 1069 }
1056 return count; 1070 return count;
1057 } 1071 }
1058 1072
1059 1073
1074 void PagedSpace::ObtainFreeListStatistics(Page* page, SizeStats* sizes) {
1075 sizes->huge_size_ = page->available_in_huge_free_list();
1076 sizes->small_size_ = page->available_in_small_free_list();
1077 sizes->medium_size_ = page->available_in_medium_free_list();
1078 sizes->large_size_ = page->available_in_large_free_list();
1079 }
1080
1081
1082 void PagedSpace::ResetFreeListStatistics() {
1083 PageIterator page_iterator(this);
1084 while (page_iterator.has_next()) {
1085 Page* page = page_iterator.next();
1086 page->ResetFreeListStatistics();
1087 }
1088 }
1089
1090
1060 void PagedSpace::ReleasePage(Page* page, bool unlink) { 1091 void PagedSpace::ReleasePage(Page* page, bool unlink) {
1061 ASSERT(page->LiveBytes() == 0); 1092 ASSERT(page->LiveBytes() == 0);
1062 ASSERT(AreaSize() == page->area_size()); 1093 ASSERT(AreaSize() == page->area_size());
1063 1094
1064 // Adjust list of unswept pages if the page is the head of the list. 1095 // Adjust list of unswept pages if the page is the head of the list.
1065 if (first_unswept_page_ == page) { 1096 if (first_unswept_page_ == page) {
1066 first_unswept_page_ = page->next_page(); 1097 first_unswept_page_ = page->next_page();
1067 if (first_unswept_page_ == anchor()) { 1098 if (first_unswept_page_ == anchor()) {
1068 first_unswept_page_ = Page::FromAddress(NULL); 1099 first_unswept_page_ = Page::FromAddress(NULL);
1069 } 1100 }
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 } 2080 }
2050 2081
2051 2082
2052 void FreeListCategory::Reset() { 2083 void FreeListCategory::Reset() {
2053 top_ = NULL; 2084 top_ = NULL;
2054 end_ = NULL; 2085 end_ = NULL;
2055 available_ = 0; 2086 available_ = 0;
2056 } 2087 }
2057 2088
2058 2089
2059 intptr_t FreeListCategory::CountFreeListItemsInList(Page* p) {
2060 int sum = 0;
2061 FreeListNode* n = top_;
2062 while (n != NULL) {
2063 if (Page::FromAddress(n->address()) == p) {
2064 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(n);
2065 sum += free_space->Size();
2066 }
2067 n = n->next();
2068 }
2069 return sum;
2070 }
2071
2072
2073 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { 2090 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) {
2074 int sum = 0; 2091 int sum = 0;
2075 FreeListNode** n = &top_; 2092 FreeListNode** n = &top_;
2076 while (*n != NULL) { 2093 while (*n != NULL) {
2077 if (Page::FromAddress((*n)->address()) == p) { 2094 if (Page::FromAddress((*n)->address()) == p) {
2078 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); 2095 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n);
2079 sum += free_space->Size(); 2096 sum += free_space->Size();
2080 *n = (*n)->next(); 2097 *n = (*n)->next();
2081 } else { 2098 } else {
2082 n = (*n)->next_address(); 2099 n = (*n)->next_address();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2163 large_list_.Reset(); 2180 large_list_.Reset();
2164 huge_list_.Reset(); 2181 huge_list_.Reset();
2165 } 2182 }
2166 2183
2167 2184
2168 int FreeList::Free(Address start, int size_in_bytes) { 2185 int FreeList::Free(Address start, int size_in_bytes) {
2169 if (size_in_bytes == 0) return 0; 2186 if (size_in_bytes == 0) return 0;
2170 2187
2171 FreeListNode* node = FreeListNode::FromAddress(start); 2188 FreeListNode* node = FreeListNode::FromAddress(start);
2172 node->set_size(heap_, size_in_bytes); 2189 node->set_size(heap_, size_in_bytes);
2190 Page* page = Page::FromAddress(start);
2173 2191
2174 // Early return to drop too-small blocks on the floor. 2192 // Early return to drop too-small blocks on the floor.
2175 if (size_in_bytes < kSmallListMin) return size_in_bytes; 2193 if (size_in_bytes < kSmallListMin) {
2194 page->add_non_available_small_blocks(size_in_bytes);
2195 return size_in_bytes;
2196 }
2176 2197
2177 // Insert other blocks at the head of a free list of the appropriate 2198 // Insert other blocks at the head of a free list of the appropriate
2178 // magnitude. 2199 // magnitude.
2179 if (size_in_bytes <= kSmallListMax) { 2200 if (size_in_bytes <= kSmallListMax) {
2180 small_list_.Free(node, size_in_bytes); 2201 small_list_.Free(node, size_in_bytes);
2202 page->add_available_in_small_free_list(size_in_bytes);
2181 } else if (size_in_bytes <= kMediumListMax) { 2203 } else if (size_in_bytes <= kMediumListMax) {
2182 medium_list_.Free(node, size_in_bytes); 2204 medium_list_.Free(node, size_in_bytes);
2205 page->add_available_in_medium_free_list(size_in_bytes);
2183 } else if (size_in_bytes <= kLargeListMax) { 2206 } else if (size_in_bytes <= kLargeListMax) {
2184 large_list_.Free(node, size_in_bytes); 2207 large_list_.Free(node, size_in_bytes);
2208 page->add_available_in_large_free_list(size_in_bytes);
2185 } else { 2209 } else {
2186 huge_list_.Free(node, size_in_bytes); 2210 huge_list_.Free(node, size_in_bytes);
2211 page->add_available_in_huge_free_list(size_in_bytes);
2187 } 2212 }
2188 2213
2189 ASSERT(IsVeryLong() || available() == SumFreeLists()); 2214 ASSERT(IsVeryLong() || available() == SumFreeLists());
2190 return 0; 2215 return 0;
2191 } 2216 }
2192 2217
2193 2218
2194 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { 2219 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
2195 FreeListNode* node = NULL; 2220 FreeListNode* node = NULL;
2221 Page* page = NULL;
2196 2222
2197 if (size_in_bytes <= kSmallAllocationMax) { 2223 if (size_in_bytes <= kSmallAllocationMax) {
2198 node = small_list_.PickNodeFromList(node_size); 2224 node = small_list_.PickNodeFromList(node_size);
2199 if (node != NULL) return node; 2225 if (node != NULL) {
2226 page = Page::FromAddress(node->address());
2227 page->add_available_in_small_free_list(-(*node_size));
2228 return node;
2229 }
2200 } 2230 }
2201 2231
2202 if (size_in_bytes <= kMediumAllocationMax) { 2232 if (size_in_bytes <= kMediumAllocationMax) {
2203 node = medium_list_.PickNodeFromList(node_size); 2233 node = medium_list_.PickNodeFromList(node_size);
2204 if (node != NULL) return node; 2234 if (node != NULL) {
2235 page = Page::FromAddress(node->address());
2236 page->add_available_in_medium_free_list(-(*node_size));
2237 return node;
2238 }
2205 } 2239 }
2206 2240
2207 if (size_in_bytes <= kLargeAllocationMax) { 2241 if (size_in_bytes <= kLargeAllocationMax) {
2208 node = large_list_.PickNodeFromList(node_size); 2242 node = large_list_.PickNodeFromList(node_size);
2209 if (node != NULL) return node; 2243 if (node != NULL) {
2244 page = Page::FromAddress(node->address());
2245 page->add_available_in_large_free_list(-(*node_size));
2246 return node;
2247 }
2210 } 2248 }
2211 2249
2212 int huge_list_available = huge_list_.available(); 2250 int huge_list_available = huge_list_.available();
2213 for (FreeListNode** cur = huge_list_.GetTopAddress(); 2251 for (FreeListNode** cur = huge_list_.GetTopAddress();
2214 *cur != NULL; 2252 *cur != NULL;
2215 cur = (*cur)->next_address()) { 2253 cur = (*cur)->next_address()) {
2216 FreeListNode* cur_node = *cur; 2254 FreeListNode* cur_node = *cur;
2217 while (cur_node != NULL && 2255 while (cur_node != NULL &&
2218 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { 2256 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
2219 huge_list_available -= reinterpret_cast<FreeSpace*>(cur_node)->Size(); 2257 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size();
2258 huge_list_available -= size;
2259 page = Page::FromAddress(cur_node->address());
2260 page->add_available_in_huge_free_list(-size);
2220 cur_node = cur_node->next(); 2261 cur_node = cur_node->next();
2221 } 2262 }
2222 2263
2223 *cur = cur_node; 2264 *cur = cur_node;
2224 if (cur_node == NULL) { 2265 if (cur_node == NULL) {
2225 huge_list_.set_end(NULL); 2266 huge_list_.set_end(NULL);
2226 break; 2267 break;
2227 } 2268 }
2228 2269
2229 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map()); 2270 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map());
2230 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); 2271 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
2231 int size = cur_as_free_space->Size(); 2272 int size = cur_as_free_space->Size();
2232 if (size >= size_in_bytes) { 2273 if (size >= size_in_bytes) {
2233 // Large enough node found. Unlink it from the list. 2274 // Large enough node found. Unlink it from the list.
2234 node = *cur; 2275 node = *cur;
2235 *cur = node->next(); 2276 *cur = node->next();
2236 *node_size = size; 2277 *node_size = size;
2237 huge_list_available -= size; 2278 huge_list_available -= size;
2279 page = Page::FromAddress(node->address());
2280 page->add_available_in_huge_free_list(-size);
2238 break; 2281 break;
2239 } 2282 }
2240 } 2283 }
2241 2284
2242 if (huge_list_.top() == NULL) { 2285 if (huge_list_.top() == NULL) {
2243 huge_list_.set_end(NULL); 2286 huge_list_.set_end(NULL);
2244 } 2287 }
2245 2288
2246 huge_list_.set_available(huge_list_available); 2289 huge_list_.set_available(huge_list_available);
2247 ASSERT(IsVeryLong() || available() == SumFreeLists()); 2290 ASSERT(IsVeryLong() || available() == SumFreeLists());
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2315 } else { 2358 } else {
2316 // TODO(gc) Try not freeing linear allocation region when bytes_left 2359 // TODO(gc) Try not freeing linear allocation region when bytes_left
2317 // are zero. 2360 // are zero.
2318 owner_->SetTop(NULL, NULL); 2361 owner_->SetTop(NULL, NULL);
2319 } 2362 }
2320 2363
2321 return new_node; 2364 return new_node;
2322 } 2365 }
2323 2366
2324 2367
2325 void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) {
2326 sizes->huge_size_ = huge_list_.CountFreeListItemsInList(p);
2327 if (sizes->huge_size_ < p->area_size()) {
2328 sizes->small_size_ = small_list_.CountFreeListItemsInList(p);
2329 sizes->medium_size_ = medium_list_.CountFreeListItemsInList(p);
2330 sizes->large_size_ = large_list_.CountFreeListItemsInList(p);
2331 } else {
2332 sizes->small_size_ = 0;
2333 sizes->medium_size_ = 0;
2334 sizes->large_size_ = 0;
2335 }
2336 }
2337
2338
2339 intptr_t FreeList::EvictFreeListItems(Page* p) { 2368 intptr_t FreeList::EvictFreeListItems(Page* p) {
2340 intptr_t sum = huge_list_.EvictFreeListItemsInList(p); 2369 intptr_t sum = huge_list_.EvictFreeListItemsInList(p);
2370 p->set_available_in_huge_free_list(0);
2341 2371
2342 if (sum < p->area_size()) { 2372 if (sum < p->area_size()) {
2343 sum += small_list_.EvictFreeListItemsInList(p) + 2373 sum += small_list_.EvictFreeListItemsInList(p) +
2344 medium_list_.EvictFreeListItemsInList(p) + 2374 medium_list_.EvictFreeListItemsInList(p) +
2345 large_list_.EvictFreeListItemsInList(p); 2375 large_list_.EvictFreeListItemsInList(p);
2376 p->set_available_in_small_free_list(0);
2377 p->set_available_in_medium_free_list(0);
2378 p->set_available_in_large_free_list(0);
2346 } 2379 }
2347 2380
2348 return sum; 2381 return sum;
2349 } 2382 }
2350 2383
2351 2384
2352 void FreeList::RepairLists(Heap* heap) { 2385 void FreeList::RepairLists(Heap* heap) {
2353 small_list_.RepairFreeList(heap); 2386 small_list_.RepairFreeList(heap);
2354 medium_list_.RepairFreeList(heap); 2387 medium_list_.RepairFreeList(heap);
2355 large_list_.RepairFreeList(heap); 2388 large_list_.RepairFreeList(heap);
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after
3143 object->ShortPrint(); 3176 object->ShortPrint();
3144 PrintF("\n"); 3177 PrintF("\n");
3145 } 3178 }
3146 printf(" --------------------------------------\n"); 3179 printf(" --------------------------------------\n");
3147 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3180 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
3148 } 3181 }
3149 3182
3150 #endif // DEBUG 3183 #endif // DEBUG
3151 3184
3152 } } // namespace v8::internal 3185 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/spaces.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698