| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #include "src/heap/heap.h" | 5 #include "src/heap/heap.h" | 
| 6 | 6 | 
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" | 
| 8 #include "src/api.h" | 8 #include "src/api.h" | 
| 9 #include "src/ast/scopeinfo.h" | 9 #include "src/ast/scopeinfo.h" | 
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" | 
| (...skipping 1581 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1592     if (map_word.IsForwardingAddress()) { | 1592     if (map_word.IsForwardingAddress()) { | 
| 1593       return map_word.ToForwardingAddress(); | 1593       return map_word.ToForwardingAddress(); | 
| 1594     } | 1594     } | 
| 1595     return NULL; | 1595     return NULL; | 
| 1596   } | 1596   } | 
| 1597 | 1597 | 
| 1598  private: | 1598  private: | 
| 1599   Heap* heap_; | 1599   Heap* heap_; | 
| 1600 }; | 1600 }; | 
| 1601 | 1601 | 
|  | 1602 void Heap::Scavenge() { | 
|  | 1603   if (incremental_marking()->IsMarking()) { | 
|  | 1604     Scavenge<PROMOTE_MARKED>(); | 
|  | 1605   } else { | 
|  | 1606     Scavenge<DEFAULT_PROMOTION>(); | 
|  | 1607   } | 
|  | 1608 } | 
| 1602 | 1609 | 
|  | 1610 template <PromotionMode promotion_mode> | 
| 1603 void Heap::Scavenge() { | 1611 void Heap::Scavenge() { | 
| 1604   TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE); | 1612   TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SCAVENGE); | 
| 1605   RelocationLock relocation_lock(this); | 1613   RelocationLock relocation_lock(this); | 
| 1606   // There are soft limits in the allocation code, designed to trigger a mark | 1614   // There are soft limits in the allocation code, designed to trigger a mark | 
| 1607   // sweep collection by failing allocations. There is no sense in trying to | 1615   // sweep collection by failing allocations. There is no sense in trying to | 
| 1608   // trigger one during scavenge: scavenges allocation should always succeed. | 1616   // trigger one during scavenge: scavenges allocation should always succeed. | 
| 1609   AlwaysAllocateScope scope(isolate()); | 1617   AlwaysAllocateScope scope(isolate()); | 
| 1610 | 1618 | 
| 1611   // Bump-pointer allocations done during scavenge are not real allocations. | 1619   // Bump-pointer allocations done during scavenge are not real allocations. | 
| 1612   // Pause the inline allocation steps. | 1620   // Pause the inline allocation steps. | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1646   // objects lie between a 'front' mark and a 'rear' mark that is | 1654   // objects lie between a 'front' mark and a 'rear' mark that is | 
| 1647   // updated as a side effect of promoting an object. | 1655   // updated as a side effect of promoting an object. | 
| 1648   // | 1656   // | 
| 1649   // There is guaranteed to be enough room at the top of the to space | 1657   // There is guaranteed to be enough room at the top of the to space | 
| 1650   // for the addresses of promoted objects: every object promoted | 1658   // for the addresses of promoted objects: every object promoted | 
| 1651   // frees up its size in bytes from the top of the new space, and | 1659   // frees up its size in bytes from the top of the new space, and | 
| 1652   // objects are at least one pointer in size. | 1660   // objects are at least one pointer in size. | 
| 1653   Address new_space_front = new_space_.ToSpaceStart(); | 1661   Address new_space_front = new_space_.ToSpaceStart(); | 
| 1654   promotion_queue_.Initialize(); | 1662   promotion_queue_.Initialize(); | 
| 1655 | 1663 | 
| 1656   ScavengeVisitor scavenge_visitor(this); | 1664   ScavengeVisitor<promotion_mode> scavenge_visitor(this); | 
| 1657 | 1665 | 
| 1658   if (FLAG_scavenge_reclaim_unmodified_objects) { | 1666   if (FLAG_scavenge_reclaim_unmodified_objects) { | 
| 1659     isolate()->global_handles()->IdentifyWeakUnmodifiedObjects( | 1667     isolate()->global_handles()->IdentifyWeakUnmodifiedObjects( | 
| 1660         &IsUnmodifiedHeapObject); | 1668         &IsUnmodifiedHeapObject); | 
| 1661   } | 1669   } | 
| 1662 | 1670 | 
| 1663   { | 1671   { | 
| 1664     // Copy roots. | 1672     // Copy roots. | 
| 1665     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); | 1673     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_ROOTS); | 
| 1666     IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 1674     IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); | 
| 1667   } | 1675   } | 
| 1668 | 1676 | 
| 1669   { | 1677   { | 
| 1670     // Copy objects reachable from the old generation. | 1678     // Copy objects reachable from the old generation. | 
| 1671     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); | 1679     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OLD_TO_NEW_POINTERS); | 
| 1672     RememberedSet<OLD_TO_NEW>::Iterate(this, [this](Address addr) { | 1680     RememberedSet<OLD_TO_NEW>::Iterate(this, [this](Address addr) { | 
| 1673       return Scavenger::CheckAndScavengeObject(this, addr, DEFAULT_PROMOTION); | 1681       return Scavenger::CheckAndScavengeObject<promotion_mode>(this, addr); | 
| 1674     }); | 1682     }); | 
| 1675 | 1683 | 
| 1676     RememberedSet<OLD_TO_NEW>::IterateTyped( | 1684     RememberedSet<OLD_TO_NEW>::IterateTyped( | 
| 1677         this, [this](SlotType type, Address addr) { | 1685         this, [this](SlotType type, Address addr) { | 
| 1678           return UpdateTypedSlotHelper::UpdateTypedSlot( | 1686           return UpdateTypedSlotHelper::UpdateTypedSlot( | 
| 1679               isolate(), type, addr, [this](Object** addr) { | 1687               isolate(), type, addr, [this](Object** addr) { | 
| 1680                 // We expect that objects referenced by code are long living. | 1688                 // We expect that objects referenced by code are long living. | 
| 1681                 // If we do not force promotion, then we need to clear | 1689                 // If we do not force promotion, then we need to clear | 
| 1682                 // old_to_new slots in dead code objects after mark-compact. | 1690                 // old_to_new slots in dead code objects after mark-compact. | 
| 1683                 return Scavenger::CheckAndScavengeObject( | 1691                 return Scavenger::CheckAndScavengeObject<FORCE_PROMOTION>( | 
| 1684                     this, reinterpret_cast<Address>(addr), FORCE_PROMOTION); | 1692                     this, reinterpret_cast<Address>(addr)); | 
| 1685               }); | 1693               }); | 
| 1686         }); | 1694         }); | 
| 1687   } | 1695   } | 
| 1688 | 1696 | 
| 1689   { | 1697   { | 
| 1690     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_WEAK); | 1698     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_WEAK); | 
| 1691     // Copy objects reachable from the encountered weak collections list. | 1699     // Copy objects reachable from the encountered weak collections list. | 
| 1692     scavenge_visitor.VisitPointer(&encountered_weak_collections_); | 1700     scavenge_visitor.VisitPointer(&encountered_weak_collections_); | 
| 1693     // Copy objects reachable from the encountered weak cells. | 1701     // Copy objects reachable from the encountered weak cells. | 
| 1694     scavenge_visitor.VisitPointer(&encountered_weak_cells_); | 1702     scavenge_visitor.VisitPointer(&encountered_weak_cells_); | 
| 1695   } | 1703   } | 
| 1696 | 1704 | 
| 1697   { | 1705   { | 
| 1698     // Copy objects reachable from the code flushing candidates list. | 1706     // Copy objects reachable from the code flushing candidates list. | 
| 1699     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_CODE_FLUSH_CANDIDATES); | 1707     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_CODE_FLUSH_CANDIDATES); | 
| 1700     MarkCompactCollector* collector = mark_compact_collector(); | 1708     MarkCompactCollector* collector = mark_compact_collector(); | 
| 1701     if (collector->is_code_flushing_enabled()) { | 1709     if (collector->is_code_flushing_enabled()) { | 
| 1702       collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor); | 1710       collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor); | 
| 1703     } | 1711     } | 
| 1704   } | 1712   } | 
| 1705 | 1713 | 
| 1706   { | 1714   { | 
| 1707     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE); | 1715     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_SEMISPACE); | 
| 1708     new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1716     new_space_front = | 
|  | 1717         DoScavenge<promotion_mode>(&scavenge_visitor, new_space_front); | 
| 1709   } | 1718   } | 
| 1710 | 1719 | 
| 1711   if (FLAG_scavenge_reclaim_unmodified_objects) { | 1720   if (FLAG_scavenge_reclaim_unmodified_objects) { | 
| 1712     isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending( | 1721     isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending( | 
| 1713         &IsUnscavengedHeapObject); | 1722         &IsUnscavengedHeapObject); | 
| 1714 | 1723 | 
| 1715     isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots( | 1724     isolate()->global_handles()->IterateNewSpaceWeakUnmodifiedRoots( | 
| 1716         &scavenge_visitor); | 1725         &scavenge_visitor); | 
| 1717     new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1726     new_space_front = | 
|  | 1727         DoScavenge<promotion_mode>(&scavenge_visitor, new_space_front); | 
| 1718   } else { | 1728   } else { | 
| 1719     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OBJECT_GROUPS); | 1729     TRACE_GC(tracer(), GCTracer::Scope::SCAVENGER_OBJECT_GROUPS); | 
| 1720     while (isolate()->global_handles()->IterateObjectGroups( | 1730     while (isolate()->global_handles()->IterateObjectGroups( | 
| 1721         &scavenge_visitor, &IsUnscavengedHeapObject)) { | 1731         &scavenge_visitor, &IsUnscavengedHeapObject)) { | 
| 1722       new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1732       new_space_front = | 
|  | 1733           DoScavenge<promotion_mode>(&scavenge_visitor, new_space_front); | 
| 1723     } | 1734     } | 
| 1724     isolate()->global_handles()->RemoveObjectGroups(); | 1735     isolate()->global_handles()->RemoveObjectGroups(); | 
| 1725     isolate()->global_handles()->RemoveImplicitRefGroups(); | 1736     isolate()->global_handles()->RemoveImplicitRefGroups(); | 
| 1726 | 1737 | 
| 1727     isolate()->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 1738     isolate()->global_handles()->IdentifyNewSpaceWeakIndependentHandles( | 
| 1728         &IsUnscavengedHeapObject); | 1739         &IsUnscavengedHeapObject); | 
| 1729 | 1740 | 
| 1730     isolate()->global_handles()->IterateNewSpaceWeakIndependentRoots( | 1741     isolate()->global_handles()->IterateNewSpaceWeakIndependentRoots( | 
| 1731         &scavenge_visitor); | 1742         &scavenge_visitor); | 
| 1732     new_space_front = DoScavenge(&scavenge_visitor, new_space_front); | 1743     new_space_front = | 
|  | 1744         DoScavenge<promotion_mode>(&scavenge_visitor, new_space_front); | 
| 1733   } | 1745   } | 
| 1734 | 1746 | 
| 1735   UpdateNewSpaceReferencesInExternalStringTable( | 1747   UpdateNewSpaceReferencesInExternalStringTable( | 
| 1736       &UpdateNewSpaceReferenceInExternalStringTableEntry); | 1748       &UpdateNewSpaceReferenceInExternalStringTableEntry); | 
| 1737 | 1749 | 
| 1738   promotion_queue_.Destroy(); | 1750   promotion_queue_.Destroy(); | 
| 1739 | 1751 | 
| 1740   incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 1752   incremental_marking()->UpdateMarkingDequeAfterScavenge(); | 
| 1741 | 1753 | 
| 1742   ScavengeWeakObjectRetainer weak_object_retainer(this); | 1754   ScavengeWeakObjectRetainer weak_object_retainer(this); | 
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1904       } | 1916       } | 
| 1905     } | 1917     } | 
| 1906 | 1918 | 
| 1907    private: | 1919    private: | 
| 1908     v8::ExternalResourceVisitor* visitor_; | 1920     v8::ExternalResourceVisitor* visitor_; | 
| 1909   } external_string_table_visitor(visitor); | 1921   } external_string_table_visitor(visitor); | 
| 1910 | 1922 | 
| 1911   external_string_table_.Iterate(&external_string_table_visitor); | 1923   external_string_table_.Iterate(&external_string_table_visitor); | 
| 1912 } | 1924 } | 
| 1913 | 1925 | 
| 1914 | 1926 template <PromotionMode promotion_mode> | 
| 1915 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, | 1927 Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, | 
| 1916                          Address new_space_front) { | 1928                          Address new_space_front) { | 
| 1917   do { | 1929   do { | 
| 1918     SemiSpace::AssertValidRange(new_space_front, new_space_.top()); | 1930     SemiSpace::AssertValidRange(new_space_front, new_space_.top()); | 
| 1919     // The addresses new_space_front and new_space_.top() define a | 1931     // The addresses new_space_front and new_space_.top() define a | 
| 1920     // queue of unprocessed copied objects.  Process them until the | 1932     // queue of unprocessed copied objects.  Process them until the | 
| 1921     // queue is empty. | 1933     // queue is empty. | 
| 1922     while (new_space_front != new_space_.top()) { | 1934     while (new_space_front != new_space_.top()) { | 
| 1923       if (!Page::IsAlignedToPageSize(new_space_front)) { | 1935       if (!Page::IsAlignedToPageSize(new_space_front)) { | 
| 1924         HeapObject* object = HeapObject::FromAddress(new_space_front); | 1936         HeapObject* object = HeapObject::FromAddress(new_space_front); | 
| 1925         new_space_front += | 1937         new_space_front += StaticScavengeVisitor<promotion_mode>::IterateBody( | 
| 1926             StaticScavengeVisitor::IterateBody(object->map(), object); | 1938             object->map(), object); | 
| 1927       } else { | 1939       } else { | 
| 1928         new_space_front = Page::FromAllocationAreaAddress(new_space_front) | 1940         new_space_front = Page::FromAllocationAreaAddress(new_space_front) | 
| 1929                               ->next_page() | 1941                               ->next_page() | 
| 1930                               ->area_start(); | 1942                               ->area_start(); | 
| 1931       } | 1943       } | 
| 1932     } | 1944     } | 
| 1933 | 1945 | 
| 1934     // Promote and process all the to-be-promoted objects. | 1946     // Promote and process all the to-be-promoted objects. | 
| 1935     { | 1947     { | 
| 1936       while (!promotion_queue()->is_empty()) { | 1948       while (!promotion_queue()->is_empty()) { | 
| 1937         HeapObject* target; | 1949         HeapObject* target; | 
| 1938         int32_t size; | 1950         int32_t size; | 
| 1939         bool was_marked_black; | 1951         bool was_marked_black; | 
| 1940         promotion_queue()->remove(&target, &size, &was_marked_black); | 1952         promotion_queue()->remove(&target, &size, &was_marked_black); | 
| 1941 | 1953 | 
| 1942         // Promoted object might be already partially visited | 1954         // Promoted object might be already partially visited | 
| 1943         // during old space pointer iteration. Thus we search specifically | 1955         // during old space pointer iteration. Thus we search specifically | 
| 1944         // for pointers to from semispace instead of looking for pointers | 1956         // for pointers to from semispace instead of looking for pointers | 
| 1945         // to new space. | 1957         // to new space. | 
| 1946         DCHECK(!target->IsMap()); | 1958         DCHECK(!target->IsMap()); | 
| 1947 | 1959 | 
| 1948         IteratePromotedObject(target, static_cast<int>(size), was_marked_black, | 1960         IteratePromotedObject(target, static_cast<int>(size), was_marked_black, | 
| 1949                               &Scavenger::ScavengeObject); | 1961                               &Scavenger::ScavengeObject<promotion_mode>); | 
| 1950       } | 1962       } | 
| 1951     } | 1963     } | 
| 1952 | 1964 | 
| 1953     // Take another spin if there are now unswept objects in new space | 1965     // Take another spin if there are now unswept objects in new space | 
| 1954     // (there are currently no more unswept promoted objects). | 1966     // (there are currently no more unswept promoted objects). | 
| 1955   } while (new_space_front != new_space_.top()); | 1967   } while (new_space_front != new_space_.top()); | 
| 1956 | 1968 | 
| 1957   return new_space_front; | 1969   return new_space_front; | 
| 1958 } | 1970 } | 
| 1959 | 1971 | 
| (...skipping 2722 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4682                                          Address end, bool record_slots, | 4694                                          Address end, bool record_slots, | 
| 4683                                          ObjectSlotCallback callback) { | 4695                                          ObjectSlotCallback callback) { | 
| 4684   Address slot_address = start; | 4696   Address slot_address = start; | 
| 4685   Page* page = Page::FromAddress(start); | 4697   Page* page = Page::FromAddress(start); | 
| 4686 | 4698 | 
| 4687   while (slot_address < end) { | 4699   while (slot_address < end) { | 
| 4688     Object** slot = reinterpret_cast<Object**>(slot_address); | 4700     Object** slot = reinterpret_cast<Object**>(slot_address); | 
| 4689     Object* target = *slot; | 4701     Object* target = *slot; | 
| 4690     if (target->IsHeapObject()) { | 4702     if (target->IsHeapObject()) { | 
| 4691       if (Heap::InFromSpace(target)) { | 4703       if (Heap::InFromSpace(target)) { | 
| 4692         callback(reinterpret_cast<HeapObject**>(slot), HeapObject::cast(target), | 4704         callback(reinterpret_cast<HeapObject**>(slot), | 
| 4693                  DEFAULT_PROMOTION); | 4705                  HeapObject::cast(target)); | 
| 4694         Object* new_target = *slot; | 4706         Object* new_target = *slot; | 
| 4695         if (InNewSpace(new_target)) { | 4707         if (InNewSpace(new_target)) { | 
| 4696           SLOW_DCHECK(Heap::InToSpace(new_target)); | 4708           SLOW_DCHECK(Heap::InToSpace(new_target)); | 
| 4697           SLOW_DCHECK(new_target->IsHeapObject()); | 4709           SLOW_DCHECK(new_target->IsHeapObject()); | 
| 4698           RememberedSet<OLD_TO_NEW>::Insert(page, slot_address); | 4710           RememberedSet<OLD_TO_NEW>::Insert(page, slot_address); | 
| 4699         } | 4711         } | 
| 4700         SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); | 4712         SLOW_DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(new_target)); | 
| 4701       } else if (record_slots && | 4713       } else if (record_slots && | 
| 4702                  MarkCompactCollector::IsOnEvacuationCandidate(target)) { | 4714                  MarkCompactCollector::IsOnEvacuationCandidate(target)) { | 
| 4703         mark_compact_collector()->RecordSlot(object, slot, target); | 4715         mark_compact_collector()->RecordSlot(object, slot, target); | 
| (...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5225        space = spaces.next()) { | 5237        space = spaces.next()) { | 
| 5226     space->EmptyAllocationInfo(); | 5238     space->EmptyAllocationInfo(); | 
| 5227   } | 5239   } | 
| 5228 } | 5240 } | 
| 5229 | 5241 | 
| 5230 | 5242 | 
| 5231 V8_DECLARE_ONCE(initialize_gc_once); | 5243 V8_DECLARE_ONCE(initialize_gc_once); | 
| 5232 | 5244 | 
| 5233 static void InitializeGCOnce() { | 5245 static void InitializeGCOnce() { | 
| 5234   Scavenger::Initialize(); | 5246   Scavenger::Initialize(); | 
| 5235   StaticScavengeVisitor::Initialize(); | 5247   StaticScavengeVisitor<DEFAULT_PROMOTION>::Initialize(); | 
|  | 5248   StaticScavengeVisitor<PROMOTE_MARKED>::Initialize(); | 
|  | 5249   StaticScavengeVisitor<FORCE_PROMOTION>::Initialize(); | 
| 5236   MarkCompactCollector::Initialize(); | 5250   MarkCompactCollector::Initialize(); | 
| 5237 } | 5251 } | 
| 5238 | 5252 | 
| 5239 | 5253 | 
| 5240 bool Heap::SetUp() { | 5254 bool Heap::SetUp() { | 
| 5241 #ifdef DEBUG | 5255 #ifdef DEBUG | 
| 5242   allocation_timeout_ = FLAG_gc_interval; | 5256   allocation_timeout_ = FLAG_gc_interval; | 
| 5243 #endif | 5257 #endif | 
| 5244 | 5258 | 
| 5245   // Initialize heap spaces and initial maps and objects. Whenever something | 5259   // Initialize heap spaces and initial maps and objects. Whenever something | 
| (...skipping 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 6391 } | 6405 } | 
| 6392 | 6406 | 
| 6393 | 6407 | 
| 6394 // static | 6408 // static | 
| 6395 int Heap::GetStaticVisitorIdForMap(Map* map) { | 6409 int Heap::GetStaticVisitorIdForMap(Map* map) { | 
| 6396   return StaticVisitorBase::GetVisitorId(map); | 6410   return StaticVisitorBase::GetVisitorId(map); | 
| 6397 } | 6411 } | 
| 6398 | 6412 | 
| 6399 }  // namespace internal | 6413 }  // namespace internal | 
| 6400 }  // namespace v8 | 6414 }  // namespace v8 | 
| OLD | NEW | 
|---|