blob: bb1c8dca3892bb752edcc1072a66ebd371c72864 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef gc_Nursery_inl_h
#define gc_Nursery_inl_h
#ifdef JSGC_GENERATIONAL
#include "gc/Heap.h"
#include "gc/Nursery.h"
namespace js {
namespace gc {
/*
* This structure overlays a Cell in the Nursery and re-purposes its memory
* for managing the Nursery collection process.
*/
class RelocationOverlay
{
friend struct MinorCollectionTracer;
/* The low bit is set so this should never equal a normal pointer. */
const static uintptr_t Relocated = uintptr_t(0xbad0bad1);
/* Set to Relocated when moved. */
uintptr_t magic_;
/* The location |this| was moved to. */
Cell *newLocation_;
/* A list entry to track all relocated things. */
RelocationOverlay *next_;
public:
static RelocationOverlay *fromCell(Cell *cell) {
JS_ASSERT(!cell->isTenured());
return reinterpret_cast<RelocationOverlay *>(cell);
}
bool isForwarded() const {
return magic_ == Relocated;
}
Cell *forwardingAddress() const {
JS_ASSERT(isForwarded());
return newLocation_;
}
void forwardTo(Cell *cell) {
JS_ASSERT(!isForwarded());
magic_ = Relocated;
newLocation_ = cell;
next_ = NULL;
}
RelocationOverlay *next() const {
return next_;
}
};
} /* namespace gc */
} /* namespace js */
template <typename T>
JS_ALWAYS_INLINE bool
js::Nursery::getForwardedPointer(T **ref)
{
JS_ASSERT(ref);
JS_ASSERT(isInside(*ref));
const gc::RelocationOverlay *overlay = reinterpret_cast<const gc::RelocationOverlay *>(*ref);
if (!overlay->isForwarded())
return false;
/* This static cast from Cell* restricts T to valid (GC thing) types. */
*ref = static_cast<T *>(overlay->forwardingAddress());
return true;
}
#endif /* JSGC_GENERATIONAL */
#endif /* gc_Nursery_inl_h */