OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 CellPrinter printer; | 277 CellPrinter printer; |
278 for (int i = 0; i < CellsCount(); i++) { | 278 for (int i = 0; i < CellsCount(); i++) { |
279 printer.Print(i, cells()[i]); | 279 printer.Print(i, cells()[i]); |
280 } | 280 } |
281 printer.Flush(); | 281 printer.Flush(); |
282 PrintF("\n"); | 282 PrintF("\n"); |
283 } | 283 } |
284 | 284 |
285 bool IsClean() { | 285 bool IsClean() { |
286 for (int i = 0; i < CellsCount(); i++) { | 286 for (int i = 0; i < CellsCount(); i++) { |
287 if (cells()[i] != 0) { | 287 if (cells()[i] != 0) return false; |
288 return false; | |
289 } | |
290 } | 288 } |
291 return true; | 289 return true; |
292 } | 290 } |
293 }; | 291 }; |
294 | 292 |
295 | 293 |
296 class SkipList; | 294 class SkipList; |
297 class SlotsBuffer; | 295 class SlotsBuffer; |
298 | 296 |
299 // MemoryChunk represents a memory region owned by a specific space. | 297 // MemoryChunk represents a memory region owned by a specific space. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 return addr >= area_start() && addr < area_end(); | 366 return addr >= area_start() && addr < area_end(); |
369 } | 367 } |
370 | 368 |
371 // Checks whether addr can be a limit of addresses in this page. | 369 // Checks whether addr can be a limit of addresses in this page. |
372 // It's a limit if it's in the page, or if it's just after the | 370 // It's a limit if it's in the page, or if it's just after the |
373 // last byte of the page. | 371 // last byte of the page. |
374 bool ContainsLimit(Address addr) { | 372 bool ContainsLimit(Address addr) { |
375 return addr >= area_start() && addr <= area_end(); | 373 return addr >= area_start() && addr <= area_end(); |
376 } | 374 } |
377 | 375 |
378 // Every n write barrier invocations we go to runtime even though | |
379 // we could have handled it in generated code. This lets us check | |
380 // whether we have hit the limit and should do some more marking. | |
381 static const int kWriteBarrierCounterGranularity = 500; | |
382 | |
383 enum MemoryChunkFlags { | 376 enum MemoryChunkFlags { |
384 IS_EXECUTABLE, | 377 IS_EXECUTABLE, |
385 ABOUT_TO_BE_FREED, | 378 ABOUT_TO_BE_FREED, |
386 POINTERS_TO_HERE_ARE_INTERESTING, | 379 POINTERS_TO_HERE_ARE_INTERESTING, |
387 POINTERS_FROM_HERE_ARE_INTERESTING, | 380 POINTERS_FROM_HERE_ARE_INTERESTING, |
388 SCAN_ON_SCAVENGE, | 381 SCAN_ON_SCAVENGE, |
389 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. | 382 IN_FROM_SPACE, // Mutually exclusive with IN_TO_SPACE. |
390 IN_TO_SPACE, // All pages in new space has one of these two set. | 383 IN_TO_SPACE, // All pages in new space has one of these two set. |
391 NEW_SPACE_BELOW_AGE_MARK, | 384 NEW_SPACE_BELOW_AGE_MARK, |
392 CONTAINS_ONLY_DATA, | 385 CONTAINS_ONLY_DATA, |
393 EVACUATION_CANDIDATE, | 386 EVACUATION_CANDIDATE, |
394 RESCAN_ON_EVACUATION, | 387 RESCAN_ON_EVACUATION, |
395 | 388 |
396 // Pages swept precisely can be iterated, hitting only the live objects. | 389 // Pages swept precisely can be iterated, hitting only the live objects. |
397 // Whereas those swept conservatively cannot be iterated over. Both flags | 390 // Whereas those swept conservatively cannot be iterated over. Both flags |
398 // indicate that marking bits have been cleared by the sweeper, otherwise | 391 // indicate that marking bits have been cleared by the sweeper, otherwise |
399 // marking bits are still intact. | 392 // marking bits are still intact. |
400 WAS_SWEPT_PRECISELY, | 393 WAS_SWEPT_PRECISELY, |
401 WAS_SWEPT_CONSERVATIVELY, | 394 WAS_SWEPT_CONSERVATIVELY, |
402 | 395 |
403 // Used for large objects only. Indicates that the object has been | |
404 // partially scanned by the incremental mark-sweep GC. Objects that have | |
405 // been partially scanned are marked black so that the write barrier | |
406 // triggers for them, and they are counted as live bytes. If the mutator | |
407 // writes to them they may be turned grey and subtracted from the live byte | |
408 // list. They move back to the marking deque either by an iteration over | |
409 // the large object space or in the write barrier. | |
410 IS_PARTIALLY_SCANNED, | |
411 | |
412 // Last flag, keep at bottom. | 396 // Last flag, keep at bottom. |
413 NUM_MEMORY_CHUNK_FLAGS | 397 NUM_MEMORY_CHUNK_FLAGS |
414 }; | 398 }; |
415 | 399 |
416 | 400 |
417 static const int kPointersToHereAreInterestingMask = | 401 static const int kPointersToHereAreInterestingMask = |
418 1 << POINTERS_TO_HERE_ARE_INTERESTING; | 402 1 << POINTERS_TO_HERE_ARE_INTERESTING; |
419 | 403 |
420 static const int kPointersFromHereAreInterestingMask = | 404 static const int kPointersFromHereAreInterestingMask = |
421 1 << POINTERS_FROM_HERE_ARE_INTERESTING; | 405 1 << POINTERS_FROM_HERE_ARE_INTERESTING; |
422 | 406 |
423 static const int kEvacuationCandidateMask = | 407 static const int kEvacuationCandidateMask = |
424 1 << EVACUATION_CANDIDATE; | 408 1 << EVACUATION_CANDIDATE; |
425 | 409 |
426 static const int kSkipEvacuationSlotsRecordingMask = | 410 static const int kSkipEvacuationSlotsRecordingMask = |
427 (1 << EVACUATION_CANDIDATE) | | 411 (1 << EVACUATION_CANDIDATE) | |
428 (1 << RESCAN_ON_EVACUATION) | | 412 (1 << RESCAN_ON_EVACUATION) | |
429 (1 << IN_FROM_SPACE) | | 413 (1 << IN_FROM_SPACE) | |
430 (1 << IN_TO_SPACE); | 414 (1 << IN_TO_SPACE); |
431 | 415 |
432 static const int kIsPartiallyScannedMask = 1 << IS_PARTIALLY_SCANNED; | |
433 | |
434 void SetPartiallyScannedProgress(int progress) { | |
435 SetFlag(IS_PARTIALLY_SCANNED); | |
436 partially_scanned_progress_ = progress; | |
437 } | |
438 | |
439 bool IsPartiallyScanned() { | |
440 return IsFlagSet(IS_PARTIALLY_SCANNED); | |
441 } | |
442 | |
443 void SetCompletelyScanned() { | |
444 ClearFlag(IS_PARTIALLY_SCANNED); | |
445 } | |
446 | |
447 int PartiallyScannedProgress() { | |
448 ASSERT(IsPartiallyScanned()); | |
449 return partially_scanned_progress_; | |
450 } | |
451 | 416 |
452 void SetFlag(int flag) { | 417 void SetFlag(int flag) { |
453 flags_ |= static_cast<uintptr_t>(1) << flag; | 418 flags_ |= static_cast<uintptr_t>(1) << flag; |
454 } | 419 } |
455 | 420 |
456 void ClearFlag(int flag) { | 421 void ClearFlag(int flag) { |
457 flags_ &= ~(static_cast<uintptr_t>(1) << flag); | 422 flags_ &= ~(static_cast<uintptr_t>(1) << flag); |
458 } | 423 } |
459 | 424 |
460 void SetFlagTo(int flag, bool value) { | 425 void SetFlagTo(int flag, bool value) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 live_byte_count_ + by); | 461 live_byte_count_ + by); |
497 } | 462 } |
498 live_byte_count_ += by; | 463 live_byte_count_ += by; |
499 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); | 464 ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_); |
500 } | 465 } |
501 int LiveBytes() { | 466 int LiveBytes() { |
502 ASSERT(static_cast<unsigned>(live_byte_count_) <= size_); | 467 ASSERT(static_cast<unsigned>(live_byte_count_) <= size_); |
503 return live_byte_count_; | 468 return live_byte_count_; |
504 } | 469 } |
505 | 470 |
506 int write_barrier_counter() { | |
507 return static_cast<int>(write_barrier_counter_); | |
508 } | |
509 | |
510 void set_write_barrier_counter(int counter) { | |
511 write_barrier_counter_ = counter; | |
512 } | |
513 | |
514 | |
515 static void IncrementLiveBytesFromGC(Address address, int by) { | 471 static void IncrementLiveBytesFromGC(Address address, int by) { |
516 MemoryChunk::FromAddress(address)->IncrementLiveBytes(by); | 472 MemoryChunk::FromAddress(address)->IncrementLiveBytes(by); |
517 } | 473 } |
518 | 474 |
519 static void IncrementLiveBytesFromMutator(Address address, int by); | 475 static void IncrementLiveBytesFromMutator(Address address, int by); |
520 | 476 |
521 static const intptr_t kAlignment = | 477 static const intptr_t kAlignment = |
522 (static_cast<uintptr_t>(1) << kPageSizeBits); | 478 (static_cast<uintptr_t>(1) << kPageSizeBits); |
523 | 479 |
524 static const intptr_t kAlignmentMask = kAlignment - 1; | 480 static const intptr_t kAlignmentMask = kAlignment - 1; |
525 | 481 |
526 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; | 482 static const intptr_t kSizeOffset = kPointerSize + kPointerSize; |
527 | 483 |
528 static const intptr_t kLiveBytesOffset = | 484 static const intptr_t kLiveBytesOffset = |
529 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + | 485 kSizeOffset + kPointerSize + kPointerSize + kPointerSize + |
530 kPointerSize + kPointerSize + | 486 kPointerSize + kPointerSize + |
531 kPointerSize + kPointerSize + kPointerSize + kIntSize; | 487 kPointerSize + kPointerSize + kPointerSize + kIntSize; |
532 | 488 |
533 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; | 489 static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; |
534 | 490 |
535 static const size_t kWriteBarrierCounterOffset = | 491 static const size_t kHeaderSize = |
536 kSlotsBufferOffset + kPointerSize + kPointerSize; | 492 kSlotsBufferOffset + kPointerSize + kPointerSize; |
537 static const size_t kPartiallyScannedProgress = | |
538 kWriteBarrierCounterOffset + kPointerSize; | |
539 | |
540 // Actually the partially_scanned_progress_ member is only an int, but on | |
541 // 64 bit the size of MemoryChunk gets rounded up to a 64 bit size so we | |
542 // have to have the header start kPointerSize after the | |
543 // partially_scanned_progress_ member. | |
544 static const size_t kHeaderSize = kPartiallyScannedProgress + kPointerSize; | |
545 | 493 |
546 static const int kBodyOffset = | 494 static const int kBodyOffset = |
547 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); | 495 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); |
548 | 496 |
549 // The start offset of the object area in a page. Aligned to both maps and | 497 // The start offset of the object area in a page. Aligned to both maps and |
550 // code alignment to be suitable for both. Also aligned to 32 words because | 498 // code alignment to be suitable for both. Also aligned to 32 words because |
551 // the marking bitmap is arranged in 32 bit chunks. | 499 // the marking bitmap is arranged in 32 bit chunks. |
552 static const int kObjectStartAlignment = 32 * kPointerSize; | 500 static const int kObjectStartAlignment = 32 * kPointerSize; |
553 static const int kObjectStartOffset = kBodyOffset - 1 + | 501 static const int kObjectStartOffset = kBodyOffset - 1 + |
554 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); | 502 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 // in a fixed array. | 618 // in a fixed array. |
671 Address owner_; | 619 Address owner_; |
672 Heap* heap_; | 620 Heap* heap_; |
673 // Used by the store buffer to keep track of which pages to mark scan-on- | 621 // Used by the store buffer to keep track of which pages to mark scan-on- |
674 // scavenge. | 622 // scavenge. |
675 int store_buffer_counter_; | 623 int store_buffer_counter_; |
676 // Count of bytes marked black on page. | 624 // Count of bytes marked black on page. |
677 int live_byte_count_; | 625 int live_byte_count_; |
678 SlotsBuffer* slots_buffer_; | 626 SlotsBuffer* slots_buffer_; |
679 SkipList* skip_list_; | 627 SkipList* skip_list_; |
680 intptr_t write_barrier_counter_; | |
681 int partially_scanned_progress_; | |
682 | 628 |
683 static MemoryChunk* Initialize(Heap* heap, | 629 static MemoryChunk* Initialize(Heap* heap, |
684 Address base, | 630 Address base, |
685 size_t size, | 631 size_t size, |
686 Address area_start, | 632 Address area_start, |
687 Address area_end, | 633 Address area_end, |
688 Executability executable, | 634 Executability executable, |
689 Space* owner); | 635 Space* owner); |
690 | 636 |
691 friend class MemoryAllocator; | 637 friend class MemoryAllocator; |
(...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2703 } | 2649 } |
2704 // Must be small, since an iteration is used for lookup. | 2650 // Must be small, since an iteration is used for lookup. |
2705 static const int kMaxComments = 64; | 2651 static const int kMaxComments = 64; |
2706 }; | 2652 }; |
2707 #endif | 2653 #endif |
2708 | 2654 |
2709 | 2655 |
2710 } } // namespace v8::internal | 2656 } } // namespace v8::internal |
2711 | 2657 |
2712 #endif // V8_SPACES_H_ | 2658 #endif // V8_SPACES_H_ |
OLD | NEW |