OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
9 #include "src/full-codegen.h" | 9 #include "src/full-codegen.h" |
10 #include "src/heap/mark-compact.h" | 10 #include "src/heap/mark-compact.h" |
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1021 | 1021 |
1022 return true; | 1022 return true; |
1023 } | 1023 } |
1024 | 1024 |
1025 | 1025 |
1026 bool PagedSpace::Expand() { | 1026 bool PagedSpace::Expand() { |
1027 if (!CanExpand()) return false; | 1027 if (!CanExpand()) return false; |
1028 | 1028 |
1029 intptr_t size = AreaSize(); | 1029 intptr_t size = AreaSize(); |
1030 | 1030 |
1031 if (anchor_.next_page() == &anchor_) { | |
1032 size = SizeOfFirstPage(); | |
1033 } | |
1034 | |
1035 Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this, | 1031 Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this, |
1036 executable()); | 1032 executable()); |
1037 if (p == NULL) return false; | 1033 if (p == NULL) return false; |
1038 | 1034 |
1039 DCHECK(Capacity() <= max_capacity_); | 1035 DCHECK(Capacity() <= max_capacity_); |
1040 | 1036 |
1041 p->InsertAfter(anchor_.prev_page()); | 1037 p->InsertAfter(anchor_.prev_page()); |
1042 | 1038 |
1043 return true; | 1039 return true; |
1044 } | 1040 } |
1045 | 1041 |
1046 | 1042 |
1047 intptr_t PagedSpace::SizeOfFirstPage() { | |
1048 // If the snapshot contains a custom script, all size guarantees are off. | |
1049 if (Snapshot::EmbedsScript()) return AreaSize(); | |
1050 // If using an ool constant pool then transfer the constant pool allowance | |
1051 // from the code space to the old pointer space. | |
1052 static const int constant_pool_delta = FLAG_enable_ool_constant_pool ? 48 : 0; | |
1053 int size = 0; | |
1054 switch (identity()) { | |
1055 case OLD_POINTER_SPACE: | |
1056 size = (128 + constant_pool_delta) * kPointerSize * KB; | |
1057 break; | |
1058 case OLD_DATA_SPACE: | |
1059 size = 192 * KB; | |
1060 break; | |
1061 case MAP_SPACE: | |
1062 size = 16 * kPointerSize * KB; | |
1063 break; | |
1064 case CELL_SPACE: | |
1065 size = 16 * kPointerSize * KB; | |
1066 break; | |
1067 case PROPERTY_CELL_SPACE: | |
1068 size = 8 * kPointerSize * KB; | |
1069 break; | |
1070 case CODE_SPACE: { | |
1071 CodeRange* code_range = heap()->isolate()->code_range(); | |
1072 if (code_range != NULL && code_range->valid()) { | |
1073 // When code range exists, code pages are allocated in a special way | |
1074 // (from the reserved code range). That part of the code is not yet | |
1075 // upgraded to handle small pages. | |
1076 size = AreaSize(); | |
1077 } else { | |
1078 size = RoundUp((480 - constant_pool_delta) * KB * | |
1079 FullCodeGenerator::kBootCodeSizeMultiplier / 100, | |
1080 kPointerSize); | |
1081 } | |
1082 break; | |
1083 } | |
1084 default: | |
1085 UNREACHABLE(); | |
1086 } | |
1087 return Min(size, AreaSize()); | |
1088 } | |
1089 | |
1090 | |
1091 int PagedSpace::CountTotalPages() { | 1043 int PagedSpace::CountTotalPages() { |
1092 PageIterator it(this); | 1044 PageIterator it(this); |
1093 int count = 0; | 1045 int count = 0; |
1094 while (it.has_next()) { | 1046 while (it.has_next()) { |
1095 it.next(); | 1047 it.next(); |
1096 count++; | 1048 count++; |
1097 } | 1049 } |
1098 return count; | 1050 return count; |
1099 } | 1051 } |
1100 | 1052 |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2075 if (from_space_.is_committed()) { | 2027 if (from_space_.is_committed()) { |
2076 size += from_space_.CommittedPhysicalMemory(); | 2028 size += from_space_.CommittedPhysicalMemory(); |
2077 } | 2029 } |
2078 return size; | 2030 return size; |
2079 } | 2031 } |
2080 | 2032 |
2081 | 2033 |
2082 // ----------------------------------------------------------------------------- | 2034 // ----------------------------------------------------------------------------- |
2083 // Free lists for old object spaces implementation | 2035 // Free lists for old object spaces implementation |
2084 | 2036 |
2085 void FreeListNode::set_size(Heap* heap, int size_in_bytes) { | |
2086 DCHECK(size_in_bytes > 0); | |
2087 DCHECK(IsAligned(size_in_bytes, kPointerSize)); | |
2088 | |
2089 // We write a map and possibly size information to the block. If the block | |
2090 // is big enough to be a FreeSpace with at least one extra word (the next | |
2091 // pointer), we set its map to be the free space map and its size to an | |
2092 // appropriate array length for the desired size from HeapObject::Size(). | |
2093 // If the block is too small (eg, one or two words), to hold both a size | |
2094 // field and a next pointer, we give it a filler map that gives it the | |
2095 // correct size. | |
2096 if (size_in_bytes > FreeSpace::kHeaderSize) { | |
2097 // Can't use FreeSpace::cast because it fails during deserialization. | |
2098 // We have to set the size first with a release store before we store | |
2099 // the map because a concurrent store buffer scan on scavenge must not | |
2100 // observe a map with an invalid size. | |
2101 FreeSpace* this_as_free_space = reinterpret_cast<FreeSpace*>(this); | |
2102 this_as_free_space->nobarrier_set_size(size_in_bytes); | |
2103 synchronized_set_map_no_write_barrier(heap->raw_unchecked_free_space_map()); | |
2104 } else if (size_in_bytes == kPointerSize) { | |
2105 set_map_no_write_barrier(heap->raw_unchecked_one_pointer_filler_map()); | |
2106 } else if (size_in_bytes == 2 * kPointerSize) { | |
2107 set_map_no_write_barrier(heap->raw_unchecked_two_pointer_filler_map()); | |
2108 } else { | |
2109 UNREACHABLE(); | |
2110 } | |
2111 // We would like to DCHECK(Size() == size_in_bytes) but this would fail during | |
2112 // deserialization because the free space map is not done yet. | |
2113 } | |
2114 | |
2115 | |
2116 FreeListNode* FreeListNode::next() { | |
2117 DCHECK(IsFreeListNode(this)); | |
2118 if (map() == GetHeap()->raw_unchecked_free_space_map()) { | |
2119 DCHECK(map() == NULL || Size() >= kNextOffset + kPointerSize); | |
2120 return reinterpret_cast<FreeListNode*>( | |
2121 Memory::Address_at(address() + kNextOffset)); | |
2122 } else { | |
2123 return reinterpret_cast<FreeListNode*>( | |
2124 Memory::Address_at(address() + kPointerSize)); | |
2125 } | |
2126 } | |
2127 | |
2128 | |
2129 FreeListNode** FreeListNode::next_address() { | |
2130 DCHECK(IsFreeListNode(this)); | |
2131 if (map() == GetHeap()->raw_unchecked_free_space_map()) { | |
2132 DCHECK(Size() >= kNextOffset + kPointerSize); | |
2133 return reinterpret_cast<FreeListNode**>(address() + kNextOffset); | |
2134 } else { | |
2135 return reinterpret_cast<FreeListNode**>(address() + kPointerSize); | |
2136 } | |
2137 } | |
2138 | |
2139 | |
2140 void FreeListNode::set_next(FreeListNode* next) { | |
2141 DCHECK(IsFreeListNode(this)); | |
2142 // While we are booting the VM the free space map will actually be null. So | |
2143 // we have to make sure that we don't try to use it for anything at that | |
2144 // stage. | |
2145 if (map() == GetHeap()->raw_unchecked_free_space_map()) { | |
2146 DCHECK(map() == NULL || Size() >= kNextOffset + kPointerSize); | |
2147 base::NoBarrier_Store( | |
2148 reinterpret_cast<base::AtomicWord*>(address() + kNextOffset), | |
2149 reinterpret_cast<base::AtomicWord>(next)); | |
2150 } else { | |
2151 base::NoBarrier_Store( | |
2152 reinterpret_cast<base::AtomicWord*>(address() + kPointerSize), | |
2153 reinterpret_cast<base::AtomicWord>(next)); | |
2154 } | |
2155 } | |
2156 | |
2157 | |
2158 intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { | 2037 intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { |
2159 intptr_t free_bytes = 0; | 2038 intptr_t free_bytes = 0; |
2160 if (category->top() != NULL) { | 2039 if (category->top() != NULL) { |
2161 // This is safe (not going to deadlock) since Concatenate operations | 2040 // This is safe (not going to deadlock) since Concatenate operations |
2162 // are never performed on the same free lists at the same time in | 2041 // are never performed on the same free lists at the same time in |
2163 // reverse order. | 2042 // reverse order. |
2164 base::LockGuard<base::Mutex> target_lock_guard(mutex()); | 2043 base::LockGuard<base::Mutex> target_lock_guard(mutex()); |
2165 base::LockGuard<base::Mutex> source_lock_guard(category->mutex()); | 2044 base::LockGuard<base::Mutex> source_lock_guard(category->mutex()); |
2166 DCHECK(category->end_ != NULL); | 2045 DCHECK(category->end_ != NULL); |
2167 free_bytes = category->available(); | 2046 free_bytes = category->available(); |
(...skipping 13 matching lines...) Expand all Loading... |
2181 | 2060 |
2182 void FreeListCategory::Reset() { | 2061 void FreeListCategory::Reset() { |
2183 set_top(NULL); | 2062 set_top(NULL); |
2184 set_end(NULL); | 2063 set_end(NULL); |
2185 set_available(0); | 2064 set_available(0); |
2186 } | 2065 } |
2187 | 2066 |
2188 | 2067 |
2189 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { | 2068 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { |
2190 int sum = 0; | 2069 int sum = 0; |
2191 FreeListNode* t = top(); | 2070 FreeSpace* t = top(); |
2192 FreeListNode** n = &t; | 2071 FreeSpace** n = &t; |
2193 while (*n != NULL) { | 2072 while (*n != NULL) { |
2194 if (Page::FromAddress((*n)->address()) == p) { | 2073 if (Page::FromAddress((*n)->address()) == p) { |
2195 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); | 2074 FreeSpace* free_space = *n; |
2196 sum += free_space->Size(); | 2075 sum += free_space->Size(); |
2197 *n = (*n)->next(); | 2076 *n = (*n)->next(); |
2198 } else { | 2077 } else { |
2199 n = (*n)->next_address(); | 2078 n = (*n)->next_address(); |
2200 } | 2079 } |
2201 } | 2080 } |
2202 set_top(t); | 2081 set_top(t); |
2203 if (top() == NULL) { | 2082 if (top() == NULL) { |
2204 set_end(NULL); | 2083 set_end(NULL); |
2205 } | 2084 } |
2206 available_ -= sum; | 2085 available_ -= sum; |
2207 return sum; | 2086 return sum; |
2208 } | 2087 } |
2209 | 2088 |
2210 | 2089 |
2211 bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) { | 2090 bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) { |
2212 FreeListNode* node = top(); | 2091 FreeSpace* node = top(); |
2213 while (node != NULL) { | 2092 while (node != NULL) { |
2214 if (Page::FromAddress(node->address()) == p) return true; | 2093 if (Page::FromAddress(node->address()) == p) return true; |
2215 node = node->next(); | 2094 node = node->next(); |
2216 } | 2095 } |
2217 return false; | 2096 return false; |
2218 } | 2097 } |
2219 | 2098 |
2220 | 2099 |
2221 FreeListNode* FreeListCategory::PickNodeFromList(int* node_size) { | 2100 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { |
2222 FreeListNode* node = top(); | 2101 FreeSpace* node = top(); |
2223 | 2102 |
2224 if (node == NULL) return NULL; | 2103 if (node == NULL) return NULL; |
2225 | 2104 |
2226 while (node != NULL && | 2105 while (node != NULL && |
2227 Page::FromAddress(node->address())->IsEvacuationCandidate()) { | 2106 Page::FromAddress(node->address())->IsEvacuationCandidate()) { |
2228 available_ -= reinterpret_cast<FreeSpace*>(node)->Size(); | 2107 available_ -= node->Size(); |
2229 node = node->next(); | 2108 node = node->next(); |
2230 } | 2109 } |
2231 | 2110 |
2232 if (node != NULL) { | 2111 if (node != NULL) { |
2233 set_top(node->next()); | 2112 set_top(node->next()); |
2234 *node_size = reinterpret_cast<FreeSpace*>(node)->Size(); | 2113 *node_size = node->Size(); |
2235 available_ -= *node_size; | 2114 available_ -= *node_size; |
2236 } else { | 2115 } else { |
2237 set_top(NULL); | 2116 set_top(NULL); |
2238 } | 2117 } |
2239 | 2118 |
2240 if (top() == NULL) { | 2119 if (top() == NULL) { |
2241 set_end(NULL); | 2120 set_end(NULL); |
2242 } | 2121 } |
2243 | 2122 |
2244 return node; | 2123 return node; |
2245 } | 2124 } |
2246 | 2125 |
2247 | 2126 |
2248 FreeListNode* FreeListCategory::PickNodeFromList(int size_in_bytes, | 2127 FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, |
2249 int* node_size) { | 2128 int* node_size) { |
2250 FreeListNode* node = PickNodeFromList(node_size); | 2129 FreeSpace* node = PickNodeFromList(node_size); |
2251 if (node != NULL && *node_size < size_in_bytes) { | 2130 if (node != NULL && *node_size < size_in_bytes) { |
2252 Free(node, *node_size); | 2131 Free(node, *node_size); |
2253 *node_size = 0; | 2132 *node_size = 0; |
2254 return NULL; | 2133 return NULL; |
2255 } | 2134 } |
2256 return node; | 2135 return node; |
2257 } | 2136 } |
2258 | 2137 |
2259 | 2138 |
2260 void FreeListCategory::Free(FreeListNode* node, int size_in_bytes) { | 2139 void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { |
2261 node->set_next(top()); | 2140 DCHECK_LE(FreeList::kSmallListMin, size_in_bytes); |
2262 set_top(node); | 2141 free_space->set_next(top()); |
| 2142 set_top(free_space); |
2263 if (end_ == NULL) { | 2143 if (end_ == NULL) { |
2264 end_ = node; | 2144 end_ = free_space; |
2265 } | 2145 } |
2266 available_ += size_in_bytes; | 2146 available_ += size_in_bytes; |
2267 } | 2147 } |
2268 | 2148 |
2269 | 2149 |
2270 void FreeListCategory::RepairFreeList(Heap* heap) { | 2150 void FreeListCategory::RepairFreeList(Heap* heap) { |
2271 FreeListNode* n = top(); | 2151 FreeSpace* n = top(); |
2272 while (n != NULL) { | 2152 while (n != NULL) { |
2273 Map** map_location = reinterpret_cast<Map**>(n->address()); | 2153 Map** map_location = reinterpret_cast<Map**>(n->address()); |
2274 if (*map_location == NULL) { | 2154 if (*map_location == NULL) { |
2275 *map_location = heap->free_space_map(); | 2155 *map_location = heap->free_space_map(); |
2276 } else { | 2156 } else { |
2277 DCHECK(*map_location == heap->free_space_map()); | 2157 DCHECK(*map_location == heap->free_space_map()); |
2278 } | 2158 } |
2279 n = n->next(); | 2159 n = n->next(); |
2280 } | 2160 } |
2281 } | 2161 } |
(...skipping 18 matching lines...) Expand all Loading... |
2300 small_list_.Reset(); | 2180 small_list_.Reset(); |
2301 medium_list_.Reset(); | 2181 medium_list_.Reset(); |
2302 large_list_.Reset(); | 2182 large_list_.Reset(); |
2303 huge_list_.Reset(); | 2183 huge_list_.Reset(); |
2304 } | 2184 } |
2305 | 2185 |
2306 | 2186 |
2307 int FreeList::Free(Address start, int size_in_bytes) { | 2187 int FreeList::Free(Address start, int size_in_bytes) { |
2308 if (size_in_bytes == 0) return 0; | 2188 if (size_in_bytes == 0) return 0; |
2309 | 2189 |
2310 FreeListNode* node = FreeListNode::FromAddress(start); | 2190 heap_->CreateFillerObjectAt(start, size_in_bytes); |
2311 node->set_size(heap_, size_in_bytes); | 2191 |
2312 Page* page = Page::FromAddress(start); | 2192 Page* page = Page::FromAddress(start); |
2313 | 2193 |
2314 // Early return to drop too-small blocks on the floor. | 2194 // Early return to drop too-small blocks on the floor. |
2315 if (size_in_bytes < kSmallListMin) { | 2195 if (size_in_bytes < kSmallListMin) { |
2316 page->add_non_available_small_blocks(size_in_bytes); | 2196 page->add_non_available_small_blocks(size_in_bytes); |
2317 return size_in_bytes; | 2197 return size_in_bytes; |
2318 } | 2198 } |
2319 | 2199 |
| 2200 FreeSpace* free_space = FreeSpace::cast(HeapObject::FromAddress(start)); |
2320 // Insert other blocks at the head of a free list of the appropriate | 2201 // Insert other blocks at the head of a free list of the appropriate |
2321 // magnitude. | 2202 // magnitude. |
2322 if (size_in_bytes <= kSmallListMax) { | 2203 if (size_in_bytes <= kSmallListMax) { |
2323 small_list_.Free(node, size_in_bytes); | 2204 small_list_.Free(free_space, size_in_bytes); |
2324 page->add_available_in_small_free_list(size_in_bytes); | 2205 page->add_available_in_small_free_list(size_in_bytes); |
2325 } else if (size_in_bytes <= kMediumListMax) { | 2206 } else if (size_in_bytes <= kMediumListMax) { |
2326 medium_list_.Free(node, size_in_bytes); | 2207 medium_list_.Free(free_space, size_in_bytes); |
2327 page->add_available_in_medium_free_list(size_in_bytes); | 2208 page->add_available_in_medium_free_list(size_in_bytes); |
2328 } else if (size_in_bytes <= kLargeListMax) { | 2209 } else if (size_in_bytes <= kLargeListMax) { |
2329 large_list_.Free(node, size_in_bytes); | 2210 large_list_.Free(free_space, size_in_bytes); |
2330 page->add_available_in_large_free_list(size_in_bytes); | 2211 page->add_available_in_large_free_list(size_in_bytes); |
2331 } else { | 2212 } else { |
2332 huge_list_.Free(node, size_in_bytes); | 2213 huge_list_.Free(free_space, size_in_bytes); |
2333 page->add_available_in_huge_free_list(size_in_bytes); | 2214 page->add_available_in_huge_free_list(size_in_bytes); |
2334 } | 2215 } |
2335 | 2216 |
2336 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2217 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2337 return 0; | 2218 return 0; |
2338 } | 2219 } |
2339 | 2220 |
2340 | 2221 |
2341 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2222 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
2342 FreeListNode* node = NULL; | 2223 FreeSpace* node = NULL; |
2343 Page* page = NULL; | 2224 Page* page = NULL; |
2344 | 2225 |
2345 if (size_in_bytes <= kSmallAllocationMax) { | 2226 if (size_in_bytes <= kSmallAllocationMax) { |
2346 node = small_list_.PickNodeFromList(node_size); | 2227 node = small_list_.PickNodeFromList(node_size); |
2347 if (node != NULL) { | 2228 if (node != NULL) { |
2348 DCHECK(size_in_bytes <= *node_size); | 2229 DCHECK(size_in_bytes <= *node_size); |
2349 page = Page::FromAddress(node->address()); | 2230 page = Page::FromAddress(node->address()); |
2350 page->add_available_in_small_free_list(-(*node_size)); | 2231 page->add_available_in_small_free_list(-(*node_size)); |
2351 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2232 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2352 return node; | 2233 return node; |
(...skipping 16 matching lines...) Expand all Loading... |
2369 if (node != NULL) { | 2250 if (node != NULL) { |
2370 DCHECK(size_in_bytes <= *node_size); | 2251 DCHECK(size_in_bytes <= *node_size); |
2371 page = Page::FromAddress(node->address()); | 2252 page = Page::FromAddress(node->address()); |
2372 page->add_available_in_large_free_list(-(*node_size)); | 2253 page->add_available_in_large_free_list(-(*node_size)); |
2373 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2254 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2374 return node; | 2255 return node; |
2375 } | 2256 } |
2376 } | 2257 } |
2377 | 2258 |
2378 int huge_list_available = huge_list_.available(); | 2259 int huge_list_available = huge_list_.available(); |
2379 FreeListNode* top_node = huge_list_.top(); | 2260 FreeSpace* top_node = huge_list_.top(); |
2380 for (FreeListNode** cur = &top_node; *cur != NULL; | 2261 for (FreeSpace** cur = &top_node; *cur != NULL; |
2381 cur = (*cur)->next_address()) { | 2262 cur = (*cur)->next_address()) { |
2382 FreeListNode* cur_node = *cur; | 2263 FreeSpace* cur_node = *cur; |
2383 while (cur_node != NULL && | 2264 while (cur_node != NULL && |
2384 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { | 2265 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { |
2385 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size(); | 2266 int size = cur_node->Size(); |
2386 huge_list_available -= size; | 2267 huge_list_available -= size; |
2387 page = Page::FromAddress(cur_node->address()); | 2268 page = Page::FromAddress(cur_node->address()); |
2388 page->add_available_in_huge_free_list(-size); | 2269 page->add_available_in_huge_free_list(-size); |
2389 cur_node = cur_node->next(); | 2270 cur_node = cur_node->next(); |
2390 } | 2271 } |
2391 | 2272 |
2392 *cur = cur_node; | 2273 *cur = cur_node; |
2393 if (cur_node == NULL) { | 2274 if (cur_node == NULL) { |
2394 huge_list_.set_end(NULL); | 2275 huge_list_.set_end(NULL); |
2395 break; | 2276 break; |
2396 } | 2277 } |
2397 | 2278 |
2398 DCHECK((*cur)->map() == heap_->raw_unchecked_free_space_map()); | 2279 int size = cur_node->Size(); |
2399 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); | |
2400 int size = cur_as_free_space->Size(); | |
2401 if (size >= size_in_bytes) { | 2280 if (size >= size_in_bytes) { |
2402 // Large enough node found. Unlink it from the list. | 2281 // Large enough node found. Unlink it from the list. |
2403 node = *cur; | 2282 node = *cur; |
2404 *cur = node->next(); | 2283 *cur = node->next(); |
2405 *node_size = size; | 2284 *node_size = size; |
2406 huge_list_available -= size; | 2285 huge_list_available -= size; |
2407 page = Page::FromAddress(node->address()); | 2286 page = Page::FromAddress(node->address()); |
2408 page->add_available_in_huge_free_list(-size); | 2287 page->add_available_in_huge_free_list(-size); |
2409 break; | 2288 break; |
2410 } | 2289 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2463 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); | 2342 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); |
2464 // Mark the old linear allocation area with a free space map so it can be | 2343 // Mark the old linear allocation area with a free space map so it can be |
2465 // skipped when scanning the heap. This also puts it back in the free list | 2344 // skipped when scanning the heap. This also puts it back in the free list |
2466 // if it is big enough. | 2345 // if it is big enough. |
2467 owner_->Free(owner_->top(), old_linear_size); | 2346 owner_->Free(owner_->top(), old_linear_size); |
2468 | 2347 |
2469 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes - | 2348 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes - |
2470 old_linear_size); | 2349 old_linear_size); |
2471 | 2350 |
2472 int new_node_size = 0; | 2351 int new_node_size = 0; |
2473 FreeListNode* new_node = FindNodeFor(size_in_bytes, &new_node_size); | 2352 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); |
2474 if (new_node == NULL) { | 2353 if (new_node == NULL) { |
2475 owner_->SetTopAndLimit(NULL, NULL); | 2354 owner_->SetTopAndLimit(NULL, NULL); |
2476 return NULL; | 2355 return NULL; |
2477 } | 2356 } |
2478 | 2357 |
2479 int bytes_left = new_node_size - size_in_bytes; | 2358 int bytes_left = new_node_size - size_in_bytes; |
2480 DCHECK(bytes_left >= 0); | 2359 DCHECK(bytes_left >= 0); |
2481 | 2360 |
2482 #ifdef DEBUG | 2361 #ifdef DEBUG |
2483 for (int i = 0; i < size_in_bytes / kPointerSize; i++) { | 2362 for (int i = 0; i < size_in_bytes / kPointerSize; i++) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2557 small_list_.RepairFreeList(heap); | 2436 small_list_.RepairFreeList(heap); |
2558 medium_list_.RepairFreeList(heap); | 2437 medium_list_.RepairFreeList(heap); |
2559 large_list_.RepairFreeList(heap); | 2438 large_list_.RepairFreeList(heap); |
2560 huge_list_.RepairFreeList(heap); | 2439 huge_list_.RepairFreeList(heap); |
2561 } | 2440 } |
2562 | 2441 |
2563 | 2442 |
2564 #ifdef DEBUG | 2443 #ifdef DEBUG |
2565 intptr_t FreeListCategory::SumFreeList() { | 2444 intptr_t FreeListCategory::SumFreeList() { |
2566 intptr_t sum = 0; | 2445 intptr_t sum = 0; |
2567 FreeListNode* cur = top(); | 2446 FreeSpace* cur = top(); |
2568 while (cur != NULL) { | 2447 while (cur != NULL) { |
2569 DCHECK(cur->map() == cur->GetHeap()->raw_unchecked_free_space_map()); | 2448 DCHECK(cur->map() == cur->GetHeap()->raw_unchecked_free_space_map()); |
2570 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur); | 2449 sum += cur->nobarrier_size(); |
2571 sum += cur_as_free_space->nobarrier_size(); | |
2572 cur = cur->next(); | 2450 cur = cur->next(); |
2573 } | 2451 } |
2574 return sum; | 2452 return sum; |
2575 } | 2453 } |
2576 | 2454 |
2577 | 2455 |
2578 static const int kVeryLongFreeList = 500; | 2456 static const int kVeryLongFreeList = 500; |
2579 | 2457 |
2580 | 2458 |
2581 int FreeListCategory::FreeListLength() { | 2459 int FreeListCategory::FreeListLength() { |
2582 int length = 0; | 2460 int length = 0; |
2583 FreeListNode* cur = top(); | 2461 FreeSpace* cur = top(); |
2584 while (cur != NULL) { | 2462 while (cur != NULL) { |
2585 length++; | 2463 length++; |
2586 cur = cur->next(); | 2464 cur = cur->next(); |
2587 if (length == kVeryLongFreeList) return length; | 2465 if (length == kVeryLongFreeList) return length; |
2588 } | 2466 } |
2589 return length; | 2467 return length; |
2590 } | 2468 } |
2591 | 2469 |
2592 | 2470 |
2593 bool FreeList::IsVeryLong() { | 2471 bool FreeList::IsVeryLong() { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2634 heap()->mark_compact_collector()->sweeping_in_progress() || | 2512 heap()->mark_compact_collector()->sweeping_in_progress() || |
2635 (unswept_free_bytes_ == 0)); | 2513 (unswept_free_bytes_ == 0)); |
2636 return Size() - unswept_free_bytes_ - (limit() - top()); | 2514 return Size() - unswept_free_bytes_ - (limit() - top()); |
2637 } | 2515 } |
2638 | 2516 |
2639 | 2517 |
2640 // After we have booted, we have created a map which represents free space | 2518 // After we have booted, we have created a map which represents free space |
2641 // on the heap. If there was already a free list then the elements on it | 2519 // on the heap. If there was already a free list then the elements on it |
2642 // were created with the wrong FreeSpaceMap (normally NULL), so we need to | 2520 // were created with the wrong FreeSpaceMap (normally NULL), so we need to |
2643 // fix them. | 2521 // fix them. |
2644 void PagedSpace::RepairFreeListsAfterBoot() { free_list_.RepairLists(heap()); } | 2522 void PagedSpace::RepairFreeListsAfterDeserialization() { |
| 2523 free_list_.RepairLists(heap()); |
| 2524 // Each page may have a small free space that is not tracked by a free list. |
| 2525 // Update the maps for those free space objects. |
| 2526 PageIterator iterator(this); |
| 2527 while (iterator.has_next()) { |
| 2528 Page* page = iterator.next(); |
| 2529 int size = static_cast<int>(page->non_available_small_blocks()); |
| 2530 if (size == 0) continue; |
| 2531 Address address = page->OffsetToAddress(Page::kPageSize - size); |
| 2532 heap()->CreateFillerObjectAt(address, size); |
| 2533 } |
| 2534 } |
2645 | 2535 |
2646 | 2536 |
2647 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { | 2537 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { |
2648 if (allocation_info_.top() >= allocation_info_.limit()) return; | 2538 if (allocation_info_.top() >= allocation_info_.limit()) return; |
2649 | 2539 |
2650 if (Page::FromAllocationTop(allocation_info_.top()) | 2540 if (Page::FromAllocationTop(allocation_info_.top()) |
2651 ->IsEvacuationCandidate()) { | 2541 ->IsEvacuationCandidate()) { |
2652 // Create filler object to keep page iterable if it was iterable. | 2542 // Create filler object to keep page iterable if it was iterable. |
2653 int remaining = | 2543 int remaining = |
2654 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); | 2544 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3227 object->ShortPrint(); | 3117 object->ShortPrint(); |
3228 PrintF("\n"); | 3118 PrintF("\n"); |
3229 } | 3119 } |
3230 printf(" --------------------------------------\n"); | 3120 printf(" --------------------------------------\n"); |
3231 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3121 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3232 } | 3122 } |
3233 | 3123 |
3234 #endif // DEBUG | 3124 #endif // DEBUG |
3235 } | 3125 } |
3236 } // namespace v8::internal | 3126 } // namespace v8::internal |
OLD | NEW |