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 |
1031 Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this, | 1035 Page* p = heap()->isolate()->memory_allocator()->AllocatePage(size, this, |
1032 executable()); | 1036 executable()); |
1033 if (p == NULL) return false; | 1037 if (p == NULL) return false; |
1034 | 1038 |
1035 DCHECK(Capacity() <= max_capacity_); | 1039 DCHECK(Capacity() <= max_capacity_); |
1036 | 1040 |
1037 p->InsertAfter(anchor_.prev_page()); | 1041 p->InsertAfter(anchor_.prev_page()); |
1038 | 1042 |
1039 return true; | 1043 return true; |
1040 } | 1044 } |
1041 | 1045 |
1042 | 1046 |
| 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 |
1043 int PagedSpace::CountTotalPages() { | 1091 int PagedSpace::CountTotalPages() { |
1044 PageIterator it(this); | 1092 PageIterator it(this); |
1045 int count = 0; | 1093 int count = 0; |
1046 while (it.has_next()) { | 1094 while (it.has_next()) { |
1047 it.next(); | 1095 it.next(); |
1048 count++; | 1096 count++; |
1049 } | 1097 } |
1050 return count; | 1098 return count; |
1051 } | 1099 } |
1052 | 1100 |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2027 if (from_space_.is_committed()) { | 2075 if (from_space_.is_committed()) { |
2028 size += from_space_.CommittedPhysicalMemory(); | 2076 size += from_space_.CommittedPhysicalMemory(); |
2029 } | 2077 } |
2030 return size; | 2078 return size; |
2031 } | 2079 } |
2032 | 2080 |
2033 | 2081 |
2034 // ----------------------------------------------------------------------------- | 2082 // ----------------------------------------------------------------------------- |
2035 // Free lists for old object spaces implementation | 2083 // Free lists for old object spaces implementation |
2036 | 2084 |
| 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 |
2037 intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { | 2158 intptr_t FreeListCategory::Concatenate(FreeListCategory* category) { |
2038 intptr_t free_bytes = 0; | 2159 intptr_t free_bytes = 0; |
2039 if (category->top() != NULL) { | 2160 if (category->top() != NULL) { |
2040 // This is safe (not going to deadlock) since Concatenate operations | 2161 // This is safe (not going to deadlock) since Concatenate operations |
2041 // are never performed on the same free lists at the same time in | 2162 // are never performed on the same free lists at the same time in |
2042 // reverse order. | 2163 // reverse order. |
2043 base::LockGuard<base::Mutex> target_lock_guard(mutex()); | 2164 base::LockGuard<base::Mutex> target_lock_guard(mutex()); |
2044 base::LockGuard<base::Mutex> source_lock_guard(category->mutex()); | 2165 base::LockGuard<base::Mutex> source_lock_guard(category->mutex()); |
2045 DCHECK(category->end_ != NULL); | 2166 DCHECK(category->end_ != NULL); |
2046 free_bytes = category->available(); | 2167 free_bytes = category->available(); |
(...skipping 13 matching lines...) Expand all Loading... |
2060 | 2181 |
2061 void FreeListCategory::Reset() { | 2182 void FreeListCategory::Reset() { |
2062 set_top(NULL); | 2183 set_top(NULL); |
2063 set_end(NULL); | 2184 set_end(NULL); |
2064 set_available(0); | 2185 set_available(0); |
2065 } | 2186 } |
2066 | 2187 |
2067 | 2188 |
2068 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { | 2189 intptr_t FreeListCategory::EvictFreeListItemsInList(Page* p) { |
2069 int sum = 0; | 2190 int sum = 0; |
2070 FreeSpace* t = top(); | 2191 FreeListNode* t = top(); |
2071 FreeSpace** n = &t; | 2192 FreeListNode** n = &t; |
2072 while (*n != NULL) { | 2193 while (*n != NULL) { |
2073 if (Page::FromAddress((*n)->address()) == p) { | 2194 if (Page::FromAddress((*n)->address()) == p) { |
2074 FreeSpace* free_space = *n; | 2195 FreeSpace* free_space = reinterpret_cast<FreeSpace*>(*n); |
2075 sum += free_space->Size(); | 2196 sum += free_space->Size(); |
2076 *n = (*n)->next(); | 2197 *n = (*n)->next(); |
2077 } else { | 2198 } else { |
2078 n = (*n)->next_address(); | 2199 n = (*n)->next_address(); |
2079 } | 2200 } |
2080 } | 2201 } |
2081 set_top(t); | 2202 set_top(t); |
2082 if (top() == NULL) { | 2203 if (top() == NULL) { |
2083 set_end(NULL); | 2204 set_end(NULL); |
2084 } | 2205 } |
2085 available_ -= sum; | 2206 available_ -= sum; |
2086 return sum; | 2207 return sum; |
2087 } | 2208 } |
2088 | 2209 |
2089 | 2210 |
2090 bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) { | 2211 bool FreeListCategory::ContainsPageFreeListItemsInList(Page* p) { |
2091 FreeSpace* node = top(); | 2212 FreeListNode* node = top(); |
2092 while (node != NULL) { | 2213 while (node != NULL) { |
2093 if (Page::FromAddress(node->address()) == p) return true; | 2214 if (Page::FromAddress(node->address()) == p) return true; |
2094 node = node->next(); | 2215 node = node->next(); |
2095 } | 2216 } |
2096 return false; | 2217 return false; |
2097 } | 2218 } |
2098 | 2219 |
2099 | 2220 |
2100 FreeSpace* FreeListCategory::PickNodeFromList(int* node_size) { | 2221 FreeListNode* FreeListCategory::PickNodeFromList(int* node_size) { |
2101 FreeSpace* node = top(); | 2222 FreeListNode* node = top(); |
2102 | 2223 |
2103 if (node == NULL) return NULL; | 2224 if (node == NULL) return NULL; |
2104 | 2225 |
2105 while (node != NULL && | 2226 while (node != NULL && |
2106 Page::FromAddress(node->address())->IsEvacuationCandidate()) { | 2227 Page::FromAddress(node->address())->IsEvacuationCandidate()) { |
2107 available_ -= node->Size(); | 2228 available_ -= reinterpret_cast<FreeSpace*>(node)->Size(); |
2108 node = node->next(); | 2229 node = node->next(); |
2109 } | 2230 } |
2110 | 2231 |
2111 if (node != NULL) { | 2232 if (node != NULL) { |
2112 set_top(node->next()); | 2233 set_top(node->next()); |
2113 *node_size = node->Size(); | 2234 *node_size = reinterpret_cast<FreeSpace*>(node)->Size(); |
2114 available_ -= *node_size; | 2235 available_ -= *node_size; |
2115 } else { | 2236 } else { |
2116 set_top(NULL); | 2237 set_top(NULL); |
2117 } | 2238 } |
2118 | 2239 |
2119 if (top() == NULL) { | 2240 if (top() == NULL) { |
2120 set_end(NULL); | 2241 set_end(NULL); |
2121 } | 2242 } |
2122 | 2243 |
2123 return node; | 2244 return node; |
2124 } | 2245 } |
2125 | 2246 |
2126 | 2247 |
2127 FreeSpace* FreeListCategory::PickNodeFromList(int size_in_bytes, | 2248 FreeListNode* FreeListCategory::PickNodeFromList(int size_in_bytes, |
2128 int* node_size) { | 2249 int* node_size) { |
2129 FreeSpace* node = PickNodeFromList(node_size); | 2250 FreeListNode* node = PickNodeFromList(node_size); |
2130 if (node != NULL && *node_size < size_in_bytes) { | 2251 if (node != NULL && *node_size < size_in_bytes) { |
2131 Free(node, *node_size); | 2252 Free(node, *node_size); |
2132 *node_size = 0; | 2253 *node_size = 0; |
2133 return NULL; | 2254 return NULL; |
2134 } | 2255 } |
2135 return node; | 2256 return node; |
2136 } | 2257 } |
2137 | 2258 |
2138 | 2259 |
2139 void FreeListCategory::Free(FreeSpace* free_space, int size_in_bytes) { | 2260 void FreeListCategory::Free(FreeListNode* node, int size_in_bytes) { |
2140 DCHECK_LE(FreeList::kSmallListMin, size_in_bytes); | 2261 node->set_next(top()); |
2141 free_space->set_next(top()); | 2262 set_top(node); |
2142 set_top(free_space); | |
2143 if (end_ == NULL) { | 2263 if (end_ == NULL) { |
2144 end_ = free_space; | 2264 end_ = node; |
2145 } | 2265 } |
2146 available_ += size_in_bytes; | 2266 available_ += size_in_bytes; |
2147 } | 2267 } |
2148 | 2268 |
2149 | 2269 |
2150 void FreeListCategory::RepairFreeList(Heap* heap) { | 2270 void FreeListCategory::RepairFreeList(Heap* heap) { |
2151 FreeSpace* n = top(); | 2271 FreeListNode* n = top(); |
2152 while (n != NULL) { | 2272 while (n != NULL) { |
2153 Map** map_location = reinterpret_cast<Map**>(n->address()); | 2273 Map** map_location = reinterpret_cast<Map**>(n->address()); |
2154 if (*map_location == NULL) { | 2274 if (*map_location == NULL) { |
2155 *map_location = heap->free_space_map(); | 2275 *map_location = heap->free_space_map(); |
2156 } else { | 2276 } else { |
2157 DCHECK(*map_location == heap->free_space_map()); | 2277 DCHECK(*map_location == heap->free_space_map()); |
2158 } | 2278 } |
2159 n = n->next(); | 2279 n = n->next(); |
2160 } | 2280 } |
2161 } | 2281 } |
(...skipping 18 matching lines...) Expand all Loading... |
2180 small_list_.Reset(); | 2300 small_list_.Reset(); |
2181 medium_list_.Reset(); | 2301 medium_list_.Reset(); |
2182 large_list_.Reset(); | 2302 large_list_.Reset(); |
2183 huge_list_.Reset(); | 2303 huge_list_.Reset(); |
2184 } | 2304 } |
2185 | 2305 |
2186 | 2306 |
2187 int FreeList::Free(Address start, int size_in_bytes) { | 2307 int FreeList::Free(Address start, int size_in_bytes) { |
2188 if (size_in_bytes == 0) return 0; | 2308 if (size_in_bytes == 0) return 0; |
2189 | 2309 |
2190 heap_->CreateFillerObjectAt(start, size_in_bytes); | 2310 FreeListNode* node = FreeListNode::FromAddress(start); |
2191 | 2311 node->set_size(heap_, size_in_bytes); |
2192 Page* page = Page::FromAddress(start); | 2312 Page* page = Page::FromAddress(start); |
2193 | 2313 |
2194 // Early return to drop too-small blocks on the floor. | 2314 // Early return to drop too-small blocks on the floor. |
2195 if (size_in_bytes < kSmallListMin) { | 2315 if (size_in_bytes < kSmallListMin) { |
2196 page->add_non_available_small_blocks(size_in_bytes); | 2316 page->add_non_available_small_blocks(size_in_bytes); |
2197 return size_in_bytes; | 2317 return size_in_bytes; |
2198 } | 2318 } |
2199 | 2319 |
2200 FreeSpace* free_space = FreeSpace::cast(HeapObject::FromAddress(start)); | |
2201 // Insert other blocks at the head of a free list of the appropriate | 2320 // Insert other blocks at the head of a free list of the appropriate |
2202 // magnitude. | 2321 // magnitude. |
2203 if (size_in_bytes <= kSmallListMax) { | 2322 if (size_in_bytes <= kSmallListMax) { |
2204 small_list_.Free(free_space, size_in_bytes); | 2323 small_list_.Free(node, size_in_bytes); |
2205 page->add_available_in_small_free_list(size_in_bytes); | 2324 page->add_available_in_small_free_list(size_in_bytes); |
2206 } else if (size_in_bytes <= kMediumListMax) { | 2325 } else if (size_in_bytes <= kMediumListMax) { |
2207 medium_list_.Free(free_space, size_in_bytes); | 2326 medium_list_.Free(node, size_in_bytes); |
2208 page->add_available_in_medium_free_list(size_in_bytes); | 2327 page->add_available_in_medium_free_list(size_in_bytes); |
2209 } else if (size_in_bytes <= kLargeListMax) { | 2328 } else if (size_in_bytes <= kLargeListMax) { |
2210 large_list_.Free(free_space, size_in_bytes); | 2329 large_list_.Free(node, size_in_bytes); |
2211 page->add_available_in_large_free_list(size_in_bytes); | 2330 page->add_available_in_large_free_list(size_in_bytes); |
2212 } else { | 2331 } else { |
2213 huge_list_.Free(free_space, size_in_bytes); | 2332 huge_list_.Free(node, size_in_bytes); |
2214 page->add_available_in_huge_free_list(size_in_bytes); | 2333 page->add_available_in_huge_free_list(size_in_bytes); |
2215 } | 2334 } |
2216 | 2335 |
2217 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2336 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2218 return 0; | 2337 return 0; |
2219 } | 2338 } |
2220 | 2339 |
2221 | 2340 |
2222 FreeSpace* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { | 2341 FreeListNode* FreeList::FindNodeFor(int size_in_bytes, int* node_size) { |
2223 FreeSpace* node = NULL; | 2342 FreeListNode* node = NULL; |
2224 Page* page = NULL; | 2343 Page* page = NULL; |
2225 | 2344 |
2226 if (size_in_bytes <= kSmallAllocationMax) { | 2345 if (size_in_bytes <= kSmallAllocationMax) { |
2227 node = small_list_.PickNodeFromList(node_size); | 2346 node = small_list_.PickNodeFromList(node_size); |
2228 if (node != NULL) { | 2347 if (node != NULL) { |
2229 DCHECK(size_in_bytes <= *node_size); | 2348 DCHECK(size_in_bytes <= *node_size); |
2230 page = Page::FromAddress(node->address()); | 2349 page = Page::FromAddress(node->address()); |
2231 page->add_available_in_small_free_list(-(*node_size)); | 2350 page->add_available_in_small_free_list(-(*node_size)); |
2232 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2351 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2233 return node; | 2352 return node; |
(...skipping 16 matching lines...) Expand all Loading... |
2250 if (node != NULL) { | 2369 if (node != NULL) { |
2251 DCHECK(size_in_bytes <= *node_size); | 2370 DCHECK(size_in_bytes <= *node_size); |
2252 page = Page::FromAddress(node->address()); | 2371 page = Page::FromAddress(node->address()); |
2253 page->add_available_in_large_free_list(-(*node_size)); | 2372 page->add_available_in_large_free_list(-(*node_size)); |
2254 DCHECK(IsVeryLong() || available() == SumFreeLists()); | 2373 DCHECK(IsVeryLong() || available() == SumFreeLists()); |
2255 return node; | 2374 return node; |
2256 } | 2375 } |
2257 } | 2376 } |
2258 | 2377 |
2259 int huge_list_available = huge_list_.available(); | 2378 int huge_list_available = huge_list_.available(); |
2260 FreeSpace* top_node = huge_list_.top(); | 2379 FreeListNode* top_node = huge_list_.top(); |
2261 for (FreeSpace** cur = &top_node; *cur != NULL; | 2380 for (FreeListNode** cur = &top_node; *cur != NULL; |
2262 cur = (*cur)->next_address()) { | 2381 cur = (*cur)->next_address()) { |
2263 FreeSpace* cur_node = *cur; | 2382 FreeListNode* cur_node = *cur; |
2264 while (cur_node != NULL && | 2383 while (cur_node != NULL && |
2265 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { | 2384 Page::FromAddress(cur_node->address())->IsEvacuationCandidate()) { |
2266 int size = cur_node->Size(); | 2385 int size = reinterpret_cast<FreeSpace*>(cur_node)->Size(); |
2267 huge_list_available -= size; | 2386 huge_list_available -= size; |
2268 page = Page::FromAddress(cur_node->address()); | 2387 page = Page::FromAddress(cur_node->address()); |
2269 page->add_available_in_huge_free_list(-size); | 2388 page->add_available_in_huge_free_list(-size); |
2270 cur_node = cur_node->next(); | 2389 cur_node = cur_node->next(); |
2271 } | 2390 } |
2272 | 2391 |
2273 *cur = cur_node; | 2392 *cur = cur_node; |
2274 if (cur_node == NULL) { | 2393 if (cur_node == NULL) { |
2275 huge_list_.set_end(NULL); | 2394 huge_list_.set_end(NULL); |
2276 break; | 2395 break; |
2277 } | 2396 } |
2278 | 2397 |
2279 int size = cur_node->Size(); | 2398 DCHECK((*cur)->map() == heap_->raw_unchecked_free_space_map()); |
| 2399 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(*cur); |
| 2400 int size = cur_as_free_space->Size(); |
2280 if (size >= size_in_bytes) { | 2401 if (size >= size_in_bytes) { |
2281 // Large enough node found. Unlink it from the list. | 2402 // Large enough node found. Unlink it from the list. |
2282 node = *cur; | 2403 node = *cur; |
2283 *cur = node->next(); | 2404 *cur = node->next(); |
2284 *node_size = size; | 2405 *node_size = size; |
2285 huge_list_available -= size; | 2406 huge_list_available -= size; |
2286 page = Page::FromAddress(node->address()); | 2407 page = Page::FromAddress(node->address()); |
2287 page->add_available_in_huge_free_list(-size); | 2408 page->add_available_in_huge_free_list(-size); |
2288 break; | 2409 break; |
2289 } | 2410 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2342 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); | 2463 int old_linear_size = static_cast<int>(owner_->limit() - owner_->top()); |
2343 // Mark the old linear allocation area with a free space map so it can be | 2464 // Mark the old linear allocation area with a free space map so it can be |
2344 // skipped when scanning the heap. This also puts it back in the free list | 2465 // skipped when scanning the heap. This also puts it back in the free list |
2345 // if it is big enough. | 2466 // if it is big enough. |
2346 owner_->Free(owner_->top(), old_linear_size); | 2467 owner_->Free(owner_->top(), old_linear_size); |
2347 | 2468 |
2348 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes - | 2469 owner_->heap()->incremental_marking()->OldSpaceStep(size_in_bytes - |
2349 old_linear_size); | 2470 old_linear_size); |
2350 | 2471 |
2351 int new_node_size = 0; | 2472 int new_node_size = 0; |
2352 FreeSpace* new_node = FindNodeFor(size_in_bytes, &new_node_size); | 2473 FreeListNode* new_node = FindNodeFor(size_in_bytes, &new_node_size); |
2353 if (new_node == NULL) { | 2474 if (new_node == NULL) { |
2354 owner_->SetTopAndLimit(NULL, NULL); | 2475 owner_->SetTopAndLimit(NULL, NULL); |
2355 return NULL; | 2476 return NULL; |
2356 } | 2477 } |
2357 | 2478 |
2358 int bytes_left = new_node_size - size_in_bytes; | 2479 int bytes_left = new_node_size - size_in_bytes; |
2359 DCHECK(bytes_left >= 0); | 2480 DCHECK(bytes_left >= 0); |
2360 | 2481 |
2361 #ifdef DEBUG | 2482 #ifdef DEBUG |
2362 for (int i = 0; i < size_in_bytes / kPointerSize; i++) { | 2483 for (int i = 0; i < size_in_bytes / kPointerSize; i++) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2436 small_list_.RepairFreeList(heap); | 2557 small_list_.RepairFreeList(heap); |
2437 medium_list_.RepairFreeList(heap); | 2558 medium_list_.RepairFreeList(heap); |
2438 large_list_.RepairFreeList(heap); | 2559 large_list_.RepairFreeList(heap); |
2439 huge_list_.RepairFreeList(heap); | 2560 huge_list_.RepairFreeList(heap); |
2440 } | 2561 } |
2441 | 2562 |
2442 | 2563 |
2443 #ifdef DEBUG | 2564 #ifdef DEBUG |
2444 intptr_t FreeListCategory::SumFreeList() { | 2565 intptr_t FreeListCategory::SumFreeList() { |
2445 intptr_t sum = 0; | 2566 intptr_t sum = 0; |
2446 FreeSpace* cur = top(); | 2567 FreeListNode* cur = top(); |
2447 while (cur != NULL) { | 2568 while (cur != NULL) { |
2448 DCHECK(cur->map() == cur->GetHeap()->raw_unchecked_free_space_map()); | 2569 DCHECK(cur->map() == cur->GetHeap()->raw_unchecked_free_space_map()); |
2449 sum += cur->nobarrier_size(); | 2570 FreeSpace* cur_as_free_space = reinterpret_cast<FreeSpace*>(cur); |
| 2571 sum += cur_as_free_space->nobarrier_size(); |
2450 cur = cur->next(); | 2572 cur = cur->next(); |
2451 } | 2573 } |
2452 return sum; | 2574 return sum; |
2453 } | 2575 } |
2454 | 2576 |
2455 | 2577 |
2456 static const int kVeryLongFreeList = 500; | 2578 static const int kVeryLongFreeList = 500; |
2457 | 2579 |
2458 | 2580 |
2459 int FreeListCategory::FreeListLength() { | 2581 int FreeListCategory::FreeListLength() { |
2460 int length = 0; | 2582 int length = 0; |
2461 FreeSpace* cur = top(); | 2583 FreeListNode* cur = top(); |
2462 while (cur != NULL) { | 2584 while (cur != NULL) { |
2463 length++; | 2585 length++; |
2464 cur = cur->next(); | 2586 cur = cur->next(); |
2465 if (length == kVeryLongFreeList) return length; | 2587 if (length == kVeryLongFreeList) return length; |
2466 } | 2588 } |
2467 return length; | 2589 return length; |
2468 } | 2590 } |
2469 | 2591 |
2470 | 2592 |
2471 bool FreeList::IsVeryLong() { | 2593 bool FreeList::IsVeryLong() { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2512 heap()->mark_compact_collector()->sweeping_in_progress() || | 2634 heap()->mark_compact_collector()->sweeping_in_progress() || |
2513 (unswept_free_bytes_ == 0)); | 2635 (unswept_free_bytes_ == 0)); |
2514 return Size() - unswept_free_bytes_ - (limit() - top()); | 2636 return Size() - unswept_free_bytes_ - (limit() - top()); |
2515 } | 2637 } |
2516 | 2638 |
2517 | 2639 |
2518 // After we have booted, we have created a map which represents free space | 2640 // After we have booted, we have created a map which represents free space |
2519 // on the heap. If there was already a free list then the elements on it | 2641 // on the heap. If there was already a free list then the elements on it |
2520 // were created with the wrong FreeSpaceMap (normally NULL), so we need to | 2642 // were created with the wrong FreeSpaceMap (normally NULL), so we need to |
2521 // fix them. | 2643 // fix them. |
2522 void PagedSpace::RepairFreeListsAfterDeserialization() { | 2644 void PagedSpace::RepairFreeListsAfterBoot() { free_list_.RepairLists(heap()); } |
2523 free_list_.RepairLists(heap()); | |
2524 } | |
2525 | 2645 |
2526 | 2646 |
2527 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { | 2647 void PagedSpace::EvictEvacuationCandidatesFromFreeLists() { |
2528 if (allocation_info_.top() >= allocation_info_.limit()) return; | 2648 if (allocation_info_.top() >= allocation_info_.limit()) return; |
2529 | 2649 |
2530 if (Page::FromAllocationTop(allocation_info_.top()) | 2650 if (Page::FromAllocationTop(allocation_info_.top()) |
2531 ->IsEvacuationCandidate()) { | 2651 ->IsEvacuationCandidate()) { |
2532 // Create filler object to keep page iterable if it was iterable. | 2652 // Create filler object to keep page iterable if it was iterable. |
2533 int remaining = | 2653 int remaining = |
2534 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); | 2654 static_cast<int>(allocation_info_.limit() - allocation_info_.top()); |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3107 object->ShortPrint(); | 3227 object->ShortPrint(); |
3108 PrintF("\n"); | 3228 PrintF("\n"); |
3109 } | 3229 } |
3110 printf(" --------------------------------------\n"); | 3230 printf(" --------------------------------------\n"); |
3111 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3231 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
3112 } | 3232 } |
3113 | 3233 |
3114 #endif // DEBUG | 3234 #endif // DEBUG |
3115 } | 3235 } |
3116 } // namespace v8::internal | 3236 } // namespace v8::internal |
OLD | NEW |