blob: 3381509beeea3910faef46f7af164e1b7b2beea9 [file] [log] [blame]
// Copyright 2014 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.
#ifndef MarkingVisitorImpl_h
#define MarkingVisitorImpl_h
#include "platform/heap/Heap.h"
#include "platform/heap/ThreadState.h"
#include "platform/heap/Visitor.h"
#include "wtf/Functional.h"
#include "wtf/HashFunctions.h"
#include "wtf/Locker.h"
#include "wtf/RawPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/TypeTraits.h"
namespace blink {
template <typename Derived>
class MarkingVisitorImpl {
protected:
inline void markHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback)
{
ASSERT(header);
ASSERT(objectPointer);
if (!toDerived()->shouldMarkObject(objectPointer))
return;
// If you hit this ASSERT, it means that there is a dangling pointer
// from a live thread heap to a dead thread heap. We must eliminate
// the dangling pointer.
// Release builds don't have the ASSERT, but it is OK because
// release builds will crash in the following header->isMarked()
// because all the entries of the orphaned heaps are zapped.
ASSERT(!pageFromObject(objectPointer)->orphaned());
if (header->isMarked())
return;
#if ENABLE(ASSERT)
ASSERT(ThreadState::current()->isInGC());
ASSERT(Heap::findPageFromAddress(header));
ASSERT(toDerived()->markingMode() != Visitor::WeakProcessing);
#endif
header->mark();
if (callback)
Heap::pushTraceCallback(const_cast<void*>(objectPointer), callback);
}
inline void mark(const void* objectPointer, TraceCallback callback)
{
if (!objectPointer)
return;
HeapObjectHeader* header = HeapObjectHeader::fromPayload(objectPointer);
markHeader(header, header->payload(), callback);
}
inline void registerDelayedMarkNoTracing(const void* objectPointer)
{
ASSERT(toDerived()->markingMode() != Visitor::WeakProcessing);
Heap::pushPostMarkingCallback(const_cast<void*>(objectPointer), &markNoTracingCallback);
}
inline void registerWeakMembers(const void* closure, const void* objectPointer, WeakCallback callback)
{
ASSERT(toDerived()->markingMode() != Visitor::WeakProcessing);
// We don't want to run weak processings when taking a snapshot.
if (toDerived()->markingMode() == Visitor::SnapshotMarking)
return;
Heap::pushThreadLocalWeakCallback(const_cast<void*>(closure), const_cast<void*>(objectPointer), callback);
}
inline void registerWeakTable(const void* closure, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback)
{
ASSERT(toDerived()->markingMode() != Visitor::WeakProcessing);
Heap::registerWeakTable(const_cast<void*>(closure), iterationCallback, iterationDoneCallback);
}
#if ENABLE(ASSERT)
inline bool weakTableRegistered(const void* closure)
{
return Heap::weakTableRegistered(closure);
}
#endif
inline bool ensureMarked(const void* objectPointer)
{
if (!objectPointer)
return false;
if (!toDerived()->shouldMarkObject(objectPointer))
return false;
#if ENABLE(ASSERT)
if (HeapObjectHeader::fromPayload(objectPointer)->isMarked())
return false;
toDerived()->markNoTracing(objectPointer);
#else
// Inline what the above markNoTracing() call expands to,
// so as to make sure that we do get all the benefits.
HeapObjectHeader* header = HeapObjectHeader::fromPayload(objectPointer);
if (header->isMarked())
return false;
header->mark();
#endif
return true;
}
Derived* toDerived()
{
return static_cast<Derived*>(this);
}
protected:
inline void registerWeakCellWithCallback(void** cell, WeakCallback callback)
{
ASSERT(toDerived()->markingMode() != Visitor::WeakProcessing);
// We don't want to run weak processings when taking a snapshot.
if (toDerived()->markingMode() == Visitor::SnapshotMarking)
return;
Heap::pushGlobalWeakCallback(cell, callback);
}
private:
static void markNoTracingCallback(Visitor* visitor, void* object)
{
visitor->markNoTracing(object);
}
};
} // namespace blink
#endif