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

Side by Side Diff: src/mark-compact.cc

Issue 5736008: Provide baseline for experimental GC implementation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 10 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 // Prepare has selected whether to compact the old generation or not. 74 // Prepare has selected whether to compact the old generation or not.
75 // Tell the tracer. 75 // Tell the tracer.
76 if (IsCompacting()) tracer_->set_is_compacting(); 76 if (IsCompacting()) tracer_->set_is_compacting();
77 77
78 MarkLiveObjects(); 78 MarkLiveObjects();
79 79
80 if (FLAG_collect_maps) ClearNonLiveTransitions(); 80 if (FLAG_collect_maps) ClearNonLiveTransitions();
81 81
82 SweepLargeObjectSpace(); 82 SweepLargeObjectSpace();
83 83
84 if (IsCompacting()) { 84 SweepSpaces();
85 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_COMPACT); 85 PcToCodeCache::FlushPcToCodeCache();
86 EncodeForwardingAddresses();
87
88 Heap::MarkMapPointersAsEncoded(true);
89 UpdatePointers();
90 Heap::MarkMapPointersAsEncoded(false);
91 PcToCodeCache::FlushPcToCodeCache();
92
93 RelocateObjects();
94 } else {
95 SweepSpaces();
96 PcToCodeCache::FlushPcToCodeCache();
97 }
98 86
99 Finish(); 87 Finish();
100 88
101 // Save the count of marked objects remaining after the collection and 89 // Save the count of marked objects remaining after the collection and
102 // null out the GC tracer. 90 // null out the GC tracer.
103 previous_marked_count_ = tracer_->marked_count(); 91 previous_marked_count_ = tracer_->marked_count();
104 ASSERT(previous_marked_count_ == 0); 92 ASSERT(previous_marked_count_ == 0);
105 tracer_ = NULL; 93 tracer_ = NULL;
106 } 94 }
107 95
108 96
109 void MarkCompactCollector::Prepare(GCTracer* tracer) { 97 void MarkCompactCollector::Prepare(GCTracer* tracer) {
98 FLAG_flush_code = false;
99 FLAG_always_compact = false;
100 FLAG_never_compact = true;
101
110 // Rather than passing the tracer around we stash it in a static member 102 // Rather than passing the tracer around we stash it in a static member
111 // variable. 103 // variable.
112 tracer_ = tracer; 104 tracer_ = tracer;
113 105
114 #ifdef DEBUG 106 #ifdef DEBUG
115 ASSERT(state_ == IDLE); 107 ASSERT(state_ == IDLE);
116 state_ = PREPARE_GC; 108 state_ = PREPARE_GC;
117 #endif 109 #endif
118 ASSERT(!FLAG_always_compact || !FLAG_never_compact); 110 ASSERT(!FLAG_always_compact || !FLAG_never_compact);
119 111
(...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1446 on_dead_path = false; 1438 on_dead_path = false;
1447 current->ClearNonLiveTransitions(real_prototype); 1439 current->ClearNonLiveTransitions(real_prototype);
1448 } 1440 }
1449 *HeapObject::RawField(current, Map::kPrototypeOffset) = 1441 *HeapObject::RawField(current, Map::kPrototypeOffset) =
1450 real_prototype; 1442 real_prototype;
1451 current = reinterpret_cast<Map*>(next); 1443 current = reinterpret_cast<Map*>(next);
1452 } 1444 }
1453 } 1445 }
1454 } 1446 }
1455 1447
1456 // -------------------------------------------------------------------------
1457 // Phase 2: Encode forwarding addresses.
1458 // When compacting, forwarding addresses for objects in old space and map
1459 // space are encoded in their map pointer word (along with an encoding of
1460 // their map pointers).
1461 //
1462 // The excact encoding is described in the comments for class MapWord in
1463 // objects.h.
1464 //
1465 // An address range [start, end) can have both live and non-live objects.
1466 // Maximal non-live regions are marked so they can be skipped on subsequent
1467 // sweeps of the heap. A distinguished map-pointer encoding is used to mark
1468 // free regions of one-word size (in which case the next word is the start
1469 // of a live object). A second distinguished map-pointer encoding is used
1470 // to mark free regions larger than one word, and the size of the free
1471 // region (including the first word) is written to the second word of the
1472 // region.
1473 //
1474 // Any valid map page offset must lie in the object area of the page, so map
1475 // page offsets less than Page::kObjectStartOffset are invalid. We use a
1476 // pair of distinguished invalid map encodings (for single word and multiple
1477 // words) to indicate free regions in the page found during computation of
1478 // forwarding addresses and skipped over in subsequent sweeps.
1479
1480
1481 // Encode a free region, defined by the given start address and size, in the
1482 // first word or two of the region.
1483 void EncodeFreeRegion(Address free_start, int free_size) {
1484 ASSERT(free_size >= kIntSize);
1485 if (free_size == kIntSize) {
1486 Memory::uint32_at(free_start) = MarkCompactCollector::kSingleFreeEncoding;
1487 } else {
1488 ASSERT(free_size >= 2 * kIntSize);
1489 Memory::uint32_at(free_start) = MarkCompactCollector::kMultiFreeEncoding;
1490 Memory::int_at(free_start + kIntSize) = free_size;
1491 }
1492
1493 #ifdef DEBUG
1494 // Zap the body of the free region.
1495 if (FLAG_enable_slow_asserts) {
1496 for (int offset = 2 * kIntSize;
1497 offset < free_size;
1498 offset += kPointerSize) {
1499 Memory::Address_at(free_start + offset) = kZapValue;
1500 }
1501 }
1502 #endif
1503 }
1504
1505
1506 // Try to promote all objects in new space. Heap numbers and sequential
1507 // strings are promoted to the code space, large objects to large object space,
1508 // and all others to the old space.
1509 inline MaybeObject* MCAllocateFromNewSpace(HeapObject* object,
1510 int object_size) {
1511 MaybeObject* forwarded;
1512 if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
1513 forwarded = Failure::Exception();
1514 } else {
1515 OldSpace* target_space = Heap::TargetSpace(object);
1516 ASSERT(target_space == Heap::old_pointer_space() ||
1517 target_space == Heap::old_data_space());
1518 forwarded = target_space->MCAllocateRaw(object_size);
1519 }
1520 Object* result;
1521 if (!forwarded->ToObject(&result)) {
1522 result = Heap::new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
1523 }
1524 return result;
1525 }
1526
1527
1528 // Allocation functions for the paged spaces call the space's MCAllocateRaw.
1529 MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace(
1530 HeapObject* ignore,
1531 int object_size) {
1532 return Heap::old_pointer_space()->MCAllocateRaw(object_size);
1533 }
1534
1535
1536 MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldDataSpace(
1537 HeapObject* ignore,
1538 int object_size) {
1539 return Heap::old_data_space()->MCAllocateRaw(object_size);
1540 }
1541
1542
1543 MUST_USE_RESULT inline MaybeObject* MCAllocateFromCodeSpace(
1544 HeapObject* ignore,
1545 int object_size) {
1546 return Heap::code_space()->MCAllocateRaw(object_size);
1547 }
1548
1549
1550 MUST_USE_RESULT inline MaybeObject* MCAllocateFromMapSpace(
1551 HeapObject* ignore,
1552 int object_size) {
1553 return Heap::map_space()->MCAllocateRaw(object_size);
1554 }
1555
1556
1557 MUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(HeapObject* ignore,
1558 int object_size) {
1559 return Heap::cell_space()->MCAllocateRaw(object_size);
1560 }
1561
1562
1563 // The forwarding address is encoded at the same offset as the current
1564 // to-space object, but in from space.
1565 inline void EncodeForwardingAddressInNewSpace(HeapObject* old_object,
1566 int object_size,
1567 Object* new_object,
1568 int* ignored) {
1569 int offset =
1570 Heap::new_space()->ToSpaceOffsetForAddress(old_object->address());
1571 Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset) =
1572 HeapObject::cast(new_object)->address();
1573 }
1574
1575
1576 // The forwarding address is encoded in the map pointer of the object as an
1577 // offset (in terms of live bytes) from the address of the first live object
1578 // in the page.
1579 inline void EncodeForwardingAddressInPagedSpace(HeapObject* old_object,
1580 int object_size,
1581 Object* new_object,
1582 int* offset) {
1583 // Record the forwarding address of the first live object if necessary.
1584 if (*offset == 0) {
1585 Page::FromAddress(old_object->address())->mc_first_forwarded =
1586 HeapObject::cast(new_object)->address();
1587 }
1588
1589 MapWord encoding =
1590 MapWord::EncodeAddress(old_object->map()->address(), *offset);
1591 old_object->set_map_word(encoding);
1592 *offset += object_size;
1593 ASSERT(*offset <= Page::kObjectAreaSize);
1594 }
1595
1596
1597 // Most non-live objects are ignored.
1598 inline void IgnoreNonLiveObject(HeapObject* object) {}
1599
1600
1601 // Function template that, given a range of addresses (eg, a semispace or a
1602 // paged space page), iterates through the objects in the range to clear
1603 // mark bits and compute and encode forwarding addresses. As a side effect,
1604 // maximal free chunks are marked so that they can be skipped on subsequent
1605 // sweeps.
1606 //
1607 // The template parameters are an allocation function, a forwarding address
1608 // encoding function, and a function to process non-live objects.
1609 template<MarkCompactCollector::AllocationFunction Alloc,
1610 MarkCompactCollector::EncodingFunction Encode,
1611 MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
1612 inline void EncodeForwardingAddressesInRange(Address start,
1613 Address end,
1614 int* offset) {
1615 // The start address of the current free region while sweeping the space.
1616 // This address is set when a transition from live to non-live objects is
1617 // encountered. A value (an encoding of the 'next free region' pointer)
1618 // is written to memory at this address when a transition from non-live to
1619 // live objects is encountered.
1620 Address free_start = NULL;
1621
1622 // A flag giving the state of the previously swept object. Initially true
1623 // to ensure that free_start is initialized to a proper address before
1624 // trying to write to it.
1625 bool is_prev_alive = true;
1626
1627 int object_size; // Will be set on each iteration of the loop.
1628 for (Address current = start; current < end; current += object_size) {
1629 HeapObject* object = HeapObject::FromAddress(current);
1630 if (object->IsMarked()) {
1631 object->ClearMark();
1632 MarkCompactCollector::tracer()->decrement_marked_count();
1633 object_size = object->Size();
1634
1635 // Allocation cannot fail, because we are compacting the space.
1636 Object* forwarded = Alloc(object, object_size)->ToObjectUnchecked();
1637 Encode(object, object_size, forwarded, offset);
1638
1639 #ifdef DEBUG
1640 if (FLAG_gc_verbose) {
1641 PrintF("forward %p -> %p.\n", object->address(),
1642 HeapObject::cast(forwarded)->address());
1643 }
1644 #endif
1645 if (!is_prev_alive) { // Transition from non-live to live.
1646 EncodeFreeRegion(free_start, static_cast<int>(current - free_start));
1647 is_prev_alive = true;
1648 }
1649 } else { // Non-live object.
1650 object_size = object->Size();
1651 ProcessNonLive(object);
1652 if (is_prev_alive) { // Transition from live to non-live.
1653 free_start = current;
1654 is_prev_alive = false;
1655 }
1656 }
1657 }
1658
1659 // If we ended on a free region, mark it.
1660 if (!is_prev_alive) {
1661 EncodeFreeRegion(free_start, static_cast<int>(end - free_start));
1662 }
1663 }
1664
1665
1666 // Functions to encode the forwarding pointers in each compactable space.
1667 void MarkCompactCollector::EncodeForwardingAddressesInNewSpace() {
1668 int ignored;
1669 EncodeForwardingAddressesInRange<MCAllocateFromNewSpace,
1670 EncodeForwardingAddressInNewSpace,
1671 IgnoreNonLiveObject>(
1672 Heap::new_space()->bottom(),
1673 Heap::new_space()->top(),
1674 &ignored);
1675 }
1676
1677
1678 template<MarkCompactCollector::AllocationFunction Alloc,
1679 MarkCompactCollector::ProcessNonLiveFunction ProcessNonLive>
1680 void MarkCompactCollector::EncodeForwardingAddressesInPagedSpace(
1681 PagedSpace* space) {
1682 PageIterator it(space, PageIterator::PAGES_IN_USE);
1683 while (it.has_next()) {
1684 Page* p = it.next();
1685
1686 // The offset of each live object in the page from the first live object
1687 // in the page.
1688 int offset = 0;
1689 EncodeForwardingAddressesInRange<Alloc,
1690 EncodeForwardingAddressInPagedSpace,
1691 ProcessNonLive>(
1692 p->ObjectAreaStart(),
1693 p->AllocationTop(),
1694 &offset);
1695 }
1696 }
1697
1698 1448
1699 // We scavange new space simultaneously with sweeping. This is done in two 1449 // We scavange new space simultaneously with sweeping. This is done in two
1700 // passes. 1450 // passes.
1701 // The first pass migrates all alive objects from one semispace to another or 1451 // The first pass migrates all alive objects from one semispace to another or
1702 // promotes them to old space. Forwading address is written directly into 1452 // promotes them to old space. Forwading address is written directly into
1703 // first word of object without any encoding. If object is dead we are writing 1453 // first word of object without any encoding. If object is dead we are writing
1704 // NULL as a forwarding address. 1454 // NULL as a forwarding address.
1705 // The second pass updates pointers to new space in all spaces. It is possible 1455 // The second pass updates pointers to new space in all spaces. It is possible
1706 // to encounter pointers to dead objects during traversal of dirty regions we 1456 // to encounter pointers to dead objects during traversal of dirty regions we
1707 // should clear them to avoid encountering them during next dirty regions 1457 // should clear them to avoid encountering them during next dirty regions
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
2061 } else { 1811 } else {
2062 ASSERT(new_allocation_top_page == first_empty_page); 1812 ASSERT(new_allocation_top_page == first_empty_page);
2063 } 1813 }
2064 #endif 1814 #endif
2065 1815
2066 space->SetTop(new_allocation_top); 1816 space->SetTop(new_allocation_top);
2067 } 1817 }
2068 } 1818 }
2069 1819
2070 1820
2071 void MarkCompactCollector::EncodeForwardingAddresses() {
2072 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
2073 // Objects in the active semispace of the young generation may be
2074 // relocated to the inactive semispace (if not promoted). Set the
2075 // relocation info to the beginning of the inactive semispace.
2076 Heap::new_space()->MCResetRelocationInfo();
2077
2078 // Compute the forwarding pointers in each space.
2079 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace,
2080 ReportDeleteIfNeeded>(
2081 Heap::old_pointer_space());
2082
2083 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace,
2084 IgnoreNonLiveObject>(
2085 Heap::old_data_space());
2086
2087 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace,
2088 ReportDeleteIfNeeded>(
2089 Heap::code_space());
2090
2091 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace,
2092 IgnoreNonLiveObject>(
2093 Heap::cell_space());
2094
2095
2096 // Compute new space next to last after the old and code spaces have been
2097 // compacted. Objects in new space can be promoted to old or code space.
2098 EncodeForwardingAddressesInNewSpace();
2099
2100 // Compute map space last because computing forwarding addresses
2101 // overwrites non-live objects. Objects in the other spaces rely on
2102 // non-live map pointers to get the sizes of non-live objects.
2103 EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace,
2104 IgnoreNonLiveObject>(
2105 Heap::map_space());
2106
2107 // Write relocation info to the top page, so we can use it later. This is
2108 // done after promoting objects from the new space so we get the correct
2109 // allocation top.
2110 Heap::old_pointer_space()->MCWriteRelocationInfoToPage();
2111 Heap::old_data_space()->MCWriteRelocationInfoToPage();
2112 Heap::code_space()->MCWriteRelocationInfoToPage();
2113 Heap::map_space()->MCWriteRelocationInfoToPage();
2114 Heap::cell_space()->MCWriteRelocationInfoToPage();
2115 }
2116
2117
2118 class MapIterator : public HeapObjectIterator {
2119 public:
2120 MapIterator() : HeapObjectIterator(Heap::map_space(), &SizeCallback) { }
2121
2122 explicit MapIterator(Address start)
2123 : HeapObjectIterator(Heap::map_space(), start, &SizeCallback) { }
2124
2125 private:
2126 static int SizeCallback(HeapObject* unused) {
2127 USE(unused);
2128 return Map::kSize;
2129 }
2130 };
2131
2132
2133 class MapCompact {
2134 public:
2135 explicit MapCompact(int live_maps)
2136 : live_maps_(live_maps),
2137 to_evacuate_start_(Heap::map_space()->TopAfterCompaction(live_maps)),
2138 map_to_evacuate_it_(to_evacuate_start_),
2139 first_map_to_evacuate_(
2140 reinterpret_cast<Map*>(HeapObject::FromAddress(to_evacuate_start_))) {
2141 }
2142
2143 void CompactMaps() {
2144 // As we know the number of maps to evacuate beforehand,
2145 // we stop then there is no more vacant maps.
2146 for (Map* next_vacant_map = NextVacantMap();
2147 next_vacant_map;
2148 next_vacant_map = NextVacantMap()) {
2149 EvacuateMap(next_vacant_map, NextMapToEvacuate());
2150 }
2151
2152 #ifdef DEBUG
2153 CheckNoMapsToEvacuate();
2154 #endif
2155 }
2156
2157 void UpdateMapPointersInRoots() {
2158 Heap::IterateRoots(&map_updating_visitor_, VISIT_ONLY_STRONG);
2159 GlobalHandles::IterateWeakRoots(&map_updating_visitor_);
2160 }
2161
2162 void UpdateMapPointersInPagedSpace(PagedSpace* space) {
2163 ASSERT(space != Heap::map_space());
2164
2165 PageIterator it(space, PageIterator::PAGES_IN_USE);
2166 while (it.has_next()) {
2167 Page* p = it.next();
2168 UpdateMapPointersInRange(p->ObjectAreaStart(), p->AllocationTop());
2169 }
2170 }
2171
2172 void UpdateMapPointersInNewSpace() {
2173 NewSpace* space = Heap::new_space();
2174 UpdateMapPointersInRange(space->bottom(), space->top());
2175 }
2176
2177 void UpdateMapPointersInLargeObjectSpace() {
2178 LargeObjectIterator it(Heap::lo_space());
2179 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
2180 UpdateMapPointersInObject(obj);
2181 }
2182
2183 void Finish() {
2184 Heap::map_space()->FinishCompaction(to_evacuate_start_, live_maps_);
2185 }
2186
2187 private:
2188 int live_maps_;
2189 Address to_evacuate_start_;
2190 MapIterator vacant_map_it_;
2191 MapIterator map_to_evacuate_it_;
2192 Map* first_map_to_evacuate_;
2193
2194 // Helper class for updating map pointers in HeapObjects.
2195 class MapUpdatingVisitor: public ObjectVisitor {
2196 public:
2197 void VisitPointer(Object** p) {
2198 UpdateMapPointer(p);
2199 }
2200
2201 void VisitPointers(Object** start, Object** end) {
2202 for (Object** p = start; p < end; p++) UpdateMapPointer(p);
2203 }
2204
2205 private:
2206 void UpdateMapPointer(Object** p) {
2207 if (!(*p)->IsHeapObject()) return;
2208 HeapObject* old_map = reinterpret_cast<HeapObject*>(*p);
2209
2210 // Moved maps are tagged with overflowed map word. They are the only
2211 // objects those map word is overflowed as marking is already complete.
2212 MapWord map_word = old_map->map_word();
2213 if (!map_word.IsOverflowed()) return;
2214
2215 *p = GetForwardedMap(map_word);
2216 }
2217 };
2218
2219 static MapUpdatingVisitor map_updating_visitor_;
2220
2221 static Map* NextMap(MapIterator* it, HeapObject* last, bool live) {
2222 while (true) {
2223 HeapObject* next = it->next();
2224 ASSERT(next != NULL);
2225 if (next == last)
2226 return NULL;
2227 ASSERT(!next->IsOverflowed());
2228 ASSERT(!next->IsMarked());
2229 ASSERT(next->IsMap() || FreeListNode::IsFreeListNode(next));
2230 if (next->IsMap() == live)
2231 return reinterpret_cast<Map*>(next);
2232 }
2233 }
2234
2235 Map* NextVacantMap() {
2236 Map* map = NextMap(&vacant_map_it_, first_map_to_evacuate_, false);
2237 ASSERT(map == NULL || FreeListNode::IsFreeListNode(map));
2238 return map;
2239 }
2240
2241 Map* NextMapToEvacuate() {
2242 Map* map = NextMap(&map_to_evacuate_it_, NULL, true);
2243 ASSERT(map != NULL);
2244 ASSERT(map->IsMap());
2245 return map;
2246 }
2247
2248 static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) {
2249 ASSERT(FreeListNode::IsFreeListNode(vacant_map));
2250 ASSERT(map_to_evacuate->IsMap());
2251
2252 ASSERT(Map::kSize % 4 == 0);
2253
2254 Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(vacant_map->address(),
2255 map_to_evacuate->address(),
2256 Map::kSize);
2257
2258 ASSERT(vacant_map->IsMap()); // Due to memcpy above.
2259
2260 MapWord forwarding_map_word = MapWord::FromMap(vacant_map);
2261 forwarding_map_word.SetOverflow();
2262 map_to_evacuate->set_map_word(forwarding_map_word);
2263
2264 ASSERT(map_to_evacuate->map_word().IsOverflowed());
2265 ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map);
2266 }
2267
2268 static Map* GetForwardedMap(MapWord map_word) {
2269 ASSERT(map_word.IsOverflowed());
2270 map_word.ClearOverflow();
2271 Map* new_map = map_word.ToMap();
2272 ASSERT_MAP_ALIGNED(new_map->address());
2273 return new_map;
2274 }
2275
2276 static int UpdateMapPointersInObject(HeapObject* obj) {
2277 ASSERT(!obj->IsMarked());
2278 Map* map = obj->map();
2279 ASSERT(Heap::map_space()->Contains(map));
2280 MapWord map_word = map->map_word();
2281 ASSERT(!map_word.IsMarked());
2282 if (map_word.IsOverflowed()) {
2283 Map* new_map = GetForwardedMap(map_word);
2284 ASSERT(Heap::map_space()->Contains(new_map));
2285 obj->set_map(new_map);
2286
2287 #ifdef DEBUG
2288 if (FLAG_gc_verbose) {
2289 PrintF("update %p : %p -> %p\n",
2290 obj->address(),
2291 reinterpret_cast<void*>(map),
2292 reinterpret_cast<void*>(new_map));
2293 }
2294 #endif
2295 }
2296
2297 int size = obj->SizeFromMap(map);
2298 obj->IterateBody(map->instance_type(), size, &map_updating_visitor_);
2299 return size;
2300 }
2301
2302 static void UpdateMapPointersInRange(Address start, Address end) {
2303 HeapObject* object;
2304 int size;
2305 for (Address current = start; current < end; current += size) {
2306 object = HeapObject::FromAddress(current);
2307 size = UpdateMapPointersInObject(object);
2308 ASSERT(size > 0);
2309 }
2310 }
2311
2312 #ifdef DEBUG
2313 void CheckNoMapsToEvacuate() {
2314 if (!FLAG_enable_slow_asserts)
2315 return;
2316
2317 for (HeapObject* obj = map_to_evacuate_it_.next();
2318 obj != NULL; obj = map_to_evacuate_it_.next())
2319 ASSERT(FreeListNode::IsFreeListNode(obj));
2320 }
2321 #endif
2322 };
2323
2324 MapCompact::MapUpdatingVisitor MapCompact::map_updating_visitor_;
2325
2326
2327 void MarkCompactCollector::SweepSpaces() { 1821 void MarkCompactCollector::SweepSpaces() {
2328 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); 1822 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
2329 1823
2330 ASSERT(state_ == SWEEP_SPACES); 1824 ASSERT(state_ == SWEEP_SPACES);
2331 ASSERT(!IsCompacting()); 1825 ASSERT(!IsCompacting());
2332 // Noncompacting collections simply sweep the spaces to clear the mark 1826 // Noncompacting collections simply sweep the spaces to clear the mark
2333 // bits and free the nonlive blocks (for old and map spaces). We sweep 1827 // bits and free the nonlive blocks (for old and map spaces). We sweep
2334 // the map space last because freeing non-live maps overwrites them and 1828 // the map space last because freeing non-live maps overwrites them and
2335 // the other spaces rely on possibly non-live maps to get the sizes for 1829 // the other spaces rely on possibly non-live maps to get the sizes for
2336 // non-live objects. 1830 // non-live objects.
2337 SweepSpace(Heap::old_pointer_space()); 1831 SweepSpace(Heap::old_pointer_space());
2338 SweepSpace(Heap::old_data_space()); 1832 SweepSpace(Heap::old_data_space());
2339 SweepSpace(Heap::code_space()); 1833 SweepSpace(Heap::code_space());
2340 SweepSpace(Heap::cell_space()); 1834 SweepSpace(Heap::cell_space());
2341 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); 1835 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
2342 SweepNewSpace(Heap::new_space()); 1836 SweepNewSpace(Heap::new_space());
2343 } 1837 }
2344 SweepSpace(Heap::map_space()); 1838 SweepSpace(Heap::map_space());
2345 1839
2346 Heap::IterateDirtyRegions(Heap::map_space(), 1840 Heap::IterateDirtyRegions(Heap::map_space(),
2347 &Heap::IteratePointersInDirtyMapsRegion, 1841 &Heap::IteratePointersInDirtyMapsRegion,
2348 &UpdatePointerToNewGen, 1842 &UpdatePointerToNewGen,
2349 Heap::WATERMARK_SHOULD_BE_VALID); 1843 Heap::WATERMARK_SHOULD_BE_VALID);
2350 1844
2351 intptr_t live_maps_size = Heap::map_space()->Size(); 1845 ASSERT(live_map_objects_size_ == Heap::map_space()->Size());
2352 int live_maps = static_cast<int>(live_maps_size / Map::kSize);
2353 ASSERT(live_map_objects_size_ == live_maps_size);
2354
2355 if (Heap::map_space()->NeedsCompaction(live_maps)) {
2356 MapCompact map_compact(live_maps);
2357
2358 map_compact.CompactMaps();
2359 map_compact.UpdateMapPointersInRoots();
2360
2361 PagedSpaces spaces;
2362 for (PagedSpace* space = spaces.next();
2363 space != NULL; space = spaces.next()) {
2364 if (space == Heap::map_space()) continue;
2365 map_compact.UpdateMapPointersInPagedSpace(space);
2366 }
2367 map_compact.UpdateMapPointersInNewSpace();
2368 map_compact.UpdateMapPointersInLargeObjectSpace();
2369
2370 map_compact.Finish();
2371 }
2372 } 1846 }
2373 1847
2374 1848
2375 // Iterate the live objects in a range of addresses (eg, a page or a 1849 // Iterate the live objects in a range of addresses (eg, a page or a
2376 // semispace). The live regions of the range have been linked into a list. 1850 // semispace). The live regions of the range have been linked into a list.
2377 // The first live region is [first_live_start, first_live_end), and the last 1851 // The first live region is [first_live_start, first_live_end), and the last
2378 // address in the range is top. The callback function is used to get the 1852 // address in the range is top. The callback function is used to get the
2379 // size of each live object. 1853 // size of each live object.
2380 int MarkCompactCollector::IterateLiveObjectsInRange( 1854 int MarkCompactCollector::IterateLiveObjectsInRange(
2381 Address start, 1855 Address start,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2414 while (it.has_next()) { 1888 while (it.has_next()) {
2415 Page* p = it.next(); 1889 Page* p = it.next();
2416 total += IterateLiveObjectsInRange(p->ObjectAreaStart(), 1890 total += IterateLiveObjectsInRange(p->ObjectAreaStart(),
2417 p->AllocationTop(), 1891 p->AllocationTop(),
2418 size_f); 1892 size_f);
2419 } 1893 }
2420 return total; 1894 return total;
2421 } 1895 }
2422 1896
2423 1897
2424 // -------------------------------------------------------------------------
2425 // Phase 3: Update pointers
2426
2427 // Helper class for updating pointers in HeapObjects.
2428 class UpdatingVisitor: public ObjectVisitor {
2429 public:
2430 void VisitPointer(Object** p) {
2431 UpdatePointer(p);
2432 }
2433
2434 void VisitPointers(Object** start, Object** end) {
2435 // Mark all HeapObject pointers in [start, end)
2436 for (Object** p = start; p < end; p++) UpdatePointer(p);
2437 }
2438
2439 void VisitCodeTarget(RelocInfo* rinfo) {
2440 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
2441 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
2442 VisitPointer(&target);
2443 rinfo->set_target_address(
2444 reinterpret_cast<Code*>(target)->instruction_start());
2445 }
2446
2447 void VisitDebugTarget(RelocInfo* rinfo) {
2448 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
2449 rinfo->IsPatchedReturnSequence()) ||
2450 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
2451 rinfo->IsPatchedDebugBreakSlotSequence()));
2452 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
2453 VisitPointer(&target);
2454 rinfo->set_call_address(
2455 reinterpret_cast<Code*>(target)->instruction_start());
2456 }
2457
2458 private:
2459 void UpdatePointer(Object** p) {
2460 if (!(*p)->IsHeapObject()) return;
2461
2462 HeapObject* obj = HeapObject::cast(*p);
2463 Address old_addr = obj->address();
2464 Address new_addr;
2465 ASSERT(!Heap::InFromSpace(obj));
2466
2467 if (Heap::new_space()->Contains(obj)) {
2468 Address forwarding_pointer_addr =
2469 Heap::new_space()->FromSpaceLow() +
2470 Heap::new_space()->ToSpaceOffsetForAddress(old_addr);
2471 new_addr = Memory::Address_at(forwarding_pointer_addr);
2472
2473 #ifdef DEBUG
2474 ASSERT(Heap::old_pointer_space()->Contains(new_addr) ||
2475 Heap::old_data_space()->Contains(new_addr) ||
2476 Heap::new_space()->FromSpaceContains(new_addr) ||
2477 Heap::lo_space()->Contains(HeapObject::FromAddress(new_addr)));
2478
2479 if (Heap::new_space()->FromSpaceContains(new_addr)) {
2480 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
2481 Heap::new_space()->ToSpaceOffsetForAddress(old_addr));
2482 }
2483 #endif
2484
2485 } else if (Heap::lo_space()->Contains(obj)) {
2486 // Don't move objects in the large object space.
2487 return;
2488
2489 } else {
2490 #ifdef DEBUG
2491 PagedSpaces spaces;
2492 PagedSpace* original_space = spaces.next();
2493 while (original_space != NULL) {
2494 if (original_space->Contains(obj)) break;
2495 original_space = spaces.next();
2496 }
2497 ASSERT(original_space != NULL);
2498 #endif
2499 new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj);
2500 ASSERT(original_space->Contains(new_addr));
2501 ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <=
2502 original_space->MCSpaceOffsetForAddress(old_addr));
2503 }
2504
2505 *p = HeapObject::FromAddress(new_addr);
2506
2507 #ifdef DEBUG
2508 if (FLAG_gc_verbose) {
2509 PrintF("update %p : %p -> %p\n",
2510 reinterpret_cast<Address>(p), old_addr, new_addr);
2511 }
2512 #endif
2513 }
2514 };
2515
2516
2517 void MarkCompactCollector::UpdatePointers() {
2518 #ifdef DEBUG
2519 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
2520 state_ = UPDATE_POINTERS;
2521 #endif
2522 UpdatingVisitor updating_visitor;
2523 Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
2524 GlobalHandles::IterateWeakRoots(&updating_visitor);
2525
2526 // Update the pointer to the head of the weak list of global contexts.
2527 updating_visitor.VisitPointer(&Heap::global_contexts_list_);
2528
2529 int live_maps_size = IterateLiveObjects(Heap::map_space(),
2530 &UpdatePointersInOldObject);
2531 int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
2532 &UpdatePointersInOldObject);
2533 int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(),
2534 &UpdatePointersInOldObject);
2535 int live_codes_size = IterateLiveObjects(Heap::code_space(),
2536 &UpdatePointersInOldObject);
2537 int live_cells_size = IterateLiveObjects(Heap::cell_space(),
2538 &UpdatePointersInOldObject);
2539 int live_news_size = IterateLiveObjects(Heap::new_space(),
2540 &UpdatePointersInNewObject);
2541
2542 // Large objects do not move, the map word can be updated directly.
2543 LargeObjectIterator it(Heap::lo_space());
2544 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
2545 UpdatePointersInNewObject(obj);
2546 }
2547
2548 USE(live_maps_size);
2549 USE(live_pointer_olds_size);
2550 USE(live_data_olds_size);
2551 USE(live_codes_size);
2552 USE(live_cells_size);
2553 USE(live_news_size);
2554 ASSERT(live_maps_size == live_map_objects_size_);
2555 ASSERT(live_data_olds_size == live_old_data_objects_size_);
2556 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
2557 ASSERT(live_codes_size == live_code_objects_size_);
2558 ASSERT(live_cells_size == live_cell_objects_size_);
2559 ASSERT(live_news_size == live_young_objects_size_);
2560 }
2561
2562
2563 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) {
2564 // Keep old map pointers
2565 Map* old_map = obj->map();
2566 ASSERT(old_map->IsHeapObject());
2567
2568 Address forwarded = GetForwardingAddressInOldSpace(old_map);
2569
2570 ASSERT(Heap::map_space()->Contains(old_map));
2571 ASSERT(Heap::map_space()->Contains(forwarded));
2572 #ifdef DEBUG
2573 if (FLAG_gc_verbose) {
2574 PrintF("update %p : %p -> %p\n", obj->address(), old_map->address(),
2575 forwarded);
2576 }
2577 #endif
2578 // Update the map pointer.
2579 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(forwarded)));
2580
2581 // We have to compute the object size relying on the old map because
2582 // map objects are not relocated yet.
2583 int obj_size = obj->SizeFromMap(old_map);
2584
2585 // Update pointers in the object body.
2586 UpdatingVisitor updating_visitor;
2587 obj->IterateBody(old_map->instance_type(), obj_size, &updating_visitor);
2588 return obj_size;
2589 }
2590
2591
2592 int MarkCompactCollector::UpdatePointersInOldObject(HeapObject* obj) {
2593 // Decode the map pointer.
2594 MapWord encoding = obj->map_word();
2595 Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
2596 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
2597
2598 // At this point, the first word of map_addr is also encoded, cannot
2599 // cast it to Map* using Map::cast.
2600 Map* map = reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr));
2601 int obj_size = obj->SizeFromMap(map);
2602 InstanceType type = map->instance_type();
2603
2604 // Update map pointer.
2605 Address new_map_addr = GetForwardingAddressInOldSpace(map);
2606 int offset = encoding.DecodeOffset();
2607 obj->set_map_word(MapWord::EncodeAddress(new_map_addr, offset));
2608
2609 #ifdef DEBUG
2610 if (FLAG_gc_verbose) {
2611 PrintF("update %p : %p -> %p\n", obj->address(),
2612 map_addr, new_map_addr);
2613 }
2614 #endif
2615
2616 // Update pointers in the object body.
2617 UpdatingVisitor updating_visitor;
2618 obj->IterateBody(type, obj_size, &updating_visitor);
2619 return obj_size;
2620 }
2621
2622
2623 Address MarkCompactCollector::GetForwardingAddressInOldSpace(HeapObject* obj) {
2624 // Object should either in old or map space.
2625 MapWord encoding = obj->map_word();
2626
2627 // Offset to the first live object's forwarding address.
2628 int offset = encoding.DecodeOffset();
2629 Address obj_addr = obj->address();
2630
2631 // Find the first live object's forwarding address.
2632 Page* p = Page::FromAddress(obj_addr);
2633 Address first_forwarded = p->mc_first_forwarded;
2634
2635 // Page start address of forwarded address.
2636 Page* forwarded_page = Page::FromAddress(first_forwarded);
2637 int forwarded_offset = forwarded_page->Offset(first_forwarded);
2638
2639 // Find end of allocation in the page of first_forwarded.
2640 int mc_top_offset = forwarded_page->AllocationWatermarkOffset();
2641
2642 // Check if current object's forward pointer is in the same page
2643 // as the first live object's forwarding pointer
2644 if (forwarded_offset + offset < mc_top_offset) {
2645 // In the same page.
2646 return first_forwarded + offset;
2647 }
2648
2649 // Must be in the next page, NOTE: this may cross chunks.
2650 Page* next_page = forwarded_page->next_page();
2651 ASSERT(next_page->is_valid());
2652
2653 offset -= (mc_top_offset - forwarded_offset);
2654 offset += Page::kObjectStartOffset;
2655
2656 ASSERT_PAGE_OFFSET(offset);
2657 ASSERT(next_page->OffsetToAddress(offset) < next_page->AllocationTop());
2658
2659 return next_page->OffsetToAddress(offset);
2660 }
2661
2662
2663 // -------------------------------------------------------------------------
2664 // Phase 4: Relocate objects
2665
2666 void MarkCompactCollector::RelocateObjects() {
2667 #ifdef DEBUG
2668 ASSERT(state_ == UPDATE_POINTERS);
2669 state_ = RELOCATE_OBJECTS;
2670 #endif
2671 // Relocates objects, always relocate map objects first. Relocating
2672 // objects in other space relies on map objects to get object size.
2673 int live_maps_size = IterateLiveObjects(Heap::map_space(),
2674 &RelocateMapObject);
2675 int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
2676 &RelocateOldPointerObject);
2677 int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(),
2678 &RelocateOldDataObject);
2679 int live_codes_size = IterateLiveObjects(Heap::code_space(),
2680 &RelocateCodeObject);
2681 int live_cells_size = IterateLiveObjects(Heap::cell_space(),
2682 &RelocateCellObject);
2683 int live_news_size = IterateLiveObjects(Heap::new_space(),
2684 &RelocateNewObject);
2685
2686 USE(live_maps_size);
2687 USE(live_pointer_olds_size);
2688 USE(live_data_olds_size);
2689 USE(live_codes_size);
2690 USE(live_cells_size);
2691 USE(live_news_size);
2692 ASSERT(live_maps_size == live_map_objects_size_);
2693 ASSERT(live_data_olds_size == live_old_data_objects_size_);
2694 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
2695 ASSERT(live_codes_size == live_code_objects_size_);
2696 ASSERT(live_cells_size == live_cell_objects_size_);
2697 ASSERT(live_news_size == live_young_objects_size_);
2698
2699 // Flip from and to spaces
2700 Heap::new_space()->Flip();
2701
2702 Heap::new_space()->MCCommitRelocationInfo();
2703
2704 // Set age_mark to bottom in to space
2705 Address mark = Heap::new_space()->bottom();
2706 Heap::new_space()->set_age_mark(mark);
2707
2708 PagedSpaces spaces;
2709 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
2710 space->MCCommitRelocationInfo();
2711
2712 Heap::CheckNewSpaceExpansionCriteria();
2713 Heap::IncrementYoungSurvivorsCounter(live_news_size);
2714 }
2715
2716
2717 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
2718 // Recover map pointer.
2719 MapWord encoding = obj->map_word();
2720 Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
2721 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
2722
2723 // Get forwarding address before resetting map pointer
2724 Address new_addr = GetForwardingAddressInOldSpace(obj);
2725
2726 // Reset map pointer. The meta map object may not be copied yet so
2727 // Map::cast does not yet work.
2728 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
2729
2730 Address old_addr = obj->address();
2731
2732 if (new_addr != old_addr) {
2733 // Move contents.
2734 Heap::MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
2735 old_addr,
2736 Map::kSize);
2737 }
2738
2739 #ifdef DEBUG
2740 if (FLAG_gc_verbose) {
2741 PrintF("relocate %p -> %p\n", old_addr, new_addr);
2742 }
2743 #endif
2744
2745 return Map::kSize;
2746 }
2747
2748
2749 static inline int RestoreMap(HeapObject* obj,
2750 PagedSpace* space,
2751 Address new_addr,
2752 Address map_addr) {
2753 // This must be a non-map object, and the function relies on the
2754 // assumption that the Map space is compacted before the other paged
2755 // spaces (see RelocateObjects).
2756
2757 // Reset map pointer.
2758 obj->set_map(Map::cast(HeapObject::FromAddress(map_addr)));
2759
2760 int obj_size = obj->Size();
2761 ASSERT_OBJECT_SIZE(obj_size);
2762
2763 ASSERT(space->MCSpaceOffsetForAddress(new_addr) <=
2764 space->MCSpaceOffsetForAddress(obj->address()));
2765
2766 #ifdef DEBUG
2767 if (FLAG_gc_verbose) {
2768 PrintF("relocate %p -> %p\n", obj->address(), new_addr);
2769 }
2770 #endif
2771
2772 return obj_size;
2773 }
2774
2775
2776 int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj,
2777 PagedSpace* space) {
2778 // Recover map pointer.
2779 MapWord encoding = obj->map_word();
2780 Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
2781 ASSERT(Heap::map_space()->Contains(map_addr));
2782
2783 // Get forwarding address before resetting map pointer.
2784 Address new_addr = GetForwardingAddressInOldSpace(obj);
2785
2786 // Reset the map pointer.
2787 int obj_size = RestoreMap(obj, space, new_addr, map_addr);
2788
2789 Address old_addr = obj->address();
2790
2791 if (new_addr != old_addr) {
2792 // Move contents.
2793 if (space == Heap::old_data_space()) {
2794 Heap::MoveBlock(new_addr, old_addr, obj_size);
2795 } else {
2796 Heap::MoveBlockToOldSpaceAndUpdateRegionMarks(new_addr,
2797 old_addr,
2798 obj_size);
2799 }
2800 }
2801
2802 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
2803
2804 HeapObject* copied_to = HeapObject::FromAddress(new_addr);
2805 if (copied_to->IsJSFunction()) {
2806 PROFILE(FunctionMoveEvent(old_addr, new_addr));
2807 PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
2808 }
2809 HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
2810
2811 return obj_size;
2812 }
2813
2814
2815 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) {
2816 return RelocateOldNonCodeObject(obj, Heap::old_pointer_space());
2817 }
2818
2819
2820 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) {
2821 return RelocateOldNonCodeObject(obj, Heap::old_data_space());
2822 }
2823
2824
2825 int MarkCompactCollector::RelocateCellObject(HeapObject* obj) {
2826 return RelocateOldNonCodeObject(obj, Heap::cell_space());
2827 }
2828
2829
2830 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) {
2831 // Recover map pointer.
2832 MapWord encoding = obj->map_word();
2833 Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
2834 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
2835
2836 // Get forwarding address before resetting map pointer
2837 Address new_addr = GetForwardingAddressInOldSpace(obj);
2838
2839 // Reset the map pointer.
2840 int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr);
2841
2842 Address old_addr = obj->address();
2843
2844 if (new_addr != old_addr) {
2845 // Move contents.
2846 Heap::MoveBlock(new_addr, old_addr, obj_size);
2847 }
2848
2849 HeapObject* copied_to = HeapObject::FromAddress(new_addr);
2850 if (copied_to->IsCode()) {
2851 // May also update inline cache target.
2852 Code::cast(copied_to)->Relocate(new_addr - old_addr);
2853 // Notify the logger that compiled code has moved.
2854 PROFILE(CodeMoveEvent(old_addr, new_addr));
2855 }
2856 HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
2857
2858 return obj_size;
2859 }
2860
2861
2862 int MarkCompactCollector::RelocateNewObject(HeapObject* obj) {
2863 int obj_size = obj->Size();
2864
2865 // Get forwarding address
2866 Address old_addr = obj->address();
2867 int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr);
2868
2869 Address new_addr =
2870 Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset);
2871
2872 #ifdef DEBUG
2873 if (Heap::new_space()->FromSpaceContains(new_addr)) {
2874 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
2875 Heap::new_space()->ToSpaceOffsetForAddress(old_addr));
2876 } else {
2877 ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() ||
2878 Heap::TargetSpace(obj) == Heap::old_data_space());
2879 }
2880 #endif
2881
2882 // New and old addresses cannot overlap.
2883 if (Heap::InNewSpace(HeapObject::FromAddress(new_addr))) {
2884 Heap::CopyBlock(new_addr, old_addr, obj_size);
2885 } else {
2886 Heap::CopyBlockToOldSpaceAndUpdateRegionMarks(new_addr,
2887 old_addr,
2888 obj_size);
2889 }
2890
2891 #ifdef DEBUG
2892 if (FLAG_gc_verbose) {
2893 PrintF("relocate %p -> %p\n", old_addr, new_addr);
2894 }
2895 #endif
2896
2897 HeapObject* copied_to = HeapObject::FromAddress(new_addr);
2898 if (copied_to->IsJSFunction()) {
2899 PROFILE(FunctionMoveEvent(old_addr, new_addr));
2900 PROFILE(FunctionCreateEventFromMove(JSFunction::cast(copied_to)));
2901 }
2902 HEAP_PROFILE(ObjectMoveEvent(old_addr, new_addr));
2903
2904 return obj_size;
2905 }
2906
2907
2908 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) { 1898 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
2909 #ifdef ENABLE_LOGGING_AND_PROFILING 1899 #ifdef ENABLE_LOGGING_AND_PROFILING
2910 if (obj->IsCode()) { 1900 if (obj->IsCode()) {
2911 PROFILE(CodeDeleteEvent(obj->address())); 1901 PROFILE(CodeDeleteEvent(obj->address()));
2912 } else if (obj->IsJSFunction()) { 1902 } else if (obj->IsJSFunction()) {
2913 PROFILE(FunctionDeleteEvent(obj->address())); 1903 PROFILE(FunctionDeleteEvent(obj->address()));
2914 } 1904 }
2915 #endif 1905 #endif
2916 } 1906 }
2917 1907
2918 1908
2919 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) { 1909 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) {
2920 MapWord map_word = obj->map_word(); 1910 MapWord map_word = obj->map_word();
2921 map_word.ClearMark(); 1911 map_word.ClearMark();
2922 return obj->SizeFromMap(map_word.ToMap()); 1912 return obj->SizeFromMap(map_word.ToMap());
2923 } 1913 }
2924 1914
2925 1915
2926 void MarkCompactCollector::Initialize() { 1916 void MarkCompactCollector::Initialize() {
2927 StaticPointersToNewGenUpdatingVisitor::Initialize(); 1917 StaticPointersToNewGenUpdatingVisitor::Initialize();
2928 StaticMarkingVisitor::Initialize(); 1918 StaticMarkingVisitor::Initialize();
2929 } 1919 }
2930 1920
2931 1921
2932 } } // namespace v8::internal 1922 } } // namespace v8::internal
OLDNEW
« src/globals.h ('K') | « src/mark-compact.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698