| Index: src/heap.cc
|
| diff --git a/src/heap.cc b/src/heap.cc
|
| index 23bfbd807d8d1430e4e38c3dc9044c41652dfe3f..ed3955c58dea10a26061cb3211c4d5fc6972ba8e 100644
|
| --- a/src/heap.cc
|
| +++ b/src/heap.cc
|
| @@ -54,6 +54,7 @@ namespace internal {
|
|
|
| String* Heap::hidden_symbol_;
|
| Object* Heap::roots_[Heap::kRootListLength];
|
| +Object* Heap::global_contexts_list_;
|
|
|
| NewSpace Heap::new_space_;
|
| OldSpace* Heap::old_pointer_space_ = NULL;
|
| @@ -1034,6 +1035,9 @@ void Heap::Scavenge() {
|
| }
|
| }
|
|
|
| + // Scavenge object reachable from the global contexts list directly.
|
| + scavenge_visitor.VisitPointer(BitCast<Object**>(&global_contexts_list_));
|
| +
|
| new_space_front = DoScavenge(&scavenge_visitor, new_space_front);
|
|
|
| UpdateNewSpaceReferencesInExternalStringTable(
|
| @@ -1101,6 +1105,44 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
|
| }
|
|
|
|
|
| +void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
|
| + Object* head = undefined_value();
|
| + Context* tail = NULL;
|
| + Object* candidate = global_contexts_list_;
|
| + while (!candidate->IsUndefined()) {
|
| + // Check whether to keep the candidate in the list.
|
| + Context* candidate_context = reinterpret_cast<Context*>(candidate);
|
| + Object* retain = retainer->RetainAs(candidate);
|
| + if (retain != NULL) {
|
| + if (head->IsUndefined()) {
|
| + // First element in the list.
|
| + head = candidate_context;
|
| + } else {
|
| + // Subsequent elements in the list.
|
| + ASSERT(tail != NULL);
|
| + tail->set_unchecked(Context::NEXT_CONTEXT_LINK,
|
| + candidate_context,
|
| + UPDATE_WRITE_BARRIER);
|
| + }
|
| + // Retained context is new tail.
|
| + tail = candidate_context;
|
| + }
|
| + // Move to next element in the list.
|
| + candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK);
|
| + }
|
| +
|
| + // Terminate the list if there is one or more elements.
|
| + if (tail != NULL) {
|
| + tail->set_unchecked(Context::NEXT_CONTEXT_LINK,
|
| + Heap::undefined_value(),
|
| + UPDATE_WRITE_BARRIER);
|
| + }
|
| +
|
| + // Update the head of the list of contexts.
|
| + Heap::global_contexts_list_ = head;
|
| +}
|
| +
|
| +
|
| class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
|
| public:
|
| static inline void VisitPointer(Object** p) {
|
| @@ -1157,6 +1199,9 @@ class ScavengingVisitor : public StaticVisitorBase {
|
| table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate);
|
| table_.Register(kVisitByteArray, &EvacuateByteArray);
|
| table_.Register(kVisitFixedArray, &EvacuateFixedArray);
|
| + table_.Register(kVisitGlobalContext,
|
| + &ObjectEvacuationStrategy<POINTER_OBJECT>::
|
| + VisitSpecialized<Context::kSize>);
|
|
|
| typedef ObjectEvacuationStrategy<POINTER_OBJECT> PointerObject;
|
|
|
| @@ -1647,7 +1692,9 @@ bool Heap::CreateInitialMaps() {
|
|
|
| obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
|
| if (obj->IsFailure()) return false;
|
| - set_global_context_map(Map::cast(obj));
|
| + Map* global_context_map = Map::cast(obj);
|
| + global_context_map->set_visitor_id(StaticVisitorBase::kVisitGlobalContext);
|
| + set_global_context_map(global_context_map);
|
|
|
| obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE,
|
| SharedFunctionInfo::kAlignedSize);
|
| @@ -4236,6 +4283,8 @@ bool Heap::Setup(bool create_heap_objects) {
|
|
|
| // Create initial objects
|
| if (!CreateInitialObjects()) return false;
|
| +
|
| + global_contexts_list_ = undefined_value();
|
| }
|
|
|
| LOG(IntPtrTEvent("heap-capacity", Capacity()));
|
|
|