OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |