Chromium Code Reviews| 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 #ifndef V8_HEAP_SPACES_H_ | 5 #ifndef V8_HEAP_SPACES_H_ |
| 6 #define V8_HEAP_SPACES_H_ | 6 #define V8_HEAP_SPACES_H_ |
| 7 | 7 |
| 8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
| 9 #include "src/atomic-utils.h" | 9 #include "src/atomic-utils.h" |
| 10 #include "src/base/atomicops.h" | 10 #include "src/base/atomicops.h" |
| 11 #include "src/base/bits.h" | 11 #include "src/base/bits.h" |
| 12 #include "src/base/platform/mutex.h" | 12 #include "src/base/platform/mutex.h" |
| 13 #include "src/flags.h" | 13 #include "src/flags.h" |
| 14 #include "src/hashmap.h" | 14 #include "src/hashmap.h" |
| 15 #include "src/list.h" | 15 #include "src/list.h" |
| 16 #include "src/objects.h" | 16 #include "src/objects.h" |
| 17 #include "src/utils.h" | 17 #include "src/utils.h" |
| 18 | 18 |
| 19 namespace v8 { | 19 namespace v8 { |
| 20 namespace internal { | 20 namespace internal { |
| 21 | 21 |
| 22 class AllocationInfo; | 22 class AllocationInfo; |
| 23 class AllocationObserver; | 23 class AllocationObserver; |
| 24 class CompactionSpace; | 24 class CompactionSpace; |
| 25 class CompactionSpaceCollection; | 25 class CompactionSpaceCollection; |
| 26 class FreeList; | 26 class FreeList; |
| 27 class Isolate; | 27 class Isolate; |
| 28 class MemoryAllocator; | 28 class MemoryAllocator; |
| 29 class MemoryChunk; | 29 class MemoryChunk; |
| 30 class NewSpacePage; | |
| 30 class Page; | 31 class Page; |
| 31 class PagedSpace; | 32 class PagedSpace; |
| 32 class SemiSpace; | 33 class SemiSpace; |
| 33 class SkipList; | 34 class SkipList; |
| 34 class SlotsBuffer; | 35 class SlotsBuffer; |
| 35 class SlotSet; | 36 class SlotSet; |
| 36 class TypedSlotSet; | 37 class TypedSlotSet; |
| 37 class Space; | 38 class Space; |
| 38 | 39 |
| 39 // ----------------------------------------------------------------------------- | 40 // ----------------------------------------------------------------------------- |
| (...skipping 1199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1239 | 1240 |
| 1240 // ---------------------------------------------------------------------------- | 1241 // ---------------------------------------------------------------------------- |
| 1241 // A space acquires chunks of memory from the operating system. The memory | 1242 // A space acquires chunks of memory from the operating system. The memory |
| 1242 // allocator allocated and deallocates pages for the paged heap spaces and large | 1243 // allocator allocated and deallocates pages for the paged heap spaces and large |
| 1243 // pages for large object space. | 1244 // pages for large object space. |
| 1244 // | 1245 // |
| 1245 // Each space has to manage it's own pages. | 1246 // Each space has to manage it's own pages. |
| 1246 // | 1247 // |
| 1247 class MemoryAllocator { | 1248 class MemoryAllocator { |
| 1248 public: | 1249 public: |
| 1250 enum AllocationMode { | |
| 1251 kRegular, | |
| 1252 kPooled, | |
| 1253 }; | |
| 1254 | |
| 1249 explicit MemoryAllocator(Isolate* isolate); | 1255 explicit MemoryAllocator(Isolate* isolate); |
| 1250 | 1256 |
| 1251 // Initializes its internal bookkeeping structures. | 1257 // Initializes its internal bookkeeping structures. |
| 1252 // Max capacity of the total space and executable memory limit. | 1258 // Max capacity of the total space and executable memory limit. |
| 1253 bool SetUp(intptr_t max_capacity, intptr_t capacity_executable); | 1259 bool SetUp(intptr_t max_capacity, intptr_t capacity_executable); |
| 1254 | 1260 |
| 1255 void TearDown(); | 1261 void TearDown(); |
| 1256 | 1262 |
| 1257 Page* AllocatePage(intptr_t size, PagedSpace* owner, | 1263 // Allocates either Page or NewSpacePage from the allocator. AllocationMode |
| 1258 Executability executable); | 1264 // is used to indicate whether pooled allocation, which only works for |
| 1265 // MemoryChunk::kPageSize, should be tried first. | |
| 1266 template <typename PageType, MemoryAllocator::AllocationMode mode = kRegular, | |
| 1267 typename SpaceType> | |
| 1268 inline PageType* AllocatePage(intptr_t size, SpaceType* owner, | |
|
Michael Lippautz
2016/04/05 07:57:42
In another CL I would then also merge AllocateLarg
| |
| 1269 Executability executable); | |
| 1259 | 1270 |
| 1260 LargePage* AllocateLargePage(intptr_t object_size, Space* owner, | 1271 LargePage* AllocateLargePage(intptr_t object_size, Space* owner, |
| 1261 Executability executable); | 1272 Executability executable); |
| 1262 | 1273 |
| 1263 // PreFree logically frees the object, i.e., it takes care of the size | 1274 // PreFree logically frees the object, i.e., it takes care of the size |
| 1264 // bookkeeping and calls the allocation callback. | 1275 // bookkeeping and calls the allocation callback. |
| 1265 void PreFreeMemory(MemoryChunk* chunk); | 1276 void PreFreeMemory(MemoryChunk* chunk); |
| 1266 | 1277 |
| 1267 // FreeMemory can be called concurrently when PreFree was executed before. | 1278 // FreeMemory can be called concurrently when PreFree was executed before. |
| 1268 void PerformFreeMemory(MemoryChunk* chunk); | 1279 void PerformFreeMemory(MemoryChunk* chunk); |
| 1269 | 1280 |
| 1270 // Free is a wrapper method, which calls PreFree and PerformFreeMemory | 1281 // Free is a wrapper method, which calls PreFree and PerformFreeMemory |
| 1271 // together. | 1282 // together. |
| 1272 void Free(MemoryChunk* chunk); | 1283 void Free(MemoryChunk* chunk); |
| 1273 | 1284 |
| 1285 // Free that chunk into the pool. | |
| 1286 void FreePooled(MemoryChunk* chunk); | |
| 1287 | |
| 1274 // Returns allocated spaces in bytes. | 1288 // Returns allocated spaces in bytes. |
| 1275 intptr_t Size() { return size_.Value(); } | 1289 intptr_t Size() { return size_.Value(); } |
| 1276 | 1290 |
| 1277 // Returns allocated executable spaces in bytes. | 1291 // Returns allocated executable spaces in bytes. |
| 1278 intptr_t SizeExecutable() { return size_executable_.Value(); } | 1292 intptr_t SizeExecutable() { return size_executable_.Value(); } |
| 1279 | 1293 |
| 1280 // Returns the maximum available bytes of heaps. | 1294 // Returns the maximum available bytes of heaps. |
| 1281 intptr_t Available() { | 1295 intptr_t Available() { |
| 1282 intptr_t size = Size(); | 1296 intptr_t size = Size(); |
| 1283 return capacity_ < size ? 0 : capacity_ - size; | 1297 return capacity_ < size ? 0 : capacity_ - size; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1315 Executability executable, Space* space); | 1329 Executability executable, Space* space); |
| 1316 | 1330 |
| 1317 Address ReserveAlignedMemory(size_t requested, size_t alignment, | 1331 Address ReserveAlignedMemory(size_t requested, size_t alignment, |
| 1318 base::VirtualMemory* controller); | 1332 base::VirtualMemory* controller); |
| 1319 Address AllocateAlignedMemory(size_t reserve_size, size_t commit_size, | 1333 Address AllocateAlignedMemory(size_t reserve_size, size_t commit_size, |
| 1320 size_t alignment, Executability executable, | 1334 size_t alignment, Executability executable, |
| 1321 base::VirtualMemory* controller); | 1335 base::VirtualMemory* controller); |
| 1322 | 1336 |
| 1323 bool CommitMemory(Address addr, size_t size, Executability executable); | 1337 bool CommitMemory(Address addr, size_t size, Executability executable); |
| 1324 | 1338 |
| 1325 void FreeNewSpaceMemory(Address addr, base::VirtualMemory* reservation, | |
| 1326 Executability executable); | |
| 1327 void FreeMemory(base::VirtualMemory* reservation, Executability executable); | 1339 void FreeMemory(base::VirtualMemory* reservation, Executability executable); |
| 1328 void FreeMemory(Address addr, size_t size, Executability executable); | 1340 void FreeMemory(Address addr, size_t size, Executability executable); |
| 1329 | 1341 |
| 1330 // Commit a contiguous block of memory from the initial chunk. Assumes that | 1342 // Commit a contiguous block of memory from the initial chunk. Assumes that |
| 1331 // the address is not NULL, the size is greater than zero, and that the | 1343 // the address is not NULL, the size is greater than zero, and that the |
| 1332 // block is contained in the initial chunk. Returns true if it succeeded | 1344 // block is contained in the initial chunk. Returns true if it succeeded |
| 1333 // and false otherwise. | 1345 // and false otherwise. |
| 1334 bool CommitBlock(Address start, size_t size, Executability executable); | 1346 bool CommitBlock(Address start, size_t size, Executability executable); |
| 1335 | 1347 |
| 1336 // Uncommit a contiguous block of memory [start..(start+size)[. | 1348 // Uncommit a contiguous block of memory [start..(start+size)[. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1369 DCHECK_NE(LO_SPACE, space); | 1381 DCHECK_NE(LO_SPACE, space); |
| 1370 return (space == CODE_SPACE) ? CodePageAreaSize() | 1382 return (space == CODE_SPACE) ? CodePageAreaSize() |
| 1371 : Page::kAllocatableMemory; | 1383 : Page::kAllocatableMemory; |
| 1372 } | 1384 } |
| 1373 | 1385 |
| 1374 MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm, | 1386 MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm, |
| 1375 Address start, size_t commit_size, | 1387 Address start, size_t commit_size, |
| 1376 size_t reserved_size); | 1388 size_t reserved_size); |
| 1377 | 1389 |
| 1378 private: | 1390 private: |
| 1391 // See AllocatePage for public interface. | |
| 1392 template <typename SpaceType> | |
| 1393 MemoryChunk* AllocatePagePooled(SpaceType* owner, Executability executable); | |
| 1394 | |
| 1379 Isolate* isolate_; | 1395 Isolate* isolate_; |
| 1380 | 1396 |
| 1381 // Maximum space size in bytes. | 1397 // Maximum space size in bytes. |
| 1382 intptr_t capacity_; | 1398 intptr_t capacity_; |
| 1383 // Maximum subset of capacity_ that can be executable | 1399 // Maximum subset of capacity_ that can be executable |
| 1384 intptr_t capacity_executable_; | 1400 intptr_t capacity_executable_; |
| 1385 | 1401 |
| 1386 // Allocated space size in bytes. | 1402 // Allocated space size in bytes. |
| 1387 AtomicNumber<intptr_t> size_; | 1403 AtomicNumber<intptr_t> size_; |
| 1388 // Allocated executable space size in bytes. | 1404 // Allocated executable space size in bytes. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1422 // values only if they did not change in between. | 1438 // values only if they did not change in between. |
| 1423 void* ptr = nullptr; | 1439 void* ptr = nullptr; |
| 1424 do { | 1440 do { |
| 1425 ptr = lowest_ever_allocated_.Value(); | 1441 ptr = lowest_ever_allocated_.Value(); |
| 1426 } while ((low < ptr) && !lowest_ever_allocated_.TrySetValue(ptr, low)); | 1442 } while ((low < ptr) && !lowest_ever_allocated_.TrySetValue(ptr, low)); |
| 1427 do { | 1443 do { |
| 1428 ptr = highest_ever_allocated_.Value(); | 1444 ptr = highest_ever_allocated_.Value(); |
| 1429 } while ((high > ptr) && !highest_ever_allocated_.TrySetValue(ptr, high)); | 1445 } while ((high > ptr) && !highest_ever_allocated_.TrySetValue(ptr, high)); |
| 1430 } | 1446 } |
| 1431 | 1447 |
| 1448 List<MemoryChunk*> chunk_pool_; | |
| 1449 | |
| 1432 DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator); | 1450 DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator); |
| 1433 }; | 1451 }; |
| 1434 | 1452 |
| 1435 | 1453 |
| 1436 // ----------------------------------------------------------------------------- | 1454 // ----------------------------------------------------------------------------- |
| 1437 // Interface for heap object iterator to be implemented by all object space | 1455 // Interface for heap object iterator to be implemented by all object space |
| 1438 // object iterators. | 1456 // object iterators. |
| 1439 // | 1457 // |
| 1440 // NOTE: The space specific object iterators also implements the own next() | 1458 // NOTE: The space specific object iterators also implements the own next() |
| 1441 // method which is used to avoid using virtual functions | 1459 // method which is used to avoid using virtual functions |
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2262 private: | 2280 private: |
| 2263 const char* name_; | 2281 const char* name_; |
| 2264 }; | 2282 }; |
| 2265 | 2283 |
| 2266 | 2284 |
| 2267 enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 }; | 2285 enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 }; |
| 2268 | 2286 |
| 2269 | 2287 |
| 2270 class NewSpacePage : public MemoryChunk { | 2288 class NewSpacePage : public MemoryChunk { |
| 2271 public: | 2289 public: |
| 2290 static inline NewSpacePage* Initialize(Heap* heap, MemoryChunk* chunk, | |
| 2291 Executability executable, | |
| 2292 SemiSpace* owner); | |
| 2293 | |
| 2272 static bool IsAtStart(Address addr) { | 2294 static bool IsAtStart(Address addr) { |
| 2273 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == | 2295 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == |
| 2274 kObjectStartOffset; | 2296 kObjectStartOffset; |
| 2275 } | 2297 } |
| 2276 | 2298 |
| 2277 static bool IsAtEnd(Address addr) { | 2299 static bool IsAtEnd(Address addr) { |
| 2278 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == 0; | 2300 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == 0; |
| 2279 } | 2301 } |
| 2280 | 2302 |
| 2281 // Finds the NewSpacePage containing the given address. | 2303 // Finds the NewSpacePage containing the given address. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2319 // GC related flags copied from from-space to to-space when | 2341 // GC related flags copied from from-space to to-space when |
| 2320 // flipping semispaces. | 2342 // flipping semispaces. |
| 2321 static const intptr_t kCopyOnFlipFlagsMask = | 2343 static const intptr_t kCopyOnFlipFlagsMask = |
| 2322 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | 2344 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | |
| 2323 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); | 2345 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); |
| 2324 | 2346 |
| 2325 // Create a NewSpacePage object that is only used as anchor | 2347 // Create a NewSpacePage object that is only used as anchor |
| 2326 // for the doubly-linked list of real pages. | 2348 // for the doubly-linked list of real pages. |
| 2327 explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); } | 2349 explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); } |
| 2328 | 2350 |
| 2329 static NewSpacePage* Initialize(Heap* heap, Address start, | |
| 2330 SemiSpace* semi_space); | |
| 2331 | |
| 2332 // Intialize a fake NewSpacePage used as sentinel at the ends | 2351 // Intialize a fake NewSpacePage used as sentinel at the ends |
| 2333 // of a doubly-linked list of real NewSpacePages. | 2352 // of a doubly-linked list of real NewSpacePages. |
| 2334 // Only uses the prev/next links, and sets flags to not be in new-space. | 2353 // Only uses the prev/next links, and sets flags to not be in new-space. |
| 2335 void InitializeAsAnchor(SemiSpace* owner); | 2354 void InitializeAsAnchor(SemiSpace* owner); |
| 2336 | 2355 |
| 2337 friend class SemiSpace; | 2356 friend class SemiSpace; |
| 2338 friend class SemiSpaceIterator; | 2357 friend class SemiSpaceIterator; |
| 2339 }; | 2358 }; |
| 2340 | 2359 |
| 2341 | 2360 |
| 2342 // ----------------------------------------------------------------------------- | 2361 // ----------------------------------------------------------------------------- |
| 2343 // SemiSpace in young generation | 2362 // SemiSpace in young generation |
| 2344 // | 2363 // |
| 2345 // A SemiSpace is a contiguous chunk of memory holding page-like memory chunks. | 2364 // A SemiSpace is a contiguous chunk of memory holding page-like memory chunks. |
| 2346 // The mark-compact collector uses the memory of the first page in the from | 2365 // The mark-compact collector uses the memory of the first page in the from |
| 2347 // space as a marking stack when tracing live objects. | 2366 // space as a marking stack when tracing live objects. |
| 2348 class SemiSpace : public Space { | 2367 class SemiSpace : public Space { |
| 2349 public: | 2368 public: |
| 2350 static void Swap(SemiSpace* from, SemiSpace* to); | 2369 static void Swap(SemiSpace* from, SemiSpace* to); |
| 2351 | 2370 |
| 2352 SemiSpace(Heap* heap, SemiSpaceId semispace) | 2371 SemiSpace(Heap* heap, SemiSpaceId semispace) |
| 2353 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), | 2372 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), |
| 2354 current_capacity_(0), | 2373 current_capacity_(0), |
| 2355 maximum_capacity_(0), | 2374 maximum_capacity_(0), |
| 2356 minimum_capacity_(0), | 2375 minimum_capacity_(0), |
| 2357 start_(nullptr), | |
| 2358 age_mark_(nullptr), | 2376 age_mark_(nullptr), |
| 2359 committed_(false), | 2377 committed_(false), |
| 2360 id_(semispace), | 2378 id_(semispace), |
| 2361 anchor_(this), | 2379 anchor_(this), |
| 2362 current_page_(nullptr) {} | 2380 current_page_(nullptr) {} |
| 2363 | 2381 |
| 2364 inline bool Contains(HeapObject* o); | 2382 inline bool Contains(HeapObject* o); |
| 2365 inline bool Contains(Object* o); | 2383 inline bool Contains(Object* o); |
| 2366 inline bool ContainsSlow(Address a); | 2384 inline bool ContainsSlow(Address a); |
| 2367 | 2385 |
| 2368 // Creates a space in the young generation. The constructor does not | 2386 void SetUp(int initial_capacity, int maximum_capacity); |
| 2369 // allocate memory from the OS. | 2387 void TearDown(); |
| 2370 void SetUp(Address start, int initial_capacity, int maximum_capacity); | 2388 bool HasBeenSetUp() { return maximum_capacity_ != 0; } |
| 2371 | 2389 |
| 2372 // Tear down the space. Heap memory was not allocated by the space, so it | 2390 bool Commit(); |
| 2373 // is not deallocated here. | 2391 bool Uncommit(); |
| 2374 void TearDown(); | 2392 bool is_committed() { return committed_; } |
| 2375 | 2393 |
| 2376 // True if the space has been set up but not torn down. | 2394 // Grow the semispace to the new capacity. The new capacity requested must |
| 2377 bool HasBeenSetUp() { return start_ != nullptr; } | 2395 // be larger than the current capacity and less than the maximum capacity. |
| 2378 | |
| 2379 // Grow the semispace to the new capacity. The new capacity | |
| 2380 // requested must be larger than the current capacity and less than | |
| 2381 // the maximum capacity. | |
| 2382 bool GrowTo(int new_capacity); | 2396 bool GrowTo(int new_capacity); |
| 2383 | 2397 |
| 2384 // Shrinks the semispace to the new capacity. The new capacity | 2398 // Shrinks the semispace to the new capacity. The new capacity requested |
| 2385 // requested must be more than the amount of used memory in the | 2399 // must be more than the amount of used memory in the semispace and less |
| 2386 // semispace and less than the current capacity. | 2400 // than the current capacity. |
| 2387 bool ShrinkTo(int new_capacity); | 2401 bool ShrinkTo(int new_capacity); |
| 2388 | 2402 |
| 2389 // Returns the start address of the first page of the space. | 2403 // Returns the start address of the first page of the space. |
| 2390 Address space_start() { | 2404 Address space_start() { |
| 2391 DCHECK_NE(anchor_.next_page(), &anchor_); | 2405 DCHECK_NE(anchor_.next_page(), anchor()); |
| 2392 return anchor_.next_page()->area_start(); | 2406 return anchor_.next_page()->area_start(); |
| 2393 } | 2407 } |
| 2394 | 2408 |
| 2409 NewSpacePage* first_page() { return anchor_.next_page(); } | |
| 2410 NewSpacePage* current_page() { return current_page_; } | |
| 2411 | |
| 2412 // Returns one past the end address of the space. | |
| 2413 Address space_end() { return anchor_.prev_page()->area_end(); } | |
| 2414 | |
| 2395 // Returns the start address of the current page of the space. | 2415 // Returns the start address of the current page of the space. |
| 2396 Address page_low() { return current_page_->area_start(); } | 2416 Address page_low() { return current_page_->area_start(); } |
| 2397 | 2417 |
| 2398 // Returns one past the end address of the space. | |
| 2399 Address space_end() { return anchor_.prev_page()->area_end(); } | |
| 2400 | |
| 2401 // Returns one past the end address of the current page of the space. | 2418 // Returns one past the end address of the current page of the space. |
| 2402 Address page_high() { return current_page_->area_end(); } | 2419 Address page_high() { return current_page_->area_end(); } |
| 2403 | 2420 |
| 2404 bool AdvancePage() { | 2421 bool AdvancePage() { |
| 2405 NewSpacePage* next_page = current_page_->next_page(); | 2422 NewSpacePage* next_page = current_page_->next_page(); |
| 2406 if (next_page == anchor()) return false; | 2423 if (next_page == anchor()) return false; |
| 2407 current_page_ = next_page; | 2424 current_page_ = next_page; |
| 2408 return true; | 2425 return true; |
| 2409 } | 2426 } |
| 2410 | 2427 |
| 2411 // Resets the space to using the first page. | 2428 // Resets the space to using the first page. |
| 2412 void Reset(); | 2429 void Reset(); |
| 2413 | 2430 |
| 2414 // Age mark accessors. | 2431 // Age mark accessors. |
| 2415 Address age_mark() { return age_mark_; } | 2432 Address age_mark() { return age_mark_; } |
| 2416 void set_age_mark(Address mark); | 2433 void set_age_mark(Address mark); |
| 2417 | 2434 |
| 2418 bool is_committed() { return committed_; } | 2435 // Returns the current capacity of the semispace. |
| 2419 bool Commit(); | |
| 2420 bool Uncommit(); | |
| 2421 | |
| 2422 NewSpacePage* first_page() { return anchor_.next_page(); } | |
| 2423 NewSpacePage* current_page() { return current_page_; } | |
| 2424 | |
| 2425 // Returns the current total capacity of the semispace. | |
| 2426 int current_capacity() { return current_capacity_; } | 2436 int current_capacity() { return current_capacity_; } |
| 2427 | 2437 |
| 2428 // Returns the maximum total capacity of the semispace. | 2438 // Returns the maximum capacity of the semispace. |
| 2429 int maximum_capacity() { return maximum_capacity_; } | 2439 int maximum_capacity() { return maximum_capacity_; } |
| 2430 | 2440 |
| 2431 // Returns the initial capacity of the semispace. | 2441 // Returns the initial capacity of the semispace. |
| 2432 int minimum_capacity() { return minimum_capacity_; } | 2442 int minimum_capacity() { return minimum_capacity_; } |
| 2433 | 2443 |
| 2434 SemiSpaceId id() { return id_; } | 2444 SemiSpaceId id() { return id_; } |
| 2435 | 2445 |
| 2436 // Approximate amount of physical memory committed for this space. | 2446 // Approximate amount of physical memory committed for this space. |
| 2437 size_t CommittedPhysicalMemory() override; | 2447 size_t CommittedPhysicalMemory() override; |
| 2438 | 2448 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2460 #else | 2470 #else |
| 2461 // Do nothing. | 2471 // Do nothing. |
| 2462 inline static void AssertValidRange(Address from, Address to) {} | 2472 inline static void AssertValidRange(Address from, Address to) {} |
| 2463 #endif | 2473 #endif |
| 2464 | 2474 |
| 2465 #ifdef VERIFY_HEAP | 2475 #ifdef VERIFY_HEAP |
| 2466 virtual void Verify(); | 2476 virtual void Verify(); |
| 2467 #endif | 2477 #endif |
| 2468 | 2478 |
| 2469 private: | 2479 private: |
| 2470 NewSpacePage* anchor() { return &anchor_; } | 2480 inline NewSpacePage* anchor() { return &anchor_; } |
| 2471 | |
| 2472 void set_current_capacity(int new_capacity) { | |
| 2473 current_capacity_ = new_capacity; | |
| 2474 } | |
| 2475 | 2481 |
| 2476 // Copies the flags into the masked positions on all pages in the space. | 2482 // Copies the flags into the masked positions on all pages in the space. |
| 2477 void FixPagesFlags(intptr_t flags, intptr_t flag_mask); | 2483 void FixPagesFlags(intptr_t flags, intptr_t flag_mask); |
| 2478 | 2484 |
| 2479 // The currently committed space capacity. | 2485 // The currently committed space capacity. |
| 2480 int current_capacity_; | 2486 int current_capacity_; |
| 2481 | 2487 |
| 2482 // The maximum capacity that can be used by this space. | 2488 // The maximum capacity that can be used by this space. |
| 2483 int maximum_capacity_; | 2489 int maximum_capacity_; |
| 2484 | 2490 |
| 2485 // The mimnimum capacity for the space. A space cannot shrink below this size. | 2491 // The minimum capacity for the space. A space cannot shrink below this size. |
| 2486 int minimum_capacity_; | 2492 int minimum_capacity_; |
| 2487 | 2493 |
| 2488 // The start address of the space. | |
| 2489 Address start_; | |
| 2490 // Used to govern object promotion during mark-compact collection. | 2494 // Used to govern object promotion during mark-compact collection. |
| 2491 Address age_mark_; | 2495 Address age_mark_; |
| 2492 | 2496 |
| 2493 bool committed_; | 2497 bool committed_; |
| 2494 SemiSpaceId id_; | 2498 SemiSpaceId id_; |
| 2495 | 2499 |
| 2496 NewSpacePage anchor_; | 2500 NewSpacePage anchor_; |
| 2497 NewSpacePage* current_page_; | 2501 NewSpacePage* current_page_; |
| 2498 | 2502 |
| 2499 friend class SemiSpaceIterator; | 2503 friend class SemiSpaceIterator; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2555 | 2559 |
| 2556 | 2560 |
| 2557 // ----------------------------------------------------------------------------- | 2561 // ----------------------------------------------------------------------------- |
| 2558 // The young generation space. | 2562 // The young generation space. |
| 2559 // | 2563 // |
| 2560 // The new space consists of a contiguous pair of semispaces. It simply | 2564 // The new space consists of a contiguous pair of semispaces. It simply |
| 2561 // forwards most functions to the appropriate semispace. | 2565 // forwards most functions to the appropriate semispace. |
| 2562 | 2566 |
| 2563 class NewSpace : public Space { | 2567 class NewSpace : public Space { |
| 2564 public: | 2568 public: |
| 2565 // Constructor. | |
| 2566 explicit NewSpace(Heap* heap) | 2569 explicit NewSpace(Heap* heap) |
| 2567 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), | 2570 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), |
| 2568 to_space_(heap, kToSpace), | 2571 to_space_(heap, kToSpace), |
| 2569 from_space_(heap, kFromSpace), | 2572 from_space_(heap, kFromSpace), |
| 2570 reservation_(), | 2573 reservation_(), |
| 2571 top_on_previous_step_(0) {} | 2574 pages_used_(0), |
| 2575 top_on_previous_step_(0), | |
| 2576 allocated_histogram_(nullptr), | |
| 2577 promoted_histogram_(nullptr) {} | |
| 2572 | 2578 |
| 2573 inline bool Contains(HeapObject* o); | 2579 inline bool Contains(HeapObject* o); |
| 2574 inline bool ContainsSlow(Address a); | 2580 inline bool ContainsSlow(Address a); |
| 2575 inline bool Contains(Object* o); | 2581 inline bool Contains(Object* o); |
| 2576 | 2582 |
| 2577 // Sets up the new space using the given chunk. | 2583 bool SetUp(int initial_semispace_capacity, int max_semispace_capacity); |
| 2578 bool SetUp(int reserved_semispace_size_, int max_semi_space_size); | |
| 2579 | 2584 |
| 2580 // Tears down the space. Heap memory was not allocated by the space, so it | 2585 // Tears down the space. Heap memory was not allocated by the space, so it |
| 2581 // is not deallocated here. | 2586 // is not deallocated here. |
| 2582 void TearDown(); | 2587 void TearDown(); |
| 2583 | 2588 |
| 2584 // True if the space has been set up but not torn down. | 2589 // True if the space has been set up but not torn down. |
| 2585 bool HasBeenSetUp() { | 2590 bool HasBeenSetUp() { |
| 2586 return to_space_.HasBeenSetUp() && from_space_.HasBeenSetUp(); | 2591 return to_space_.HasBeenSetUp() && from_space_.HasBeenSetUp(); |
| 2587 } | 2592 } |
| 2588 | 2593 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2631 return from_space_.MaximumCommittedMemory() + | 2636 return from_space_.MaximumCommittedMemory() + |
| 2632 to_space_.MaximumCommittedMemory(); | 2637 to_space_.MaximumCommittedMemory(); |
| 2633 } | 2638 } |
| 2634 | 2639 |
| 2635 // Approximate amount of physical memory committed for this space. | 2640 // Approximate amount of physical memory committed for this space. |
| 2636 size_t CommittedPhysicalMemory() override; | 2641 size_t CommittedPhysicalMemory() override; |
| 2637 | 2642 |
| 2638 // Return the available bytes without growing. | 2643 // Return the available bytes without growing. |
| 2639 intptr_t Available() override { return Capacity() - Size(); } | 2644 intptr_t Available() override { return Capacity() - Size(); } |
| 2640 | 2645 |
| 2641 intptr_t PagesFromStart(Address addr) { | |
| 2642 return static_cast<intptr_t>(addr - bottom()) / Page::kPageSize; | |
| 2643 } | |
| 2644 | |
| 2645 size_t AllocatedSinceLastGC() { | 2646 size_t AllocatedSinceLastGC() { |
|
Michael Lippautz
2016/04/05 07:57:43
This is roughly 1:1 translation to non-cont. space
| |
| 2646 intptr_t allocated = top() - to_space_.age_mark(); | 2647 bool seen_age_mark = false; |
| 2647 if (allocated < 0) { | 2648 Address age_mark = to_space_.age_mark(); |
| 2648 // Runtime has lowered the top below the age mark. | 2649 NewSpacePage* current_page = to_space_.first_page(); |
| 2650 NewSpacePage* age_mark_page = NewSpacePage::FromAddress(age_mark); | |
| 2651 NewSpacePage* last_page = NewSpacePage::FromAddress(top() - kPointerSize); | |
| 2652 if (age_mark_page == last_page) { | |
| 2653 if (top() - age_mark > 0) { | |
|
ulan
2016/04/05 08:46:25
Should be (top() - age_mark >= 0) to preserve the
Michael Lippautz
2016/04/05 09:42:34
Done.
| |
| 2654 return top() - age_mark; | |
| 2655 } | |
| 2656 // Top was reset at some point, invalidating this metric. | |
| 2649 return 0; | 2657 return 0; |
| 2650 } | 2658 } |
| 2651 // Correctly account for non-allocatable regions at the beginning of | 2659 while (current_page != last_page) { |
| 2652 // each page from the age_mark() to the top(). | 2660 if (current_page == age_mark_page) { |
| 2653 intptr_t pages = | 2661 seen_age_mark = true; |
| 2654 PagesFromStart(top()) - PagesFromStart(to_space_.age_mark()); | 2662 break; |
| 2655 allocated -= pages * (NewSpacePage::kObjectStartOffset); | 2663 } |
| 2656 DCHECK(0 <= allocated && allocated <= Size()); | 2664 current_page = current_page->next_page(); |
| 2665 } | |
| 2666 if (!seen_age_mark) { | |
| 2667 // Top was reset at some point, invalidating this metric. | |
| 2668 return 0; | |
| 2669 } | |
| 2670 intptr_t allocated = age_mark_page->area_end() - age_mark; | |
| 2671 current_page = current_page->next_page(); | |
|
ulan
2016/04/05 08:46:25
Did you mean current_page = age_mark_page->next_pa
Michael Lippautz
2016/04/05 09:42:34
current_page == age_mark_page at this point. Added
| |
| 2672 while (current_page != last_page) { | |
| 2673 allocated += NewSpacePage::kAllocatableMemory; | |
| 2674 current_page = current_page->next_page(); | |
| 2675 } | |
| 2676 allocated += top() - current_page->area_start(); | |
| 2677 DCHECK_LE(0, allocated); | |
| 2678 DCHECK_LE(allocated, Size()); | |
| 2657 return static_cast<size_t>(allocated); | 2679 return static_cast<size_t>(allocated); |
| 2658 } | 2680 } |
| 2659 | 2681 |
| 2660 // Return the maximum capacity of a semispace. | 2682 // Return the maximum capacity of a semispace. |
| 2661 int MaximumCapacity() { | 2683 int MaximumCapacity() { |
| 2662 DCHECK(to_space_.maximum_capacity() == from_space_.maximum_capacity()); | 2684 DCHECK(to_space_.maximum_capacity() == from_space_.maximum_capacity()); |
| 2663 return to_space_.maximum_capacity(); | 2685 return to_space_.maximum_capacity(); |
| 2664 } | 2686 } |
| 2665 | 2687 |
| 2666 bool IsAtMaximumCapacity() { return TotalCapacity() == MaximumCapacity(); } | 2688 bool IsAtMaximumCapacity() { return TotalCapacity() == MaximumCapacity(); } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2798 | 2820 |
| 2799 void PauseAllocationObservers() override; | 2821 void PauseAllocationObservers() override; |
| 2800 void ResumeAllocationObservers() override; | 2822 void ResumeAllocationObservers() override; |
| 2801 | 2823 |
| 2802 private: | 2824 private: |
| 2803 // Update allocation info to match the current to-space page. | 2825 // Update allocation info to match the current to-space page. |
| 2804 void UpdateAllocationInfo(); | 2826 void UpdateAllocationInfo(); |
| 2805 | 2827 |
| 2806 base::Mutex mutex_; | 2828 base::Mutex mutex_; |
| 2807 | 2829 |
| 2808 Address chunk_base_; | |
| 2809 uintptr_t chunk_size_; | |
| 2810 | |
| 2811 // The semispaces. | 2830 // The semispaces. |
| 2812 SemiSpace to_space_; | 2831 SemiSpace to_space_; |
| 2813 SemiSpace from_space_; | 2832 SemiSpace from_space_; |
| 2814 base::VirtualMemory reservation_; | 2833 base::VirtualMemory reservation_; |
| 2815 int pages_used_; | 2834 int pages_used_; |
| 2816 | 2835 |
| 2817 // Allocation pointer and limit for normal allocation and allocation during | 2836 // Allocation pointer and limit for normal allocation and allocation during |
| 2818 // mark-compact collection. | 2837 // mark-compact collection. |
| 2819 AllocationInfo allocation_info_; | 2838 AllocationInfo allocation_info_; |
| 2820 | 2839 |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3085 count = 0; | 3104 count = 0; |
| 3086 } | 3105 } |
| 3087 // Must be small, since an iteration is used for lookup. | 3106 // Must be small, since an iteration is used for lookup. |
| 3088 static const int kMaxComments = 64; | 3107 static const int kMaxComments = 64; |
| 3089 }; | 3108 }; |
| 3090 #endif | 3109 #endif |
| 3091 } // namespace internal | 3110 } // namespace internal |
| 3092 } // namespace v8 | 3111 } // namespace v8 |
| 3093 | 3112 |
| 3094 #endif // V8_HEAP_SPACES_H_ | 3113 #endif // V8_HEAP_SPACES_H_ |
| OLD | NEW |