2296
2320
PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n",
2297
2321
Capacity(), Waste(), Available(), pct);
2299
// Report remembered set statistics.
2300
int rset_marked_pointers = 0;
2301
int rset_marked_arrays = 0;
2302
int rset_marked_array_elements = 0;
2303
int cross_gen_pointers = 0;
2304
int cross_gen_array_elements = 0;
2306
PageIterator page_it(this, PageIterator::PAGES_IN_USE);
2307
while (page_it.has_next()) {
2308
Page* p = page_it.next();
2310
for (Address rset_addr = p->RSetStart();
2311
rset_addr < p->RSetEnd();
2312
rset_addr += kIntSize) {
2313
int rset = Memory::int_at(rset_addr);
2317
static_cast<int>(rset_addr - p->address() - Page::kRSetOffset);
2319
for (; bitoff < kBitsPerInt; ++bitoff) {
2320
if ((rset & (1 << bitoff)) != 0) {
2321
int bitpos = intoff*kBitsPerByte + bitoff;
2322
Address slot = p->OffsetToAddress(bitpos << kObjectAlignmentBits);
2323
Object** obj = reinterpret_cast<Object**>(slot);
2324
if (*obj == Heap::raw_unchecked_fixed_array_map()) {
2325
rset_marked_arrays++;
2326
FixedArray* fa = FixedArray::cast(HeapObject::FromAddress(slot));
2328
rset_marked_array_elements += fa->length();
2329
// Manually inline FixedArray::IterateBody
2330
Address elm_start = slot + FixedArray::kHeaderSize;
2331
Address elm_stop = elm_start + fa->length() * kPointerSize;
2332
for (Address elm_addr = elm_start;
2333
elm_addr < elm_stop; elm_addr += kPointerSize) {
2334
// Filter non-heap-object pointers
2335
Object** elm_p = reinterpret_cast<Object**>(elm_addr);
2336
if (Heap::InNewSpace(*elm_p))
2337
cross_gen_array_elements++;
2340
rset_marked_pointers++;
2341
if (Heap::InNewSpace(*obj))
2342
cross_gen_pointers++;
2350
pct = rset_marked_pointers == 0 ?
2351
0 : cross_gen_pointers * 100 / rset_marked_pointers;
2352
PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n",
2353
rset_marked_pointers, cross_gen_pointers, pct);
2354
PrintF(" rset_marked arrays %d, ", rset_marked_arrays);
2355
PrintF(" elements %d, ", rset_marked_array_elements);
2356
pct = rset_marked_array_elements == 0 ? 0
2357
: cross_gen_array_elements * 100 / rset_marked_array_elements;
2358
PrintF(" pointers to new space %d (%%%d)\n", cross_gen_array_elements, pct);
2359
PrintF(" total rset-marked bits %d\n",
2360
(rset_marked_pointers + rset_marked_arrays));
2361
pct = (rset_marked_pointers + rset_marked_array_elements) == 0 ? 0
2362
: (cross_gen_pointers + cross_gen_array_elements) * 100 /
2363
(rset_marked_pointers + rset_marked_array_elements);
2364
PrintF(" total rset pointers %d, true cross generation ones %d (%%%d)\n",
2365
(rset_marked_pointers + rset_marked_array_elements),
2366
(cross_gen_pointers + cross_gen_array_elements),
2369
2323
ClearHistograms();
2370
2324
HeapObjectIterator obj_it(this);
2371
2325
for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next())
2372
2326
CollectHistogramInfo(obj);
2373
2327
ReportHistogram(true);
2377
// Dump the range of remembered set words between [start, end) corresponding
2378
// to the pointers starting at object_p. The allocation_top is an object
2379
// pointer which should not be read past. This is important for large object
2380
// pages, where some bits in the remembered set range do not correspond to
2381
// allocated addresses.
2382
static void PrintRSetRange(Address start, Address end, Object** object_p,
2383
Address allocation_top) {
2384
Address rset_address = start;
2386
// If the range starts on on odd numbered word (eg, for large object extra
2387
// remembered set ranges), print some spaces.
2388
if ((reinterpret_cast<uintptr_t>(start) / kIntSize) % 2 == 1) {
2392
// Loop over all the words in the range.
2393
while (rset_address < end) {
2394
uint32_t rset_word = Memory::uint32_at(rset_address);
2395
int bit_position = 0;
2397
// Loop over all the bits in the word.
2398
while (bit_position < kBitsPerInt) {
2399
if (object_p == reinterpret_cast<Object**>(allocation_top)) {
2400
// Print a bar at the allocation pointer.
2402
} else if (object_p > reinterpret_cast<Object**>(allocation_top)) {
2403
// Do not dereference object_p past the allocation pointer.
2405
} else if ((rset_word & (1 << bit_position)) == 0) {
2406
// Print a dot for zero bits.
2408
} else if (Heap::InNewSpace(*object_p)) {
2409
// Print an X for one bits for pointers to new space.
2412
// Print a circle for one bits for pointers to old space.
2416
// Print a space after every 8th bit except the last.
2417
if (bit_position % 8 == 7 && bit_position != (kBitsPerInt - 1)) {
2421
// Advance to next bit.
2426
// Print a newline after every odd numbered word, otherwise a space.
2427
if ((reinterpret_cast<uintptr_t>(rset_address) / kIntSize) % 2 == 1) {
2433
// Advance to next remembered set word.
2434
rset_address += kIntSize;
2439
void PagedSpace::DoPrintRSet(const char* space_name) {
2440
PageIterator it(this, PageIterator::PAGES_IN_USE);
2441
while (it.has_next()) {
2442
Page* p = it.next();
2443
PrintF("%s page 0x%x:\n", space_name, p);
2444
PrintRSetRange(p->RSetStart(), p->RSetEnd(),
2445
reinterpret_cast<Object**>(p->ObjectAreaStart()),
2446
p->AllocationTop());
2452
void OldSpace::PrintRSet() { DoPrintRSet("old"); }
2455
2331
// -----------------------------------------------------------------------------
2570
2462
PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n",
2571
2463
Capacity(), Waste(), Available(), pct);
2573
// Report remembered set statistics.
2574
int rset_marked_pointers = 0;
2575
int cross_gen_pointers = 0;
2577
PageIterator page_it(this, PageIterator::PAGES_IN_USE);
2578
while (page_it.has_next()) {
2579
Page* p = page_it.next();
2581
for (Address rset_addr = p->RSetStart();
2582
rset_addr < p->RSetEnd();
2583
rset_addr += kIntSize) {
2584
int rset = Memory::int_at(rset_addr);
2588
static_cast<int>(rset_addr - p->address() - Page::kRSetOffset);
2590
for (; bitoff < kBitsPerInt; ++bitoff) {
2591
if ((rset & (1 << bitoff)) != 0) {
2592
int bitpos = intoff*kBitsPerByte + bitoff;
2593
Address slot = p->OffsetToAddress(bitpos << kObjectAlignmentBits);
2594
Object** obj = reinterpret_cast<Object**>(slot);
2595
rset_marked_pointers++;
2596
if (Heap::InNewSpace(*obj))
2597
cross_gen_pointers++;
2604
pct = rset_marked_pointers == 0 ?
2605
0 : cross_gen_pointers * 100 / rset_marked_pointers;
2606
PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n",
2607
rset_marked_pointers, cross_gen_pointers, pct);
2609
2465
ClearHistograms();
2610
2466
HeapObjectIterator obj_it(this);
2611
2467
for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next())
2612
2468
CollectHistogramInfo(obj);
2613
2469
ReportHistogram(false);
2617
void FixedSpace::PrintRSet() { DoPrintRSet(name_); }
2851
2696
return Failure::Exception();
2855
void LargeObjectSpace::ClearRSet() {
2856
ASSERT(Page::is_rset_in_use());
2858
LargeObjectIterator it(this);
2859
for (HeapObject* object = it.next(); object != NULL; object = it.next()) {
2860
// We only have code, sequential strings, or fixed arrays in large
2861
// object space, and only fixed arrays need remembered set support.
2862
if (object->IsFixedArray()) {
2863
// Clear the normal remembered set region of the page;
2864
Page* page = Page::FromAddress(object->address());
2867
// Clear the extra remembered set.
2868
int size = object->Size();
2869
int extra_rset_bytes = ExtraRSetBytesFor(size);
2870
memset(object->address() + size, 0, extra_rset_bytes);
2876
void LargeObjectSpace::IterateRSet(ObjectSlotCallback copy_object_func) {
2877
ASSERT(Page::is_rset_in_use());
2879
static void* lo_rset_histogram = StatsTable::CreateHistogram(
2882
// Keeping this histogram's buckets the same as the paged space histogram.
2883
Page::kObjectAreaSize / kPointerSize,
2699
void LargeObjectSpace::IterateDirtyRegions(ObjectSlotCallback copy_object) {
2886
2700
LargeObjectIterator it(this);
2887
2701
for (HeapObject* object = it.next(); object != NULL; object = it.next()) {
2888
2702
// We only have code, sequential strings, or fixed arrays in large
2889
2703
// object space, and only fixed arrays can possibly contain pointers to
2890
2704
// the young generation.
2891
2705
if (object->IsFixedArray()) {
2892
// Iterate the normal page remembered set range.
2893
2706
Page* page = Page::FromAddress(object->address());
2894
Address object_end = object->address() + object->Size();
2895
int count = Heap::IterateRSetRange(page->ObjectAreaStart(),
2896
Min(page->ObjectAreaEnd(), object_end),
2900
// Iterate the extra array elements.
2901
if (object_end > page->ObjectAreaEnd()) {
2902
count += Heap::IterateRSetRange(page->ObjectAreaEnd(), object_end,
2903
object_end, copy_object_func);
2905
if (lo_rset_histogram != NULL) {
2906
StatsTable::AddHistogramSample(lo_rset_histogram, count);
2707
uint32_t marks = page->GetRegionMarks();
2708
uint32_t newmarks = Page::kAllRegionsCleanMarks;
2710
if (marks != Page::kAllRegionsCleanMarks) {
2711
// For a large page a single dirty mark corresponds to several
2712
// regions (modulo 32). So we treat a large page as a sequence of
2713
// normal pages of size Page::kPageSize having same dirty marks
2714
// and subsequently iterate dirty regions on each of these pages.
2715
Address start = object->address();
2716
Address end = page->ObjectAreaEnd();
2717
Address object_end = start + object->Size();
2719
// Iterate regions of the first normal page covering object.
2720
uint32_t first_region_number = page->GetRegionNumberForAddress(start);
2722
Heap::IterateDirtyRegions(marks >> first_region_number,
2725
&Heap::IteratePointersInDirtyRegion,
2726
copy_object) << first_region_number;
2729
end = start + Page::kPageSize;
2730
while (end <= object_end) {
2731
// Iterate next 32 regions.
2733
Heap::IterateDirtyRegions(marks,
2736
&Heap::IteratePointersInDirtyRegion,
2739
end = start + Page::kPageSize;
2742
if (start != object_end) {
2743
// Iterate the last piece of an object which is less than
2746
Heap::IterateDirtyRegions(marks,
2749
&Heap::IteratePointersInDirtyRegion,
2753
page->SetRegionMarks(newmarks);
3051
void LargeObjectSpace::PrintRSet() {
3052
LargeObjectIterator it(this);
3053
for (HeapObject* object = it.next(); object != NULL; object = it.next()) {
3054
if (object->IsFixedArray()) {
3055
Page* page = Page::FromAddress(object->address());
3057
Address allocation_top = object->address() + object->Size();
3058
PrintF("large page 0x%x:\n", page);
3059
PrintRSetRange(page->RSetStart(), page->RSetEnd(),
3060
reinterpret_cast<Object**>(object->address()),
3062
int extra_array_bytes = object->Size() - Page::kObjectAreaSize;
3063
int extra_rset_bits = RoundUp(extra_array_bytes / kPointerSize,
3065
PrintF("------------------------------------------------------------"
3067
PrintRSetRange(allocation_top,
3068
allocation_top + extra_rset_bits / kBitsPerByte,
3069
reinterpret_cast<Object**>(object->address()
3070
+ Page::kObjectAreaSize),
3076
2899
#endif // DEBUG
3078
2901
} } // namespace v8::internal