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

Side by Side Diff: src/spaces.cc

Issue 11348174: Prepare FreeList for parallel and concurrent sweeping. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 1 month 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
« src/spaces.h ('K') | « 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 1919 matching lines...) Expand 10 before | Expand all | Expand 10 after
1930 1930
1931 1931
1932 FreeList::FreeList(PagedSpace* owner) 1932 FreeList::FreeList(PagedSpace* owner)
1933 : owner_(owner), heap_(owner->heap()) { 1933 : owner_(owner), heap_(owner->heap()) {
1934 Reset(); 1934 Reset();
1935 } 1935 }
1936 1936
1937 1937
1938 void FreeList::Reset() { 1938 void FreeList::Reset() {
1939 available_ = 0; 1939 available_ = 0;
1940 small_list_ = NULL; 1940 Reset(&small_list_);
1941 medium_list_ = NULL; 1941 Reset(&medium_list_);
1942 large_list_ = NULL; 1942 Reset(&large_list_);
1943 huge_list_ = NULL; 1943 Reset(&huge_list_);
1944 } 1944 }
1945 1945
1946 1946
1947 void FreeList::Reset(FreeListCategorie *categorie) {
1948 categorie->top = NULL;
1949 categorie->end = NULL;
1950 }
1951
1952
1953 void FreeList::GetList(struct FreeListCategorie *categorie,
1954 FreeListNode** top,
1955 FreeListNode** end) {
1956 *top = categorie->top;
1957 *end = categorie->end;
1958 categorie->top = NULL;
1959 categorie->end = NULL;
1960 }
1961
1962
1963 void AddList(struct FreeListCategorie *categorie,
1964 FreeListNode* top,
1965 FreeListNode* end) {
1966 end->set_next(categorie->top);
1967 categorie->top = top;
1968 }
1969
1970
1971 void FreeList::ConcurrentGetList(struct FreeListCategorie *categorie,
1972 FreeListNode** top,
1973 FreeListNode** end) {
1974 do {
1975 *top = categorie->top;
1976 *end = categorie->end;
1977 } while (*top != categorie->top ||
1978 NoBarrier_CompareAndSwap(
1979 reinterpret_cast<AtomicWord*>(&categorie->top),
1980 reinterpret_cast<AtomicWord>(*top), 0) !=
1981 reinterpret_cast<AtomicWord>(*top));
1982 NoBarrier_CompareAndSwap(
1983 reinterpret_cast<AtomicWord*>(&categorie->end),
1984 reinterpret_cast<AtomicWord>(*end), 0);
1985 }
1986
1987
1988 void ConcurrentAddList(struct FreeListCategorie *categorie,
1989 FreeListNode* top,
1990 FreeListNode* end) {
1991 FreeListNode* current_top;
1992 do {
1993 current_top = categorie->top;
1994 end->set_next(current_top);
1995 } while(current_top != categorie->top ||
1996 NoBarrier_CompareAndSwap(
1997 reinterpret_cast<AtomicWord*>(&categorie->top),
1998 reinterpret_cast<AtomicWord>(current_top),
1999 reinterpret_cast<AtomicWord>(top)) !=
2000 reinterpret_cast<AtomicWord>(current_top));
2001 }
2002
2003
1947 int FreeList::Free(Address start, int size_in_bytes) { 2004 int FreeList::Free(Address start, int size_in_bytes) {
1948 if (size_in_bytes == 0) return 0; 2005 if (size_in_bytes == 0) return 0;
1949 FreeListNode* node = FreeListNode::FromAddress(start); 2006 FreeListNode* node = FreeListNode::FromAddress(start);
1950 node->set_size(heap_, size_in_bytes); 2007 node->set_size(heap_, size_in_bytes);
1951 2008
1952 // Early return to drop too-small blocks on the floor. 2009 // Early return to drop too-small blocks on the floor.
1953 if (size_in_bytes < kSmallListMin) return size_in_bytes; 2010 if (size_in_bytes < kSmallListMin) return size_in_bytes;
1954 2011
1955 // Insert other blocks at the head of a free list of the appropriate 2012 // Insert other blocks at the head of a free list of the appropriate
1956 // magnitude. 2013 // magnitude.
1957 if (size_in_bytes <= kSmallListMax) { 2014 if (size_in_bytes <= kSmallListMax) {
1958 node->set_next(small_list_); 2015 node->set_next(small_list_.top);
1959 small_list_ = node; 2016 small_list_.top = node;
2017 if (small_list_.end == NULL) {
2018 small_list_.end = node;
2019 }
1960 } else if (size_in_bytes <= kMediumListMax) { 2020 } else if (size_in_bytes <= kMediumListMax) {
1961 node->set_next(medium_list_); 2021 node->set_next(medium_list_.top);
1962 medium_list_ = node; 2022 medium_list_.top = node;
2023 if (medium_list_.end == NULL) {
2024 medium_list_.end = node;
2025 }
1963 } else if (size_in_bytes <= kLargeListMax) { 2026 } else if (size_in_bytes <= kLargeListMax) {
1964 node->set_next(large_list_); 2027 node->set_next(large_list_.top);
1965 large_list_ = node; 2028 large_list_.top = node;
2029 if (large_list_.end == NULL) {
2030 large_list_.end = node;
2031 }
1966 } else { 2032 } else {
1967 node->set_next(huge_list_); 2033 node->set_next(huge_list_.top);
1968 huge_list_ = node; 2034 huge_list_.top = node;
2035 if (huge_list_.end == NULL) {
2036 huge_list_.end = node;
2037 }
1969 } 2038 }
1970 available_ += size_in_bytes; 2039 available_ += size_in_bytes;
1971 ASSERT(IsVeryLong() || available_ == SumFreeLists()); 2040 ASSERT(IsVeryLong() || available_ == SumFreeLists());
1972 return 0; 2041 return 0;
1973 } 2042 }
1974 2043
1975 2044
1976 FreeListNode* FreeList::PickNodeFromList(FreeListNode** list, int* node_size) { 2045 FreeListNode* FreeList::PickNodeFromList(FreeListCategorie* categorie,
1977 FreeListNode* node = *list; 2046 int* node_size) {
2047 FreeListNode* node = categorie->top;
1978 2048
1979 if (node == NULL) return NULL; 2049 if (node == NULL) return NULL;
1980 2050
1981 while (node != NULL && 2051 while (node != NULL &&
1982 Page::FromAddress(node->address())->IsEvacuationCandidate()) { 2052 Page::FromAddress(node->address())->IsEvacuationCandidate()) {
1983 available_ -= node->Size(); 2053 available_ -= node->Size();
1984 node = node->next(); 2054 node = node->next();
1985 } 2055 }
1986 2056
1987 if (node != NULL) { 2057 if (node != NULL) {
1988 *node_size = node->Size(); 2058 *node_size = node->Size();
1989 *list = node->next(); 2059 categorie->top = node->next();
1990 } else { 2060 } else {
1991 *list = NULL; 2061 categorie->top = NULL;
2062 }
2063
2064 if (categorie->top == NULL) {
2065 categorie->end = NULL;
1992 } 2066 }
1993 2067
1994 return node; 2068 return node;
1995 } 2069 }
1996 2070
1997 2071
1998 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { 2072 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) {
1999 FreeListNode* node = NULL; 2073 FreeListNode* node = NULL;
2000 2074
2001 if (size_in_bytes <= kSmallAllocationMax) { 2075 if (size_in_bytes <= kSmallAllocationMax) {
2002 node = PickNodeFromList(&small_list_, node_size); 2076 node = PickNodeFromList(&small_list_, node_size);
2003 if (node != NULL) return node; 2077 if (node != NULL) return node;
2004 } 2078 }
2005 2079
2006 if (size_in_bytes <= kMediumAllocationMax) { 2080 if (size_in_bytes <= kMediumAllocationMax) {
2007 node = PickNodeFromList(&medium_list_, node_size); 2081 node = PickNodeFromList(&medium_list_, node_size);
2008 if (node != NULL) return node; 2082 if (node != NULL) return node;
2009 } 2083 }
2010 2084
2011 if (size_in_bytes <= kLargeAllocationMax) { 2085 if (size_in_bytes <= kLargeAllocationMax) {
2012 node = PickNodeFromList(&large_list_, node_size); 2086 node = PickNodeFromList(&large_list_, node_size);
2013 if (node != NULL) return node; 2087 if (node != NULL) return node;
2014 } 2088 }
2015 2089
2016 for (FreeListNode** cur = &huge_list_; 2090 for (FreeListNode** cur = &(huge_list_.top);
2017 *cur != NULL; 2091 *cur != NULL;
2018 cur = (*cur)->next_address()) { 2092 cur = (*cur)->next_address()) {
2019 FreeListNode* cur_node = *cur; 2093 FreeListNode* cur_node = *cur;
2020 while (cur_node != NULL && 2094 while (cur_node != NULL &&
2021 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { 2095 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) {
2022 available_ -= reinterpret_cast<FreeSpace*>(cur_node)->Size(); 2096 available_ -= reinterpret_cast<FreeSpace*>(cur_node)->Size();
2023 cur_node = cur_node->next(); 2097 cur_node = cur_node->next();
2024 } 2098 }
2025 2099
2026 *cur = cur_node; 2100 *cur = cur_node;
2027 if (cur_node == NULL) break; 2101 if (cur_node == NULL) {
2102 huge_list_.end = NULL;
2103 break;
2104 }
2028 2105
2029 ASSERT((*cur)->map() == HEAP->raw_unchecked_free_space_map()); 2106 ASSERT((*cur)->map() == HEAP->raw_unchecked_free_space_map());
2030 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); 2107 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur);
2031 int size = cur_as_free_space->Size(); 2108 int size = cur_as_free_space->Size();
2032 if (size >= size_in_bytes) { 2109 if (size >= size_in_bytes) {
2033 // Large enough node found. Unlink it from the list. 2110 // Large enough node found. Unlink it from the list.
2034 node = *cur; 2111 node = *cur;
2035 *node_size = size; 2112 *node_size = size;
2036 *cur = node->next(); 2113 *cur = node->next();
2037 break; 2114 break;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2109 } else { 2186 } else {
2110 // TODO(gc) Try not freeing linear allocation region when bytes_left 2187 // TODO(gc) Try not freeing linear allocation region when bytes_left
2111 // are zero. 2188 // are zero.
2112 owner_->SetTop(NULL, NULL); 2189 owner_->SetTop(NULL, NULL);
2113 } 2190 }
2114 2191
2115 return new_node; 2192 return new_node;
2116 } 2193 }
2117 2194
2118 2195
2119 static intptr_t CountFreeListItemsInList(FreeListNode* n, Page* p) { 2196 static intptr_t CountFreeListItemsInList(FreeListCategorie* categorie,
Michael Starzinger 2012/11/27 13:51:53 I think the code would be easier to read if the st
Hannes Payer (out of office) 2012/11/29 13:17:42 Done. Now we just call the method on the given obj
2197 Page* p) {
2120 intptr_t sum = 0; 2198 intptr_t sum = 0;
2199 FreeListNode* n = categorie->top;
2121 while (n != NULL) { 2200 while (n != NULL) {
2122 if (Page::FromAddress(n->address()) == p) { 2201 if (Page::FromAddress(n->address()) == p) {
2123 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(n); 2202 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(n);
2124 sum += free_space->Size(); 2203 sum += free_space->Size();
2125 } 2204 }
2126 n = n->next(); 2205 n = n->next();
2127 } 2206 }
2128 return sum; 2207 return sum;
2129 } 2208 }
2130 2209
2131 2210
2132 void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) { 2211 void FreeList::CountFreeListItems(Page* p, SizeStats* sizes) {
2133 sizes->huge_size_ = CountFreeListItemsInList(huge_list_, p); 2212 sizes->huge_size_ = CountFreeListItemsInList(&huge_list_, p);
2134 if (sizes->huge_size_ < p->area_size()) { 2213 if (sizes->huge_size_ < p->area_size()) {
2135 sizes->small_size_ = CountFreeListItemsInList(small_list_, p); 2214 sizes->small_size_ = CountFreeListItemsInList(&small_list_, p);
2136 sizes->medium_size_ = CountFreeListItemsInList(medium_list_, p); 2215 sizes->medium_size_ = CountFreeListItemsInList(&medium_list_, p);
2137 sizes->large_size_ = CountFreeListItemsInList(large_list_, p); 2216 sizes->large_size_ = CountFreeListItemsInList(&large_list_, p);
2138 } else { 2217 } else {
2139 sizes->small_size_ = 0; 2218 sizes->small_size_ = 0;
2140 sizes->medium_size_ = 0; 2219 sizes->medium_size_ = 0;
2141 sizes->large_size_ = 0; 2220 sizes->large_size_ = 0;
2142 } 2221 }
2143 } 2222 }
2144 2223
2145 2224
2146 static intptr_t EvictFreeListItemsInList(FreeListNode** n, Page* p) { 2225 static intptr_t EvictFreeListItemsInList(FreeListCategorie* categorie,
2226 Page* p) {
2147 intptr_t sum = 0; 2227 intptr_t sum = 0;
2228 FreeListNode** n = &(categorie->top);
2148 while (*n != NULL) { 2229 while (*n != NULL) {
2149 if (Page::FromAddress((*n)->address()) == p) { 2230 if (Page::FromAddress((*n)->address()) == p) {
2150 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); 2231 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n);
2151 sum += free_space->Size(); 2232 sum += free_space->Size();
2152 *n = (*n)->next(); 2233 *n = (*n)->next();
2153 } else { 2234 } else {
2154 n = (*n)->next_address(); 2235 n = (*n)->next_address();
2155 } 2236 }
2156 } 2237 }
2157 return sum; 2238 return sum;
2158 } 2239 }
2159 2240
2160 2241
2161 intptr_t FreeList::EvictFreeListItems(Page* p) { 2242 intptr_t FreeList::EvictFreeListItems(Page* p) {
2162 intptr_t sum = EvictFreeListItemsInList(&huge_list_, p); 2243 intptr_t sum = EvictFreeListItemsInList(&huge_list_, p);
2163 2244
2164 if (sum < p->area_size()) { 2245 if (sum < p->area_size()) {
2165 sum += EvictFreeListItemsInList(&small_list_, p) + 2246 sum += EvictFreeListItemsInList(&small_list_, p) +
2166 EvictFreeListItemsInList(&medium_list_, p) + 2247 EvictFreeListItemsInList(&medium_list_, p) +
2167 EvictFreeListItemsInList(&large_list_, p); 2248 EvictFreeListItemsInList(&large_list_, p);
2168 } 2249 }
2169 2250
2170 available_ -= static_cast<int>(sum); 2251 available_ -= static_cast<int>(sum);
2171 2252
2172 return sum; 2253 return sum;
2173 } 2254 }
2174 2255
2175 2256
2176 #ifdef DEBUG 2257 #ifdef DEBUG
2177 intptr_t FreeList::SumFreeList(FreeListNode* cur) { 2258 intptr_t FreeList::SumFreeList(FreeListCategorie* categorie) {
2178 intptr_t sum = 0; 2259 intptr_t sum = 0;
2260 FreeListNode* cur = categorie->top;
2179 while (cur != NULL) { 2261 while (cur != NULL) {
2180 ASSERT(cur->map() == HEAP->raw_unchecked_free_space_map()); 2262 ASSERT(cur->map() == HEAP->raw_unchecked_free_space_map());
2181 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur); 2263 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur);
2182 sum += cur_as_free_space->Size(); 2264 sum += cur_as_free_space->Size();
2183 cur = cur->next(); 2265 cur = cur->next();
2184 } 2266 }
2185 return sum; 2267 return sum;
2186 } 2268 }
2187 2269
2188 2270
2189 static const int kVeryLongFreeList = 500; 2271 static const int kVeryLongFreeList = 500;
2190 2272
2191 2273
2192 int FreeList::FreeListLength(FreeListNode* cur) { 2274 int FreeList::FreeListLength(FreeListCategorie* categorie) {
2193 int length = 0; 2275 int length = 0;
2276 FreeListNode* cur = categorie->top;
2194 while (cur != NULL) { 2277 while (cur != NULL) {
2195 length++; 2278 length++;
2196 cur = cur->next(); 2279 cur = cur->next();
2197 if (length == kVeryLongFreeList) return length; 2280 if (length == kVeryLongFreeList) return length;
2198 } 2281 }
2199 return length; 2282 return length;
2200 } 2283 }
2201 2284
2202 2285
2203 bool FreeList::IsVeryLong() { 2286 bool FreeList::IsVeryLong() {
2204 if (FreeListLength(small_list_) == kVeryLongFreeList) return true; 2287 if (FreeListLength(&small_list_) == kVeryLongFreeList) return true;
2205 if (FreeListLength(medium_list_) == kVeryLongFreeList) return true; 2288 if (FreeListLength(&medium_list_) == kVeryLongFreeList) return true;
2206 if (FreeListLength(large_list_) == kVeryLongFreeList) return true; 2289 if (FreeListLength(&large_list_) == kVeryLongFreeList) return true;
2207 if (FreeListLength(huge_list_) == kVeryLongFreeList) return true; 2290 if (FreeListLength(&huge_list_) == kVeryLongFreeList) return true;
2208 return false; 2291 return false;
2209 } 2292 }
2210 2293
2211 2294
2212 // This can take a very long time because it is linear in the number of entries 2295 // This can take a very long time because it is linear in the number of entries
2213 // on the free list, so it should not be called if FreeListLength returns 2296 // on the free list, so it should not be called if FreeListLength returns
2214 // kVeryLongFreeList. 2297 // kVeryLongFreeList.
2215 intptr_t FreeList::SumFreeLists() { 2298 intptr_t FreeList::SumFreeLists() {
2216 intptr_t sum = SumFreeList(small_list_); 2299 intptr_t sum = SumFreeList(&small_list_);
2217 sum += SumFreeList(medium_list_); 2300 sum += SumFreeList(&medium_list_);
2218 sum += SumFreeList(large_list_); 2301 sum += SumFreeList(&large_list_);
2219 sum += SumFreeList(huge_list_); 2302 sum += SumFreeList(&huge_list_);
2220 return sum; 2303 return sum;
2221 } 2304 }
2222 #endif 2305 #endif
2223 2306
2224 2307
2225 // ----------------------------------------------------------------------------- 2308 // -----------------------------------------------------------------------------
2226 // OldSpace implementation 2309 // OldSpace implementation
2227 2310
2228 bool NewSpace::ReserveSpace(int bytes) { 2311 bool NewSpace::ReserveSpace(int bytes) {
2229 // We can't reliably unpack a partial snapshot that needs more new space 2312 // We can't reliably unpack a partial snapshot that needs more new space
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2311 *map_location = heap->free_space_map(); 2394 *map_location = heap->free_space_map();
2312 } else { 2395 } else {
2313 ASSERT(*map_location == heap->free_space_map()); 2396 ASSERT(*map_location == heap->free_space_map());
2314 } 2397 }
2315 n = n->next(); 2398 n = n->next();
2316 } 2399 }
2317 } 2400 }
2318 2401
2319 2402
2320 void FreeList::RepairLists(Heap* heap) { 2403 void FreeList::RepairLists(Heap* heap) {
2321 RepairFreeList(heap, small_list_); 2404 RepairFreeList(heap, small_list_.top);
2322 RepairFreeList(heap, medium_list_); 2405 RepairFreeList(heap, medium_list_.top);
2323 RepairFreeList(heap, large_list_); 2406 RepairFreeList(heap, large_list_.top);
2324 RepairFreeList(heap, huge_list_); 2407 RepairFreeList(heap, huge_list_.top);
2325 } 2408 }
2326 2409
2327 2410
2328 // After we have booted, we have created a map which represents free space 2411 // After we have booted, we have created a map which represents free space
2329 // on the heap. If there was already a free list then the elements on it 2412 // on the heap. If there was already a free list then the elements on it
2330 // were created with the wrong FreeSpaceMap (normally NULL), so we need to 2413 // were created with the wrong FreeSpaceMap (normally NULL), so we need to
2331 // fix them. 2414 // fix them.
2332 void PagedSpace::RepairFreeListsAfterBoot() { 2415 void PagedSpace::RepairFreeListsAfterBoot() {
2333 free_list_.RepairLists(heap()); 2416 free_list_.RepairLists(heap());
2334 } 2417 }
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
2947 object->ShortPrint(); 3030 object->ShortPrint();
2948 PrintF("\n"); 3031 PrintF("\n");
2949 } 3032 }
2950 printf(" --------------------------------------\n"); 3033 printf(" --------------------------------------\n");
2951 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); 3034 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes());
2952 } 3035 }
2953 3036
2954 #endif // DEBUG 3037 #endif // DEBUG
2955 3038
2956 } } // namespace v8::internal 3039 } } // namespace v8::internal
OLDNEW
« src/spaces.h ('K') | « src/spaces.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698