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 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 chunk_size, | 690 chunk_size, |
691 area_start, | 691 area_start, |
692 area_end, | 692 area_end, |
693 executable, | 693 executable, |
694 owner); | 694 owner); |
695 result->set_reserved_memory(&reservation); | 695 result->set_reserved_memory(&reservation); |
696 return result; | 696 return result; |
697 } | 697 } |
698 | 698 |
699 | 699 |
700 void Page::ResetFreeListStatistics() { | |
701 non_available_small_blocks_ = 0; | |
702 available_in_small_free_list_ = 0; | |
703 available_in_medium_free_list_ = 0; | |
704 available_in_large_free_list_ = 0; | |
705 available_in_huge_free_list_ = 0; | |
706 } | |
707 | |
708 | |
709 Page* MemoryAllocator::AllocatePage(intptr_t size, | 700 Page* MemoryAllocator::AllocatePage(intptr_t size, |
710 PagedSpace* owner, | 701 PagedSpace* owner, |
711 Executability executable) { | 702 Executability executable) { |
712 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner); | 703 MemoryChunk* chunk = AllocateChunk(size, size, executable, owner); |
713 | 704 |
714 if (chunk == NULL) return NULL; | 705 if (chunk == NULL) return NULL; |
715 | 706 |
716 return Page::Initialize(isolate_->heap(), chunk, executable, owner); | 707 return Page::Initialize(isolate_->heap(), chunk, executable, owner); |
717 } | 708 } |
718 | 709 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 PageIterator it(this); | 1050 PageIterator it(this); |
1060 int count = 0; | 1051 int count = 0; |
1061 while (it.has_next()) { | 1052 while (it.has_next()) { |
1062 it.next(); | 1053 it.next(); |
1063 count++; | 1054 count++; |
1064 } | 1055 } |
1065 return count; | 1056 return count; |
1066 } | 1057 } |
1067 | 1058 |
1068 | 1059 |
1069 void PagedSpace::ObtainFreeListStatistics(Page* page, SizeStats* sizes) { | |
1070 sizes->huge_size_ = page->available_in_huge_free_list(); | |
1071 sizes->small_size_ = page->available_in_small_free_list(); | |
1072 sizes->medium_size_ = page->available_in_medium_free_list(); | |
1073 sizes->large_size_ = page->available_in_large_free_list(); | |
1074 } | |
1075 | |
1076 | |
1077 void PagedSpace::ResetFreeListStatistics() { | |
1078 PageIterator page_iterator(this); | |
1079 while (page_iterator.has_next()) { | |
1080 Page* page = page_iterator.next(); | |
1081 page->ResetFreeListStatistics(); | |
1082 } | |
1083 } | |
1084 | |
1085 | |
1086 void PagedSpace::ReleasePage(Page* page, bool unlink) { | 1060 void PagedSpace::ReleasePage(Page* page, bool unlink) { |
1087 ASSERT(page->LiveBytes() == 0); | 1061 ASSERT(page->LiveBytes() == 0); |
1088 ASSERT(AreaSize() == page->area_size()); | 1062 ASSERT(AreaSize() == page->area_size()); |
1089 | 1063 |
1090 // Adjust list of unswept pages if the page is the head of the list. | 1064 // Adjust list of unswept pages if the page is the head of the list. |
1091 if (first_unswept_page_ == page) { | 1065 if (first_unswept_page_ == page) { |
1092 first_unswept_page_ = page->next_page(); | 1066 first_unswept_page_ = page->next_page(); |
1093 if (first_unswept_page_ == anchor()) { | 1067 if (first_unswept_page_ == anchor()) { |
1094 first_unswept_page_ = Page::FromAddress(NULL); | 1068 first_unswept_page_ = Page::FromAddress(NULL); |
1095 } | 1069 } |
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2075 } | 2049 } |
2076 | 2050 |
2077 | 2051 |
2078 void FreeListCategory::Reset() { | 2052 void FreeListCategory::Reset() { |
2079 top_ = NULL; | 2053 top_ = NULL; |
2080 end_ = NULL; | 2054 end_ = NULL; |
2081 available_ = 0; | 2055 available_ = 0; |
2082 } | 2056 } |
2083 | 2057 |
2084 | 2058 |
| 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 |
2085 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { | 2073 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { |
2086 int sum = 0; | 2074 int sum = 0; |
2087 FreeListNode** n = &top_; | 2075 FreeListNode** n = &top_; |
2088 while (*n != NULL) { | 2076 while (*n != NULL) { |
2089 if (Page::FromAddress((*n)->address()) == p) { | 2077 if (Page::FromAddress((*n)->address()) == p) { |
2090 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); | 2078 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); |
2091 sum += free_space->Size(); | 2079 sum += free_space->Size(); |
2092 *n = (*n)->next(); | 2080 *n = (*n)->next(); |
2093 } else { | 2081 } else { |
2094 n = (*n)->next_address(); | 2082 n = (*n)->next_address(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2175 large_list_.Reset(); | 2163 large_list_.Reset(); |
2176 huge_list_.Reset(); | 2164 huge_list_.Reset(); |
2177 } | 2165 } |
2178 | 2166 |
2179 | 2167 |
2180 int FreeList::Free(Address start, int size_in_bytes) { | 2168 int FreeList::Free(Address start, int size_in_bytes) { |
2181 if (size_in_bytes == 0) return 0; | 2169 if (size_in_bytes == 0) return 0; |
2182 | 2170 |
2183 FreeListNode* node = FreeListNode::FromAddress(start); | 2171 FreeListNode* node = FreeListNode::FromAddress(start); |
2184 node->set_size(heap_, size_in_bytes); | 2172 node->set_size(heap_, size_in_bytes); |
2185 Page* page = Page::FromAddress(start); | |
2186 | 2173 |
2187 // Early return to drop too-small blocks on the floor. | 2174 // Early return to drop too-small blocks on the floor. |
2188 if (size_in_bytes < kSmallListMin) { | 2175 if (size_in_bytes < kSmallListMin) return size_in_bytes; |
2189 page->add_non_available_small_blocks(size_in_bytes); | |
2190 return size_in_bytes; | |
2191 } | |
2192 | 2176 |
2193 // Insert other blocks at the head of a free list of the appropriate | 2177 // Insert other blocks at the head of a free list of the appropriate |
2194 // magnitude. | 2178 // magnitude. |
2195 if (size_in_bytes <= kSmallListMax) { | 2179 if (size_in_bytes <= kSmallListMax) { |
2196 small_list_.Free(node, size_in_bytes); | 2180 small_list_.Free(node, size_in_bytes); |
2197 page->add_available_in_small_free_list(size_in_bytes); | |
2198 } else if (size_in_bytes <= kMediumListMax) { | 2181 } else if (size_in_bytes <= kMediumListMax) { |
2199 medium_list_.Free(node, size_in_bytes); | 2182 medium_list_.Free(node, size_in_bytes); |
2200 page->add_available_in_medium_free_list(size_in_bytes); | |
2201 } else if (size_in_bytes <= kLargeListMax) { | 2183 } else if (size_in_bytes <= kLargeListMax) { |
2202 large_list_.Free(node, size_in_bytes); | 2184 large_list_.Free(node, size_in_bytes); |
2203 page->add_available_in_large_free_list(size_in_bytes); | |
2204 } else { | 2185 } else { |
2205 huge_list_.Free(node, size_in_bytes); | 2186 huge_list_.Free(node, size_in_bytes); |
2206 page->add_available_in_huge_free_list(size_in_bytes); | |
2207 } | 2187 } |
2208 | 2188 |
2209 ASSERT(IsVeryLong() || available() == SumFreeLists()); | 2189 ASSERT(IsVeryLong() || available() == SumFreeLists()); |
2210 return 0; | 2190 return 0; |
2211 } | 2191 } |
2212 | 2192 |
2213 | 2193 |
2214 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2194 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
2215 FreeListNode* node = NULL; | 2195 FreeListNode* node = NULL; |
2216 Page* page = NULL; | |
2217 | 2196 |
2218 if (size_in_bytes <= kSmallAllocationMax) { | 2197 if (size_in_bytes <= kSmallAllocationMax) { |
2219 node = small_list_.PickNodeFromList(node_size); | 2198 node = small_list_.PickNodeFromList(node_size); |
2220 if (node != NULL) { | 2199 if (node != NULL) return node; |
2221 page = Page::FromAddress(node->address()); | |
2222 page->add_available_in_small_free_list(-(*node_size)); | |
2223 return node; | |
2224 } | |
2225 } | 2200 } |
2226 | 2201 |
2227 if (size_in_bytes <= kMediumAllocationMax) { | 2202 if (size_in_bytes <= kMediumAllocationMax) { |
2228 node = medium_list_.PickNodeFromList(node_size); | 2203 node = medium_list_.PickNodeFromList(node_size); |
2229 if (node != NULL) { | 2204 if (node != NULL) return node; |
2230 page = Page::FromAddress(node->address()); | |
2231 page->add_available_in_medium_free_list(-(*node_size)); | |
2232 return node; | |
2233 } | |
2234 } | 2205 } |
2235 | 2206 |
2236 if (size_in_bytes <= kLargeAllocationMax) { | 2207 if (size_in_bytes <= kLargeAllocationMax) { |
2237 node = large_list_.PickNodeFromList(node_size); | 2208 node = large_list_.PickNodeFromList(node_size); |
2238 if (node != NULL) { | 2209 if (node != NULL) return node; |
2239 page = Page::FromAddress(node->address()); | |
2240 page->add_available_in_large_free_list(-(*node_size)); | |
2241 return node; | |
2242 } | |
2243 } | 2210 } |
2244 | 2211 |
2245 int huge_list_available = huge_list_.available(); | 2212 int huge_list_available = huge_list_.available(); |
2246 for (FreeListNode** cur = huge_list_.GetTopAddress(); | 2213 for (FreeListNode** cur = huge_list_.GetTopAddress(); |
2247 *cur != NULL; | 2214 *cur != NULL; |
2248 cur = (*cur)->next_address()) { | 2215 cur = (*cur)->next_address()) { |
2249 FreeListNode* cur_node = *cur; | 2216 FreeListNode* cur_node = *cur; |
2250 while (cur_node != NULL && | 2217 while (cur_node != NULL && |
2251 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { | 2218 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { |
2252 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size(); | 2219 huge_list_available -= reinterpret_cast<FreeSpace*>(cur_node)->Size(); |
2253 huge_list_available -= size; | |
2254 page = Page::FromAddress(node->address()); | |
2255 page->add_available_in_huge_free_list(-size); | |
2256 cur_node = cur_node->next(); | 2220 cur_node = cur_node->next(); |
2257 } | 2221 } |
2258 | 2222 |
2259 *cur = cur_node; | 2223 *cur = cur_node; |
2260 if (cur_node == NULL) { | 2224 if (cur_node == NULL) { |
2261 huge_list_.set_end(NULL); | 2225 huge_list_.set_end(NULL); |
2262 break; | 2226 break; |
2263 } | 2227 } |
2264 | 2228 |
2265 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map()); | 2229 ASSERT((*cur)->map() == heap_->raw_unchecked_free_space_map()); |
2266 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); | 2230 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); |
2267 int size = cur_as_free_space->Size(); | 2231 int size = cur_as_free_space->Size(); |
2268 if (size >= size_in_bytes) { | 2232 if (size >= size_in_bytes) { |
2269 // Large enough node found. Unlink it from the list. | 2233 // Large enough node found. Unlink it from the list. |
2270 node = *cur; | 2234 node = *cur; |
2271 *cur = node->next(); | 2235 *cur = node->next(); |
2272 *node_size = size; | 2236 *node_size = size; |
2273 huge_list_available -= size; | 2237 huge_list_available -= size; |
2274 page = Page::FromAddress(node->address()); | |
2275 page->add_available_in_huge_free_list(-size); | |
2276 break; | 2238 break; |
2277 } | 2239 } |
2278 } | 2240 } |
2279 | 2241 |
2280 if (huge_list_.top() == NULL) { | 2242 if (huge_list_.top() == NULL) { |
2281 huge_list_.set_end(NULL); | 2243 huge_list_.set_end(NULL); |
2282 } | 2244 } |
2283 | 2245 |
2284 huge_list_.set_available(huge_list_available); | 2246 huge_list_.set_available(huge_list_available); |
2285 ASSERT(IsVeryLong() || available() == SumFreeLists()); | 2247 ASSERT(IsVeryLong() || available() == SumFreeLists()); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2353 } else { | 2315 } else { |
2354 // TODO(gc) Try not freeing linear allocation region when bytes_left | 2316 // TODO(gc) Try not freeing linear allocation region when bytes_left |
2355 // are zero. | 2317 // are zero. |
2356 owner_->SetTop(NULL, NULL); | 2318 owner_->SetTop(NULL, NULL); |
2357 } | 2319 } |
2358 | 2320 |
2359 return new_node; | 2321 return new_node; |
2360 } | 2322 } |
2361 | 2323 |
2362 | 2324 |
| 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 |
2363 intptr_t FreeList::EvictFreeListItems(Page* p) { | 2339 intptr_t FreeList::EvictFreeListItems(Page* p) { |
2364 intptr_t sum = huge_list_.EvictFreeListItemsInList(p); | 2340 intptr_t sum = huge_list_.EvictFreeListItemsInList(p); |
2365 p->set_available_in_huge_free_list(0); | |
2366 | 2341 |
2367 if (sum < p->area_size()) { | 2342 if (sum < p->area_size()) { |
2368 sum += small_list_.EvictFreeListItemsInList(p) + | 2343 sum += small_list_.EvictFreeListItemsInList(p) + |
2369 medium_list_.EvictFreeListItemsInList(p) + | 2344 medium_list_.EvictFreeListItemsInList(p) + |
2370 large_list_.EvictFreeListItemsInList(p); | 2345 large_list_.EvictFreeListItemsInList(p); |
2371 p->set_available_in_small_free_list(0); | |
2372 p->set_available_in_medium_free_list(0); | |
2373 p->set_available_in_large_free_list(0); | |
2374 } | 2346 } |
2375 | 2347 |
2376 return sum; | 2348 return sum; |
2377 } | 2349 } |
2378 | 2350 |
2379 | 2351 |
2380 void FreeList::RepairLists(Heap* heap) { | 2352 void FreeList::RepairLists(Heap* heap) { |
2381 small_list_.RepairFreeList(heap); | 2353 small_list_.RepairFreeList(heap); |
2382 medium_list_.RepairFreeList(heap); | 2354 medium_list_.RepairFreeList(heap); |
2383 large_list_.RepairFreeList(heap); | 2355 large_list_.RepairFreeList(heap); |
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3171 object->ShortPrint(); | 3143 object->ShortPrint(); |
3172 PrintF("\n"); | 3144 PrintF("\n"); |
3173 } | 3145 } |
3174 printf(" --------------------------------------\n"); | 3146 printf(" --------------------------------------\n"); |
3175 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3147 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3176 } | 3148 } |
3177 | 3149 |
3178 #endif // DEBUG | 3150 #endif // DEBUG |
3179 | 3151 |
3180 } } // namespace v8::internal | 3152 } } // namespace v8::internal |
OLD | NEW |