Index: Source/platform/heap/PersistentNode.cpp |
diff --git a/Source/platform/heap/PersistentNode.cpp b/Source/platform/heap/PersistentNode.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d8e22fc6cff30e688c7ac5ba96c984c4e041e02c |
--- /dev/null |
+++ b/Source/platform/heap/PersistentNode.cpp |
@@ -0,0 +1,93 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "config.h" |
+#include "platform/heap/PersistentNode.h" |
+ |
+namespace blink { |
+ |
+PersistentRegion::~PersistentRegion() |
+{ |
+ PersistentNodeSlots* slots = m_slots; |
+ while (slots) { |
+ PersistentNodeSlots* deadSlots = slots; |
+ slots = slots->m_next; |
+ delete deadSlots; |
+ } |
+} |
+ |
+int PersistentRegion::numberOfPersistents() |
+{ |
+ int persistentCount = 0; |
+ for (PersistentNodeSlots* slots = m_slots; slots; slots = slots->m_next) { |
+ for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
+ if (!slots->m_slot[i].isUnused()) |
+ ++persistentCount; |
+ } |
+ } |
+ ASSERT(persistentCount == m_persistentCount); |
+ return persistentCount; |
+} |
+ |
+void PersistentRegion::ensurePersistentNodeSlots(void* self, TraceCallback trace) |
+{ |
+ ASSERT(!m_freeListHead); |
+ PersistentNodeSlots* slots = new PersistentNodeSlots; |
+ for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
+ PersistentNode* node = &slots->m_slot[i]; |
+ node->setFreeListNext(m_freeListHead); |
+ m_freeListHead = node; |
+ ASSERT(node->isUnused()); |
+ } |
+ slots->m_next = m_slots; |
+ m_slots = slots; |
+} |
+ |
+// This function traces all PersistentNodes. If we encounter |
+// a PersistentNodeSlot that contains only freed PersistentNodes, |
+// we delete the PersistentNodeSlot. This function rebuilds the free |
+// list of PersistentNodes. |
+void PersistentRegion::tracePersistentNodes(Visitor* visitor) |
+{ |
+ m_freeListHead = nullptr; |
+ int persistentCount = 0; |
+ PersistentNodeSlots** prevNext = &m_slots; |
+ PersistentNodeSlots* slots = m_slots; |
+ while (slots) { |
+ PersistentNode* freeListNext = nullptr; |
+ PersistentNode* freeListLast = nullptr; |
+ int freeCount = 0; |
+ for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
+ PersistentNode* node = &slots->m_slot[i]; |
+ if (node->isUnused()) { |
+ if (!freeListNext) |
+ freeListLast = node; |
+ node->setFreeListNext(freeListNext); |
+ freeListNext = node; |
+ ++freeCount; |
+ } else { |
+ node->tracePersistentNode(visitor); |
+ ++persistentCount; |
+ } |
+ } |
+ if (freeCount == PersistentNodeSlots::slotCount) { |
+ PersistentNodeSlots* deadSlots = slots; |
+ *prevNext = slots->m_next; |
+ slots = slots->m_next; |
+ delete deadSlots; |
+ } else { |
+ if (freeListLast) { |
+ ASSERT(freeListNext); |
+ ASSERT(!freeListLast->freeListNext()); |
+ freeListLast->setFreeListNext(m_freeListHead); |
+ m_freeListHead = freeListNext; |
+ } |
+ prevNext = &slots->m_next; |
+ slots = slots->m_next; |
+ } |
+ } |
+ ASSERT(persistentCount == m_persistentCount); |
+} |
+ |
+} // namespace blink |