#include "config.h"
#include "GCLogging.h"
#include "ClassInfo.h"
#include "Heap.h"
#include "HeapIterationScope.h"
#include "JSCell.h"
#include "JSCellInlines.h"
#include <wtf/PrintStream.h>
namespace JSC {
const char* GCLogging::levelAsString(Level level)
{
switch (level) {
case None:
return "None";
case Basic:
return "Basic";
case Verbose:
return "Verbose";
default:
RELEASE_ASSERT_NOT_REACHED();
return "";
}
}
class LoggingFunctor {
public:
LoggingFunctor(SlotVisitor& slotVisitor)
: m_slotVisitor(slotVisitor)
{
m_savedMarkStack.resize(m_slotVisitor.markStack().size());
m_slotVisitor.markStack().fillVector(m_savedMarkStack);
}
~LoggingFunctor()
{
reviveCells();
}
IterationStatus operator()(JSCell* cell)
{
m_liveCells.append(cell);
MarkedBlock::blockFor(cell)->clearMarked(cell);
return IterationStatus::Continue;
}
void log()
{
m_slotVisitor.clearMarkStack();
for (JSCell* cell : m_liveCells) {
cell->methodTable()->visitChildren(cell, m_slotVisitor);
dataLog("\n", *cell, ":\n", m_slotVisitor);
for (const JSCell* neighbor : m_slotVisitor.markStack())
MarkedBlock::blockFor(neighbor)->clearMarked(neighbor);
m_slotVisitor.clearMarkStack();
}
m_slotVisitor.reset();
}
void reviveCells()
{
for (JSCell* cell : m_liveCells)
MarkedBlock::blockFor(cell)->setMarked(cell);
for (const JSCell* cell : m_savedMarkStack) {
m_slotVisitor.markStack().append(cell);
const_cast<JSCell*>(cell)->setRemembered(true);
}
}
typedef void ReturnType;
void returnValue() { };
private:
Vector<const JSCell*> m_savedMarkStack;
Vector<JSCell*> m_liveCells;
SlotVisitor& m_slotVisitor;
};
void GCLogging::dumpObjectGraph(Heap* heap)
{
LoggingFunctor loggingFunctor(heap->m_slotVisitor);
HeapIterationScope iterationScope(*heap);
heap->objectSpace().forEachLiveCell(iterationScope, loggingFunctor);
loggingFunctor.log();
}
}
namespace WTF {
void printInternal(PrintStream& out, JSC::GCLogging::Level level)
{
switch (level) {
case JSC::GCLogging::Level::None:
out.print("None");
return;
case JSC::GCLogging::Level::Basic:
out.print("Basic");
return;
case JSC::GCLogging::Level::Verbose:
out.print("Verbose");
return;
default:
out.print("Level=", level - JSC::GCLogging::Level::None);
return;
}
}
}