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

Side by Side Diff: src/heap/spaces.h

Issue 1360553003: [heap] Sort declarations for MemoryChunk. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment Created 5 years, 3 months 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
« no previous file with comments | « no previous file | src/heap/spaces.cc » ('j') | 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 // 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"
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 261
262 class SkipList; 262 class SkipList;
263 class SlotsBuffer; 263 class SlotsBuffer;
264 264
265 // MemoryChunk represents a memory region owned by a specific space. 265 // MemoryChunk represents a memory region owned by a specific space.
266 // It is divided into the header and the body. Chunk start is always 266 // It is divided into the header and the body. Chunk start is always
267 // 1MB aligned. Start of the body is aligned so it can accommodate 267 // 1MB aligned. Start of the body is aligned so it can accommodate
268 // any heap object. 268 // any heap object.
269 class MemoryChunk { 269 class MemoryChunk {
270 public: 270 public:
271 enum MemoryChunkFlags {
272 IS_EXECUTABLE,
273 ABOUT_TO_BE_FREED,
274 POINTERS_TO_HERE_ARE_INTERESTING,
275 POINTERS_FROM_HERE_ARE_INTERESTING,
276 SCAN_ON_SCAVENGE,
277 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE.
278 IN_TO_SPACE, // All pages in new space has one of these two set.
279 NEW_SPACE_BELOW_AGE_MARK,
280 EVACUATION_CANDIDATE,
281 RESCAN_ON_EVACUATION,
282 NEVER_EVACUATE, // May contain immortal immutables.
283 POPULAR_PAGE, // Slots buffer of this page overflowed on the previous GC.
284
285 // WAS_SWEPT indicates that marking bits have been cleared by the sweeper,
286 // otherwise marking bits are still intact.
287 WAS_SWEPT,
288
289 // Large objects can have a progress bar in their page header. These object
290 // are scanned in increments and will be kept black while being scanned.
291 // Even if the mutator writes to them they will be kept black and a white
292 // to grey transition is performed in the value.
293 HAS_PROGRESS_BAR,
294
295 // This flag is intended to be used for testing. Works only when both
296 // FLAG_stress_compaction and FLAG_manual_evacuation_candidates_selection
297 // are set. It forces the page to become an evacuation candidate at next
298 // candidates selection cycle.
299 FORCE_EVACUATION_CANDIDATE_FOR_TESTING,
300
301 // The memory chunk is already logically freed, however the actual freeing
302 // still has to be performed.
303 PRE_FREED,
304
305 // Last flag, keep at bottom.
306 NUM_MEMORY_CHUNK_FLAGS
307 };
308
271 // |kCompactionDone|: Initial compaction state of a |MemoryChunk|. 309 // |kCompactionDone|: Initial compaction state of a |MemoryChunk|.
272 // |kCompactingInProgress|: Parallel compaction is currently in progress. 310 // |kCompactingInProgress|: Parallel compaction is currently in progress.
273 // |kCompactingFinalize|: Parallel compaction is done but the chunk needs to 311 // |kCompactingFinalize|: Parallel compaction is done but the chunk needs to
274 // be finalized. 312 // be finalized.
275 // |kCompactingAborted|: Parallel compaction has been aborted, which should 313 // |kCompactingAborted|: Parallel compaction has been aborted, which should
276 // for now only happen in OOM scenarios. 314 // for now only happen in OOM scenarios.
277 enum ParallelCompactingState { 315 enum ParallelCompactingState {
278 kCompactingDone, 316 kCompactingDone,
279 kCompactingInProgress, 317 kCompactingInProgress,
280 kCompactingFinalize, 318 kCompactingFinalize,
281 kCompactingAborted, 319 kCompactingAborted,
282 }; 320 };
283 321
284 // |kSweepingDone|: The page state when sweeping is complete or sweeping must 322 // |kSweepingDone|: The page state when sweeping is complete or sweeping must
285 // not be performed on that page. 323 // not be performed on that page.
286 // |kSweepingFinalize|: A sweeper thread is done sweeping this page and will 324 // |kSweepingFinalize|: A sweeper thread is done sweeping this page and will
287 // not touch the page memory anymore. 325 // not touch the page memory anymore.
288 // |kSweepingInProgress|: This page is currently swept by a sweeper thread. 326 // |kSweepingInProgress|: This page is currently swept by a sweeper thread.
289 // |kSweepingPending|: This page is ready for parallel sweeping. 327 // |kSweepingPending|: This page is ready for parallel sweeping.
290 enum ParallelSweepingState { 328 enum ParallelSweepingState {
291 kSweepingDone, 329 kSweepingDone,
292 kSweepingFinalize, 330 kSweepingFinalize,
293 kSweepingInProgress, 331 kSweepingInProgress,
294 kSweepingPending 332 kSweepingPending
295 }; 333 };
296 334
335 // Every n write barrier invocations we go to runtime even though
336 // we could have handled it in generated code. This lets us check
337 // whether we have hit the limit and should do some more marking.
338 static const int kWriteBarrierCounterGranularity = 500;
339
340 static const int kPointersToHereAreInterestingMask =
341 1 << POINTERS_TO_HERE_ARE_INTERESTING;
342
343 static const int kPointersFromHereAreInterestingMask =
344 1 << POINTERS_FROM_HERE_ARE_INTERESTING;
345
346 static const int kEvacuationCandidateMask = 1 << EVACUATION_CANDIDATE;
347
348 static const int kSkipEvacuationSlotsRecordingMask =
349 (1 << EVACUATION_CANDIDATE) | (1 << RESCAN_ON_EVACUATION) |
350 (1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE);
351
352 static const intptr_t kAlignment =
353 (static_cast<uintptr_t>(1) << kPageSizeBits);
354
355 static const intptr_t kAlignmentMask = kAlignment - 1;
356
357 static const intptr_t kSizeOffset = 0;
358
359 static const intptr_t kLiveBytesOffset =
360 kSizeOffset + kPointerSize // size_t size
361 + kIntptrSize // intptr_t flags_
362 + kPointerSize // Address area_start_
363 + kPointerSize // Address area_end_
364 + 2 * kPointerSize // base::VirtualMemory reservation_
365 + kPointerSize // Address owner_
366 + kPointerSize // Heap* heap_
367 + kIntSize; // int store_buffer_counter_
368
369 static const size_t kSlotsBufferOffset =
370 kLiveBytesOffset + kIntSize; // int live_byte_count_
371
372 static const size_t kWriteBarrierCounterOffset =
373 kSlotsBufferOffset + kPointerSize // SlotsBuffer* slots_buffer_;
374 + kPointerSize; // SkipList* skip_list_;
375
376 static const size_t kMinHeaderSize =
377 kWriteBarrierCounterOffset +
378 kIntptrSize // intptr_t write_barrier_counter_
379 + kIntSize // int progress_bar_
380 + kPointerSize // AtomicValue high_water_mark_
381 + kPointerSize // base::Mutex* mutex_
382 + kPointerSize // base::AtomicWord parallel_sweeping_
383 + kPointerSize // AtomicValue parallel_compaction_
384 + 5 * kPointerSize // AtomicNumber free-list statistics
385 + kPointerSize // AtomicValue next_chunk_
386 + kPointerSize; // AtomicValue prev_chunk_
387
388 // We add some more space to the computed header size to amount for missing
389 // alignment requirements in our computation.
390 // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines.
391 static const size_t kHeaderSize = kMinHeaderSize + kIntSize;
392
393 static const int kBodyOffset =
394 CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize);
395
396 // The start offset of the object area in a page. Aligned to both maps and
397 // code alignment to be suitable for both. Also aligned to 32 words because
398 // the marking bitmap is arranged in 32 bit chunks.
399 static const int kObjectStartAlignment = 32 * kPointerSize;
400 static const int kObjectStartOffset =
401 kBodyOffset - 1 +
402 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment);
403
404 static const int kFlagsOffset = kPointerSize;
405
406 static void IncrementLiveBytesFromMutator(HeapObject* object, int by);
407
297 // Only works if the pointer is in the first kPageSize of the MemoryChunk. 408 // Only works if the pointer is in the first kPageSize of the MemoryChunk.
298 static MemoryChunk* FromAddress(Address a) { 409 static MemoryChunk* FromAddress(Address a) {
299 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); 410 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask);
300 } 411 }
412
301 static const MemoryChunk* FromAddress(const byte* a) { 413 static const MemoryChunk* FromAddress(const byte* a) {
302 return reinterpret_cast<const MemoryChunk*>(OffsetFrom(a) & 414 return reinterpret_cast<const MemoryChunk*>(OffsetFrom(a) &
303 ~kAlignmentMask); 415 ~kAlignmentMask);
304 } 416 }
305 417
418 static void IncrementLiveBytesFromGC(HeapObject* object, int by) {
419 MemoryChunk::FromAddress(object->address())->IncrementLiveBytes(by);
420 }
421
306 // Only works for addresses in pointer spaces, not data or code spaces. 422 // Only works for addresses in pointer spaces, not data or code spaces.
307 static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr); 423 static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr);
308 424
425 static inline uint32_t FastAddressToMarkbitIndex(Address addr) {
426 const intptr_t offset = reinterpret_cast<intptr_t>(addr) & kAlignmentMask;
427 return static_cast<uint32_t>(offset) >> kPointerSizeLog2;
428 }
429
430 static inline void UpdateHighWaterMark(Address mark) {
431 if (mark == nullptr) return;
432 // Need to subtract one from the mark because when a chunk is full the
433 // top points to the next address after the chunk, which effectively belongs
434 // to another chunk. See the comment to Page::FromAllocationTop.
435 MemoryChunk* chunk = MemoryChunk::FromAddress(mark - 1);
436 intptr_t new_mark = static_cast<intptr_t>(mark - chunk->address());
437 intptr_t old_mark = 0;
438 do {
439 old_mark = chunk->high_water_mark_.Value();
440 } while ((new_mark > old_mark) &&
441 !chunk->high_water_mark_.TrySetValue(old_mark, new_mark));
442 }
443
309 Address address() { return reinterpret_cast<Address>(this); } 444 Address address() { return reinterpret_cast<Address>(this); }
310 445
311 bool is_valid() { return address() != NULL; } 446 bool is_valid() { return address() != NULL; }
312 447
313 MemoryChunk* next_chunk() const { 448 MemoryChunk* next_chunk() { return next_chunk_.Value(); }
314 return reinterpret_cast<MemoryChunk*>(base::Acquire_Load(&next_chunk_));
315 }
316 449
317 MemoryChunk* prev_chunk() const { 450 MemoryChunk* prev_chunk() { return prev_chunk_.Value(); }
318 return reinterpret_cast<MemoryChunk*>(base::Acquire_Load(&prev_chunk_));
319 }
320 451
321 void set_next_chunk(MemoryChunk* next) { 452 void set_next_chunk(MemoryChunk* next) { next_chunk_.SetValue(next); }
322 base::Release_Store(&next_chunk_, reinterpret_cast<base::AtomicWord>(next));
323 }
324 453
325 void set_prev_chunk(MemoryChunk* prev) { 454 void set_prev_chunk(MemoryChunk* prev) { prev_chunk_.SetValue(prev); }
326 base::Release_Store(&prev_chunk_, reinterpret_cast<base::AtomicWord>(prev));
327 }
328 455
329 Space* owner() const { 456 Space* owner() const {
330 if ((reinterpret_cast<intptr_t>(owner_) & kPageHeaderTagMask) == 457 if ((reinterpret_cast<intptr_t>(owner_) & kPageHeaderTagMask) ==
331 kPageHeaderTag) { 458 kPageHeaderTag) {
332 return reinterpret_cast<Space*>(reinterpret_cast<intptr_t>(owner_) - 459 return reinterpret_cast<Space*>(reinterpret_cast<intptr_t>(owner_) -
333 kPageHeaderTag); 460 kPageHeaderTag);
334 } else { 461 } else {
335 return NULL; 462 return NULL;
336 } 463 }
337 } 464 }
338 465
339 void set_owner(Space* space) { 466 void set_owner(Space* space) {
340 DCHECK((reinterpret_cast<intptr_t>(space) & kPageHeaderTagMask) == 0); 467 DCHECK((reinterpret_cast<intptr_t>(space) & kPageHeaderTagMask) == 0);
341 owner_ = reinterpret_cast<Address>(space) + kPageHeaderTag; 468 owner_ = reinterpret_cast<Address>(space) + kPageHeaderTag;
342 DCHECK((reinterpret_cast<intptr_t>(owner_) & kPageHeaderTagMask) == 469 DCHECK((reinterpret_cast<intptr_t>(owner_) & kPageHeaderTagMask) ==
343 kPageHeaderTag); 470 kPageHeaderTag);
344 } 471 }
345 472
346 base::VirtualMemory* reserved_memory() { return &reservation_; } 473 base::VirtualMemory* reserved_memory() { return &reservation_; }
347 474
348 void InitializeReservedMemory() { reservation_.Reset(); }
349
350 void set_reserved_memory(base::VirtualMemory* reservation) { 475 void set_reserved_memory(base::VirtualMemory* reservation) {
351 DCHECK_NOT_NULL(reservation); 476 DCHECK_NOT_NULL(reservation);
352 reservation_.TakeControl(reservation); 477 reservation_.TakeControl(reservation);
353 } 478 }
354 479
355 bool scan_on_scavenge() { return IsFlagSet(SCAN_ON_SCAVENGE); } 480 bool scan_on_scavenge() { return IsFlagSet(SCAN_ON_SCAVENGE); }
356 void initialize_scan_on_scavenge(bool scan) { 481 void initialize_scan_on_scavenge(bool scan) {
357 if (scan) { 482 if (scan) {
358 SetFlag(SCAN_ON_SCAVENGE); 483 SetFlag(SCAN_ON_SCAVENGE);
359 } else { 484 } else {
(...skipping 11 matching lines...) Expand all
371 return addr >= area_start() && addr < area_end(); 496 return addr >= area_start() && addr < area_end();
372 } 497 }
373 498
374 // Checks whether addr can be a limit of addresses in this page. 499 // Checks whether addr can be a limit of addresses in this page.
375 // It's a limit if it's in the page, or if it's just after the 500 // It's a limit if it's in the page, or if it's just after the
376 // last byte of the page. 501 // last byte of the page.
377 bool ContainsLimit(Address addr) { 502 bool ContainsLimit(Address addr) {
378 return addr >= area_start() && addr <= area_end(); 503 return addr >= area_start() && addr <= area_end();
379 } 504 }
380 505
381 // Every n write barrier invocations we go to runtime even though
382 // we could have handled it in generated code. This lets us check
383 // whether we have hit the limit and should do some more marking.
384 static const int kWriteBarrierCounterGranularity = 500;
385
386 enum MemoryChunkFlags {
387 IS_EXECUTABLE,
388 ABOUT_TO_BE_FREED,
389 POINTERS_TO_HERE_ARE_INTERESTING,
390 POINTERS_FROM_HERE_ARE_INTERESTING,
391 SCAN_ON_SCAVENGE,
392 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE.
393 IN_TO_SPACE, // All pages in new space has one of these two set.
394 NEW_SPACE_BELOW_AGE_MARK,
395 EVACUATION_CANDIDATE,
396 RESCAN_ON_EVACUATION,
397 NEVER_EVACUATE, // May contain immortal immutables.
398 POPULAR_PAGE, // Slots buffer of this page overflowed on the previous GC.
399
400 // WAS_SWEPT indicates that marking bits have been cleared by the sweeper,
401 // otherwise marking bits are still intact.
402 WAS_SWEPT,
403
404 // Large objects can have a progress bar in their page header. These object
405 // are scanned in increments and will be kept black while being scanned.
406 // Even if the mutator writes to them they will be kept black and a white
407 // to grey transition is performed in the value.
408 HAS_PROGRESS_BAR,
409
410 // This flag is intended to be used for testing. Works only when both
411 // FLAG_stress_compaction and FLAG_manual_evacuation_candidates_selection
412 // are set. It forces the page to become an evacuation candidate at next
413 // candidates selection cycle.
414 FORCE_EVACUATION_CANDIDATE_FOR_TESTING,
415
416 // The memory chunk is already logically freed, however the actual freeing
417 // still has to be performed.
418 PRE_FREED,
419
420 // Last flag, keep at bottom.
421 NUM_MEMORY_CHUNK_FLAGS
422 };
423
424
425 static const int kPointersToHereAreInterestingMask =
426 1 << POINTERS_TO_HERE_ARE_INTERESTING;
427
428 static const int kPointersFromHereAreInterestingMask =
429 1 << POINTERS_FROM_HERE_ARE_INTERESTING;
430
431 static const int kEvacuationCandidateMask = 1 << EVACUATION_CANDIDATE;
432
433 static const int kSkipEvacuationSlotsRecordingMask =
434 (1 << EVACUATION_CANDIDATE) | (1 << RESCAN_ON_EVACUATION) |
435 (1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE);
436
437
438 void SetFlag(int flag) { flags_ |= static_cast<uintptr_t>(1) << flag; } 506 void SetFlag(int flag) { flags_ |= static_cast<uintptr_t>(1) << flag; }
439 507
440 void ClearFlag(int flag) { flags_ &= ~(static_cast<uintptr_t>(1) << flag); } 508 void ClearFlag(int flag) { flags_ &= ~(static_cast<uintptr_t>(1) << flag); }
441 509
442 void SetFlagTo(int flag, bool value) { 510 void SetFlagTo(int flag, bool value) {
443 if (value) { 511 if (value) {
444 SetFlag(flag); 512 SetFlag(flag);
445 } else { 513 } else {
446 ClearFlag(flag); 514 ClearFlag(flag);
447 } 515 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 } 602 }
535 } 603 }
536 604
537 bool IsLeftOfProgressBar(Object** slot) { 605 bool IsLeftOfProgressBar(Object** slot) {
538 Address slot_address = reinterpret_cast<Address>(slot); 606 Address slot_address = reinterpret_cast<Address>(slot);
539 DCHECK(slot_address > this->address()); 607 DCHECK(slot_address > this->address());
540 return (slot_address - (this->address() + kObjectStartOffset)) < 608 return (slot_address - (this->address() + kObjectStartOffset)) <
541 progress_bar(); 609 progress_bar();
542 } 610 }
543 611
544 static void IncrementLiveBytesFromGC(HeapObject* object, int by) {
545 MemoryChunk::FromAddress(object->address())->IncrementLiveBytes(by);
546 }
547
548 static void IncrementLiveBytesFromMutator(HeapObject* object, int by);
549
550 static const intptr_t kAlignment =
551 (static_cast<uintptr_t>(1) << kPageSizeBits);
552
553 static const intptr_t kAlignmentMask = kAlignment - 1;
554
555 static const intptr_t kSizeOffset = 0;
556
557 static const intptr_t kLiveBytesOffset =
558 kSizeOffset + kPointerSize // size_t size
559 + kIntptrSize // intptr_t flags_
560 + kPointerSize // Address area_start_
561 + kPointerSize // Address area_end_
562 + 2 * kPointerSize // base::VirtualMemory reservation_
563 + kPointerSize // Address owner_
564 + kPointerSize // Heap* heap_
565 + kIntSize; // int store_buffer_counter_
566
567
568 static const size_t kSlotsBufferOffset =
569 kLiveBytesOffset + kIntSize; // int live_byte_count_
570
571 static const size_t kWriteBarrierCounterOffset =
572 kSlotsBufferOffset + kPointerSize // SlotsBuffer* slots_buffer_;
573 + kPointerSize; // SkipList* skip_list_;
574
575 static const size_t kMinHeaderSize =
576 kWriteBarrierCounterOffset +
577 kIntptrSize // intptr_t write_barrier_counter_
578 + kIntSize // int progress_bar_
579 + kPointerSize // AtomicValue high_water_mark_
580 + kPointerSize // base::Mutex* mutex_
581 + kPointerSize // base::AtomicWord parallel_sweeping_
582 + kPointerSize // AtomicValue parallel_compaction_
583 + 5 * kPointerSize // AtomicNumber free-list statistics
584 + kPointerSize // base::AtomicWord next_chunk_
585 + kPointerSize; // base::AtomicWord prev_chunk_
586
587 // We add some more space to the computed header size to amount for missing
588 // alignment requirements in our computation.
589 // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines.
590 static const size_t kHeaderSize = kMinHeaderSize + kIntSize;
591
592 static const int kBodyOffset =
593 CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize);
594
595 // The start offset of the object area in a page. Aligned to both maps and
596 // code alignment to be suitable for both. Also aligned to 32 words because
597 // the marking bitmap is arranged in 32 bit chunks.
598 static const int kObjectStartAlignment = 32 * kPointerSize;
599 static const int kObjectStartOffset =
600 kBodyOffset - 1 +
601 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment);
602
603 size_t size() const { return size_; } 612 size_t size() const { return size_; }
604 613
605 void set_size(size_t size) { size_ = size; } 614 void set_size(size_t size) { size_ = size; }
606 615
607 void SetArea(Address area_start, Address area_end) { 616 void SetArea(Address area_start, Address area_end) {
608 area_start_ = area_start; 617 area_start_ = area_start;
609 area_end_ = area_end; 618 area_end_ = area_end;
610 } 619 }
611 620
612 Executability executable() { 621 Executability executable() {
613 return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE; 622 return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE;
614 } 623 }
615 624
616 bool InNewSpace() { 625 bool InNewSpace() {
617 return (flags_ & ((1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE))) != 0; 626 return (flags_ & ((1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE))) != 0;
618 } 627 }
619 628
620 bool InToSpace() { return IsFlagSet(IN_TO_SPACE); } 629 bool InToSpace() { return IsFlagSet(IN_TO_SPACE); }
621 630
622 bool InFromSpace() { return IsFlagSet(IN_FROM_SPACE); } 631 bool InFromSpace() { return IsFlagSet(IN_FROM_SPACE); }
623 632
624 // ---------------------------------------------------------------------
625 // Markbits support 633 // Markbits support
626 634
627 inline Bitmap* markbits() { 635 inline Bitmap* markbits() {
628 return Bitmap::FromAddress(address() + kHeaderSize); 636 return Bitmap::FromAddress(address() + kHeaderSize);
629 } 637 }
630 638
631 void PrintMarkbits() { markbits()->Print(); } 639 void PrintMarkbits() { markbits()->Print(); }
632 640
633 inline uint32_t AddressToMarkbitIndex(Address addr) { 641 inline uint32_t AddressToMarkbitIndex(Address addr) {
634 return static_cast<uint32_t>(addr - this->address()) >> kPointerSizeLog2; 642 return static_cast<uint32_t>(addr - this->address()) >> kPointerSizeLog2;
635 } 643 }
636 644
637 inline static uint32_t FastAddressToMarkbitIndex(Address addr) {
638 const intptr_t offset = reinterpret_cast<intptr_t>(addr) & kAlignmentMask;
639
640 return static_cast<uint32_t>(offset) >> kPointerSizeLog2;
641 }
642
643 inline Address MarkbitIndexToAddress(uint32_t index) { 645 inline Address MarkbitIndexToAddress(uint32_t index) {
644 return this->address() + (index << kPointerSizeLog2); 646 return this->address() + (index << kPointerSizeLog2);
645 } 647 }
646 648
647 void InsertAfter(MemoryChunk* other); 649 void InsertAfter(MemoryChunk* other);
648 void Unlink(); 650 void Unlink();
649 651
650 inline Heap* heap() const { return heap_; } 652 inline Heap* heap() const { return heap_; }
651 653
652 static const int kFlagsOffset = kPointerSize;
653
654 bool NeverEvacuate() { return IsFlagSet(NEVER_EVACUATE); } 654 bool NeverEvacuate() { return IsFlagSet(NEVER_EVACUATE); }
655 655
656 void MarkNeverEvacuate() { SetFlag(NEVER_EVACUATE); } 656 void MarkNeverEvacuate() { SetFlag(NEVER_EVACUATE); }
657 657
658 bool IsEvacuationCandidate() { 658 bool IsEvacuationCandidate() {
659 DCHECK(!(IsFlagSet(NEVER_EVACUATE) && IsFlagSet(EVACUATION_CANDIDATE))); 659 DCHECK(!(IsFlagSet(NEVER_EVACUATE) && IsFlagSet(EVACUATION_CANDIDATE)));
660 return IsFlagSet(EVACUATION_CANDIDATE); 660 return IsFlagSet(EVACUATION_CANDIDATE);
661 } 661 }
662 662
663 bool ShouldSkipEvacuationSlotRecording() { 663 bool ShouldSkipEvacuationSlotRecording() {
(...skipping 23 matching lines...) Expand all
687 Address area_end() { return area_end_; } 687 Address area_end() { return area_end_; }
688 int area_size() { return static_cast<int>(area_end() - area_start()); } 688 int area_size() { return static_cast<int>(area_end() - area_start()); }
689 bool CommitArea(size_t requested); 689 bool CommitArea(size_t requested);
690 690
691 // Approximate amount of physical memory committed for this chunk. 691 // Approximate amount of physical memory committed for this chunk.
692 size_t CommittedPhysicalMemory() { return high_water_mark_.Value(); } 692 size_t CommittedPhysicalMemory() { return high_water_mark_.Value(); }
693 693
694 // Should be called when memory chunk is about to be freed. 694 // Should be called when memory chunk is about to be freed.
695 void ReleaseAllocatedMemory(); 695 void ReleaseAllocatedMemory();
696 696
697 static inline void UpdateHighWaterMark(Address mark) { 697 protected:
698 if (mark == nullptr) return; 698 static MemoryChunk* Initialize(Heap* heap, Address base, size_t size,
699 // Need to subtract one from the mark because when a chunk is full the 699 Address area_start, Address area_end,
700 // top points to the next address after the chunk, which effectively belongs 700 Executability executable, Space* owner);
701 // to another chunk. See the comment to Page::FromAllocationTop.
702 MemoryChunk* chunk = MemoryChunk::FromAddress(mark - 1);
703 intptr_t new_mark = static_cast<intptr_t>(mark - chunk->address());
704 intptr_t old_mark = 0;
705 do {
706 old_mark = chunk->high_water_mark_.Value();
707 } while ((new_mark > old_mark) &&
708 !chunk->high_water_mark_.TrySetValue(old_mark, new_mark));
709 }
710 701
711 protected:
712 size_t size_; 702 size_t size_;
713 intptr_t flags_; 703 intptr_t flags_;
714 704
715 // Start and end of allocatable memory on this chunk. 705 // Start and end of allocatable memory on this chunk.
716 Address area_start_; 706 Address area_start_;
717 Address area_end_; 707 Address area_end_;
718 708
719 // If the chunk needs to remember its memory reservation, it is stored here. 709 // If the chunk needs to remember its memory reservation, it is stored here.
720 base::VirtualMemory reservation_; 710 base::VirtualMemory reservation_;
721 // The identity of the owning space. This is tagged as a failure pointer, but 711 // The identity of the owning space. This is tagged as a failure pointer, but
(...skipping 21 matching lines...) Expand all
743 AtomicValue<ParallelCompactingState> parallel_compaction_; 733 AtomicValue<ParallelCompactingState> parallel_compaction_;
744 734
745 // PagedSpace free-list statistics. 735 // PagedSpace free-list statistics.
746 AtomicNumber<intptr_t> available_in_small_free_list_; 736 AtomicNumber<intptr_t> available_in_small_free_list_;
747 AtomicNumber<intptr_t> available_in_medium_free_list_; 737 AtomicNumber<intptr_t> available_in_medium_free_list_;
748 AtomicNumber<intptr_t> available_in_large_free_list_; 738 AtomicNumber<intptr_t> available_in_large_free_list_;
749 AtomicNumber<intptr_t> available_in_huge_free_list_; 739 AtomicNumber<intptr_t> available_in_huge_free_list_;
750 AtomicNumber<intptr_t> non_available_small_blocks_; 740 AtomicNumber<intptr_t> non_available_small_blocks_;
751 741
752 // next_chunk_ holds a pointer of type MemoryChunk 742 // next_chunk_ holds a pointer of type MemoryChunk
753 base::AtomicWord next_chunk_; 743 AtomicValue<MemoryChunk*> next_chunk_;
754 // prev_chunk_ holds a pointer of type MemoryChunk 744 // prev_chunk_ holds a pointer of type MemoryChunk
755 base::AtomicWord prev_chunk_; 745 AtomicValue<MemoryChunk*> prev_chunk_;
756
757 static MemoryChunk* Initialize(Heap* heap, Address base, size_t size,
758 Address area_start, Address area_end,
759 Executability executable, Space* owner);
760 746
761 private: 747 private:
748 void InitializeReservedMemory() { reservation_.Reset(); }
749
762 friend class MemoryAllocator; 750 friend class MemoryAllocator;
763 friend class MemoryChunkValidator; 751 friend class MemoryChunkValidator;
764 }; 752 };
765 753
766 754
767 // ----------------------------------------------------------------------------- 755 // -----------------------------------------------------------------------------
768 // A page is a memory chunk of a size 1MB. Large object pages may be larger. 756 // A page is a memory chunk of a size 1MB. Large object pages may be larger.
769 // 757 //
770 // The only way to get a page pointer is by calling factory methods: 758 // The only way to get a page pointer is by calling factory methods:
771 // Page* p = Page::FromAddress(addr); or 759 // Page* p = Page::FromAddress(addr); or
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 #endif // DEBUG 858 #endif // DEBUG
871 859
872 friend class MemoryAllocator; 860 friend class MemoryAllocator;
873 }; 861 };
874 862
875 863
876 class LargePage : public MemoryChunk { 864 class LargePage : public MemoryChunk {
877 public: 865 public:
878 HeapObject* GetObject() { return HeapObject::FromAddress(area_start()); } 866 HeapObject* GetObject() { return HeapObject::FromAddress(area_start()); }
879 867
880 inline LargePage* next_page() const { 868 inline LargePage* next_page() {
881 return static_cast<LargePage*>(next_chunk()); 869 return static_cast<LargePage*>(next_chunk());
882 } 870 }
883 871
884 inline void set_next_page(LargePage* page) { set_next_chunk(page); } 872 inline void set_next_page(LargePage* page) { set_next_chunk(page); }
885 873
886 private: 874 private:
887 static inline LargePage* Initialize(Heap* heap, MemoryChunk* chunk); 875 static inline LargePage* Initialize(Heap* heap, MemoryChunk* chunk);
888 876
889 friend class MemoryAllocator; 877 friend class MemoryAllocator;
890 }; 878 };
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after
2110 public: 2098 public:
2111 // GC related flags copied from from-space to to-space when 2099 // GC related flags copied from from-space to to-space when
2112 // flipping semispaces. 2100 // flipping semispaces.
2113 static const intptr_t kCopyOnFlipFlagsMask = 2101 static const intptr_t kCopyOnFlipFlagsMask =
2114 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | 2102 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) |
2115 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) | 2103 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) |
2116 (1 << MemoryChunk::SCAN_ON_SCAVENGE); 2104 (1 << MemoryChunk::SCAN_ON_SCAVENGE);
2117 2105
2118 static const int kAreaSize = Page::kMaxRegularHeapObjectSize; 2106 static const int kAreaSize = Page::kMaxRegularHeapObjectSize;
2119 2107
2120 inline NewSpacePage* next_page() const { 2108 inline NewSpacePage* next_page() {
2121 return static_cast<NewSpacePage*>(next_chunk()); 2109 return static_cast<NewSpacePage*>(next_chunk());
2122 } 2110 }
2123 2111
2124 inline void set_next_page(NewSpacePage* page) { set_next_chunk(page); } 2112 inline void set_next_page(NewSpacePage* page) { set_next_chunk(page); }
2125 2113
2126 inline NewSpacePage* prev_page() const { 2114 inline NewSpacePage* prev_page() {
2127 return static_cast<NewSpacePage*>(prev_chunk()); 2115 return static_cast<NewSpacePage*>(prev_chunk());
2128 } 2116 }
2129 2117
2130 inline void set_prev_page(NewSpacePage* page) { set_prev_chunk(page); } 2118 inline void set_prev_page(NewSpacePage* page) { set_prev_chunk(page); }
2131 2119
2132 SemiSpace* semi_space() { return reinterpret_cast<SemiSpace*>(owner()); } 2120 SemiSpace* semi_space() { return reinterpret_cast<SemiSpace*>(owner()); }
2133 2121
2134 bool is_anchor() { return !this->InNewSpace(); } 2122 bool is_anchor() { return !this->InNewSpace(); }
2135 2123
2136 static bool IsAtStart(Address addr) { 2124 static bool IsAtStart(Address addr) {
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after
2977 count = 0; 2965 count = 0;
2978 } 2966 }
2979 // Must be small, since an iteration is used for lookup. 2967 // Must be small, since an iteration is used for lookup.
2980 static const int kMaxComments = 64; 2968 static const int kMaxComments = 64;
2981 }; 2969 };
2982 #endif 2970 #endif
2983 } 2971 }
2984 } // namespace v8::internal 2972 } // namespace v8::internal
2985 2973
2986 #endif // V8_HEAP_SPACES_H_ 2974 #endif // V8_HEAP_SPACES_H_
OLDNEW
« no previous file with comments | « no previous file | src/heap/spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698