Title: [133358] trunk/Source/_javascript_Core
- Revision
- 133358
- Author
- [email protected]
- Date
- 2012-11-02 15:14:28 -0700 (Fri, 02 Nov 2012)
Log Message
MarkedBlocks should use something other than the mark bits to indicate liveness for newly allocated objects
https://bugs.webkit.org/show_bug.cgi?id=100877
Reviewed by Filip Pizlo.
Currently when we canonicalize cell liveness data in MarkedBlocks, we set the mark bit for every cell in the
block except for those in the free list. This allows us to consider objects that were allocated since the
previous collection to be considered live until they have a chance to be properly marked by the collector.
If we want to use the mark bits to signify other types of information, e.g. using sticky mark bits for generational
collection, we will have to keep track of newly allocated objects in a different fashion when we canonicalize cell liveness.
One method would be to allocate a separate set of bits while canonicalizing liveness data. These bits would
track the newly allocated objects in the block separately from those objects who had already been marked. We would
then check these bits, along with the mark bits, when determining liveness.
* heap/Heap.h:
(Heap):
(JSC::Heap::isLive): We now check for the presence of the newlyAllocated Bitmap.
(JSC):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::specializedSweep): We clear the newlyAllocated Bitmap if we're creating a free list. This
will happen if we canonicalize liveness data for some other reason than collection (e.g. forEachCell) and
then start allocating again.
(JSC::SetNewlyAllocatedFunctor::SetNewlyAllocatedFunctor):
(SetNewlyAllocatedFunctor):
(JSC::SetNewlyAllocatedFunctor::operator()): We set the newlyAllocated bits for all the objects
that aren't already marked. We undo the bits for the objects in the free list later in canonicalizeCellLivenessData.
(JSC::MarkedBlock::canonicalizeCellLivenessData): We should never have a FreeListed block with a newlyAllocated Bitmap.
We allocate the new Bitmap, set the bits for all the objects that aren't already marked, and then unset all of the
bits for the items currently in the FreeList.
* heap/MarkedBlock.h:
(JSC::MarkedBlock::clearMarks): We clear the newlyAllocated bitmap if it exists because at this point we don't need it
any more.
(JSC::MarkedBlock::isEmpty): If we have some objects that are newlyAllocated, we are not empty.
(JSC::MarkedBlock::isNewlyAllocated):
(JSC):
(JSC::MarkedBlock::setNewlyAllocated):
(JSC::MarkedBlock::clearNewlyAllocated):
(JSC::MarkedBlock::isLive): We now check the newlyAllocated Bitmap, if it exists, when determining liveness of a cell in
a block that is Marked.
* heap/WeakBlock.cpp:
(JSC::WeakBlock::visit): We need to make sure we don't finalize objects that are in the newlyAllocated Bitmap.
(JSC::WeakBlock::reap): Ditto.
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (133357 => 133358)
--- trunk/Source/_javascript_Core/ChangeLog 2012-11-02 22:12:40 UTC (rev 133357)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-11-02 22:14:28 UTC (rev 133358)
@@ -1,3 +1,50 @@
+2012-11-02 Mark Hahnenberg <[email protected]>
+
+ MarkedBlocks should use something other than the mark bits to indicate liveness for newly allocated objects
+ https://bugs.webkit.org/show_bug.cgi?id=100877
+
+ Reviewed by Filip Pizlo.
+
+ Currently when we canonicalize cell liveness data in MarkedBlocks, we set the mark bit for every cell in the
+ block except for those in the free list. This allows us to consider objects that were allocated since the
+ previous collection to be considered live until they have a chance to be properly marked by the collector.
+
+ If we want to use the mark bits to signify other types of information, e.g. using sticky mark bits for generational
+ collection, we will have to keep track of newly allocated objects in a different fashion when we canonicalize cell liveness.
+
+ One method would be to allocate a separate set of bits while canonicalizing liveness data. These bits would
+ track the newly allocated objects in the block separately from those objects who had already been marked. We would
+ then check these bits, along with the mark bits, when determining liveness.
+
+ * heap/Heap.h:
+ (Heap):
+ (JSC::Heap::isLive): We now check for the presence of the newlyAllocated Bitmap.
+ (JSC):
+ * heap/MarkedBlock.cpp:
+ (JSC::MarkedBlock::specializedSweep): We clear the newlyAllocated Bitmap if we're creating a free list. This
+ will happen if we canonicalize liveness data for some other reason than collection (e.g. forEachCell) and
+ then start allocating again.
+ (JSC::SetNewlyAllocatedFunctor::SetNewlyAllocatedFunctor):
+ (SetNewlyAllocatedFunctor):
+ (JSC::SetNewlyAllocatedFunctor::operator()): We set the newlyAllocated bits for all the objects
+ that aren't already marked. We undo the bits for the objects in the free list later in canonicalizeCellLivenessData.
+ (JSC::MarkedBlock::canonicalizeCellLivenessData): We should never have a FreeListed block with a newlyAllocated Bitmap.
+ We allocate the new Bitmap, set the bits for all the objects that aren't already marked, and then unset all of the
+ bits for the items currently in the FreeList.
+ * heap/MarkedBlock.h:
+ (JSC::MarkedBlock::clearMarks): We clear the newlyAllocated bitmap if it exists because at this point we don't need it
+ any more.
+ (JSC::MarkedBlock::isEmpty): If we have some objects that are newlyAllocated, we are not empty.
+ (JSC::MarkedBlock::isNewlyAllocated):
+ (JSC):
+ (JSC::MarkedBlock::setNewlyAllocated):
+ (JSC::MarkedBlock::clearNewlyAllocated):
+ (JSC::MarkedBlock::isLive): We now check the newlyAllocated Bitmap, if it exists, when determining liveness of a cell in
+ a block that is Marked.
+ * heap/WeakBlock.cpp:
+ (JSC::WeakBlock::visit): We need to make sure we don't finalize objects that are in the newlyAllocated Bitmap.
+ (JSC::WeakBlock::reap): Ditto.
+
2012-11-02 Filip Pizlo <[email protected]>
JIT::privateCompileGetByVal should use MacroAssemblerCodePtr::createFromExecutableAddress like JIT::privateCompilePutByVal
Modified: trunk/Source/_javascript_Core/heap/Heap.h (133357 => 133358)
--- trunk/Source/_javascript_Core/heap/Heap.h 2012-11-02 22:12:40 UTC (rev 133357)
+++ trunk/Source/_javascript_Core/heap/Heap.h 2012-11-02 22:14:28 UTC (rev 133358)
@@ -86,6 +86,7 @@
// our scan to run faster.
static const unsigned s_timeCheckResolution = 16;
+ static bool isLive(const void*);
static bool isMarked(const void*);
static bool testAndSetMarked(const void*);
static void setMarked(const void*);
@@ -305,6 +306,11 @@
return heap(v.asCell());
}
+ inline bool Heap::isLive(const void* cell)
+ {
+ return MarkedBlock::blockFor(cell)->isLiveCell(cell);
+ }
+
inline bool Heap::isMarked(const void* cell)
{
return MarkedBlock::blockFor(cell)->isMarked(cell);
Modified: trunk/Source/_javascript_Core/heap/MarkedBlock.cpp (133357 => 133358)
--- trunk/Source/_javascript_Core/heap/MarkedBlock.cpp 2012-11-02 22:12:40 UTC (rev 133357)
+++ trunk/Source/_javascript_Core/heap/MarkedBlock.cpp 2012-11-02 22:14:28 UTC (rev 133358)
@@ -78,7 +78,7 @@
FreeCell* head = 0;
size_t count = 0;
for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
- if (blockState == Marked && m_marks.get(i))
+ if (blockState == Marked && (m_marks.get(i) || (m_newlyAllocated && m_newlyAllocated->get(i))))
continue;
JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
@@ -94,6 +94,11 @@
}
}
+ // We only want to discard the newlyAllocated bits if we're creating a FreeList,
+ // otherwise we would lose information on what's currently alive.
+ if (sweepMode == SweepToFreeList && m_newlyAllocated)
+ m_newlyAllocated.clear();
+
m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Marked);
return FreeList(head, count * cellSize());
}
@@ -138,12 +143,21 @@
return FreeList();
}
-class SetAllMarksFunctor : public MarkedBlock::VoidFunctor {
+class SetNewlyAllocatedFunctor : public MarkedBlock::VoidFunctor {
public:
+ SetNewlyAllocatedFunctor(MarkedBlock* block)
+ : m_block(block)
+ {
+ }
+
void operator()(JSCell* cell)
{
- MarkedBlock::blockFor(cell)->setMarked(cell);
+ ASSERT(MarkedBlock::blockFor(cell) == m_block);
+ m_block->setNewlyAllocated(cell);
}
+
+private:
+ MarkedBlock* m_block;
};
void MarkedBlock::canonicalizeCellLivenessData(const FreeList& freeList)
@@ -168,14 +182,17 @@
// allocated from our free list are not currently marked, so we need another
// way to tell what's live vs dead.
- SetAllMarksFunctor functor;
+ ASSERT(!m_newlyAllocated);
+ m_newlyAllocated = adoptPtr(new WTF::Bitmap<atomsPerBlock>());
+
+ SetNewlyAllocatedFunctor functor(this);
forEachCell(functor);
FreeCell* next;
for (FreeCell* current = head; current; current = next) {
next = current->next;
reinterpret_cast<JSCell*>(current)->zap();
- clearMarked(current);
+ clearNewlyAllocated(current);
}
m_state = Marked;
Modified: trunk/Source/_javascript_Core/heap/MarkedBlock.h (133357 => 133358)
--- trunk/Source/_javascript_Core/heap/MarkedBlock.h 2012-11-02 22:12:40 UTC (rev 133357)
+++ trunk/Source/_javascript_Core/heap/MarkedBlock.h 2012-11-02 22:14:28 UTC (rev 133358)
@@ -159,6 +159,10 @@
void setMarked(const void*);
void clearMarked(const void*);
+ bool isNewlyAllocated(const void*);
+ void setNewlyAllocated(const void*);
+ void clearNewlyAllocated(const void*);
+
bool needsSweeping();
#if ENABLE(GGC)
@@ -218,6 +222,8 @@
#else
WTF::Bitmap<atomsPerBlock, WTF::BitmapNotAtomic> m_marks;
#endif
+ OwnPtr<WTF::Bitmap<atomsPerBlock> > m_newlyAllocated;
+
DestructorType m_destructorType;
MarkedAllocator* m_allocator;
BlockState m_state;
@@ -313,6 +319,7 @@
ASSERT(m_state != New && m_state != FreeListed);
m_marks.clearAll();
+ m_newlyAllocated.clear();
// This will become true at the end of the mark phase. We set it now to
// avoid an extra pass to do so later.
@@ -326,7 +333,7 @@
inline bool MarkedBlock::isEmpty()
{
- return m_marks.isEmpty() && m_weakSet.isEmpty();
+ return m_marks.isEmpty() && m_weakSet.isEmpty() && (!m_newlyAllocated || m_newlyAllocated->isEmpty());
}
inline size_t MarkedBlock::cellSize()
@@ -375,6 +382,21 @@
m_marks.clear(atomNumber(p));
}
+ inline bool MarkedBlock::isNewlyAllocated(const void* p)
+ {
+ return m_newlyAllocated->get(atomNumber(p));
+ }
+
+ inline void MarkedBlock::setNewlyAllocated(const void* p)
+ {
+ m_newlyAllocated->set(atomNumber(p));
+ }
+
+ inline void MarkedBlock::clearNewlyAllocated(const void* p)
+ {
+ m_newlyAllocated->clear(atomNumber(p));
+ }
+
inline bool MarkedBlock::isLive(const JSCell* cell)
{
switch (m_state) {
@@ -382,7 +404,7 @@
return true;
case Marked:
- return m_marks.get(atomNumber(cell));
+ return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell));
case New:
case FreeListed:
Modified: trunk/Source/_javascript_Core/heap/WeakBlock.cpp (133357 => 133358)
--- trunk/Source/_javascript_Core/heap/WeakBlock.cpp 2012-11-02 22:12:40 UTC (rev 133357)
+++ trunk/Source/_javascript_Core/heap/WeakBlock.cpp 2012-11-02 22:14:28 UTC (rev 133358)
@@ -102,7 +102,7 @@
continue;
const JSValue& jsValue = weakImpl->jsValue();
- if (Heap::isMarked(jsValue.asCell()))
+ if (Heap::isLive(jsValue.asCell()))
continue;
WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner();
@@ -127,7 +127,7 @@
if (weakImpl->state() > WeakImpl::Dead)
continue;
- if (Heap::isMarked(weakImpl->jsValue().asCell())) {
+ if (Heap::isLive(weakImpl->jsValue().asCell())) {
ASSERT(weakImpl->state() == WeakImpl::Live);
continue;
}
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes