#include "config.h"
#include "ConservativeRoots.h"
+#include "CodeBlock.h"
+#include "CodeBlockSet.h"
+#include "CopiedSpace.h"
+#include "CopiedSpaceInlines.h"
+#include "JSCell.h"
+#include "JSObject.h"
+#include "JSCInlines.h"
+#include "Structure.h"
+
namespace JSC {
-inline bool isPointerAligned(void* p)
+ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks, CopiedSpace* copiedSpace)
+ : m_roots(m_inlineRoots)
+ , m_size(0)
+ , m_capacity(inlineCapacity)
+ , m_blocks(blocks)
+ , m_copiedSpace(copiedSpace)
+{
+}
+
+ConservativeRoots::~ConservativeRoots()
{
- return !((intptr_t)(p) & (sizeof(char*) - 1));
+ if (m_roots != m_inlineRoots)
+ OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));
}
void ConservativeRoots::grow()
m_roots = newRoots;
}
-void ConservativeRoots::add(void* begin, void* end)
+template<typename MarkHook>
+inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook)
+{
+ markHook.mark(p);
+
+ m_copiedSpace->pinIfNecessary(p);
+
+ MarkedBlock* candidate = MarkedBlock::blockFor(p);
+ if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) {
+ ASSERT(!candidate || !m_blocks->set().contains(candidate));
+ return;
+ }
+
+ if (!MarkedBlock::isAtomAligned(p))
+ return;
+
+ if (!m_blocks->set().contains(candidate))
+ return;
+
+ if (!candidate->isLiveCell(p))
+ return;
+
+ if (m_size == m_capacity)
+ grow();
+
+ m_roots[m_size++] = static_cast<JSCell*>(p);
+}
+
+template<typename MarkHook>
+void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHook)
{
- ASSERT(begin <= end);
- ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000);
- ASSERT(isPointerAligned(begin));
- ASSERT(isPointerAligned(end));
+ if (begin > end) {
+ void* swapTemp = begin;
+ begin = end;
+ end = swapTemp;
+ }
+
+ RELEASE_ASSERT(isPointerAligned(begin));
+ RELEASE_ASSERT(isPointerAligned(end));
+ TinyBloomFilter filter = m_blocks->filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated.
for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it)
- add(*it);
+ genericAddPointer(*it, filter, markHook);
+}
+
+class DummyMarkHook {
+public:
+ void mark(void*) { }
+};
+
+void ConservativeRoots::add(void* begin, void* end)
+{
+ DummyMarkHook dummy;
+ genericAddSpan(begin, end, dummy);
+}
+
+void ConservativeRoots::add(void* begin, void* end, JITStubRoutineSet& jitStubRoutines)
+{
+ genericAddSpan(begin, end, jitStubRoutines);
+}
+
+template<typename T, typename U>
+class CompositeMarkHook {
+public:
+ CompositeMarkHook(T& first, U& second)
+ : m_first(first)
+ , m_second(second)
+ {
+ }
+
+ void mark(void* address)
+ {
+ m_first.mark(address);
+ m_second.mark(address);
+ }
+
+private:
+ T& m_first;
+ U& m_second;
+};
+
+void ConservativeRoots::add(
+ void* begin, void* end, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks)
+{
+ CompositeMarkHook<JITStubRoutineSet, CodeBlockSet> markHook(jitStubRoutines, codeBlocks);
+ genericAddSpan(begin, end, markHook);
}
} // namespace JSC